Forum: Compiler & IDEs IAR: MSP430 in Endlosschleife


von Jochen (Gast)


Angehängte Dateien:

Lesenswert?

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

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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.

von Jochen (Gast)


Lesenswert?

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

von Stefan B. (stefan) Benutzerseite


Lesenswert?


von Jochen (Gast)


Lesenswert?

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

von Helmut L. (helmi1)


Lesenswert?

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.

von Christian R. (supachris)


Lesenswert?

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.

von Helmut L. (helmi1)


Lesenswert?

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.

von Jochen (Gast)


Lesenswert?

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.

von Jochen (Gast)


Lesenswert?

Kann man eigentlich diese "0-Initialisierung" global/allgemein 
deaktivieren?

von Stefan B. (stefan) Benutzerseite


Lesenswert?

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?

von Helmut L. (helmi1)


Lesenswert?

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.

von Helmut L. (helmi1)


Lesenswert?

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 ...

von Jochen (Gast)


Lesenswert?

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

von Helmut L. (helmi1)


Lesenswert?

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.

von Jochen (Gast)


Lesenswert?

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.

von Jochen (Gast)


Lesenswert?

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. ;)

von Helmut L. (helmi1)


Lesenswert?

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
Noch kein Account? Hier anmelden.