Forum: Mikrocontroller und Digitale Elektronik Bootloader für FW-Update


von Stephan S. (stephan1008)


Lesenswert?

Hallo zusammen,

gleich verneweg, ich arbeite mit einem STM32F207VC und Keil µVision 4.

SO nun zu meinem Problem:
Ich versuche im Startupcode zu verzweigen, das sieht momentan so aus:

; Reset handler
Reset_Handler    PROC
                 EXPORT Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main
                 LDR    R0, =SystemInit
                 BLX    R0
          LDR    R0, =0x2001FFF0
          LDR    R1, =0xDEADBEEF
          CMP    R2,R1
          BEQ    Reboot_Loader
                 LDR    R0, =0x0800C000;
                 BX     R0
                 ENDP

Reboot_Loader    PROC
          EXPORT Reboot_Loader
          LDR    R0, =0x08004004
          LDR    SP, =0x08004000
                 BX     R0
                 ENDP

An der Position 0x0800 C0000 soll mein Hauptprogramm liegen und bei 
0x0800 4000 mein Flashloader zum updaten.

Den Flashloader bekomme ich mit 
__attribute__((section(".ARM.__at_0x08004000"))) void 
fnFlashloader(void); an die entsprechende Stelle bei den ganzen anderen 
Funktionen im Hauptprogramm wird dies allerdings etwas schwieriger.

Kann mir hier jemand weiterhelfen?

Schonmal vielen Dank im voraus.

Stephan

von Stephan S. (stephan1008)


Angehängte Dateien:

Lesenswert?

Ich habe es mittlerweile geschafft meinen Code dort abzulegen, wo ich 
ihn haben will.
Hierzu habe ich meinen Flashspeicher in zwei teile zerlegt, den 
Flashloader mit dem obigen Befehl und den Rest mit 
__attribute__((section(".ARM.--autoat_0x0800C000"))).

Den Startup-Code habe ich dann dem ersten Flashbereich zugewiesen.

Allerdings lande ich beim sprung in die main() im HardFault_Handler.

Im Bild ist die Speicherverteilung zu sehen.

mfg Stephan

von Lutz (Gast)


Lesenswert?

Schau dir doch die Länge deiner HEX-Adresse noch mal aufmerksam an ...

von Lutz (Gast)


Lesenswert?

Na der Chip hat ja 'ne lustige Adressierung; Kommando zurück.

von Stephan S. (stephan1008)


Lesenswert?

Ich hab es jetzt soweit hinbekommen, dass er mir in die main-Schleife 
springt:

; Reset handler
Reset_Handler    PROC
                 EXPORT Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main
                 LDR    R0, =SystemInit
                 BLX    R0
          LDR    R0, =0x2001FFF0
          LDR    R1, =0xDEADBEEF
           CMP    R2,R1
                 BEQ    Reboot_Loader
                 LDR    R0, =0x0800C001;
                 BX     R0
                 ENDP

Allerdings läuft er mir irgendwann in einen Hard-Fault.
Die verwendete Funktion läuft allerdings im "normalbetrieb", also ohne 
bootloaser einwandfrei.

von Kindergärtner (Gast)


Lesenswert?

Stephan Scherer schrieb:
> LDR    R0, =0x0800C001;
Das Thumb-Bit schlägt zurück. mit "BX main" wäre das nicht passiert. Was 
hast du denn am Anfang des Flashs vor 0x0800C000 ?

Stephan Scherer schrieb:
> LDR    SP, =0x08004000
Du lässt den Stack Pointer in den Flash zeigen? Das klingt ungesund.

Stephan Scherer schrieb:
> Allerdings läuft er mir irgendwann in einen Hard-Fault.
Das ist eine äußerst präzise Fehlerbeschreibung. Assembler-Listing der 
jeweiligen Stelle und Register-Inhalte anschauen.

Stephan Scherer schrieb:
> Die verwendete Funktion läuft allerdings im "normalbetrieb", also ohne
> bootloaser einwandfrei.
Du rufst nach dem Bootloader wieder den Reset_Handler auf? Direkt? Oder 
führst du einen kompletten System-Reset durch (NVIC_Reset oder wie das 
ging)? Wird denn dabei der Stack richtig initialisiert? In 0x08000000 
sollte sich der initiale Stack-Pointer-Wert befinden, der wird beim 
normalen starten automatisch von da geladen.

von Stephan S. (stephan1008)


Lesenswert?

Hallo Kindergärtner,

Kindergärtner schrieb:
> Das Thumb-Bit schlägt zurück. mit "BX main" wäre das nicht passiert.

Wie meinst du das genau?

Wenn ich BX main mache bekomme ich vom compiler eine Fehlermeldung.

Kindergärtner schrieb:
> Was
> hast du denn am Anfang des Flashs vor 0x0800C000 ?

Im ersten Sektor soll nur der Bootloader selber stehen und in den 
nächsten beiden ab 0x08004000 die Routinen zum Löschen und neu 
beschreiben. Aber soweit bin ich noch nicht :D

Bei dem fehler greift er auf die Adresse 0x600xxxx zu. Das sollte nicht 
möglich sein.

Der plan ist so, dass ich im Normalbetrieb den Magic value (0xDEADBEEF) 
in den Ram schreibe und mit NVIC_SystemReset(); den µC neu starte, den 
Magic Value auslese und dann in die Updateroutine wechsle.

von Bastler (Gast)


Lesenswert?

Was macht den [WEAK] hinter dem ResetHandler?
Sollte das nicht weg, um sicherzugehen, das auch wirklich dieser Code 
gelinkt wird, und nicht der aus irgend einer Lib?

von Stephan S. (stephan1008)


Lesenswert?

Bastler schrieb:
> Was macht den [WEAK] hinter dem ResetHandler?

Könnte man entfernen, aber den Reset_Hanlder gibt es nur einmal.

von Kindergärtner (Gast)


Lesenswert?

Stephan Scherer schrieb:
> Wie meinst du das genau?
Wenn das unterste Bit der Sprungziel-Adresse 0 ist, versucht der Core in 
den ARM-Modus zu wechseln, was die Cortex-M nicht können, und daher 
crashen.
> Wenn ich BX main mache bekomme ich vom compiler eine Fehlermeldung.
Eher vom Linker... Da der Linker weiß dass die main im Thumb-Mode 
erstellt wurde setzt er der unterste bit auf 1 s.d. der Core den Sprung 
durchführen kann.

Stephan Scherer schrieb:
> Bei dem fehler greift er auf die Adresse 0x600xxxx zu. Das sollte nicht
> möglich sein.
Wo kommt die Adresse denn her? Musst du ein bisschen debuggen.

Stephan Scherer schrieb:
> Der plan ist so, dass ich im Normalbetrieb den Magic value (0xDEADBEEF)
> in den Ram schreibe
Na hoffentlich wird der nicht mit resettet... Schau mal ob der F2 auch 
Backup-Register hat, die werden wimre nicht gelöscht.

von Bastler (Gast)


Lesenswert?

Obwohl selbst noch keine Zeile ARM-ASM geschrieben, frage ich mich was 
wohl in R2 steht?
Wurde da von irgendwo außerhalb schon der Magische Wert aus dem RAM 
reingefüllt?
Wenn nicht, was macht dann CMP R2,R1 ?

von Stephan S. (stephan1008)


Lesenswert?

Das unterste Bit ist mittlerweile ne 1 und der Sprung ansich 
funktioniert ja auch.

Stephan Scherer schrieb:
> LDR    R0, =0x0800C001;

Bastler schrieb:
> was wohl in R2 steht?

Da steht im Normalfall irgendwas drin.
Der magische Wert wird im laufenden Betrieb vor dem Reset dort hin 
geschrieben und bleibt nach dem Reset auch dort.

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.