Hi, ich baue derzeit für ein Projekt eine Bootloader Firmware in C für den o.g. Mikrocontroller. Die Bootloader Firmware soll bei jedem Start ausgeführt werden. Ziel der Bootloader Firmware ist es: 1) Checken, ob eine valide Firmwareversion in mindestens einer von zwei Flash-Regionen vorliegt. Sind valide Firmwareversionen vorhanden? Dann lade die neueste Version. Ich möchte hierfür Flash Sektor 8-9(ab 0x08080000) und 10-11(ab 0x080C0000) verwenden. Diese Regionen habe ich bereits im Linkerscript des Bootloaders vermerkt. Hier habe ich noch nicht dran gearbeitet. Meine Idee ist, an festen Positionen im Flash eine Prüfsumme zu hinterlegen, die dann durch Auslesen des Flashs verifiziert werden kann. 2) Firmwareupdate per RS485 Schnittstelle als .Hex File. Ist keine valide FW-Version vorhanden ODER ist ein FW-Update explizit gewünscht, lass dir von einem PC eine neue FW-Version als .Hex File übertragen. Was hierbei bereits funktioniert: Per PC liest das.Hex-File aus, dieses wird Zeile für Zeile übertragen. Die Datenverarbeitung des .Hex-Files funktioniert auch. D.h. ich erhalte entsprechend https://de.wikipedia.org/wiki/Intel_HEX#End_of_File_Record_(Typ_01) Bytecount, Adresse, Typ, Datenfeld und Prüfsumme. Die Verarbeitung des Addressoffsets passt auch. Jede Zeile wird auch bereits per Prüfsumme verifiziert. Im Prinzip schaffe ich es auch, den Flash jetzt ab der angegebenen Adresse Byte pro Byte zu beschreiben. Ich habe mir ein Probeprogramm geschrieben, zu dem der Bootloader nach dem Flashprozess springen soll. Bei dem Compilieren dieses Probeprogrammes habe ich im Linker den ROM - Bereich auf die absolute Adresse 0x08080000 geändert und habe das Vector Table Offset auf 0x00080000 gestellt. ABER: Wie springe ich nach erfolgreichem Flashen zu dem Programm? Muss ich wirklich einfach nur an die gegebene Adresse springen mit irgendeiner Art Jump Befehl?
1 | #define NVIC_VectTab_FLASH 0x90000
|
2 | #define SP_OFFS 0
|
3 | #define RESET_OFFS 4
|
4 | |
5 | void (*user_code_entry)(void); |
6 | register uint32_t MSP __ASM("msp"); |
7 | |
8 | //__DSB();
|
9 | //__ISB();
|
10 | SCB->VTOR = NVIC_VectTab_FLASH; |
11 | user_code_entry = (void (*)(void))(( *((unsigned int *)(NVIC_VectTab_FLASH + RESET_OFFS))) ); |
12 | MSP = *((unsigned int *)(NVIC_VectTab_FLASH + SP_OFFS)); |
13 | //__DSB();
|
14 | //__ISB();
|
15 | user_code_entry(); |
16 | |
17 | while(1); // should never reach this ... |
Hi, ich mach das so:
1 | void Bootloader_JumpToApplication(void) |
2 | {
|
3 | uint32_t JumpAddress = *(__IO uint32_t*)(APP_ADDRESS + 4); // one byte past vector table |
4 | pFunction Jump = (pFunction)JumpAddress; |
5 | |
6 | HAL_RCC_DeInit(); |
7 | HAL_DeInit(); |
8 | |
9 | SysTick->CTRL = 0; |
10 | SysTick->LOAD = 0; |
11 | SysTick->VAL = 0; |
12 | |
13 | #if(SET_VECTOR_TABLE)
|
14 | SCB->VTOR = APP_ADDRESS; |
15 | #endif
|
16 | |
17 | __set_MSP(*(__IO uint32_t*)APP_ADDRESS); |
18 | Jump(); |
19 | }
|
und die APP_ADDRESS
1 | #define APP_ADDRESS (uint32_t)0x08008000
|
Hab ich halt von einem Beispiel abgeschaut ;-)
Random .. schrieb: >
1 | > #define NVIC_VectTab_FLASH 0x90000 |
2 | > #define SP_OFFS 0 |
3 | > #define RESET_OFFS 4 |
4 | >
|
5 | >
|
Danke für die Antwort! D.h. NVIC_VectTab_FLASH wäre bei mir 0x08008000 und dann muss man 1Byte weiterspringen? Was bedeutet SP_OFFS?
Werner P. schrieb: > Hab ich halt von einem Beispiel abgeschaut ;-) Danke, ein solches Beispiel hat mir eben gefehlt! Ich werde es morgen mal ausprobieren. Wo steht eigentlich, dass man 1Byte weiter springen muss, als zur Vector Table?
:
Bearbeitet durch User
Alex K. schrieb: > Werner P. schrieb: > Wo steht eigentlich, dass man 1Byte weiter springen muss, als zur Vector > Table? Kann ich Dir spontan nicht sagen. Ich musste auf die Schnelle einen Bootloader schreiben. Da hab ich das mal so übernommen.
SP = Stack Pointer RESET = Reset Vector Die ersten beiden Einträge in deinem "fertig gelinkten" Image sind der Stack Pointer und der Reset Vector (Einsprungpunkt). Diese werden nach RESET von der CPU automatisch geladen. Willst du jetzt Bootloader und Programm jeweils in sich abgeschlossen linken, kannst du auf dieses zurückgreifen, und den Reset der CPU vom Bootloader aus nachstellen, um deine Firmware zu starten. Der StackPointer wird in das MSP (Main Stack Pointer) geladen. Der ResetVector wird in den Function Pointer geladen, welcher dann später als Funktion ausgeführt wird. Man könnte noch ein __NO_RETURN einfügen. Der Vector Table Offset ist der Start des Images, und wird in das VTOR Register geladen.
Random .. schrieb: > SP = Stack Pointer > RESET = Reset Vector > .... Danke für die Erklärung! Werner P. schrieb: > Hi, > > ich mach das so: Funktioniert tadellos, vielen Dank!
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.