14 Commits

Author SHA1 Message Date
69801df648 InitFlash manquante : tout le firmware tournait 4x trop lentement
DEFAUT PRINCIPAL -- etats d'attente de la flash jamais configures

  Le firmware s'execute depuis la flash (_FLASH), mais InitFlash() n'etait
  jamais appelee. Au reset FBANKWAIT vaut son MAXIMUM (0x0F0F, soit
  RANDWAIT = PAGEWAIT = 15) : chaque acces flash coutait 16 cycles au lieu
  des 3 necessaires a 60 MHz.

  Ironie : le memcpy des ramfuncs en tete de main() existe PRECISEMENT pour
  copier InitFlash() en RAM, puisqu'elle doit s'executer hors flash. La
  recopie se faisait depuis le premier jour sans que la fonction ne soit
  jamais appelee -- la section ramfuncs ne contenait que 4 mots, elle en
  fait 0x21 maintenant.

  Mesure au scope sur l'ISR ADC :
    avant : 22,3 kHz, ISR 30 us, 88 % de charge CPU
    apres : 66,85 kHz, ISR 4,9 us, 33 % de charge CPU
  66,85 kHz est le maximum theorique (200 kHz / SOCAPRD=3), atteint sans
  aucun declenchement manque. Recoupe au compteur : 67,5 kHz.

Optimisation compilateur

  -O2 ajoute : le projet compilait sans aucune option d'optimisation.
  Contribution mesuree : ISR de 41 a 30 us, mais SANS changer la cadence --
  ce n'etait pas le facteur limitant. Conserve, le gain reste reel.

Discipline ISR (ni multiplication ni division en interruption)

  status_led_tick() : quatre modulos (%200, %40, %100, %100) remplaces par
    un compteur qui reboucle sur comparaison.
  cpu_timer0_isr()  : "tick % 30" remplace par un compteur dedie.
  control_tick()    : le tableau stages[2] etait initialise sur la pile a
    chaque appel, des dizaines de milliers de fois par seconde -> static const.
  pwm_set_duty_counts() : une division flottante y mettait a jour la
    consigne, sur un F28027 sans FPU. Supprimee ; pwm_get_duty() relit
    CMPA, la telemetrie reste juste.

control.c/h -- balayage de caracterisation (BOUCLE OUVERTE)

  Ce module ne regule rien : il balaie le duty de 1 % a 50 % puis revient,
  par pas de 1 LSB de CMPA a chaque conversion ADC. Appel cadence depuis
  l'ISR ADC, conformement a PROMPT §6 etape 8.

  API en counts ajoutee a pwm.c : le pas minimal est 1 LSB de CMPA et
  DEPEND DE L'ETAGE (1/300 = 0,333 % a 200 kHz, 1/600 = 0,167 % a 100 kHz).
  Une consigne flottante ne permet pas d'exprimer "le plus petit pas".

  Resultat mesure a 66,7 kHz :
    etage 1 : 1->50 % en 2,2 ms, cycle 4,4 ms, 22 %/ms
    etage 2 : 1->50 % en 4,4 ms, cycle 8,9 ms, 11 %/ms
  L'etage 2 est deux fois plus lent PARCE QUE sa resolution est deux fois
  plus fine, a cadence de mise a jour identique.

  La telemetrie transporte desormais le duty reel, relu depuis CMPA.

L'instrumentation de mesure a ete RETIREE : GPIO32 est rendue a HV_EN, qui
en a de nouveau l'usage exclusif (verifie sur cible, broche stable a 0).

Note : ce defaut de wait states etait present depuis le debut du projet.
Toutes les mesures de timing anterieures etaient faussees d'un facteur 4.
Les frequences PWM et les protections sont materielles et restent valides.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 21:28:34 +02:00
b1bb0fa21a Reprise controlee apres EMUSTOP, sans lever le verrouillage des defauts
Le verrouillage total decide precedemment (aucun effacement, cycle
d'alimentation obligatoire) rendait le developpement intenable : chaque
breakpoint tuait le PWM jusqu'a debranchement. EMUSTOP n'est pourtant pas
un defaut de puissance mais un artefact du debogueur.

La distinction est maintenant explicite dans la boucle principale :

  overcurrent / overtemp -> enter_safe_state(), VERROUILLE jusqu'au cycle
                            d'alimentation (PROMPT §8), aucun acquittement
  emustop seul           -> reprise controlee

La reprise ne redemarre PAS la conversion la ou elle s'etait arretee :
elle repasse par start_conversion(), le meme chemin qu'au boot, duty remis
a zero d'abord. Quand la rampe de soft-start existera, la reprise apres
breakpoint en beneficiera automatiquement.

uart_link_restart()
  Reset logiciel du SCI, vidage des FIFO, abandon de la ligne en cours et
  de la trame en attente. Pendant la halte l'ESP32 a continue d'emettre :
  l'anneau de reception a deborde et la ligne assemblee est tronquee.
  Le vidage avance seulement la QUEUE de l'anneau ; s_rx_head appartient a
  l'ISR et n'est pas touche, ce qui exclut toute course.

TZCLR au demarrage dans safety_init()
  TZFLG.OST est latche dans le materiel : il survit a un reset logiciel
  comme a un rechargement de programme, et sans ce clear le PWM restait
  coupe sans raison visible.
  Sans danger, pour une raison precise : a ce stade pwm_init() a deja
  force les deux sorties a l'etat bas (AQCSFRC), donc rien ne demarre ; et
  si la condition de defaut est toujours presente le trip se re-verrouille
  immediatement. On n'efface qu'un etat perime, jamais un defaut reel.

start_conversion()
  Sequence de demarrage factorisee, appelee au boot et a la reprise.
  Inhibe la decharge AVANT d'autoriser les etages -- jamais l'inverse,
  sinon la conversion travaillerait contre le circuit de decharge.

Valide sur cible apres cycle pause/reprise/pause :
  TZEINT.OST rearme a 1 (l'ISR l'avait mis a 0), AQCSFRC.CSFA a 0,
  GPIO5 a 1 (decharge inhibee), GPIO16 a 1.

LIMITE CONNUE, non resolue ici : a la reprise l'effacement est immediat
alors que la telemetrie ne part que toutes les 300 ms. FAULT=1 ne sera
donc quasiment jamais emis, et l'ESP32 ignorera qu'un EMUSTOP a eu lieu
(sans meme voir de timeout si la halte a dure moins de 2 s). Transmettre
FAULT=1 AVANT la halte est structurellement impossible : la halte est
asynchrone, imposee par la logique de debug, sans point d'accroche
prealable -- c'est justement pourquoi TZ6 est un chemin materiel. La
solution sera un drapeau collant maintenu quelques secondes apres la
reprise.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 17:22:44 +02:00
26c1d499e0 Champ FAULT, decharge HT active, et surtemperature par voie
Circuit de decharge rapide (GPIO5, broche 40)

  Commande DISCHARGE du circuit de la carte de puissance : MOSFET en serie
  avec 47 kOhm aux bornes du condensateur de sortie, soit tau = 0,94 s et
  environ 2 s pour passer de 500 V a 50 V. Sans lui, le seul bleeder de
  1 MOhm demandait ~42 s.

  POLARITE INVERSEE, et c'est le coeur du montage. Le GPIO pilote un NPN
  qui court-circuite la grille du MOSFET :
    niveau haut -> NPN conduit -> grille a la masse -> decharge INHIBEE
    niveau bas ou broche non pilotee -> grille tiree a 12 V -> decharge ACTIVE

  GPIO5 est une broche a fonction PWM : pas de pull-up au reset (PROMPT §6
  etape 3), elle flotte. La decharge est donc active au reset, pendant un
  plantage, et surtout ALIMENTATION COUPEE -- exactement le cas ou le
  firmware ne garantit plus rien et ou l'operateur croit la carte
  inoffensive. C'est precisement le cas impose par le choix de n'effacer un
  defaut que par cycle d'alimentation.

  Sequencement explicite :
   - enter_safe_state() active la decharge APRES avoir coupe HV_EN : la
     charge est isolee d'abord, le condensateur vide ensuite ;
   - le retour au nominal inhibe la decharge AVANT d'autoriser les etages,
     jamais l'inverse ;
   - bsp_gpio_control_init() la laisse ACTIVE au demarrage : au boot le
     condensateur peut encore etre charge par une session precedente.

Champ FAULT dans la trame $T

  Codes 0-5, priorite 2 > 3 > 4 > 5 > 1. EMUSTOP (code 1) a donc la
  priorite la PLUS BASSE malgre son numero : en developpement il se
  declenche a chaque halte du debogueur et ne doit jamais masquer une
  surintensite reelle.

  Pas de code court-circuit : il franchit le meme comparateur et le meme
  seuil qu'une surintensite, le firmware ne peut pas les distinguer.

  Aucun effacement automatique ni par commande UART : le verrouillage
  n'est leve que par un cycle d'alimentation (PROMPT §8).

Surtemperature suivie PAR VOIE

  s_overtemp_t1 / s_overtemp_t2 separes, avec hysteresis chacun. L'ancien
  maximum des deux voies ne permettait pas de distinguer les codes 4 et 5.
  Seuil ramene a 80 degC pour coller au protocole.

Divers
  UART_LINE_MAX porte a 200 (buffer ESP32 g_lineBuf[200]).
  append_field_int() pour les champs entiers, meme convention de bornage
  que append_field : un champ qui ne tient pas est abandonne entierement.

Documentation
  docs/mesure-cartepuissance.md ajoute au depot (source de tracabilite des
  coefficients de calib.h).
  docs/ESP32-UART.md mis a jour, avec deux corrections de fond :
   - la mention "remettre FAULT=0 automatiquement des que la cause a
     disparu" est remplacee par une section sur le verrouillage ; elle
     contredisait le comportement reel, le TMS320 reemettant indefiniment
     le code latche ;
   - l'icone danger est specifiee comme dependant UNIQUEMENT de VOUT et
     jamais de FAULT. Un defaut ne decharge pas le condensateur : la faire
     disparaitre reviendrait a rassurer l'operateur quand le risque est
     maximal.
  Le piege strtol / uint8_t 16 bits y est documente pour eviter qu'il soit
  reintroduit ailleurs.

A cabler cote materiel : liaison broche 40 vers la carte de puissance, et
pull-down 10 kOhm sur la base du NPN.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 17:00:32 +02:00
46ddf30a64 Etape 2 validee sur cible : trip comparateur, arret global, Stagex-EN
safety_init() complet est maintenant appele a la place de
safety_arm_emustop_only() : comparateurs + Digital Compare + Trip Zone.
Seuils DAC verifies sur cible a 601 / 603, conformes au calcul de
docs/mesure-cartepuissance.md pour 3,0 A.

CORRECTIF -- les trips ne remontaient pas au logiciel (safety.c)

  TZFLG.INT est le drapeau GLOBAL d'interruption Trip Zone : tant qu'il
  n'est pas efface via TZCLR.INT, plus AUCUNE interruption TZ n'est generee.
  Les ISR ne faisaient que PIEACK. Consequence : le premier trip de la
  session (un EMUSTOP provoque par une pause du debogueur) consommait
  l'unique notification, et tous les suivants coupaient bien le PWM en
  materiel mais en SILENCE, sans lever de drapeau logiciel.

  Constate au banc : surintensite reelle sur I2, EPwm2Regs.TZFLG = 0x0D
  (INT + OST + DCAEVT1, donc trip comparateur bien latche), PWM2 coupe,
  et pourtant LED au nominal.

  Ce defaut etait invisible en testant un seul trip a la fois. Il ne serait
  apparu qu'en exploitation, sous la forme "la protection coupe mais l'IHM
  n'affiche aucun defaut".

  Second piege evite : effacer INT alors que la surintensite persiste
  regenere l'evenement immediatement -> tempete d'interruptions qui
  affamerait la boucle principale, donc plus de telemetrie ni de LED, au
  pire moment. L'ISR desarme donc TZEINT.OST : une seule notification par
  episode. Le rearmement est fait par safety_clear_faults() uniquement,
  jamais automatiquement (PROMPT §8).

  safety_clear_faults() efface desormais DCAEVT1 (sinon le prochain trip
  serait attribue a une surintensite meme s'il vient d'EMUSTOP), INT, et
  rearme TZEINT.OST.

Arret global sur defaut (main.c)

  enter_safe_state() : les deux etages inhibes (PWM + Stagex-EN) ET HV_EN
  coupe. Sur un boost en cascade, laisser tourner l'etage 2 pendant que
  l'etage 1 est coupe n'a pas de sens. Couper HV_EN n'est pas redondant :
  un boost a 0 % de duty ne donne PAS 0 V en sortie, le chemin
  Vin -> L -> diode -> Cout reste passant ; HV_EN (VOM1271) est le seul
  organe qui isole reellement la charge (PROMPT §6 etape 6).

  Les Trip Zones restent independantes en materiel : cet arret global est
  la couche systeme au-dessus, executee au rythme de la boucle principale.
  La coupure rapide (~30 ns) reste la porte ET + le Trip Zone.

  Stagex-EN est maintenant pilote en continu : 1 au nominal, 0 sur defaut.
  Inhibition SUPPLEMENTAIRE, le logiciel ne peut jamais outrepasser la
  coupure materielle deja faite par COMPxOUT sur l'autre entree de la porte.

Valide au banc : injection de 2 A sur le shunt 2 avec seuil abaisse a
1,5 A -> les deux etages coupes, LED rouge fixe, defaut latche.

ATTENTION, toujours en place dans main.c : le harnais de bring-up force le
PWM a 50 % en dur, et Stagex-EN passe desormais a 1 automatiquement au
demarrage. Des que les drivers UCC27517 seront montes, la carte se mettra
donc a decouper A LA MISE SOUS TENSION, sans commande -- exactement ce que
le PROMPT §6 etape 6 interdit (demarrage a 0 % + rampe de soft-start).
Retirer ce harnais AVANT de monter les drivers.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 20:30:53 +02:00
a05c1e8124 Machine d'etats LED, protection thermique, et correctif checksum RX
CORRECTIF CRITIQUE -- reception UART cassee (uart_link.c)

  Le decodage du checksum utilisait strtol sur s_line, qui n'est JAMAIS
  terminee par un '\0'. strtol lisait donc au-dela de la trame, dans les
  residus de la ligne precedente.

  Aggravant, specifique au C28x : uint8_t y fait 16 bits (pas d'adressage
  par octet), donc le cast (uint8_t) ne tronquait rien. Un "7D" suivi d'un
  "7D" residuel donnait 0x7D7D = 32125, conserve tel quel, et TOUTE trame
  etait rejetee. Sur une architecture a octets le cast aurait masque le
  probleme et le bug serait passe inapercu.

  Constate sur cible : cs_calc = 0x7D (correct), cs_recv = 0x7D7D.
  Consequence visible : plus aucune commande $C acceptee, donc timeout de
  liaison permanent alors que l'ESP32 emettait correctement.

  Remplace par parse_hex2(), borne a exactement deux chiffres, qui ne
  depend d'aucune terminaison et rejette un checksum malforme. Supprime au
  passage la dependance a stdlib.

status_led.c/h -- affichage d'etat
  STARTUP      bleu fixe (1 s minimum, sinon jamais visible)
  NOMINAL      bleu 0,2 / 1,8 s
  LINK_LOST    bleu 0,2 / 0,2 s   (> 2 s sans trame $C valide)
  EMUSTOP      alternance bleu/rouge 0,5 / 0,5 s
  OVERTEMP     rouge 0,5 / 0,5 s
  OVERCURRENT  rouge fixe

  Priorite : surintensite > surtemperature > EMUSTOP > liaison perdue.
  La surintensite passe devant EMUSTOP : en developpement EMUSTOP se
  declenche en permanence et ne doit jamais masquer un defaut de puissance.

  Limite de principe : pendant une halte CPU, plus aucun code ne tourne,
  les GPIO restent figes sur la phase courante du motif. L'alternance
  EMUSTOP est donc un indicateur a posteriori, jamais un etat live.

safety.c/h -- origine du trip
  TZFLG.DCAEVT1 (bit 3) est distinct de TZFLG.OST (bit 2), ce qui permet de
  separer une surintensite reelle (comparateur) d'un arret du debugger.
  Les ISR ne pilotent plus les LED, elles ne font que relever la cause.

Protection thermique (main.c, calib.h)
  Seuil 85 degC avec hysteresis de 10 degC, coupure du PWM et de HV_EN.
  Lente par nature, donc entierement logicielle -- aucun chemin materiel
  requis, contrairement a la surintensite.
  Pas de redemarrage automatique : rien ne reactive le PWM une fois coupe.
  Seuil PROVISOIRE : les NTC sont a 5 mm des MOSFET, donc elles mesurent le
  cuivre et non la jonction (ecart statique et retard thermique notables).
  A recaler quand la temperature de boitier en charge sera connue.

Valide sur cible : commandes $C de nouveau acceptees, chaine NTC lue a
24,5 / 24,7 degC sur pont 10k/10k (coherent avec des resistances a 1 %).

Note : un pont 10k/10k ne discrimine PAS le sens de la formule NTC, les
deux formes coincidant au point d'equilibre. Verification a faire avec une
resistance asymetrique (4,7 kOhm -> environ 47 degC).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 19:53:32 +02:00
888723abc7 Etape 5 : measure.c et constantes de calibration reelles
Report des mesures de docs/mesure-cartepuissance.md dans calib.h, avec une
structure par voie (gain, offset) plutot que des constantes isolees.

calib.h
  Tensions   : VIN 11,11 / V1 31,25 / VOUT 181,82 V/V (mesures)
  IIN        : 1,2019 A/V -- un seul point mesure, offset suppose nul
  IOUT       : 0,016667 A/V -- NON MESURE, valeur theorique de conception
  Shunts     : I1 offset 47,3 mV gain 0,631 V/A
               I2 offset 34,0 mV gain 0,637 V/A
               Deux jeux separes : les voies different d'environ 1 % en gain
               et n'ont pas le meme offset, ne jamais moyenner.

Seuil de protection : le code DAC est maintenant calcule par macro a partir
de SAFETY_ISHUNT_THRESHOLD_A et des gain/offset mesures, et il est PROPRE A
CHAQUE ETAGE (601 et 603 au lieu d'un 558 commun).

  Correction d'analyse : le 558 precedent supposait un gain de 30 pile. Le
  gain reel etant plus eleve (~31,5), le seuil de 1,8 V etait atteint a
  2,78 A et non a 3 A -- la protection declenchait donc TROP TOT, et non
  trop tard comme indique au §5 du document de mesures. Conservatif, sans
  danger, mais corrige.

measure.c/h (etape 5)
  measure_vin/iin/v1/vout/iout/i1/i2/temp, signature float f(uint16_t raw).
  Deux fonctions distinctes pour les shunts, puisque gain ET offset
  different. measure_i1/i2 peuvent renvoyer une valeur negative a courant
  nul : volontaire, une derive d'offset apres changement d'ampli devient
  ainsi visible en telemetrie au lieu d'etre masquee par une saturation.

  NTC : la relation du PROMPT §5 est INVERSEE. Avec la NTC cote 3,3 V c'est
  R_ntc = R_fixe * (VREF - Vadc) / Vadc. Verifie sur les points de repere du
  PROMPT lui-meme : 0,75 V a 0 degC donne 34,2 kOhm, ce que beta=4000
  predit, alors que la forme inversee donnerait 2,94 kOhm (donc du chaud).
  Telle qu'ecrite, la protection thermique aurait ete inexploitable.

La telemetrie transporte desormais de vraies grandeurs physiques.

Reste en suspens (voir docs/mesure-cartepuissance.md §6) : IOUT jamais
mesure, second point pour IIN, valeur reelle de la resistance fixe des
ponts NTC, et surtout gain/offset des shunts A REMESURER apres passage du
MCP6001 au TLV9151 -- l'offset actuel est domine par le Vos de l'ampli.

Note : l'"auto-zero logiciel au boot" evoque dans le document de mesures
n'existe pas dans le firmware et n'a pas ete ajoute ; mesurer un offset au
boot figerait une valeur fausse si du courant circule deja.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 18:50:21 +02:00
d26c07d3a1 Etapes 3/4/6 : GPIO de commande, PWM et ADC valides sur cible
Campagne de bring-up materiel complete, carte de conversion DECONNECTEE.

pwm.c/h (etape 6) -- valide au scope
  ePWM1 -> etage 1, EPWM1A/GPIO0/broche 29, 200 kHz (TBPRD=299)
  ePWM2 -> etage 2, EPWM2A/GPIO2/broche 37, 100 kHz (TBPRD=599)
  Mode up-count, TBCLK = SYSCLKOUT = 60 MHz, duty 0 au demarrage,
  inhibition par forcage continu AQCSFRC. Tranche le point ouvert §9.1.
  HRPWM non implemente, notes de portage consignees dans pwm.c.

adc.c/h (etape 4) -- 9 voies validees, T1/T2 comprises
  Reference interne (ADCREFSEL=0), SOC declenches par ePWM1 SOCA avec
  SOCAPRD=3 (~66 kHz), jamais en free-run. ISR ADCINT1 courte : rangement
  des valeurs brutes uniquement, aucun flottant.
  Note materielle : les 9 voies lisaient 4095 tant que VDDA (broche 11)
  n'etait pas alimentee -- y compris VREFLO converti en interne, ce qui a
  permis d'ecarter le logiciel.

bsp_gpio (etape 3)
  HV_EN (GPIO32), Stage1/2-EN (GPIO16/17) en sortie, etat sur a 0, et
  pull-ups internes de GPIO16/17 desactivees : sinon elles presentent un 1
  sur une entree de chaque porte ET avant que le firmware ne tourne.
  bsp_gpio_stage_default_override_init() : pilotage manuel de GPIO1/GPIO3
  pour valider les portes ET, exclusif avec safety_init().

safety_arm_emustop_only() -- BRING-UP
  Arme TZ6 seul, sans les comparateurs, pour valider EMUSTOP isolement
  quand les entrees shunt ne sont pas cablees.

Resultats materiels :
  - portes ET IC8/IC9 : sortie = ET logique des deux entrees, verifie au
    scope avec des cadences distinctes (default 400 ms, EN 1 s)
  - comparateur : entree shunt 0 -> 3 V declenche bien le trip
  - EMUSTOP : arret du debugger -> broches 29 et 37 a 0, TZFLG.OST latche,
    et le flag ne se rearme pas apres continue
  - un trip EMUSTOP ne peut PAS etre efface tant que le CPU est halte (la
    source reste assertee) : l'effacement devra passer par une commande
    UART en fonctionnement (etape 7)

main.c contient encore le bloc de bring-up (PWM force a 50 %, telemetrie
transportant les tensions ADC brutes en volts) : A RETIRER, et remplacer
safety_arm_emustop_only() par safety_init(), avant toute mise sous tension
de la puissance (PROMPT §8).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 20:42:14 +02:00
d185d73422 Etape 7 : liaison UART SCI-A 57600 8N1 validee sur cible
Emission $T,...*XX et reception $C,...*XX conformes a docs/ESP32-UART.md.
Trame mesuree a 129 caracteres, checksum XOR verifie independamment.

Corrections trouvees au bring-up sur materiel :

- StartCpuTimer0() manquant : ConfigCpuTimer() laisse le timer arrete, donc
  le tick d'emission ne se produisait jamais et rien ne partait sur la ligne.

- Suppression de "%f" dans sprintf. Sur C28x le support flottant de printf
  passe par du long double 64 bits emule (frexpl/scalbnl/L$$DIV) : le CPU
  partait a PC=0 des le premier envoi. Formatage decimal manuel a la place,
  comme le prevoyait deja PROMPT §7 etape 7.

- RXFFIENA n'etait pas arme dans SCIFFRX : aucune interruption de reception.

- Recuperation de SCIRXST.RXERROR. Un FE/OE/PE/BRKDT le latche et bloque le
  recepteur jusqu'a un SW RESET du SCI ; sans ca une seule perturbation
  arretait la reception definitivement (constate : RXERROR+FE+BRKDT latches).

- Formatage borne : clamp des valeurs (NaN et saturation) puis snprintf avec
  la capacite restante. Un champ qui ne tient pas est abandonne entierement,
  ce que le protocole autorise, plutot que de deborder s_tx_frame.

- Emission non bloquante : send_telemetry() ne fait que mettre en attente,
  uart_link_service_tx() pousse au plus une FIFO (4 octets) puis rend la
  main. L'ancienne version monopolisait 22 ms par trame, incompatible avec
  la priorite donnee a la boucle de regulation.

Plan memoire (F2802x_generic_flash.cmd) :
- les 4 secteurs flash du F28027 sont declares (32K mots au lieu de 8K)
- .ebss bascule en RAML0 : il etait colle juste apres .stack, donc tout
  debordement de pile ecrasait silencieusement les globales
- pile portee a 1024 mots, seule dans RAMM1

LED : polarite reelle confirmee active-haut (cathode commune a la masse,
anodes pilotees par GPIO12/GPIO33 a travers 1k) -> LED_ACTIVE_LOW = 0.
Repond au point ouvert §9.2 du PROMPT.

safety_init() reste desactive dans main.c : bring-up isole LED+UART, a
reactiver quand l'etage de puissance sera cable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 18:38:18 +02:00
e717d0deec Fix broken self-referential C2000Ware path in .cproject
The previous commit replaced the hardcoded path with a variable
reference to itself (${COM_TI_C2000WARE_INSTALL_DIR}), which broke
include resolution and the build entirely. Restore the absolute path
confirmed via getProjectProductReferences.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-02 12:24:42 +02:00
e0efeebe94 Ignore IDE-local files; make C2000Ware path portable in .cproject
.mcp.json and CLAUDE.md are auto-generated by CCS with machine-specific
absolute paths and shouldn't be shared via git. The .cproject change
(likely from a CCS reimport) replaces the hardcoded C2000Ware install
path with a variable reference.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-02 11:44:49 +02:00
f9f6909a56 Fix red LED pin number in comment (36, not 35); add corrected pinout doc 2026-08-02 11:12:52 +02:00
616ae539cc Steps 1+2: clock init (INTOSC1 60MHz), LED heartbeat, comparator/DAC/TripZone safety + EMUSTOP (build OK, HW validation pending) 2026-08-01 20:34:27 +02:00
8d71489f48 Restructure project: remove LED demo, switch to Flash linker 2026-08-01 20:33:47 +02:00
ad51f1d9c6 Initial commit: F28027 dualboost LED blink project 2026-08-01 11:20:37 +02:00