Forum: Mikrocontroller und Digitale Elektronik Bootloader (Initial SP)


von Nico W. (nico_w)


Lesenswert?

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?

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

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

: Bearbeitet durch User
von Nico W. (nico_w)


Lesenswert?

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.

von Torsten R. (Firma: Torrox.de) (torstenrobitzki)


Lesenswert?

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.

von Vincent H. (vinci)


Lesenswert?

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.

von Nico W. (nico_w)


Lesenswert?

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...

von Nico W. (nico_w)


Lesenswert?

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.

von Nico W. (nico_w)


Lesenswert?

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.

von Nico W. (nico_w)


Lesenswert?

Kleine Korrektur.

- Breakpoint bei 0x8001b4e
- Single Step nach 0x8001b50
- Continue
- Alles klappt


- Breakpoint bei 0x8001b50
- Continue
- Absturz

von Nico W. (nico_w)


Lesenswert?

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.

von Dr. Sommer (Gast)


Lesenswert?

VTOR auf 0x8010000 setzen wäre noch so ein Punkt...

von Nico W. (nico_w)


Lesenswert?

Ja, macht Der Bootloader auch.


Ich hab jetzt zusätzlich noch das CONTROL und BASEPRI auf Null gesetzt. 
Hatte damit auch einmal Probleme.

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
Noch kein Account? Hier anmelden.