Hallo zusammen, ich arbeite aktuell mit einem MSP430G2553. Ich hatte das 'System' eigentlich sehr stabil am Laufen, musste aber nun noch etwas hinzufügen. Jetzt habe ich das Problem, dass der Controller scheinbar gelegentlich einen Reset macht. Nachdem ich bereits den Verdacht hatte, habe ich einen Breakpoint am Anfang des Codes erstellt und konnte damit tatsächlich den Reset nachweisen. Der Reset-Pin ist mit 47k an VCC und 1nF an GND angebunden. Meine Vermutung ist, dass ich den Flash-Speicher überschreite. CCS zeigt mir an, dass 79% genutzt werden. Aber das ist ja nur ein statischer Wert. Im Worst Case kann es ja auch mehr werden. Hat jemand eine Idee, wie ich herausfinden kann, ob das das Problem ist? Gibt es da eventuell einen Interrupt oder bietet CCS da irgend eine Funktion, um das zu prüfen? Vielen Dank, Grüße Andreas
Andreas S. schrieb: > Meine Vermutung ist, dass ich den Flash-Speicher überschreite. Wieso? Viel wahrscheinlicher ist, daß Du mit dem RAM Probleme hast. Ein Stacküberlauf beispielsweise. Das Flash ist konstant, das verändert sich nicht zur Laufzeit. Das RAM hingegen sehr wohl.
https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/746272/faq-handling-msp430-system-reset-events > When a reset occurs, the cause of the event it logged by the MSP430 > CPU’s System peripheral (SYS).
Du könntest mal in den Compilereinstellung die Stackgröße größer machen. Vielleicht hast du da einen Überlauf.
Hannes J. schrieb: > https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/746272/faq-handling-msp430-system-reset-events >> When a reset occurs, the cause of the event it logged by the MSP430 >> CPU’s System peripheral (SYS). Das werde ich mal checken und dann berichten. Vielen Dank 🙏🏻
Andreas S. schrieb: > Nachdem ich bereits den Verdacht hatte, habe ich > einen Breakpoint am Anfang des Codes erstellt und konnte damit > tatsächlich den Reset nachweisen. Nö, Du hast damit nur festgestellt, daß der Programmcounter in den Resetvektor läuft. Ob ein Reset erfolgte kannst Du nur mit den Flags für den Resetgrund feststellen. Z.B. beim AVR-GCC läuft jeder Interrupt in den Resetvektor, für den kein Handler aufgesetzt wurde.
:
Bearbeitet durch User
Andreas S. schrieb: > Meine Vermutung ist, dass ich den Flash-Speicher überschreite. Dann kriegst Du schon vom Programmer bzw. Bootloader die rote Karte, weil spätestens das Verify fehlschlägt. Der Flash darf zu 100% genutzt werden.
:
Bearbeitet durch User
Hannes J. schrieb: > https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/746272/faq-handling-msp430-system-reset-events >> When a reset occurs, the cause of the event it logged by the MSP430 >> CPU’s System peripheral (SYS). Hallo Hannes, vielen Dank für deinen Tipp. Wäre zu schön gewesen, wenn ich damit weiter gekommen wäre. Allerdings besitzt die MSP430F2xx, MSP430G2xx Family dieses Feature und somit auch das SYSRSTIV Register nicht. Ersatzweise bin ich dann über die (Non)-Maskable Interrupts (NMI) gegangen und habe herausgefunden, dass der Reset scheinbar durch eine Flash Access Violation (ACCVIFG) ausgelöst wird. Jetzt muss ich nur noch herausfinden, wie ich das behebe. Vielen Dank für eure Hilfe! Grüße Andy P.S.: Vergrößerung des Stacks hat das Problem nicht gelöst :-(
Andreas S. schrieb: > Ersatzweise bin ich dann über die (Non)-Maskable Interrupts (NMI) > gegangen Und warum hast Du Dein Programm nicht im Debugger laufen lassen?
Nochmal kurz zum genaueren Verständnis. Ich lasse das Programm die ganze Zeit im Debugger laufen. Allerdings hatte ich das Problem, dass sich der Controller gelegentlich aufgehangen hat. Habe dann durch das Debugging herausgefunden, dass der Controller zwischendurch ungeplant zum Anfang der main() springt. Wenn er das tut, während er gerade mit anderen Komponenten kommuniziert, hängt er sich auf. Das er sich aufhängt, konnte ich fixen. Aber die Sprünge zum Anfang der main() sind weiter vorhanden. Ich habe die Sprünge als Reset interpretiert. Nun habe ich folgende ISR hinzugefügt
1 | #pragma vector=NMI_VECTOR
|
2 | __interrupt void NMI_ISR_HOOK(void) |
3 | {
|
4 | if (IFG1 & WDTIFG) |
5 | {
|
6 | //while(1); // Watchdog timer+ interrupt flag
|
7 | }
|
8 | else if (IFG1 & OFIFG) |
9 | {
|
10 | while(1); // Oscillator fault interrupt |
11 | }
|
12 | else if (IFG1 & NMIIFG) |
13 | {
|
14 | while(1); // NMI interrupt flag |
15 | }
|
16 | else if (FCTL3 & ACCVIFG) |
17 | {
|
18 | while(1); <- hier bleibt er haengen |
19 | }
|
20 | }
|
Im Debugger kann ich nun sehen, dass er in die while-Schleife (Zeile 18) springt. Daraus schließe ich: Es tritt ein Flash-Zugriffs Fehler auf, der laut Datenblatt automatisch zu einem Reset führt. Auszug aus Datenblatt: A (non)-maskable NMI interrupt can be generated by three sources: • An edge on the RST/NMI pin when configured in NMI mode • An oscillator fault occurs • An access violation to the flash memory Sehe ich das soweit richtig?
Andreas S. schrieb: > habe herausgefunden, dass der Reset scheinbar durch eine Flash Access > Violation (ACCVIFG) ausgelöst wird. Jetzt muss ich nur noch herausfinden, > wie ich das behebe. ACCVIFG wird gesetzt, wenn du zum falschen Zeitpunkt (während der Flash geschrieben oder gelöscht wird, siehe Tabelle 7-3) auf den Flash zugreifst. Ich vermute mal, dass sich dein Code sich nicht an die Vorgaben in Kapitel 7.3.2/7.3.3 hält.
Clemens L. schrieb: > Andreas S. schrieb: >> habe herausgefunden, dass der Reset scheinbar durch eine Flash Access >> Violation (ACCVIFG) ausgelöst wird. Jetzt muss ich nur noch herausfinden, >> wie ich das behebe. > > ACCVIFG wird gesetzt, wenn du zum falschen Zeitpunkt (während der Flash > geschrieben oder gelöscht wird, siehe Tabelle 7-3) auf den Flash > zugreifst. > > Ich vermute mal, dass sich dein Code sich nicht an die Vorgaben in > Kapitel 7.3.2/7.3.3 hält. Hallo Clemens, ja, das wird es sein, denke ich. Allerdings weiß ich noch nicht, wie ich das Problem beheben soll. Ich kann doch nicht jedes Mal vor dem Zugriff das Busy-Bit prüfen :-O
Andreas S. schrieb: > Allerdings weiß ich noch nicht, wie ich das Problem beheben soll. Ich kenne deinen Code zum Flash-Schreiben nicht, also weiß ich auch nichts.
Andreas S. schrieb: > Ich kann doch nicht jedes Mal vor dem Zugriff > das Busy-Bit prüfen Dein Programm schreibt im Flash herum? Wirklich?
Harald K. schrieb: > Andreas S. schrieb: >> Ich kann doch nicht jedes Mal vor dem Zugriff >> das Busy-Bit prüfen > > Dein Programm schreibt im Flash herum? Wirklich? Anscheinend, aber ich mach das nicht bewusst. Ich arbeite eigentlich nur mit den Variablen, SPI, I2C, Timer und ADC. Das dürfte sich ja eigentlich alles im RAM abspielen oder? Aber irgendwie scheint es ja zur Flash Access Violation zu kommen :-(
:
Bearbeitet durch User
Andreas S. schrieb: > Anscheinend, aber ich mach das nicht bewusst. Hmm. Verwendest Du einen Bootloader oder irgendsoetwas? Denn irgendwo muss ja der Code herkommen, der versucht, das Flash zu beschreiben (oder auf welche Art und Weise auch immer darauf zuzugreifen, daß es zur Zugriffsverletzung kommt). Einfaches Lesen sorgt natürlich nicht für so etwas.
Andreas S. schrieb: > Ich kann doch nicht jedes Mal vor dem Zugriff > das Busy-Bit prüfen :-O Merkwürdige Ansicht. Du kannst natürlich alternativ pauschal x ms abwarten vor dem nächsten Zugriff. Aber egal wie Du das machst - abwarten mußt Du die Busy-Phase ...
Jens G. schrieb: > Andreas S. schrieb: >> Ich kann doch nicht jedes Mal vor dem Zugriff >> das Busy-Bit prüfen :-O > > Merkwürdige Ansicht. Du kannst natürlich alternativ pauschal x ms > abwarten vor dem nächsten Zugriff. Aber egal wie Du das machst - > abwarten mußt Du die Busy-Phase ... Wenn ich bewusst auf den Flash zugreifen würde, würde ich das Busy-Bit natürlich abfragen. Aber ich greife ja eigentlich immer nur auf Variablen zu und da kann ich ja nicht jedes Mal vorher das Busy-Bit abfragen. Muss ja auch eigentlich nicht, da ich da ja nur auf den RAM zugreife. Sry, arbeite schon einige Weile mit dem Controller, habe aber noch nie explizit auf den Flash zugegriffen. Ich hatte bisher auch noch nie solch ein Problem. Daher bin ich etwas unwissend in dem Bereich. Ich flashe den Controller übrigens mit dem MSP-FET, also kein Bootloader.
Andreas S. schrieb: > Wenn ich bewusst auf den Flash zugreifen würde, würde ich das Busy-Bit > natürlich abfragen. Aber ich greife ja eigentlich immer nur auf > Variablen zu und da kann ich ja nicht jedes Mal vorher das Busy-Bit > abfragen. Wenn Du nicht drauf zugreifst, dann ist das ja auch klar. Aber das war vorhin eben noch nicht klar ...
Andreas S. schrieb: > Meine Vermutung ist, dass ich den Flash-Speicher überschreite. Das wird es wohl eher nicht sein. Das Teil hat lt. DaBla einen Watchdog, den Du hoffentlich abgeschalten hast oder immer rechtzeitig zurücksetzt. Für den Fall, das Du den immer zurücksetzt, könnte es sein, Wenn Du noch was dazu gebastelt hast, daß Du das nicht mehr rechtzeitig schaffst. Dann läuft der nämlich über und startet den Controller einfach neu. Das nur mal so als Gedankenanstoß.
Der Flash Int löst glaube ich ebenfalls aus wenn manche key Register falsch/nicht beschrieben werden (Register die man mit einer bestimmten Sequenz beschreiben muss um irgendwelche anderen Register zu ändern). Oder zb wenn du auf nicht existenten Speicher zugreifst. Also zb von einem NULL Pointer lesen. Zu überprüfen wäre ob es nicht initialisierte Pointer gibt oder ob irgendwo Stellen existieren welche durch zweifachen Zugriff (Interrupts) korrumpiert werden. Generell würde ich als erstes empfehlen den Users Guide nach diesem Interrupt zu durchsuchen und die Möglichen Ursachen alle auflisten.
:
Bearbeitet durch User
Wenn Du im Debugger siehst, daß der NMI wegen des "Flash-Fehlers" ausgelöst wurde, kannst Du Dir natürlich auch den Stack ansehen, und so herausfinden, welche Funktion gerade aktiv war, als der Interrupt ausgelöst wurde. Das sollte eigentlich schon einen gewissen Hinweis geben.
Harald K. schrieb: > Wenn Du im Debugger siehst, daß der NMI wegen des "Flash-Fehlers" > ausgelöst wurde, kannst Du Dir natürlich auch den Stack ansehen, und so > herausfinden, welche Funktion gerade aktiv war, als der Interrupt > ausgelöst wurde. > > Das sollte eigentlich schon einen gewissen Hinweis geben. Das ist eine gute Idee. Ich habe den Debugger so noch nie genutzt. Werde ich morgen aber mal versuchen. Wenn ich die verursachende Funktion so ermitteln kann, wäre ich einen großen Schritt weiter. Grüße Andreas
Ich gehe mal davon aus, dass du dann auch noch nicht die Nase in die Assemblerbefehle des MSP gesteckt hast. Solltest du evtl nachholen, damit du siehst was genau der Knödel da treibt. Die angesprungenen C-Zeilen sind nämlich nicht die ganze Wahrheit...
Roland E. schrieb: > Ich gehe mal davon aus, dass du dann auch noch nicht die Nase in die > Assemblerbefehle des MSP gesteckt hast. Das ist korrekt. Muss ich schlimmstenfalls noch machen.
Andreas S. schrieb: > Roland E. schrieb: >> Ich gehe mal davon aus, dass du dann auch noch nicht die Nase in die >> Assemblerbefehle des MSP gesteckt hast. > > Das ist korrekt. Muss ich schlimmstenfalls noch machen. Nicht schlimmstenfalls. Sieh es als Bereicherung deiner Welt.
Folgende neue Erkenntnisse: Andreas S. schrieb: > Daraus schließe ich: Es tritt ein Flash-Zugriffs Fehler auf, der laut > Datenblatt automatisch zu einem Reset führt. Diese Aussage muss ich zurücknehmen, fürchte ich. Zumindestens weiß ich nicht, wo ich das im Datenblatt gelesen haben soll. Lediglich die "A Flash memory security key violation" führt zu einem PUC/Reset. Dennoch kommt es bei mir zu NMIs mit Flash Access Violation (ACCVIFG), gefolgt von einem Reset. Jetzt überlege ich doch wieder, ob ich einen Stack-Überlauf habe, der aus irgend einem Grund auch das ACCVIFG setzt. Im angehängten Bild sieht man einen Screenshot vom Debugger. Damit ich nichts falsch verstehe, oben links (rot markiert) sehe ich den Stack? Da kann ich leider keine Schlüsse draus ziehen. Im Stack Usage unten links sehe ich, dass der Stack meiner main() anscheinend 184 Byte groß werden kann?! Die Adressen im Stack sind 2 Byte lang/groß. Also werden im Worst case 92 Funktionen verschachtelt aufgerufen :-O. Ich habe im Linker nur 144 Byte angegeben. Das hat bereits zur Folge, dass mein RAM zu 88% ausgelastet ist. Bei 184 Byte Stack size hätte ich 96% RAM auslastung, was wahrscheinlich zu anderen Fehlern führen würde. Gibt es eine Möglichkeit, wie ich einen Stack-Überlauf eindeutig identifizieren kann? Im Internet habe ich dieses Video gefunden: https://youtu.be/edHHRf0v7Gk?feature=shared Allerdings gibt es bei mir nur die Optionen Breakpoint, Hardware Breakpoint und Watchpoint. Hat jemand eine Idee, warum ich die anderen Optionen nicht habe? Grüße Andreas
Andreas S. schrieb: > Allerdings besitzt die MSP430F2xx, > MSP430G2xx Family dieses Feature und somit auch das SYSRSTIV Register > nicht. Dann schau eben ins Register IFG1: • PORIFG and RSTIFG flags have been added to IFG1 to indicate the cause of a reset. • An instruction fetch from the address range 0x0000 - 0x01FF will reset the device
Auch wenn ich mich noch nicht an die Assemblerbefehle getraut habe, konnte ich durch diesen Fehler doch wieder einiges Neues lernen :-) Ich habe dank dieses Threads nun endlich mit Gewissheit den Stack Überlauf nachweisen können: https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/396854/detect-stack-overflow Jetzt, wo der Fehler eindeutig nachgewiesen ist, kann ich mich an die Fehlerbehebung setzen und mich mit Code-Optimierung beschäftigen. Vielen Dank für eure Unterstützung. Grüße Andreas
Andreas S. schrieb: > mich mit Code-Optimierung beschäftigen. Man darf auf einem kleinen µC nicht so verschwenderisch den RAM nach dem Gießkannenprinzip verteilen, wie auf einem PC. Man sollte also schon ermitteln, welche maximale Größe ein Array wirklich benötigt. Und jedesmal hübsch testen, ob die Größe noch ausreicht, d.h. nicht blind auf einen Pointer schreiben. Und man darf auf einem 16-Bitter auch 8-Bit Variablen verwenden, um RAM zu sparen. Kritisch kann es werden, wenn man malloc verwendet, da dafür ein fester RAM-Bereich reserviert werden muß. Es kann dann passieren, daß zwar ausreichend gesamter RAM verfügbar ist, aber im falschen Segment verteilt. Ich hab mir für den AVR ein kleines Stacktestprogramm geschrieben, das den Bereich zwischen statischen Daten und Stackpointer prüft, ob da noch das Testpattern (0x77) drinsteht, bzw. ihn damit füllt. Es gibt den verfügbaren und den genutzten Stack zwischen 2 Aufrufen aus. Kleiner 16 Bytes Reserve würde ich als kritisch ansehen, größer 256 Bytes sollten ausreichen.
Hallo Peter, vielen Dank für deine Tipps! Peter D. schrieb: > Man sollte also schon > ermitteln, welche maximale Größe ein Array wirklich benötigt. Das mache ich selbstverständlich immer! Peter D. schrieb: > Und man darf auf einem 16-Bitter auch 8-Bit > Variablen verwenden, um RAM zu sparen. Mache ich ausschließlich, abgesehen von Variablen, die größer sein müssen. Peter D. schrieb: > Kritisch kann es werden, wenn man malloc verwendet, da dafür ein fester > RAM-Bereich reserviert werden muß. Es kann dann passieren, daß zwar > ausreichend gesamter RAM verfügbar ist, aber im falschen Segment > verteilt. Mit malloc arbeite ich auf Mikrocontrollern eigentlich gar nicht mehr. Eigentlich weiß ich auch immer genau, wie groß meine Variablen sein müssen. Peter D. schrieb: > Ich hab mir für den AVR ein kleines Stacktestprogramm geschrieben, das > den Bereich zwischen statischen Daten und Stackpointer prüft, ob da noch > das > Testpattern (0x77) drinsteht, bzw. ihn damit füllt. So habe ich es jetzt auch gemacht. Peter D. schrieb: > Kleiner 16 > Bytes Reserve würde ich als kritisch ansehen, größer 256 Bytes sollten > ausreichen. Auch wenn du wahrscheinlich mehr Ahnung hast als ich, würde ich dem so nicht zustimmen. Mein MSP430 hat nur 512 Byte RAM. Da habe ich gar nicht die Möglichkeit nur annähernd 256 Byte Reserve einzuplanen. Ich habe nun nach der Code-Optimierung 24 Byte reserve und es läuft jetzt zuverlässig (Die Standardeinstellung im Linker ist beim MSP430 in CCS übrigens auch nur insgesamt 80 Byte und ich habe nun auf 128 erweitert). Ich komme somit auf eine allgemeine RAM-Reserve von 150 Byte. Grüße Andreas
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.