Hallo zusammen,
nachdem unaligned-Zugriffe auf dem Cortex M4 mit einer Zeitstrafe belegt
werden, wollte ich mein Programm dahingehend testen. Also habe ich
irgendwo an Anfang von main() die "unalign_trp" aktiviert:
1
uint32_t*CCR=0xE000ED14;
2
uint32_tunalign_trp=1<<3;
3
*CCR|=1<<3;
In meinem eigentlichen Programm habe ich damit ein schlecht
ausgerichtetes struct erwischt (auch wenn es mir da noch ein Rätsel ist,
warum an dieser Stelle kein padding war - aber das ist eine andere
Geschichte), aber ansonsten ist das komplett glimpflich abgelaufen.
Es gibt allerdings eine Funktion in den Modultests auf dem STM32F446RE,
bei dem ich überhaupt nicht verstehe, wie und warum die unalign-Falle
hier zuschnappt.
Der Quelltext:
Sprich: Der Hard Fault wird schon in der ersten Zeile "uint8_t
buffer[12]="Hello";" erzeugt.
Die einzige Möglichkeit, wie ich die Frage formulieren könnte, lautet:
"WTF"?
Wieso wird der Wert #0 überhaupt auf den Stack geschoben? Und warum auf
diese Weise? Und warum als Wort kompletter Breite? Und überhaupt?
Walter T. schrieb:> Wieso wird der Wert #0 überhaupt auf den Stack geschoben?
Um das Array mit Nullen aufzufüllen, denn es sind ja nur die ersten 5
Einträge belegt.
Kompilierst du mit "-munaligned-access"? Was genau macht dieses
TEST-Makro, wie sieht exakt der erzeugte C-Code aus?
Walter T. schrieb:> uint32_t *CCR = 0xE000ED14;
PS: Das kompiliert, so ganz ohne cast? "volatile" fehlt auch.
Ein minimaler Testcase, gern auch auf godbolt.org, wäre nicht schlecht.
Niklas Gürtler schrieb:> Das kompiliert, so ganz ohne cast? "volatile" fehlt auch.
Ja, die Warnung "makes pointer from integer without a cast" ist drin.
Ich habe sie mit Absicht nicht weggecastet, damit ich nachher nicht
vergesse, das später wieder zu entfernen.
Niklas Gürtler schrieb:> Kompilierst du mit "-munaligned-access"?
Nein
Kompletter Compiler-Aufruf:
Niklas Gürtler schrieb:> Was genau macht dieses> TEST-Makro, wie sieht exakt der erzeugte C-Code aus?
Das stückelt drei Makro-"Funktionen" (TEST_SETUP(crc), TEST(crc,
testValues) und TEST_TEAR_DOWN(crc)) zu einer Funtion
TEST_crc_testValues_() zusammen. Da die beiden anderen Makro-Funktionen
hier leer sind, spielen sie hier keine Rolle.
Niklas Gürtler schrieb:> Um das Array mit Nullen aufzufüllen, denn es sind ja nur die ersten 5> Einträge belegt.
Okay, das Array wird direkt auf dem Stack angelegt, und er versucht, die
fehlenden 6 Elemente als zwei WORDs zu schreiben - was aufgrund des
Index mit einem unaligned-access fehlschlägt. Außerdem schreibt er zwei
Null-Bytes dahinter, die gar nicht gebraucht werden.
Niklas Gürtler schrieb:> Ein minimaler Testcase, gern auch auf godbolt.org, wäre nicht schlecht.
Stimmt. Mal sehen, ob ich das hinbekomme.
Walter T. schrieb:> Nein> Kompletter Compiler-Aufruf:
Ich glaube das ist standardmäßig an für ARMv7M. Übergebe mal
-mno-unaligned-access.
Walter T. schrieb:> -fno-strict-aliasing
Sicher dass du das aktiviert haben willst?
Walter T. schrieb:> Außerdem schreibt er zwei Null-Bytes dahinter, die gar nicht gebraucht> werden.
Der GCC war noch nie gut darin Variablen effizient zu initialisieren...
Viel effizienter wäre es wohl einen schlichten Pointer auf ein
String-Literal zu verwenden anstatt den String in ein Stack-Array zu
kopieren.
Haste denn bei "Hardfault in dieser Zeile" schon den Pipelining Offset
abgezogen?
Sonst reden wir über die falsche Stelle.
Der Inhalt des SP Registers wär an der Stelle auch interessant.
Ich bekomme auch im Godbolt den unaligned access (netterweise direkt
kommentiert):
https://godbolt.org/z/PzM6fdez4
Er wird durch die Option "-mcpu=cortex-m4" ausgelöst. Ohne ist er weg.
Niklas Gürtler schrieb:> Übergebe mal> -mno-unaligned-access.
Stimmt. Mit dieser Option ist er auch mit -mcpu=cortex-m4 weg.
Mw E. schrieb:> Haste denn bei "Hardfault in dieser Zeile" schon den Pipelining Offset> abgezogen?> Sonst reden wir über die falsche Stelle.
Ich habe mich mit dem Debugger bis zu dieser Zeile vorgetastet und lande
danach im HardFault-Handler. Und das Listing zeigt ja, dass da wirklich
etwas im Stack nicht ausgerichtet ist.
Wahnsinn. 20595 Zeilen Quelltext und das ist die einzige Stelle, wo mir
das Alignment auf die Füße fällt.
Niklas Gürtler schrieb:> Walter T. schrieb:>> -fno-strict-aliasing>> Sicher dass du das aktiviert haben willst?
Guter Hinweis. Eigentlich brauche ich das schon lange nicht mehr.
Niklas Gürtler schrieb:> Ich glaube das ist standardmäßig an für ARMv7M.
Stimmt, siehe https://gcc.gnu.org/onlinedocs/gcc/ARM-Options.html :
-munaligned-access
-mno-unaligned-access
Enables (or disables) reading and writing of 16- and 32- bit values from
addresses that are not 16- or 32- bit aligned. By default unaligned
access is disabled for all pre-ARMv6, all ARMv6-M and for ARMv8-M
Baseline architectures, and enabled for all other architectures. If
unaligned access is not enabled then words in packed data structures are
accessed a byte at a time.
Niklas Gürtler schrieb:> Viel effizienter wäre es wohl einen schlichten Pointer auf ein> String-Literal zu verwenden anstatt den String in ein Stack-Array zu> kopieren
Ich will nicht drüber reden. peinlich
Walter T. schrieb:> Ich habe mich mit dem Debugger bis zu dieser Zeile vorgetastet und lande> danach im HardFault-Handler. Und das Listing zeigt ja, dass da wirklich> etwas im Stack nicht ausgerichtet ist.
Ja dann wirds da sein.
Wo du noch unaligned Probleme bekommen kannst ist die FPU.
Die mag keine unaligned floats einlesen/schreiben, das gibt direkt nen
fault.
Jetzt weiss ich auch wieder, warum diese komische String-Variante. Eine
Altlast. In einer früheren Inkarnation hat die CRC-Funktion das Ergebnis
an das Array angehängt.
Hänsele schrieb:> Walter T. schrieb:>> uint8_t buffer[12]="Hello";>> Dem Index 0 eines 12 byte großen Array auf uint8_t wird> "Hello" zugewiesen???
Nein.
Hänsele schrieb:> Walter T. schrieb:>> uint8_t buffer[12]="Hello";>> Dem Index 0 eines 12 byte großen Array auf uint8_t wird> "Hello"> zugewiesen???
Index 0 ist und wird immer Index 0 bleiben, wenn du einer Indexvariable
was anderes als 0 zuweist, ist sie nicht mehr 0 ;-)
Natürlich füllt oberes Konstrukt den Speicherbereich "buffer" mit
{ 'H', 'e', 'l', 'l', 'o', 0, 0, 0, 0, 0, 0, 0 }