Moin,
ich habe einen STM32F103 mit Bootloader und Firmware.
Bootloader startet normal bei 0x8000000. Firmware bei 0x8010000.
Problem ist, dass ich an der Firmware aktuell keine Veränderungen machen
kann. Firmware wurde extern mit Keil erzeugt.
Wenn ich mit meinem GCC einen Bootloader und eine Firmware erzeuge, so
ist der Sprung vom Bootloader in die Firmware kein Thema. Sobald ich
aber an 0x8010000 die eigentliche Firmware habe, friert mir die
Geschichte komplett ein.
Nun kann ich im Hex-Viewer sehen, dass der SP im Flash auf 0x20000400
bei mir liegt. In der eigentlichen Firmware allerdings auf 0x20005CE8.
Liegt hier schon der Hund begraben? Wo müsste ich ansetzen, dass mein
Bootloader mit der anderen Firmware zusammen arbeitet?
Nico W. schrieb:> Problem ist, dass ich an der Firmware aktuell keine Veränderungen machen> kann. Firmware wurde extern mit Keil erzeugt.
Ja, das ist Dein Problem.
> Nun kann ich im Hex-Viewer sehen, dass der SP im Flash auf 0x20000400> bei mir liegt. In der eigentlichen Firmware allerdings auf 0x20005CE8.>> Liegt hier schon der Hund begraben? Wo müsste ich ansetzen, dass mein> Bootloader mit der anderen Firmware zusammen arbeitet?
Nein, den Stack teilen sich Bootlaoder und Firmware ja nicht. Das ist
somit auch der einzige Eintrag in der Vector-Table, der keine Probleme
macht.
Als Du die Firmware mit der Start-Adresse 0x8000000 gelinkt hast,
bezogen sich z.B. auch alle Einträge in der Vector-Table auf diese
Start-Adresse. Jeder Interrupt schlägt also fehl, weil jeder Eintrag um
0x10000 korregiert werden müsste. Jeder absolute Sprung in der Firmware
führt jetzt an eine um 0x10000 zu korrigierende Adresse.
Die einzige Möglichkeit, die ich sehe, ist die Firmware ab 0x8000000
stehen zu lassen und den Bootloader dort drüber zu plazieren Dann
könntest Du den Reset_Handler()-Eintrag in der Vector-Table der Firmware
auf den Start des Bootloaders setzen und dann vom Bootloader aus den
Reset_Handler() der Firmware aufrufen (den Wert musst Du dann fest in
den Bootloader backen).
HTH Torsten
Danke für deine Antwort.
Vielleicht kam das im ersten Post nicht genau rüber.
Die Firmware liegt generell bei 0x8010000. Das ist keine Idee von mir.
Davor liegt ein Bootloader. Den möchte ich mit meinem Bootloader
überschreiben.
Sobald ich diesen Bootloader aber überschreibe, läuft die normale
Firmware nicht mehr an und hängt sich auf.
Nico W. schrieb:> Sobald ich diesen Bootloader aber überschreibe, läuft die normale> Firmware nicht mehr an und hängt sich auf.
Das klingt so, als würde Dein Bootloader die Applikation nicht richtig
starten. Ich würde da mal im Assembler durch debuggen und mir die
Register angucken.
Hast Du im Bootloader alle Interrupts disabled, bevor Du die Firmware
startest?
In meinen Bootloadern gehe ich dazu immer noch mal eine Extra-Runde
durch Reset. Dazu schreibe ich ein sehr spezielles Muster irgendwo ins
RAM und wenn das direkt nach dem Reset dort steht, startet der
Startup-Code die Firmware. Damit kann man dann sicher stellen, dass die
HW wirklich ausreichend zurück gesetzt ist.
Was heißt "einfrieren"? Endlosschleife, Hardfault?
Neben den Interrupts ist auch die Clock-Init eine gefährliche Sache.
Wenn der Bootloader etwa die PLL schon entsprechend konfiguriert kann es
durchaus sein, dass in der eigentlichen Applikation ewig auf
irgendwelche Bits gewartet wird weil man vergeblich versucht die PLL
erneut zu setzen.
Torsten R. schrieb:> In meinen Bootloadern gehe ich dazu immer noch mal eine Extra-Runde> durch Reset. Dazu schreibe ich ein sehr spezielles Muster irgendwo ins> RAM und wenn das direkt nach dem Reset dort steht, startet der> Startup-Code die Firmware. Damit kann man dann sicher stellen, dass die> HW wirklich ausreichend zurück gesetzt ist.
Das scheint keine schlechte Idee zu sein.
Bin dank deinem Post mal allgemein auf die Idee gekommen, den Bootloader
auf möglichst wenig zu reduzieren. Hab jetzt eigentlich keine
Initialisierung von nix mehr drinne. Steht noch immer.
Ich geh mal weiter in die Tiefen...
Vincent H. schrieb:> Was heißt "einfrieren"? Endlosschleife, Hardfault?
Muss meinen Debugger noch zum laufen bekommen. Werde das aber noch
genauer betrachten. Melde mich aber dazu nochmal.
Bin einen kleinen Schritt weiter.
Es sieht zumindest so aus, dass mein Bootloader und der ursprüngliche
Bootloader im Prinzip das gleiche machen. Alle Register sind am Ende
zumindest identisch.
Ich bin jetzt mal ein wenig durch den ursprünglichen Bootloader
gesteppt. Bei einem bestimmten Punkt lege ich den STM dermaßen lahm,
dass mein ST-Link keine Verbindung mehr bekommt. Dann hilft nur noch
Strom komplett vom STM ziehen und ein Neustart. (Ich habe hier einen
originalen ST-Link/V2 Isol).
Hier der Bereich der abschmiert.
1
08001b3a: ldr r0, [pc, #504] ; (0x8001d34)
2
08001b3c: ldr r0, [r0, #24]
3
08001b3e: orr.w r0, r0, #1
4
08001b42: ldr r1, [pc, #496] ; (0x8001d34)
5
08001b44: str r0, [r1, #24]
6
08001b46: ldr r0, [pc, #496] ; (0x8001d38)
7
08001b48: ldr r0, [r0, #4]
8
08001b4a: orr.w r0, r0, #67108864 ; 0x4000000
9
08001b4e: ldr r1, [pc, #488] ; (0x8001d38)
10
08001b50: str r0, [r1, #4] ; <--- break point
11
08001b52: ldr r0, [pc, #480]
Bei Break point sehen die Register wie folgt aus:
1
r0 0x4000000 (Hex)
2
r1 0x40010000 (Hex)
3
sp 0x20000f68
4
lr 0x8001b3b (Hex)
5
pc 0x8001b50
6
xPSR 0xa1000000 (Hex)
7
msp 0x20000f68
8
psp 0x3129b1a0
Wenn ich nach dem Break Point einen single Step mache, dann hängt sich
alles auf. Bei einem Continue läuft die ganze Geschichte durch zur
Firmware.
Torsten R. schrieb:> Hast Du im Bootloader alle Interrupts disabled, bevor Du die Firmware> startest?>> In meinen Bootloadern gehe ich dazu immer noch mal eine Extra-Runde> durch Reset. Dazu schreibe ich ein sehr spezielles Muster irgendwo ins> RAM und wenn das direkt nach dem Reset dort steht, startet der> Startup-Code die Firmware. Damit kann man dann sicher stellen, dass die> HW wirklich ausreichend zurück gesetzt ist.
Da war bei mir anscheinend noch der Systick an. Asche über mein Haupt.
Den zweiten Tipp habe ich jetzt aber auch genutzt. Ich nutze dazu jetzt
das BKP-Register. Magic-Code ins BKP und dann einmal nen
NVIC_SystemReset. In der nächsten Runde wird dann die komplette
Initialisierung ausgelassen und direkt gesprungen.