Hallo, ich arbeite mich gerade in das Thema Bootloader - bei ST "in Application programming" ein. In meinem Fall will ich ein STM32F103 via CAN flashen. Der Bootloader sollte möglichst nur aus der Anwendung aufgerufen werden können. Ich hab hier im Forum ein wenig gestöbert und bin hautsächlich auf die Prozedur gestoßen: Bootloader am Anfang vom Flash, wenn keine Anfrage, dann nach x ms in Anwendung springen. Idee wäre den Bootloader irgendwo ans Ende zu schreiben, nur wenn was schief geht muss man wieder mit einem Programmer anrücken oder? Mir geht es hier nicht um Verschlüsselung, ich will mir nur den Weg zu den µC sparen. Vielen Dank schon im Vorraus. MfG Peter
Hi! Ich hab das (allerdings beim STM32F4) so gemacht: - Die Anwendung liegt bei 0x08000000, der Bootloader bei 0x08020000, so kann man mit normalem Programmierer immer auch die Anwendung überschreiben, ohne den Bootloader mit zu überschreiben; den Bootloader programmiere ich an diese Adresse mit dem ST-Link Utility - Wichtig hier ist, sich die Sektoraufteilung des Flash anzusehen, am einfachsten beim Beschreiben ist es, ganze Sektoren zu löschen. Daher am besten den Bootloader bei einem neuen Sektor starten lassen! - Das Bootloader-Programm braucht einige Besonderheiten: Im Linker-File muss der ROM Origin auf 0x08020000 gesetzt werden. Zudem muss die Vektor-Tabelle ein Offset von 0x20000 bekommen (verwendet in der system_stm32fxxx.c Datei):
1 | #define VECT_TAB_OFFSET 0x00000
|
- In der eigentlichen Anwendung gibt es einen Aufruf, welcher den Proz. zurücksetzt und dann in den Bootloader springt, etwa so:
1 | uint8_t bootloader_init(void) { |
2 | |
3 | //magic RAM constant
|
4 | *((uint32_t *)0x2000FFF0) = 0xDEADBEEF; |
5 | NVIC_SystemReset(); |
6 | |
7 | return 1; |
8 | |
9 | }
|
- Vor Aufruf des Reset-Vektors wird eine Speicheradresse 0x2000FFF0 mit einem besonderen Wert (magic constant) beschrieben. - Im Startskript der Anwendung ist dann die eigentliche Verzweigung in den Bootloader:
1 | Reset_Handler: |
2 | //check for magic constant in RAM for bootloader operation |
3 | ldr r0, =0x2000FFF0 |
4 | ldr r1, =0xDEADBEEF |
5 | ldr r2, [r0, #0] |
6 | str r0, [r0, #0] //invalidate constant to prevent jumping twice |
7 | cmp r2, r1 |
8 | beq BootLoader |
9 | //... |
10 | //normal start script follows here |
11 | //... |
12 | BootLoader: |
13 | ldr r0, =0x08020000 |
14 | ldr sp, [r0, #0] |
15 | ldr r0, [r0, #4] |
16 | bx r0 |
Empfehlenswert für das Beschreiben des Flash ist auch das Flash-Beispiel aus der STM32 Standard Peripheral Lib. Viel Erfolg!
wosnet schrieb: > Ich hab das (allerdings beim STM32F4) so gemacht: > - Die Anwendung liegt bei 0x08000000, der Bootloader bei 0x08020000, so > kann man mit normalem Programmierer immer auch die Anwendung > überschreiben, ohne den Bootloader mit zu überschreiben; Das kannst Du auch wenn der Bootloader vorne und die Anwendung hinten liegt. Auch dann kann man problemlos die Anwendung flashen und debuggen ohne dabei den Bootloader zu berühren.
verwende EM-Blocks mit dem ST-Link. Da kann ich leider nirgends eine (andere) Basisadresse einstellen für den Debugger, d.h. debuggen und programmieren auf einer anderen Adresse als 0x08000000 bekomme ich nicht hin. Kannst bitte kurz beschrieben wo da was zu konfigurieren ist? Vielen Dank!
Peter schrieb: > Idee wäre den Bootloader irgendwo ans Ende zu schreiben, nur wenn was > schief geht muss man wieder mit einem Programmer anrücken oder? Die Frage ist nur, wie möchtest Du zum Bootloader verzweigen, wenn etwas schief gegangen ist? Du lässt den Bootloader von deiner Firmware starten. Jetzt ist etwas schief gegangen und die Firmware läuft nicht mehr richtig. Dann wirst Du auch den Bootloader nicht mehr aktiviert bekommen.
wosnet schrieb: > Kannst bitte kurz beschrieben wo da was zu konfigurieren ist? Mein Bootloader liegt vorne (bei Kinetis ist das 0x0) und startet nach dem Reset. Wenn er 200ms lang erfolglos auf Kommunikation von meinem Update-Tool gewartet hat dann biegt er die Vektortabelle um auf 0x800 (er ist kleiner als 2k) und macht einen simulierten Reset um in die Anwendung zu springen indem er SP und PC von 0x800 und 0x804 lädt (letzteres ist ein Sprung). Wenn ich die (für 0x800 gelinkte) Anwendung mit gdb hochlade und debugge dann springt er natürlich zuerst mal in den Bootloader (der muss natürlich schon da sein) aber nach 200ms springt er dann in die zu debuggende Anwendung und wenn ich dort irgendeinen Breakpoint setze dann trifft er den auch und ich kann ganz normal debuggen. > Da kann ich leider nirgends eine (andere) > Basisadresse einstellen für den Debugger Das steht doch alles im .elf file drin. Es war keine irgendwie geartete Konfiguration dazu nötig denn wozu auch? Der gdb weiß aus dem .elf file automatisch ganz genau daß diese Anwendung bei 0x800 anfängt, wohin er sie laden muss und an welche Adressen welche Symbole gelinkt wurden, deshalb lädt er sie auch genau dort hin und deshalb kann ich dort auch Breakpoints setzen, warum sollte das nicht gehen? Der gdb lädt es brav nach 0x800, genau so wie es im elf drin steht, dann macht er einen Reset (bei 0x0), dann dreht der Controller eine Ehrenrunde in meinem Bootloader und nach 200ms läuft er auf irgendeinen Breakpoint in meiner Anwendung.
:
Bearbeitet durch User
Das es geht, wenn die Anwendung bei 0x08000000 liegt und startet verstehe ich. Angenommen ich möchte aber nur den Bootloader bei 0x08020000 debuggen, ohne dass bei 0x08000000 eine Anwendung liegt. Im ELF steht dann ja auch diese Adresse als Startadresse drin, funktionieren tuts bei mir trotzdem nur in den Fällen, in denen das Programm bei 0x08000000 beginnt.
wosnet schrieb: > Das es geht, wenn die Anwendung bei 0x08000000 liegt und startet > verstehe ich. Angenommen ich möchte aber nur den Bootloader bei > 0x08020000 debuggen, ohne dass bei 0x08000000 eine Anwendung liegt. Natürlich muss dann bei 0x0800000 irgendwas liegen das ihn nach einem Reset in wohlgeordneter Weise nach 0x08020000 befördert wo man es dann debuggen kann, und wenns auch nur ein untätiger Stub ist der nur den Sprung macht. Bei mir ist das der Bootloader. Ich flashe zuerst den Bootloader. Danach kann ich sicher sein daß nach jedem Einschalten oder jedem Reset (zum Beispiel beim Reset durch den Start im Debugger) irgendwann (nach 0.2s) nach hinten gesprungen wird (wo dann der Debugger schon wartet wenn ich das debuggen will was ich hinten hingeladen habe).
:
Bearbeitet durch User
Peter schrieb: > Der Bootloader sollte möglichst nur aus der Anwendung aufgerufen werden > können. Ich mach das in meinen IO-Link devices so, ich kann jederzeit per Befehl in den Bootloader springen. Ganz vorne im Flash liegt mein Bootloader, ein Stück weiter hinten liegt beginnend an einer Seitengrenze die eigentliche Anwendung. Beim Einschalten oder bei jedem Reset startet immer erst der Bootloader und kurz danach lässt dieser in die Anwendung springen. Die Anwendung kommuniziert dann für den Rest ihres Lebens per IO-Link-Protokoll mit dem Master, so wie sich das für ein anständiges IO-Link Device gehört. Jedoch gibt es im Protokoll ein Master-Kommando mit dem der Master (in dem Fall mein PC-Update-Tool) dem Device per IO-Link sagen kann: "Mache jetzt sofort einen Reset [und implizit: und springe somit logischerweise wieder in den Bootloader]". Wenn ich das Kommando empfange dann schalte ich alle Interrupts ab, biege die Vektortabelle wieder zurück auf 0x00000000 (könnt ich mir wahrscheinlich sogar sparen) und mache dann einen NVIC_SystemReset(). Danach hat mein PC-Tool etwa 200ms Zeit dem Bootloader Hallo zu sagen. Wenn das unterbleibt springt er automatisch wieder in die Anwendung und die Anwendung startet neu.
:
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.