Hallo, ich schreibe gerade für meine BLE Debug Probe einige Flash Routinen für verschiedene Microcontroller. Diese Routinen werden ins RAM des Targets geladen und dort ausgeführt, um das flash der Controller zu beschreiben. Ausgeführt werden diese Routinen, in dem die Parameter direkt in Register geladen werden, der PC auf den Start der Routine gesetzt wird und die CPU nach einen Halt wieder los gelassen wird. Am Ende der rennt die Routine auf einen Break-Point und der Debugger wartet auf das Erreichen des Breakpoints. Dann kann sich der Debugger das Ergebnis der Routine in einem Register abholen (so grob skizziert). Im Moment geht es ausschließlich um ARM Assembler (Thumb). Einige Flash Controller sind allerdings komplex genug, damit es recht schnell unübersichtlich wird, diese Routinen von Hand in Assembler zu schreiben. Welche Alternativen hätte ich? (Einen Stack könnte ich wohl in der Regel aufsetzen). Verwendete Toolchain ist arm-none-eabi-gcc. schöne Grüße, Torsten
Seltsame Frage... Torsten R. schrieb: > Verwendete Toolchain ist arm-none-eabi-gcc. Das unterstützt C, C++ und Assembler. Die sollten alle drei gehen. Wo ist das Problem?
Dr. Sommer schrieb: > Seltsame Frage... > > Torsten R. schrieb: >> Verwendete Toolchain ist arm-none-eabi-gcc. > > Das unterstützt C, C++ und Assembler. Die sollten alle drei gehen. Wo > ist das Problem? Ich kann in C, C++ keinen ausführbaren Code deklarieren, der ausserhalb einer Funktion steht:
1 | start:
|
2 | MOV R7, #result_ok |
3 | LDR R3, nvmc_ready /* R3 == NVMC_READY */ |
4 | LDR R4, nvmc_config /* R4 == NVMC_CONFIG */ |
5 | |
6 | MOV R5, #NVMC_CONFIG_WEN_Wen |
7 | STR R5, [ R4 ] /* NVMC_CONFIG = NVMC_CONFIG_WEN_Wen */ |
8 | ...
|
9 | BKPT
|
Aufgerufen wird so eine "Routine", in dem ich die CPU des Controllers anhalte, die Routine ins RAM lade. Den PC auf den Anfang der Routine setze, die Register mit Parametern fülle und die CPU dann wieder weiter laufen lasse. Am Ende der Routine ist dann ein SW-Breakpoint, auf den wartet der Debugger. Ich könnte natürlich von dieser ASM-Routine aus, eine C Funktion aufrufen. Ich frage mich, ob es aber ggf. einfacher geht, ohne direkt Assembler schreiben zu müssen.
Ich habe gerade mal in die Source von der Blackmagic Probe geguckt. Die verwenden C Funktionen, der mit `__attribute__((naked))` anotiert ist:
1 | void __attribute__((naked)) |
2 | efm32_flash_write_stub(uint32_t *dest, uint32_t *src, uint32_t size, uint32_t msc) |
3 | {
|
4 | ...
|
5 | }
|
Die Dokumentation vom GCC sagt dazu aber:
1 | naked
|
2 | This attribute allows the compiler to construct the requisite function declaration, while allowing the body of the function to be assembly code. The specified function will not have prologue/epilogue sequences generated by the compiler. Only basic asm statements can safely be included in naked functions (see Basic Asm). While using extended asm or a mixture of basic asm and C code may appear to work, they cannot be depended upon to work reliably and are not supported. |
Das Problem ist dass es keinerlei Garantie gibt dass Code innerhalb einer Funktion nicht munter am Stack herumspielt. Das Attribut entfernt lediglich Stackpointer Manipulation am Anfang und Ende einer Funktion, nicht aber dazwischen.
Dann mach halt normale C-Funktionen, auf die paar Byte wirds ja wohl nicht ankommen. Initialisier den Stackpointer, ruf die Funktion auf und wenn sie zurückkommt lass es in den Breakpoint laufen. Dann hast Du ne kleine Hand voll Assembler der immer gleich ist und eine bliebig komplexe stinknormale C-Funktion.
Vincent H. schrieb: > Das Problem ist dass es keinerlei Garantie gibt dass Code innerhalb > einer Funktion nicht munter am Stack herumspielt. Das Attribut entfernt > lediglich Stackpointer Manipulation am Anfang und Ende einer Funktion, > nicht aber dazwischen. Genau, und ich würde den Compiler gerne dazu bringen, z.B. eine Fehlermeldung auszugeben, wenn er doch einen Stackframe braucht (z.B. weil die Register nicht ausreichen).
Torsten R. schrieb: > Vincent H. schrieb: >> Das Problem ist dass es keinerlei Garantie gibt dass Code innerhalb >> einer Funktion nicht munter am Stack herumspielt. Das Attribut entfernt >> lediglich Stackpointer Manipulation am Anfang und Ende einer Funktion, >> nicht aber dazwischen. > > Genau, und ich würde den Compiler gerne dazu bringen, z.B. eine > Fehlermeldung auszugeben, wenn er doch einen Stackframe braucht (z.B. > weil die Register nicht ausreichen). Beim GCC kann man sich mit -fstack-usage den Stackbedarf der einzelnen Funktionen ausgeben lassen. Das landet dann in einer .su-Datei die du mit einem Python-Script o.Ä., aufgerufen durch dein Build-System auswerten könntest. Eine direkte Warnung kannst du ausgeben, wenn du die Compileroption -Wstack-usage=byte-size nutzt, wobei byte-size in deinem Fall dann logischerweise 0 sein müsste.
>Welche Alternativen hätte ich? (Einen Stack könnte ich wohl in der Regel >aufsetzen). Verwendete Toolchain ist arm-none-eabi-gcc. Nimm C, das ist nichts anderes als ein Makro-Assembler!
da gibt es ja noch das Schlüsselwort Register wo man den Compiler fast soweit kriegt daß er Code absetzt wie man ihn auch selbst geschrieben hätte. Nur für einen Schleifenaufbau mit Rotieren durchs Carry bit habe ich noch nichts gefunden. Aber man muß halt immer höllisch aufpassen daß gcc keinen Blödsinn macht. Ist halt wie beim Autorouter in der Hardware...
J. V. schrieb: > da gibt es ja noch das Schlüsselwort Register welches seit einem gefühlten Jahrhundert ganz offiziell von jedem Compiler ignoriert wird. Oliver
Oliver S. schrieb: > J. V. schrieb: >> da gibt es ja noch das Schlüsselwort Register > > welches seit einem gefühlten Jahrhundert ganz offiziell von jedem > Compiler ignoriert wird. Oder besser nach eigenem Gutduenken optimiert... Deshalb sagte ich dem gcc sowas:
1 | register int foo asm ("r12"); |
> Oliver
leo
Die gesamten Mikrokontroller sind von GCC Code besetzt. Die gesamten? Nein, ein von unbeugsamen Programmieren erstellter Compiler macht das anders (cosmic)
:
Bearbeitet durch User
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.