Hallo alle zusammen, ich bin gerade dabei eine kleine Firmware mit IAR zu entwickeln. Des Öfteren kommt es vor, dass sich der MSP beim Starten des Debugvorgangs in einer Endlosschleife aufhängt, die mir jedoch völlig unbekannt ist. Ein Screenshot vom Disassembly-Fenster von IAR habe ich als Anlage beigefügt. Die Endlosschleife geht von bereits markierten Startadresse 0x4378 bis zum Befehl "jne" auf der Adresse 0x4380. Könnt ihr mir sagen, wass hier passiert und für was das gut ist? Danke für eure Hilfe! Gruß Jochen
Das ist ein Teil des C-Startupcodes vor dem Aufruf von main(). An dieser Stelle wird der Datenbereich inititalisiert und zwar wohl ausgenullt (memzero). Vielleicht stimmt die Speichergröße des eingestellten Targets nicht und die Funktion hat bei den Registern (R15,R12) einen 16-Bit Integeroverflow. 002796 531C inc.w R12 002798 9F0C cmp.w R15,R12 Bei einem Target mit mehr als 64KB RAM ist dieser Code IMHO problematisch. Nachsehen würde ich in der IAR Doku zur sog. _low_level_init Funktion, im Startupcode/Linkerkontrollskript (wenn es das beim IAR gibt) und in den Projekteinstellungen. Der Codeabschnitt befindet sich eventuell direkt hinter dem Aufruf von main() und dem anschliessenden exit() (vgl. http://bbs.lierda.com/archive/index.php/t-21935.html). Da würde ich prüfen, ob das Programm vom call exit zurückkommt und mit uninitialierten Argumenten in die problematische Funktion durchfällt.
Hi! Es gibt einen __low_level_init. Hier wird der Watchdog mit
1 | WDTCTL = WDTPW+WDTHOLD; |
deaktiviert. Beim Target handelt es sich um den MSP430F2410. Der hat nur 4k RAM. Gruß Jochen
Vielleicht funktioniert das Deaktivieren des Watchdogs nicht richtig oder ist zu spät. Beitrag "MSP430F1611 - Controller hängt beim löschen des Speichers" http://www.embeddedrelated.com/groups/msp430/show/38619.php http://www.embeddedrelated.com/groups/msp430/show/27276.php NB: Zu dem (hier nicht relevanten) 16-Bit Überlauf http://tech.groups.yahoo.com/group/msp430/message/44063
Hallo Stefan, deine Antwort und die geposteten Links hörten sich vielversprechend an. Ich habe Stellenweise einige große Arrays (x mal 256 Byte), aber die meisten haben feste Werte und da wirkt "__no_init" nicht. Bei denen, wo es möglich ist habe ich den Präprozessorbefehl hinzugefügt. Das Ergebnis ist dennoch das gleiche. Fakt ist aber, dass das Ausschalten den Watchdogs funktioniert, denn die __low_level_init-Funktion, in der der Watchdog deaktiviert, wird wirklich als Erstes ausgeführt. Die Funktionsbeschreibung enthält auch den markanten Satz:
1 | IAR-standard function will be executed prior to initializing memory space |
Sonst noch eine Idee? Gruß Jochen
Deine RAM Initialisierung dauert laenger als die Timeoutzeit des Watchdogs. Daher in deiner Intialisierungsroutine schlaegt der Watchdog zu und das Spiel beginnt von neuen. Wie du schon richtig erkannt hast muss du den im Startupcode abschalten und erst nach der Initialisierung wieder einschalten. Das beinhaltet allerdings eine kurze Zeit wo kein Watchdog das System ueberwacht. Besser ist es in der Initialisierungsroutine fuer das RAM den Watchdog regelmaessig zu bedienen.
Genau dagegen ist ja die _low_level_init Funktion. Interessant wäre mal im Debugger zu schauen, ob der WDT wirklich aus ist und/oder ab das Flag für den WDT Reset gesetzt ist, also ob der WDT da wirklich reinspuckt. Kann ja auch was ganz anderes sein.
Dafuer gibt es einen einfachen Test. Wenn man die Anzahl der Variablen mal kleiner macht ist diese Initialisierungsroutine auch schneller fertig. Und dann sollte der WD auch nicht ausloessen. Ich hatte mal das gleiche Problem. Irgendwann startete das Programm nicht mehr nachdem ich noch etwas mehr RAM brauchte. Der Fehler war anschliessend das die Initroutine mehr Zeit brauchte als der WD einem lies.
Was bringt mir das Variablen zu entfernen, wenn ich sie doch für meine Anwendung benötige ... !? Ich kann nur sagen, dass
1 | WDTHOLD |
auf "1" gesetzt ist, während sich der MSP in der im Anfangsbeitrag beschriebenen Endlosschleife befindet.
Kann man eigentlich diese "0-Initialisierung" global/allgemein deaktivieren?
Ja, ist oben in den Links genannt, Stichwort __no_init Kennzeichnung der Variablen. Aber wenn der Watchdog das Problem ist (was noch zu testen oder anhand des Startupcodes zu kontrollieren wäre): Den müsste man doch auch früher im Startupcode ausschalten können bzw. zunächst auslassen können und erst nach der Initialisierung z.B. am Anfang von main() anstellen können. Hast du mal einen Debuggerlauf ohne Watchdog gemacht oder kann man das bei dem MSP430 nicht?
Jochen schrieb: > Was bringt mir das Variablen zu entfernen, wenn ich sie doch für meine > Anwendung benötige ... !? Du sollst es ja auch nur mal testen ob es daran liegt. Im C Startup wird doch die Routine __data16_memzero aufgerufen. Die bekommt doch vorher ihre Laenge und Startadresse mitgeteilt. Die must du halt nur aufsplitten in 2 oder 3 Teile und dazwischen einmal den WD betaetigen.
Stefan B. schrieb: > Den müsste man doch auch früher im Startupcode ausschalten können bzw. > zunächst auslassen können und erst nach der Initialisierung z.B. am > Anfang von main() anstellen können. Kann man machen nur hast du dann ein Stelle am Anfang die nicht ueberwacht wird. Sollte jetzt eine Stoerung auftreten und der WD ausloesen und direkt danach im Startupcode nochmal ausloesen dann hast du ein Problem ...
Hallo! Ehrlich gesagt (und peinlicher Weise) verstehe ich nun immer weniger statt mehr. Stefan B. schrieb: > Ja, ist oben in den Links genannt, Stichwort __no_init Kennzeichnung der > > Variablen. Das ist mir bekannt, mach ich ja auch schon stellenweise. Meine Frage war aber nach einem "Globalen Flag", dass ich nur einmal setzen muss und alle Variablen werden nicht initialisert. Stefan B. schrieb: > Den müsste man doch auch früher im Startupcode ausschalten können bzw. > > zunächst auslassen können und erst nach der Initialisierung z.B. am > > Anfang von main() anstellen können. Früher als in der __low_level_init-Funktion (LLI)? Inzwischen deaktiviere ich den Watchdog sowohl in der LLI-, als auch in meiner main-Funktion. Helmut Lenzen schrieb: > Im C Startup wird doch die Routine __data16_memzero aufgerufen. > > Die bekommt doch vorher ihre Laenge und Startadresse mitgeteilt. > > Die must du halt nur aufsplitten in 2 oder 3 Teile und dazwischen einmal > den WD betaetigen. Wie soll ich das bitte machen? An den generierten Code komme ich doch gar nicht ran ... Entwickle in C und nicht Assembler. Viele Grüße Jochen
Jochen schrieb: > Wie soll ich das bitte machen? An den generierten Code komme ich doch > gar nicht ran ... Entwickle in C und nicht Assembler. Und ob du daran kommst. Die Datei heist "cstartup.s43" und ist Bestandteil der IAR Library. Suche mal in deinem IAR Ordner nach dieser Datei. Liegt meistens in ... SRC/LIB/430. Bei allen C Compiler die ich kenne ist der Startupcode immer dabei gewesen. Muss er ja auch sonst kann man mit dem Compiler nicht allzu viel anfangen. PS. Auch ein C Programmierer muss ab und zu mal etwas Assembler programmieren. Und wenn es nur darum geht den Startupcode zu modifizieren.
Anderes Problem: Da ich ja mit IAR nicht vorangekommen bin, habe ich jetzt mal das Ti Code Composer Studio ausprobiert. Ergebnis: Wie auch bei IAR ist der WDT deaktiviert, ABER er löst trotzdem aus! Wann bzw. welchen Code er dabei gerade ausführt kann ich jedoch nicht einsehen! Helmut Lenzen schrieb: > PS. Auch ein C Programmierer muss ab und zu mal etwas Assembler > programmieren. Und wenn es nur darum geht den Startupcode zu > modifizieren. Gestehe: Hab schon seit Uni-Zeiten nichts mehr mit Assembler gemacht und das ist nun über 10 Jahre her! Mir wird das modifizieren des Startupcodes entsprechend schwer fallen.
Ok, das Problem in Eclipse habe ich gefunden. Hab vergessen eine Callback-Funktion mit 0 zu initialisieren (muss ich ja in CCS nun manuell machen). Da stand dann ein Zufallswert drin und meine Funktion prüft auf != 0 ab. Dadurch ist dann ein Sprung ins Nirvana erfolgt. Im Momment läuft also mein Code unter CCS. ;)
Suche mal in dem CSTARTUP diese Stelle PUBLIC ?cstart_begin ?cstart_begin: Und trage das dort ein #define WDTPW (0x5A00) #define WDTHOLD (0x0080) #define WDTCTL (0x0120) #define WDTSSEL (0x0004) Dann suche diese Stelle ?cstart_init_zero: MOV #SFB DATA16_Z, CW0 MOV #1024, CW1 MOV #WDTPW + WDTHOLD + WDTSSEL, &WDTCTL XCALL #__data16_memzero MOV #SFB DATA16_Z+1024, CW0 MOV #1024, CW1 MOV #WDTPW + WDTHOLD + WDTSSEL, &WDTCTL XCALL #__data16_memzero MOV #SFB DATA16_Z+2048, CW0 MOV #1024, CW1 MOV #WDTPW + WDTHOLD + WDTSSEL, &WDTCTL XCALL #__data16_memzero MOV #SFB DATA16_Z+3072, CW0 MOV #1024, CW1 MOV #WDTPW + WDTHOLD + WDTSSEL, &WDTCTL XCALL #__data16_memzero Und aendere dort den Code Ich initialsiere dann das RAM (4096 Byte) in 1024 Byte grossen Haeppchen. Dazwischen wird der schlafende Hund wachgeruettelt PS. Ist noch nicht von mir getestet. Versuch es infach mal.
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.