Hallo,
Ich habe einen STM32F103ZET6.
Da ist viel Code drin und neuerdings Stürzt der Prozessor bei "leichter"
Erwärmung ab. (ca. 50..60°C)
Ich habe nun die Aufgabe bekommen, das näher zu analysieren und habe
auch die Stelle gefunden:
1
return((UINT16)((tempCount32+2)>>2));
Wenn das so programmiert wird, geht es ohne Absturz:
1
return((UINT16)((tempCount32+2)/4));//>> 2));
Also mit der 2. Variante muss ich mit dem Fön wirklich lange drauf,
halten und wenn der dann schon glüht stürzt der ab, aber die erste
stürzt wirklich bei leichter Erwärmung ab.
Es war einiges an Arbeit die ganzen Datensicherungen durch zu ackern und
dann jedes mal die vielen C/H Dateien zu vergleichen.
Hat jemand eine Idee wieso der abstürzt?
- Reproduzierbar an mindestens 5 Boards
- Mit Mehreren Rechner kompiliert und geladen
- An unterschiedlichen Tagen, also der Mond ist es nicht.
PS: Im Reset-Register "RCC->CSR" steht dann in den oberen 8 Bit 0x14,
also SW-Reset, kein WDG oder IWDG.
Grüße Markus.
Welcher Compiler kommt zum Einsatz? Welche Optimierungsstufe?
Welcher Temperaturbereich ist für CPU spezifiziert?
Wie sieht das Assembler-Listing dieser Funktion aus?
Es gibt also einen Unterschied zwischen >> 2 und / 4. Da sollte die
letzere Variante doch eigentlich "länger" sein (mehr Code, längere
Ausführungszeit).
Vielleicht ist die längere Ausführungszeit "besser" für das restliche
Programm, also vielleicht ein anderer Seiteneffekt als die Temperatur ?
Nachtrag: Wie kommt man eigentlich darauf >> 2 durch / 4 zu ersetzen?
Ein / 4 sollte ja eigentlich eh der Compiler zu einem >> 2 optimieren?
Markus Müller schrieb:> PS: Im Reset-Register "RCC->CSR" steht dann in den oberen 8 Bit 0x14,> also SW-Reset, kein WDG oder IWDG.
Welcher "fault" tritt denn genau auf?
Coudesourcery Arm-None-Eabi, -O1
Temperaturbereich T6
Nun das Listing:
Wenn ich den funktionierenden Code übersetzte, stürzt der nicht ab.
Wenn ich exakt den gleichen Code nehme und im Makefile:
1
-Wa,-ahlms=$(addprefix $(OBJDIR), $(<:.c=.lst))
hinzufüge, dann stürzt der ab bei Erwärmung.
Somit kann ich kein Listing ausgeben um einen Unterschied zu sehen
geht/geht nicht :-(
>Welcher "fault" tritt denn genau auf?
Reset. Der Prozessor startet neu.
Es gibt zwar im Code solche Stellen:
SCB->AIRCR = 0x05FA0001;
Die werden aber garantiert nicht abgearbeitet und ich habe die auch
schon alle auskommentiert. (Braucht es wegen implementierten Bootloader)
Jetzt wollte ich das Disassemby unter Eclipse an schauen.
Nun ja, die Routine wird gar nicht durchlaufen. !!?!?!
(Das Projekt hab ich nicht programmiert)
Markus Müller schrieb:> Hallo,>> Ich habe einen STM32F103ZET6.> Da ist viel Code drin und neuerdings Stürzt der Prozessor bei "leichter"> Erwärmung ab. (ca. 50..60°C)>> Ich habe nun die Aufgabe bekommen, das näher zu analysieren und habe> auch die Stelle gefunden:
schschsch....oene Aufgabe ;-)
>>
1
return((UINT16)((tempCount32+2)>>2));
>> Wenn das so programmiert wird, geht es ohne Absturz:>
1
return((UINT16)((tempCount32+2)/4));//>> 2));
Du wirst Dir sicher anschauen was die unterschiedlichen Uebersetzungen
in ASM sind. Oft ist es nicht der Unterschied im Coding sonder wo das
Programm dann zu liegen kommt. Falls also der DIV 4 anders uebersetzt
wird vom Compiler als mit shift right, (dann ist es kein guter Compiler)
aber andererseits kannste dann mal versuchen den shift mit NOPs zu
ergaenzen, so dass die Laenge des Befehles in ASM gleich wird. Ich hoffe
das ist klar was ich demit meine.
Falls dem so ist, dann verschiebt sich einfach ein Teil des Codes in
"eine unguenstige Stelle". Ursache sind dann meist nicht initialisierte
Pointer.
Die Temperaturabhaengigkeit ist allerdings merkwuerdig.
Wird ein interner Oszilator irgendwo beuetzt? Die sind manchmal stark
temperaturabhaengig. Wird das Ergebnis einer ADC Wandlung fuer eine
Verzweigung benutzt? ADC kann auch etwas schwanken mit Temp. Oder hat
der Chip einen internen Temperatursensor, der als Bedingung fuer
Verzweigungen verwendet wird?
Einfach mal so ein paar Gedanken, was temp abhaengig sein kann. Alles
analoge, z.B. ein Comperator kann auch temp abhaengig sein.
Wie sieht's denn aus mit dem Frequenz? Ich nehme mal an im gruenen
Bereich und kein Uebertakten?
Kannst Du mal im Linker eine Reihenfolge der Funktionen angeben, damit
der Code woanders zu liegen kommt? Das aendert das Verhalten solcher
Nadeln im Heuhaufen auch manchmal.
Jetzt faellt mir gerade nichts mehr ein. Sorry fuer die etwas konfuse
Aneinanderreihung der Vorschlaege. Hab mich nur gemeldet weil Du oft
gute Beitraege lieferst und Input verdient hast.
Gruss, Robert
Hast Du es mal mit einem anderen Exemplar eines STM32F103ZET6 probiert?
Gibt auch Produktionsfehler. Hatte mal von einem 68000 gelesen, der bei
bestimmten ASM Befehlen abgeschmiert ist.
> Falls also der DIV 4 anders uebersetzt wird vom Compiler als mit shift> right, (dann ist es kein guter Compiler)
Sehe ich genauso.
Ansonsten ist das wohl ein Fall für ST selbst.
Hallo Markus,
Robert Teufel schrieb:> Oder hat>> der Chip einen internen Temperatursensor, der als Bedingung fuer>> Verzweigungen verwendet wird?
Nutzt Du den internen Temperatursensor im ADC?
Hast Du in deinem Code die Flash Waitstates entsprechend der
Taktfrequenz richtig eingestellt? Wenn die Waitstates fehlen könnte es
sein, dass bestimmte Flashbereiche über den Temperaturbereich
unterschiedlich reagieren.
Hast Du eine möglichkeit zu tracen?
Gruß,
Ralf
@Robert, vielen Dank, Antwort dazwischen
Robert Teufel schrieb:> Du wirst Dir sicher anschauen was die unterschiedlichen Uebersetzungen> in ASM sind. Oft ist es nicht der Unterschied im Coding sonder wo das> Programm dann zu liegen kommt. Falls also der DIV 4 anders uebersetzt> wird vom Compiler als mit shift right, (dann ist es kein guter Compiler)> aber andererseits kannste dann mal versuchen den shift mit NOPs zu> ergaenzen, so dass die Laenge des Befehles in ASM gleich wird. Ich hoffe> das ist klar was ich demit meine.
Ja, ich habe das Listing an geschaut, der Compiller macht in beiden
Fällen das gleiche, auch die HEX-Datei ist bei beiden Fällen exakt
gleich.
> Falls dem so ist, dann verschiebt sich einfach ein Teil des Codes in> "eine unguenstige Stelle". Ursache sind dann meist nicht initialisierte> Pointer.
Bei einem nicht initialisierten Pointer springt der in den Hard-Fault
Interrupt und bleibt darin stecken, der macht aber einen Reset.
Ich sehe grad, dort steht nicht mehr das while(1); sondern ein
NVIC_SystemReset();
Jetzt weiß ich wenigstens woher noch ein SW-Reset kommt ;-)
> Die Temperaturabhaengigkeit ist allerdings merkwuerdig.> Wird ein interner Oszilator irgendwo beuetzt? Die sind manchmal stark> temperaturabhaengig.
Da ist ein Quarz drauf. Wenn ich auch mit der alten SW das Board laufen
lasse, dann kann ich den zum glühen föhnen und die serielle Ausgabe ist
ohne Fehlerzeichen, somit sollte die Frequenz einigermaßen Konstant
sein.
> Wird das Ergebnis einer ADC Wandlung fuer eine> Verzweigung benutzt? ADC kann auch etwas schwanken mit Temp. Oder hat> der Chip einen internen Temperatursensor, der als Bedingung fuer> Verzweigungen verwendet wird?> Einfach mal so ein paar Gedanken, was temp abhaengig sein kann. Alles> analoge, z.B. ein Comperator kann auch temp abhaengig sein.
Der interne Temp-Sensor ist inaktiv. Ansonsten sind ein paar Kanäle
verwendet. Ich muss die Berechnungen mal alle durch gehen.
> Wie sieht's denn aus mit dem Frequenz? Ich nehme mal an im gruenen> Bereich und kein Uebertakten?
Nein natürlich nicht übertaktet.
> Kannst Du mal im Linker eine Reihenfolge der Funktionen angeben, damit> der Code woanders zu liegen kommt? Das aendert das Verhalten solcher> Nadeln im Heuhaufen auch manchmal.
Dazu muss ich nur die Reihelfolge der C-Dateien im Makefile ändern,
probiere ich mal.
> Jetzt faellt mir gerade nichts mehr ein. Sorry fuer die etwas konfuse> Aneinanderreihung der Vorschlaege. Hab mich nur gemeldet weil Du oft> gute Beitraege lieferst und Input verdient hast.>> Gruss, RobertArne schrieb:> Hast Du es mal mit einem anderen Exemplar eines STM32F103ZET6 probiert?> Gibt auch Produktionsfehler. Hatte mal von einem 68000 gelesen, der bei> bestimmten ASM Befehlen abgeschmiert ist.>> Falls also der DIV 4 anders uebersetzt wird vom Compiler als mit shift>> right, (dann ist es kein guter Compiler)> Sehe ich genauso.>> Ansonsten ist das wohl ein Fall für ST selbst.
Ich habe bei denen im Forum auch mal geschrieben.
Ich hatte schon mal ein Fehler wegen einem Chip der 384KB Flash haben
sollte aber der nur 256 drin hatte. Aber dieser Chip hat garantiert mehr
als 256KB, denn sonst würde das Programm nicht rein passen.
In jedem Fall gehe ich all eure Hinweise Stück für Stück durch. Ich
bastle mir da jetzt auch eine Stack-Aufzeichnung rein mit der ich jeden
Funktionsaufruf in eine Variable merke. Somit habe ich einen echten
Trace, das hat mir schon manchmal geholfen.
Ralf schrieb:> Hast Du in deinem Code die Flash Waitstates entsprechend der> Taktfrequenz richtig eingestellt? Wenn die Waitstates fehlen könnte es> sein, dass bestimmte Flashbereiche über den Temperaturbereich> unterschiedlich reagieren.>> Hast Du eine möglichkeit zu tracen?>> Gruß,> Ralf
Schaue ich auch gleich an.
Einen Trace muss ich erst noch ein proggen, dauert ein wenig da ich das
in jede Routine rein machen muss.
Hallo Markus,
ich dachte eher an einen Debugger mit Trace Funktion wenn Du einen hast.
Ansonsten kannst Du ja jetzt in deinen HardFault Handler einen
Breakpoint setzen und dann über den Stack Trace nachsehen aus welcher
Funktion die Software zum HardFault gesprungen ist.
Was allerdings komisch ist, ist der identische Code. Wenn beide Code
Zeilen zum identischen Ergebnis führen kann das eigentlich nicht die
Ursache sein. Gibt es vielleicht Unterschiede in deinen Option Byte
Settings? (bin mir gerade nicht sicher was da alles drin steht)
Gruß,
Ralf
Temperaturabhängigkeit dürfte ein Flashtiming Problem sein.
Kann aber auch durch eine instabile PLL entstehen.
Die Codeabhängigkeit ist typisch für kritisches Timing, da der Code mal
zufällig auf langsamen Flashzellen landet und mal nicht.
Abhilfe, das Flashtiming runter setzen (mehr Waits) und Code, der
schnell sein muß, in den RAM kopieren.
Um Quarzprobleme auszuschließen, erstmal einen Quarzoszillator
anschließen.
Und auch mal mit den VCCs rumspielen, obs davon abhängig ist.
Peter
Einen Debugger mit Trace Funktion hab ich nicht.
Ich mache das etwas anders. In jedem Funktionsaufruf mache ich ein
SAVE_SP() mit rein, damit wird der aktuelle Adresszeiger in einem
Ringbuffer gesichert (u32 Array[16]).
Um noch andere Infos zu sichern, mache ich dazwischen SAVE_U32(x).
Jetzt springt der in den Fault-Interrupt und darin gebe ich auf dem UART
die gespeicherten Zahlen aus:
1
HardFault Exception! STOP.
2
Stack:
3
0 0000CE90
4
1 00000001
5
2 00000003
6
3 0000EC9C
7
4 0001080C
8
5 000108C4
9
6 0000ED08
10
7 000105C0
11
8 00012934
12
9 00006C16
13
10 0000C6AE
14
11 0000C36A
15
12 00000001
16
13 00009CF2
17
14 000087B2 <
18
15 00025B92
das nächste mal so:
1
HardFault Exception! STOP.
2
Stack:
3
0 00007086
4
1 00007086
5
2 00027B7C
6
3 00027AD6 <
7
4 00007086
8
5 00007086
9
6 00027B7C
10
7 00027AD6
11
8 00006E4E
12
9 00008242
13
10 00007086
14
11 00007086
15
12 00027B7C
16
13 00027AD6
17
14 00006E4E
18
15 00008242
Der "<" zeigt die letzte Schreib-Position im Ringbuffer.
Nachteil: Wenn der Prozi ganz tot ist geht das natürlich nicht, aber in
der Regel ist ja nicht das ganze Flash/Ram defekt und die seriellen
Routinen sollten noch tun. Vorteil: geht auch beim Kunde und ohne
Debugger.
Nun schaue ich nach der Routine bei 00027AD6 und mache da eine weitere
Debug-Info rein, das nächste mal stürzt der bei einer ganz anderen
Routine bei 00009DD6 ab, also in einer kleineren Flash-Adresse.
Der Flash war auf FLASH_Latency_1 eingestellt, ist lt. Doku für 48MHz
auch gut so. Dennoch hab ich mal 2 eingestellt um diese Probleme auch zu
umgehen, falls es eines geben sollte.
Aber der stürzt immer noch ab.
Mit einem alten Code war FLASH_Latency_1 eingestellt und der ist nicht
abgestürzt.
Auch ohne Debugger stürzt der ab.
Langsam gehen mir die Ideen aus.
Markus Müller schrieb:> Ja, ich habe das Listing an geschaut, der Compiller macht in beiden> Fällen das gleiche, auch die HEX-Datei ist bei beiden Fällen exakt> gleich.
Übersehen ...
Markus Müller schrieb:> Bei einem nicht initialisierten Pointer springt der in den Hard-Fault> Interrupt und bleibt darin stecken, der macht aber einen Reset.> Ich sehe grad, dort steht nicht mehr das while(1); sondern ein> NVIC_SystemReset();> Jetzt weiß ich wenigstens woher noch ein SW-Reset kommt ;-)
Ein Rätsel gelöst.
Ralf schrieb:> Ansonsten kannst Du ja jetzt in deinen HardFault Handler einen> Breakpoint setzen und dann über den Stack Trace nachsehen aus welcher> Funktion die Software zum HardFault gesprungen ist.
Hinter einem "hard fault" können sich ja andere "faults" verstecken,
wenn man die Eskalation nicht ausschaltet.
Die Frage ist also: Welcher "fault" steckt wirklich dahinter?
Und wie schon Ralf geschrieben hat, lässt sich die Stelle herausfinden.
Dann ist die Frage, ob es immer die gleiche Stelle ist.
Ich hatte schon einmal mit einem ähnlichen Problem zu kämpfen. Ursache
war dann, dass das Flash-Utility einen Fehler hatte und den Flash
unvollständig beschrieben hat. Geringste Abweichungen im Code waren dann
der Unterschied zwischen "geht" und "geht nicht".
Also auch mal das Flash an der Stelle auslesen.
Ich habe im Bootloader noch einen Zahlendreher gefunden:
1
// Flash-Zugriff vor Takterhoehung festlegen
2
FLASH->ACR&=0x31;// Flash Latency 1 (bis 48 MHz)
3
FLASH->ACR|=0x10;// Flash Prefetch Buffer EIN
Morgen testen wir noch weiter ob es wirklich nur daran lag.
In der Applikation würde zwar Latency 1 gesetzt werden, aber da der
Bootloader die USB Verbindung initialisiert darf die Applikation die
Taktfrequenz nicht mehr ändern. Sonst klappt das nicht mehr mit dem
"übernehmen" der USB Verbindung Bootloader <> Applikation.
Somit: Problem erst mal gelöst, wenn nicht schreibe ich morgen nochmals.
Vielen Dank für die Tipps.
> Ich habe im Bootloader noch einen Zahlendreher gefunden
Genau deswegen nimmt man auch benamte Konstanten und bastelt sich den
Zielwert zusammen. So muss man immer das Datenblatt parat haben.
Normalerweise wird auch alles mit der STM Library gemacht. Dann hat man
diese Probleme automatisch nicht.
Aber der Bootloader darf diesen Code leider nicht nutzen, da bei einem
Update der Applikation der Flash gelöscht wird.
Bootloader und App sind in den gleichen Sourcen.
Markus Müller schrieb:> Ja, ich habe das Listing an geschaut, der Compiller macht in beiden> Fällen das gleiche, auch die HEX-Datei ist bei beiden Fällen exakt> gleich.Markus Müller schrieb:> Ich habe im Bootloader noch einen Zahlendreher gefunden:
Das kann der Bootloader nichts mit zu tun haben. Wenn alles inkl.
HEX-Datei gleich ist (btw: Wie festgestellt? MD5 o.ä.?), kann es ja nur
noch etwas Externes sein, wie z.B. Versorgungsspannung oder EMV.
???
Das verstehe ich nicht. Wenn wirklich alles inkl. der HEX-Datei gleich
ist, wie kann dann
Markus Müller schrieb:> return((UINT16)((tempCount32+2) >> 2));> Wenn das so programmiert wird, geht es ohne Absturz:> return((UINT16) ((tempCount32+2) / 4));//>> 2));
die Ursache dafür sein, daß der Chip abschmiert? Bei gleicher HEX-Datei
besteht doch gar keine Möglichkeit für den Chip "herauszufinden", welche
der beiden Codeformen zur gleichen HEX-Datei geführt hat. Entweder hat
das esoterische Züge oder ich habe bisher einen großen Verständnisfehler
gehabt (was ich nicht unbedingt ausschließen will).
Wenn man den Flash Latency falsch einstellt und man bewegt sich im
Grenzbereich, dann macht das Flash je nach Temperatur was falsches oder
auch doch nicht.
"esoterische Züge" hatte ich nach 2 Tagen auch vermutet.
Wenn also jemand auf Nummer Sicher gehen will/muss, dass besser eine
Flash Latency Stufe höher bzw. kleinere Frequenz einstellen.
Beim STM32F4xx hat man da noch mehr Möglichkeiten. Da ist auch die Flash
Latency Zahl abhängig von Taktfrequenz UND Betriebsspannung.