Hallo,
habe ein seltsames Problem festgestellt, als ich versucht habe eine
andere IDE zu verwenden. Ich weiß auch, dass man solche Divisionen auf
Mikrocontrollern aus Zeitgründen vermeiden sollte, aber die Funktion
wird nur einmal zu Beginn aufgerufen, von daher nicht zeitkritisch.
Unter KEIL µVision 5 funktioniert die Division
"wSlope = wCalibValue/wCalibCurrent;"
ohne Probleme. In der IAR Embedded Workbench IDE (7.70) geht der STM32F0
aber nach dieser Zeile in den HardFaultHandler. Weiß jemand woran es
liegen könnte?
Die Funktion macht eigentlich nichts anderes als Daten aus dem Flash
lesen und dann aus ihnen eine Steigung bestimmen.
Dr. Sommer schrieb:> Wenn wCalibCurrent = 0 ist, gibts eine Exception.
Mist, ich dachte ich wär noch schnell genug mit dem zweiten Post. Daran
dachte ich auch, aber die Daten werden aus dem Flash geholt und sind
nicht 0.
A. K. schrieb:> ide schrieb:>> uint16_t* flashPtr = (USIGN16*)CAL_FLASHPAGEBASEADDR;>> wCalibCurrent = (USIGN16)(*(flashPtr + 8*(ch+1)+2));>> wCalibValue = (USIGN16)(*(flashPtr + 8*(ch+1)+3));>> Du hast verifiziert, dass diese Rechnerei die richtige Adresse ergibt?
Ja, es funktioniert unter KEIL und auch unter IAR werden die Daten aus
dem Flash gelesen. Habe einen Breakpoint in die Zeile mit der Division
gesetzt und gesehen, dass die Werte zugewiesen waren.
Clemens L. schrieb:> Was sind denn die genauen Werte?
CalibValue ist 135, CalibCurrent ist 5 bei der ersten Rechnung und nach
dieser gehts auch schon in den HardFault.
Wie genau ist denn der HardFault qualifiziert? Da gibt es ja einige
Register die entsprechend gesetzt werden. Das steht aber genau im
Manual, was da angezeigt wird und was man dazu tun muss.
Hmm, leider F0, dann kann man nicht so viel über den Grund des
Hardfaults rausfinden leider.
Alignment Fehler sollte es bei soft division auch nicht sein..
Da bleibt wohl nur noch übrig den ASM-Code anzusehen.
Danke für die rege Beteiligung soweit. Ich werde den ASM-Code morgen mal
nachliefern, von beiden KEIL und IAR, meine Assembler-Kenntnisse halten
sich leider in Grenzen.
Hab beim Portieren schon interessante Sachen festgestellt, aber dass es
selbst bei einer Division hakt hätte ich nicht erwartet.
Hanswurst schrieb:> Mist! Kein CFSR und kein HFSR.>> Aber es gibt wohl doch einige Tips, wie ich z.B. hier sehe:> https://community.arm.com/thread/5414
Ich werds mir morgen genauer ansehen, vor allem das mit dem Stack ist
interessant. Habe da vielleicht schon einen kleinen Verdacht wegen der
Stack-Größe. Nicht dass der IAR-Compiler die Division so umständlich
baut, dass da irgendwas überläuft.
Hallo,
wenn Du den Pointer hochzählst sollte das mit der "sizeof" des Datentyps
sein.
Es kommt auch drauf an wie die Daten hintereinander liegen, ist eine
32Bit Architektur aber Du hast ein Datum von 16Bit, ein 16Bit-Wert kann
in einer Zelle liegen, aber auch 2 in einer SpeicherZelle?
Und man muss aufpassen wegen unaligned access:
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/BABFAIGG.html
Wenn Du weißt woran es liegt, schreib mal, ich lerne auch gern immer was
dazu.
Grüße
Sebastian
Da könnte sein.
wCalibCurrent = (USIGN16)(*(flashPtr + 8*(ch+1)+2));
wCalibValue = (USIGN16)(*(flashPtr + 8*(ch+1)+3));
Vielleicht verhakt er sich damit ja bei der Pointer-Arithmetik. Wenn
dann wCalibValue nur in der Division gebraucht wird, eliminiert er
vielleicht die lokale Variable und setzt in der Division direkt diese
Pointer-Dereferenzierung.
Wenn's das ist, ersetz die Division da doch mal testweise durch eine
Addition. Nur um zu schauen, ob es dann immer noch crasht.
Wie sind die Daten im Flash abgelegt, byteweise als 8-Bit-Werte? Oder
sind das im Flash auch uint16_t?
Nop schrieb:> vielleicht die lokale Variable und setzt in der Division direkt diese> Pointer-Dereferenzierung.
Wie soll das funktionieren? Die Division ist sehr wahrscheinlich eine
Funktion der Laufzeitbibliothek des Compilers.
A. K. schrieb:> Wie soll das funktionieren?
Naja indem er direkt vor dem Aufruf der Divisionsfunktion erst das Laden
macht, also die Zeile mit dem Laden nicht IN der Zeile ausführt. Der
Effekt wäre, daß er scheinbar bei der Division abschmiert, in Wahrheit
aber die Zeile davor mit dem Laden die Ursache ist. Ich hatte schon
unterhaltsame Fehler, weil der Sourcelevel-Debugger da nicht immer 1:1
mit dem Quellcode einhergeht.
Abhilfe schafft es natürlich, sich im Debugger neben dem Quellcode den
Maschinencode anzuzeigen und anstatt per Singlestep durch den C-Code zu
gehen, per Singlestep durch den Maschinencode zu gehen.
Oder eben die Division durch die Addition zu ersetzen. Wenn das Laden
die Ursache ist, wird er da genauso abstürzen wie bei einer Division.
Nop schrieb:> Naja indem er direkt vor dem Aufruf der Divisionsfunktion erst das Laden> macht, also die Zeile mit dem Laden nicht IN der Zeile ausführt.
Deshalb auch die Frage nach dem Code, und ob die Adresse wirklich
stimmt.
> Abhilfe schafft es natürlich, sich im Debugger neben dem Quellcode den> Maschinencode anzuzeigen und anstatt per Singlestep durch den C-Code zu> gehen, per Singlestep durch den Maschinencode zu gehen.
Richtig, das wäre der nahe liegende Ansatz.
Das ist jetzt die Disassembly vom IAR, ich habe den Breakpoint in der
Zeile gesetzt, in der wohl die Funktion für die Division aufgerufen
wird, danach zwei mal den Single Step gemacht und direkt im
HardFaultHandler gelandet.
Die Daten im Flash habe ich auch mal hochgeladen. Für die erste Rechnung
wird die 0x015F und die 0x0005 aus dem Flash geholt und diese sollen
dann dividiert werden.
Nop schrieb:> Wenn's das ist, ersetz die Division da doch mal testweise durch eine> Addition. Nur um zu schauen, ob es dann immer noch crasht.
Addition funktioniert und es kommt auch das erwartete Ergebnis dabei
raus. Er scheint nur die Division nicht zu mögen.
@ Sebastian
Meinst du mit der Ausrichtung little und big Endian? Die Daten scheinen
vor der Division zumindest richtig aligned in den Registern R0 und R1 zu
stehen.
ide schrieb:> Meinst du mit der Ausrichtung little und big Endian? Die Daten scheinen> vor der Division zumindest richtig aligned in den Registern R0 und R1 zu> stehen.
Nein, zum Beispiel hatte ich bei Verwendung der FPU mal das gleiche
Problem, dass der immer im Hardfault gelandet ist. Und das lag daran,
dass die Floats nicht an einer Adresse die durch 4 teilbar ist gestartet
haben. Wüsste aber nicht, warum das hier bei einer
Soft-Division-Funktion ein Problem sein sollte. Scheint außerdem ja auch
zu laden in die Register.
Dein Stackpointer scheint mir aber an recht niedrieger Adresse zu sein.
Kann es sein, dass bis dorthin noch Daten im RAM sind?
Im Zweifel schau dir also auch mal die unterschiedlichen Linkerfiles und
Startup-Skripte an, wo hier das Stackend liegt und ob es dann richtig
gesetzt wird (erster Eintrag in der Vector Table als Beginn des Stacks).
Bild 2 sagt es sehr deutlich: Da, wo wo _aeabi_idivmod sein sollte, ist
kein Code im Flash, sondern alles ist 0xff. Das sind keine
Instruktionen, und deswegen stürzt der Controller ab, wenn er dorthin
springt.
Vermutlich ein Problem im Linker-Setup.
Nop schrieb:> Bild 2 sagt es sehr deutlich: Da, wo wo _aeabi_idivmod sein> sollte, ist kein Code im Flash, sondern alles ist 0xff. Das sind keine> Instruktionen, und deswegen stürzt der Controller ab, wenn er dorthin> springt.>> Vermutlich ein Problem im Linker-Setup.
In der Tat, völlig übersehen. Welcher Controller genau und welcher
Debugger?
@ Horst und Nop
Ich habe das ganze mal in die main eingefügt und dort scheint die
Division zu klappen.
1
intmain(){
2
...
3
USIGN16*flashPtr=(USIGN16*)CAL_FLASHPAGEBASEADDR;
4
USIGN8i=0;
5
USIGN16wCalibCurrent,wCalibValue,wSlope;
6
7
ch=0;
8
wCalibCurrent=(USIGN16)(*(flashPtr+8*(ch+1)+2));
9
wCalibValue=(USIGN16)(*(flashPtr+8*(ch+1)+3));
10
wSlope=wCalibValue/wCalibCurrent;
11
12
...
13
}
Ich glaube in der Startup-Datei, die KEIL benutzt konnte man die
Stack-Größe einstellen. Unter IAR finde ich es nicht. Weiß einer wo man
sie einstellen kann?
Horst schrieb:> In der Tat, völlig übersehen. Welcher Controller genau und welcher> Debugger?
STM32F0C8 und IAR Debugger. Die Division funktioniert in der main, in
der Funktion nicht.
ide schrieb:> Ich glaube in der Startup-Datei, die KEIL benutzt konnte man die> Stack-Größe einstellen. Unter IAR finde ich es nicht. Weiß einer wo man> sie einstellen kann?
Wenn kein Division-Code im Flash ist, dann ist der Stack erst einmal
uninteressant.
A. K. schrieb:> Wenn kein Division-Code im Flash ist, dann ist der Stack erst einmal> uninteressant.
Hatte den Code für die Division auch in der main stehen um zu testen ob
sie überhaupt geht und es ging.
Hatte ihn dann drin gelassen und danach die eigentliche Funktion
aufgerufen und jetzt gehts auch in der Funktion... Wie kann das sein?
Sobald ich die paar Zeilen in der main auskommentiere geht es wieder
nicht.
Danke für die Hilfe bisher :-)
A. K. schrieb:> Unter dieser exakten Bezeichnung finde ich nichts. Google auch nicht.
Sorry, meinte STM32F030C8. Ob die Division in der aufgerufenen Funktion
klappt ist abhängig ob in der main ein paar Zeilen mehr oder weniger
stehen. Ist das ein Linker-Problem? Wenn ja, was kann man da tun?
A. K. schrieb:> Das ist nicht zufällig eine IAR Kickstart Version, die beim Cortex> M0> nur 16KB Code unterstützt?
Es ist eine Testversion, die allerdings eine Zeitbeschränkung und keine
Code-Beschränkung hat. Die Code-Größe insgesamt ist schon über 35K und
die Division in der Funktion funktioniert ja auch mit ein paar Zeilen
mehr in der main und nicht weniger.
- Map-File oder Symboltabelle anschauen
- Speicher an den entsprechenden Stellen wo die Funktion stehen sollte
im Binary prüfen (wird es falsch erzeugt oder falsch programmiert?)
- Wenn man sich den 2. Screenshot ansieht, sind noch deutlich mehr
Funktionen von der FF-Eritis betroffen. Herausfinden, wo das anfängt
(und ob das wieder aufhört).
- Prüfen, ob an den entsprechenden Addressen irgendetwas im
Linker-Skript passiert oder gar der Flash aus ist?
- Sind das irgendwelche verkrüppelte Demo-Versionen? (Wer hat schon Keil
und IAR gleichzeitig im Zugriff?)
- Falls alles bezahlt -> Support des Herstellers. (Habe auch schon
komische Sachen bei einem TriCore mit dem TASKING Compiler erlebt. Der
ist bei einer bestimmten Kombination selbst in den Tod gesprungen)
- Alle Warnungen des Linkers anschalten und dem nachgehen
- arm-none-eabi-gcc nehmen (SCNR)
Hallo,
Horst hat es gesagt, hatte Probleme dass die Adresse nicht durch 4
teilbar war,.. "unaligned access".
Du wirst dasselbe Problem haben wenn Du die Werte nur "umspeicherst",
probier mal, lass mal division,.. alles weg, oder mach eine
Addition,.... wird auch crashen.
Grüße
Sebastian
Karl schrieb:> - arm-none-eabi-gcc nehmen (SCNR)
FullACK ;)
Das Linkerscript fehlt noch wegen Stackgröße.
Iar debugger heißt die Software? Also ich will nur ausschließen, dass es
kein JLink ist. Hatte da auch in der STM32F0 Serie, dass das Flash nicht
richtig beschrieben wurde.
Also im Zweifel nochmal schauen ob im Binary auch alles FF ist oder ob
es beim Schreiben irgendwie verloren gegangen ist
Sebastian schrieb:> Du wirst dasselbe Problem haben wenn Du die Werte nur "umspeicherst",> probier mal, lass mal division,.. alles weg, oder mach eine> Addition,.... wird auch crashen.
Hat er doch schon probiert. Auslesen aus dem Falsh klappt, aber da wo
die divisions-Routine im Flash sein sollte steht halt nur 0xFF
Horst schrieb:> Also ich will nur ausschließen, dass es> kein JLink ist. Hatte da auch in der STM32F0 Serie, dass das Flash nicht> richtig beschrieben wurde.
Vom J-Link hört man immer wieder solche Sachen. Scheint ziemlich
ausgefuchst zu sein mit viel Caching auf dem Debugger und ständigem neu
flashen für unendliche Breakpoints.
ide schrieb:> Das Problem hat sich erübrigt, nachdem ich weiter oben im Code ein> FLASH_Lock()
Das klingt, als hättest du im Code "wilde" Flash-Schreibzugriffe, die
deinen Divisionscode löschen würden, die du jetzt blockiert hast. Da
würde ich ja lieber versuchen diese Zugriffe ausfindig zu machen anstatt
das Symptom zu beheben...
Dr. Sommer schrieb:> ide schrieb:>> Das Problem hat sich erübrigt, nachdem ich weiter oben im Code ein>> FLASH_Lock()>> Das klingt, als hättest du im Code "wilde" Flash-Schreibzugriffe, die> deinen Divisionscode löschen würden, die du jetzt blockiert hast. Da> würde ich ja lieber versuchen diese Zugriffe ausfindig zu machen anstatt> das Symptom zu beheben...
Das könnte natürlich sein. Danke für den Tipp. Werde morgen mal den Code
nach Schreibzugriffen absuchen.
Und danke an alle, die geholfen haben dem Fehler auf die schlichte zu
kommen.
Ja :-)
Das Problem war ein #define EEPROM_EMULATION_START_ADDRESS 0x8007000,
das voll in den Code-Bereich zeigte, nachdem sich der Code die letzten
Tage um mehr als 10KB vergrößert hat.
Der neue Inhalt an der Stelle hat den Zustandsautomat der
EEPROM-Emulation ziemlich irritiert, worauf dieser sich mit dem Löschen
seiner zugewiesenen Pages bedankte, um für sich einen definierten
Zustand wieder herzurichten. Zufälligerweise Stand dort meine Division.
Hab das ganze jetzt ganz nach hinten auf Page 62 & 63 verfrachtet und
jetzt ist alles gut.
Jetzt gehts bestimmt um die Division an sich, oder die wilde
Flashaddressierung, oder den "Bezeichnungsmix" unint und USIGN (der
wurde schon bereinigt) :-)
Schieß los, wenn du willst. Ich hab für Dinge die man besser machen
könnte immer ein offenes Ohr.
Mit so einem kleinkram halte ich mich nicht auf. Typedefs soll doch
jeder machen Wie er will. Macht jeder sowieso so.
Worauf ich hinauswollte:es gibt ein Programm das sich sozusagen
hauptberuflich mit der Vergabe von speicheradressen beschäftigt. Es ist
der linker. Wenn du die Inhalte eines speichersegments beeinflussen
willst sollte das dem compiler und linker auch bekannt sein. Also
definiere eine entsprechende output section und übergib dem Compiler die
entsprechenden Adressen über Symbole aus dem linker. Dann gibt es
zumindest eine halbwegs aussagekräftige Fehlermeldung.