Ich habe hier einen E-Bike-Controller, den ich gern über UART flashen würde. Wäre prinzipiell kein Problem, leider hat der Hersteller den Boot0 Pin nicht auf einen Header gelegt und die Platine komplett vergossen. Also möchte ich einen eigenen Bootloader auf die Startadresse legen und mein eigentliches Programm an eine höhere Adresse. Dazu gibt es einige Beispielprojekte, ich habe dieses auf den STM32F031C6 portiert: https://github.com/ferenc-nemeth/stm32-bootloader#references Das Blöde ist, der Bootloader frisst alleine schon knapp 8kB und der C6 hat nur 32, so daß die Luft für das eigentliche Programm knapp wird. Kennt jemand einen geeigneten Bootloader, der weniger Speicher frisst? Gruß hochsitzcola
Da ist doch schon ein UART Bootloader eingebaut, man muss ihn "nur" starten. Dein Bootloader müsste nur entscheiden, was gestartet werden soll, Hauptprogramm oder integrierter Bootloader. Das darf maximal 42 Byte kosten. Wenn der NRST Pin raus geführt ist, kann dein Bootloader das RCC_CSR abfragen. Wenn PIN_RSTF nicht gesetzt ist, wird das Hauptprogramm gestartet, sonst der UART Bootloader. Ohne Reset-Pin muss man irgendwas anderes abfragen, aber das Prinzip bleibt gleich. Obwohl so ein Programm nur ein paar Zeilen hat, findet man vor allem viele misslungene Versuche. Die BootLoaderUniversalAnsprungFunktion() hat auch einige Anläufe gebraucht, aber sie hat am Ende funktioniert: Beitrag "Re: STM32L031K6 Sprung in Bootloader aus Applikation funktioniert nicht"
Da der integrierte Bootloader nicht verwendbar war (UART-Pins anderweitig besetzt) musste ich einen eigenen schreiben, incl. CRC-Berechnung, Software-UART, der nach dem Reset max. 10ms auf ein bestimmtes Muster wartet und sonst in die Applikation springt. Das ging mit etwas Mühe beim G030 in 2kByte, man muss halt das ganze HAL-Zeugs weglassen ...
Bauform B. schrieb: > Die BootLoaderUniversalAnsprungFunktion() > hat auch einige Anläufe gebraucht Prima, auf die Idee, per Software den nativen Bootloader anzuspringen, bin ich gar nicht gekommen, das werde ich ausprobieren! Gruß hochsitzcola
Hm, der STM32F031c6 ist ein ARM Cortex M0 Prozessor, der anscheinend das Remapping nicht beherrscht: [q]Physical remap Once the boot mode is selected, the application software can modify the memory accessible in the code area. This modification is performed by programming the MEM_MODE bits in the SYSCFG configuration register 1 (SYSCFG_CFGR1). Unlike Cortex® M3 and M4, the M0 CPU does not support the vector table relocation. For application code which is located in a different address than 0x0800 0000, some additional code must be added in order to be able to serve the application interrupts. A solution is to relocate by software the vector table to the internal SRAM: • Copy the vector table from the flash (mapped at the base of the application load address) to the base address of the SRAM at 0x2000 0000. • Remap SRAM at address 0x0000 0000, using SYSCFG configuration register 1. • Then once an interrupt occurs, the Cortex®-M0 processor fetches the interrupt handler start address from the relocated vector table in SRAM, then it jumps to execute the interrupt handler located in the flash. [/q] Prinzipiell steht da ja, was man machen muß, für mich sind das allerdings bisher böhmische Dörfer, da werde ich mich wohl tiefer reinknien müssen. https://community.st.com/t5/stm32-mcus-embedded-software/interrupt-vector-table-relocation-on-cortex-m0/td-p/483434 Gruß hochsitzcola
:
Bearbeitet durch User
Hochsitz C. schrieb: > Dazu gibt es einige Beispielprojekte, ich habe dieses auf > den STM32F031C6 portiert: > https://github.com/ferenc-nemeth/stm32-bootloader#references Wie weit bist du denn mit der Portierung? Im Original wird doch auch das VTOR benutzt? Die Kopie im RAM ist für die Hardware oder auf Assembler-Ebene kein Problem, aber wie sieht das Linker Script dafür aus??? Welchen Compiler bzw. welche IDE benutzt du für das Hauptprogramm? Ich glaube, es wird einfacher, wenn es nur ein Programm gibt. Dann liegt die Vectortable ganz normal im Flash auf 0. Das normale Hauptprogramm entscheidet dann, ob es selbst starten soll oder ob es zum eingebauten UART-Bootloader springt. Diese Entscheidung könnte theoretisch ein Menüpunkt in der normalen Benutzeroberfläche sein. Aber ich würde auf jeden Fall den NRST-Pin o.ä. abfragen. Wenn der Code dafür erstmal funktioniert, sollte der Mechanismus doch genauso unkaputtbar sein wie ein getrennter Bootloader. Es sind ja nur wenige Zeilen im crt0 aka reset_handler aka startup_xxx.s.
Ich habe jetzt viel gelesen, leider funktioniert es nicht :-( Es stolpern wohl regelmäßig Verwender der STM32F0-Prozessoren über dieses Problem: Zum Beispiel hier: https://community.st.com/t5/stm32-mcus-products/stm32f072-boot-to-random-address-without-vtor/td-p/579357 Ich habe versucht die vector Tabelle an die Adresse 0x20000000 zu schreiben:
1 | __IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable"))); |
2 | ...
|
3 | |
4 | void __attribute__ ((noreturn))BootLoaderUniversalAnsprungFunktion(void) // ™pegel |
5 | {
|
6 | |
7 | |
8 | |
9 | for(i = 0; i < 48; i++) |
10 | {
|
11 | VectorTable[i] = *(__IO uint32_t*)(0x08000000 + (i<<2)); |
12 | }
|
13 | RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; //Takt aktivieren |
14 | SYSCFG->CFGR1 &= ~SYSCFG_CFGR1_MEM_MODE_1; //Bit löschen |
15 | SYSCFG->CFGR1 |= SYSCFG_CFGR1_MEM_MODE_0; //System Memory auf Adresse 0 remappen |
16 | // //SysTick zurücksetzen, wird im Bootloader benötigt
|
17 | SysTick->CTRL = 0; |
18 | SysTick->LOAD = 0; |
19 | SysTick->VAL = 0; |
20 | |
21 | |
22 | __asm__ volatile ( |
23 | " movs r0, #0\n" // Auf 0x0 befindet sich jetzt system memory |
24 | " ldr r1, [r0, #4]\n" // Startadresse des Bootloaders |
25 | " ldr r0, [r0, #0]\n" // sein initial Stackpointer |
26 | " msr msp, r0\n" // |
27 | " mov pc, r1\n" // dies ist ein jump aka branch |
28 | );
|
29 | |
30 | while(1); |
31 | }
|
Geht leider nicht :-( Ich arbeite mit der Cube IDE. Ich konnte nicht mal herausfinden wo .RAMVectorTable definiert ist, aber er kennt es anscheinend.. Irgendwelche Ideen? Gruß hochsitzcola
Hochsitz C. schrieb:
1 | SYSCFG->CFGR1 &= ~SYSCFG_CFGR1_MEM_MODE_1; //Bit löschen |
2 | SYSCFG->CFGR1 |= SYSCFG_CFGR1_MEM_MODE_0; //System Memory auf Adresse 0 remappen |
Das ist die Einstellung für System Memory, also für den internen Bootloader, Wenn du den starten willst, musst du nichts kopieren. Es geht auch garnicht, weil ab 0 Flash ist (eben System Memory). Für den Bootloader braucht man auch kein VTOR. Für RAM ab 0 müssten beide CFGR Bits gesetzt sein. Aber dazu passt die Flash-Adresse der Kopie nicht. 0x08000000 wäre ja dein Bootloader. Was hast du jetzt genau vor? > Ich arbeite mit der Cube IDE. Ich konnte nicht mal herausfinden wo > .RAMVectorTable definiert ist, aber er kennt es anscheinend.. Nachdem der Name nur für die section gebraucht wird, muss er den nicht kennen. Der Linker legt einfach eine section mit dem Namen an.
Bauform B. schrieb: > Das normale Hauptprogramm > entscheidet dann, ob es selbst starten soll oder ob es zum eingebauten > UART-Bootloader springt. Bauform B. schrieb: > Was hast du jetzt genau vor? Ich möchte einfach nur auf Befehl in den nativen Bootloader springen, damit ich mit dem STM32CubeProgrammer über UART die Firmware updaten kann. Der Befehl kann zum Beispiel ein gezogener Bremhebel (GPIO Pin wird auf 0 gezogen) beim Einschalten sein. Kann ich dann nicht einfach an die Bootloaderadresse 0x1FFFEC00 springen?! https://www.st.com/resource/en/application_note/an2606-stm32-microcontroller-system-memory-boot-mode-stmicroelectronics.pdf Gruß hochsitzcola
:
Bearbeitet durch User
Hochsitz C. schrieb: > Ich möchte einfach nur auf Befehl in den nativen Bootloader springen, Aus dem normalen Hauptprogramm heraus? Das auf 0x08000000 beginnt? Dann befindet sich die Vectortable ja automatisch auf der richtigen Adresse und es funktioniert ohne VTOR und du musst nichts kopieren. > Kann ich dann nicht einfach an die Bootloaderadresse 0x1FFFEC00 > springen?! Du musst nicht einmal die genaue Adresse kennen, die steht ja im Flash (System Memory) und das wird mit dem SYSCFG.CFGR nach 0 umgeschaltet. Danach steht die Adresse für den Sprung auf 0x00000004. Das kleine Assemblerprogramm liest die und springt zum Bootloader.
Bauform B. schrieb: > Das kleine > Assemblerprogramm liest die und springt zum Bootloader. Hm, funktioniert aber nicht. Wenn ich das
1 | SysTick->CTRL = 0; |
2 | SysTick->LOAD = 0; |
3 | SysTick->VAL = 0; |
weglasse, bootet der Prozessor sofort neu in das normale Programm. Mit den drei Zeilen stoppt zwar die "normale" UART Kommunikation, aber CubeProgrammer kann sich trotzdem nicht mit dem Prozessor verbinden: > 06:44:29 : Serial Port COM6 is successfully opened. > 06:44:29 : Port configuration: parity = even, baudrate = 115200, data-bit= 8, stop-bit = 1.0, flow-control = off > 06:44:31 : Timeout error occured while waiting for acknowledgement. > 06:44:31 : Error: Activating device: KO. Please, verify the boot mode configuration and check the serial port configuration. Reset your device then try again... Gruß hochsitzcola
:
Bearbeitet durch User
Schön langsam brauchen wir jemand, der sich mit Cube auskennt... Hochsitz C. schrieb: > bootet der Prozessor sofort neu in das normale Programm. Immerhin, es könnte schlimmer sein, vielleicht fehlt nur eine kleine Kleinigkeit. Aber auch dafür wäre es seht hilfreich, wenn wir hier dein aktuelles Programm anschauen könnten. Besonders interessant ist natürlich deine Datei mit dem Assemblertext, und main, und die startup Datei. In dem github-Projekt heißt die startup/startup_stm32f100xb.s; weiß jemand, wo Cube den entsprechenden Quelltext versteckt? Wenn du die nicht findest: die ELF-Datei, die du zum Flashen benutzt hast, wäre ein guter Ersatz.
Hi, ich habe das ganze für einen STM32F072 umgesetzt, dazu hier ein paar Code-Schnipsel, ich hoffe sie helfen weiter. Für die Vektortabelle muss man im Linkerskript (z.B. STM32F072C8TX.ld im CUBE-Projektverzeichnis) eine zusätzliche Section am Anfang des RAM anlegen. Die muss die erste RAM-Section sein, also vor der .data-Section: Das muss sowohl im (Boot)Loader als auch in der eigentlichen Applikation gemacht werden, damit die Vektortabelle dort jeweils an der richtigen Stelle liegt.
1 | /* zus?tzliche Section f?r Vektortabelle im RAM: */
|
2 | |
3 | .isr_vector_ram (NOLOAD): |
4 | {
|
5 | . = ALIGN(4); |
6 | KEEP(*(.isr_vector_ram)) /* Startup code */ |
7 | . = ALIGN(4); |
8 | } >RAM |
Die Vektortabelle dann folgendermaßen im RAM definieren (main.c):
1 | #define VECTOR_TABLE_SRAM
|
2 | #define VECTOR_TABLE_LENGTH 48 // Länge der Interrupt-Vektortabelle, siehe Startup-Code.
|
3 | #define ST_BOOTLOADER_STARTADRESSE 0x1FFFC800 // siehe Datenblatt
|
4 | #define BOOTLOADER_FLASH_SIZE_KB 12 // für Bootloader reservierter Speicher. Muss ein Vielfaches der Pagegröße sein!
|
5 | |
6 | #define VECTOR_TABLE_ARRAY_SIZE (VECTOR_TABLE_LENGTH+1) // hinter Vektortabelle noch 1 Platz mehr für Variable für Bootloader-Request
|
7 | |
8 | // Muss mit Angaben im Linkerskript der Applikation übereinstimmen. Linkerskript des Bootloaders idealerweise auch anpassen, damit es keine Überlappung geben kann.
|
9 | #define APPLIKATION_STARTADRESSE (0x08000000 + BOOTLOADER_FLASH_SIZE_KB * 1024) // Platz für Bootloader freihalten
|
10 | |
11 | #ifdef VECTOR_TABLE_SRAM
|
12 | // Die Interrupt-Vektortabelle im RAM. Dort müssen nachher die Vektoren der Applikation hinkopiert werden
|
13 | volatile uint32_t VectorTable[VECTOR_TABLE_ARRAY_SIZE] __attribute__((section(".isr_vector_ram"))) = {0}; // |
14 | #endif
|
Ich habe hinter der Vektortabelle noch einen zusätzlichen Eintrag freigelassen, damit kann das Hauptprogramm dort eine Magic Number reinschreiben und anschließend einen RESET auslösen. Der Bootloader kann dann auf diese Nummer prüfen und ggf. den ST-Bootloader starten. So kann der Bootloader indirekt aus dem Hauptprogramm gestartet werden
1 | static uint32_t check_backup_reg_bootloader() |
2 | {
|
3 | uint32_t ret = 0; |
4 | uint32_t bkup_reg; |
5 | |
6 | // reservierte RAM-Variable laden
|
7 | bkup_reg = VectorTable[VECTOR_TABLE_ARRAY_SIZE-1]; |
8 | |
9 | if (bkup_reg == MAGIC_NUMBER_START_ST_BOOTLOADER) // ST-Bootloader starten, vorher aber Nummber löschen, sonst Endlosschleife. |
10 | {
|
11 | ret = 1; |
12 | }
|
13 | else if (bkup_reg == MAGIC_NUMBER_START_CUSTOM_BOOTLOADER) // custom Bootloader bleibt aktiv, Timeout deaktivieren |
14 | {
|
15 | ret = 2; |
16 | }
|
17 | else if (bkup_reg == MAGIC_NUMBER_START_APP) |
18 | {
|
19 | ret = 3; |
20 | }
|
21 | |
22 | VectorTable[VECTOR_TABLE_ARRAY_SIZE-1] = 0; // Nummer löschen |
23 | __DSB(); // memory barrier, damit Schreibzugriff garantiert zu Ende ist |
24 | |
25 | return ret; |
26 | }
|
Das Anspringen von ST-Bootloader oder Hauptprogramm geht folgendermaßen:
1 | int main(void) |
2 | {
|
3 | uint32_t check; |
4 | check = check_backup_reg_bootloader(); // Backupregister prüfen, ggf. Bootloader starten |
5 | if (check == 1) |
6 | {
|
7 | // ST-Bootloader
|
8 | start_app_or_bootloader(0); |
9 | }
|
10 | else if (check == 2) |
11 | {
|
12 | // Applikation
|
13 | start_app_or_bootloader(1); |
14 | }
|
15 | |
16 | while(1) |
17 | {
|
18 | }
|
19 | }
|
20 | |
21 | // 0 = Bootloader, 1 = Applikation
|
22 | static void start_app_or_bootloader(uint32_t mode) |
23 | {
|
24 | void (*JumpAddress)(void); |
25 | |
26 | // Startadresse der Applikation bzw des Bootloaders: dort beginnt die Vektortabelle
|
27 | volatile uint32_t addr; |
28 | if (mode == 0) |
29 | {
|
30 | addr = ST_BOOTLOADER_STARTADRESSE; // Adresse des SystemFLASH Bootloaders |
31 | }
|
32 | else
|
33 | {
|
34 | addr = APPLIKATION_STARTADRESSE; |
35 | }
|
36 | |
37 | if (mode == 0) // Bootloader --> System Memory auf 0 remappen |
38 | {
|
39 | __DSB(); // memory access barrier |
40 | __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); // remap system memory to address 0: |
41 | __DSB(); |
42 | }
|
43 | else // Applikation: Vektortabelle der Applikation dorthin kopieren und dann SRAM auf 0 remappen |
44 | {
|
45 | #ifdef VECTOR_TABLE_SRAM
|
46 | // Vektortabelle ins RAM kopieren
|
47 | uint32_t* app_ptr = (uint32_t*)((uint32_t)APPLIKATION_STARTADRESSE); |
48 | for (uint32_t i=0; i<VECTOR_TABLE_LENGTH; i++) |
49 | {
|
50 | VectorTable[i] = app_ptr[i]; |
51 | }
|
52 | __DSB(); // memory access barrier |
53 | __HAL_SYSCFG_REMAPMEMORY_SRAM(); // remap SRAM to address 0: |
54 | __DSB(); |
55 | #else
|
56 | // TODO: VTOR setzen für Prozessoren die es haben
|
57 | #error "VTOR noch nicht implementiert!"
|
58 | #endif
|
59 | }
|
60 | |
61 | // Sprungadresse ist zweiter Eintrag der Vektortabelle (erster Eintrag ist Stackpointer)
|
62 | // Use address with 4 bytes offset which specifies jump location where program starts
|
63 | JumpAddress = (void (*)(void)) (*((uint32_t *)(addr + 4))); |
64 | |
65 | /**
|
66 | * Set main stack pointer.
|
67 | * This step must be done last otherwise local variables in this function
|
68 | * don't have proper value since stack pointer is located on different position
|
69 | *
|
70 | * Set direct address location which specifies stack pointer in SRAM location
|
71 | */
|
72 | __set_MSP(*(uint32_t *)addr); |
73 | __DSB(); |
74 | |
75 | /**
|
76 | * Call our function to jump to set location
|
77 | * This will start system memory execution
|
78 | */
|
79 | JumpAddress(); |
80 | |
81 | // sollte hier nie ankommen
|
82 | while(1) HAL_NVIC_SystemReset(); |
83 | }
|
Bauform B. schrieb: > Aber auch dafür wäre es seht hilfreich, wenn wir hier dein aktuelles > Programm anschauen könnten. Das Projekt findest du hier: https://github.com/stancecoke/Lishui9FET Allerdings habe ich die nicht funktionierende Funktion noch nicht commited. Kann ich heute Abend mal machen und auch die elf Datei mit hochladen. @emigraen: das muss ich erst mal sacken lassen 😁 Ich bin gestern über ähnliche Tipps gestolpert, aber mir fehlt da offensichtlich eine Menge Hintergrundwissen. Ich will ja gar keinen custom Bootloader verwenden, wenn es auch mit dem nativen geht... Gruß hochsitzcola
:
Bearbeitet durch User
Hochsitz C. schrieb: > Ich will ja gar keinen custom Bootloader verwenden, > wenn es auch mit dem nativen geht... Musst du auch nicht, dann vereinfacht es die Sache deutlich. Dann brauchst du die Vektortabelle im RAM garnicht, sondern musst einfach direkt aus deinem Hauptprogramm meine Beispielfunktion aufrufen:
1 | start_app_or_bootloader(0); |
Die entsprechenden Code-Teile zum Umkopieren der Tabelle kannst du dort dann rauslöschen und das Linkerskript muss dann auch nicht angepasst werden. Der Vorteil an einem kleinen Custom-Bootloader wäre, dass er prüfen könnte ob überhaupt eine Applikation geflasht ist und dann im Notfall immer den ST-Bootloader anspringt. (Er braucht gar keine eigene Flash-Funktion haben, sondern springt nur weiter entweder zur Applikation oder zum ST-Bootloader.)
Chris R. schrieb: > Die entsprechenden Code-Teile zum Umkopieren der Tabelle kannst du dort > dann rauslöschen und das Linkerskript muss dann auch nicht angepasst > werden Das habe ich jetzt auch gemacht, natürlich die Bootloaderadresse angepasst, aber das geht auch nicht :-( Wenn ich im Debugmode die Routine anspringe kommt diese Meldung: >Break at address "0x2050604" with no debug information available, or outside of program code. Ich habe mit den verschiedensten Kombinationen der vorgeschlagenen Lösungen rum gespielt, darum nicht über die vielen auskommentierten Zeilen wundern. https://github.com/stancecoke/Lishui9FET/commit/541ecbb84eb2d1370c0b425124a7ff16c917790c Die elf-Datei liegt auch im Repo: https://github.com/stancecoke/Lishui9FET/blob/main/Documentation/Lishui9FET.elf Gruß hochsitzcola
Bauform B. schrieb: > Ich glaube, es wird einfacher, wenn es nur ein Programm gibt. Dann liegt > die Vectortable ganz normal im Flash auf 0. Das normale Hauptprogramm > entscheidet dann, ob es selbst starten soll oder ob es zum eingebauten > UART-Bootloader springt. Das ist genau das Gegenteil von einem guten Bootloader. Von so einem sollte das zu ladende "Hauptprogramm" überhaupt nichts wissen müssen (allerhöchstens, dass es etwas weniger Flash zur Verfügung hat als es "normal" für das Target ist, damit beim Linken eine entsprechende Fehlermeldung geworfen werden kann). Und wenn es nötig ist, das aus dem "Hauptprogramm" den Bootloader zu starten, dann sollte es reichen, den µC einfach von dort aus zu zu resetten. Wenn die Architektur keine Softwarelösung dafür hergibt (eher die Ausnahme), dann halt notfalls über einen GPIO an RESET (mit entsprechender Hilfsschaltung dazwischen, sprich: Monoflop).
Hochsitz C. schrieb: > Das habe ich jetzt auch gemacht, natürlich die Bootloaderadresse > angepasst, aber das geht auch nicht :-( Es fehlt (in deinem auskommentierten Code) mindestens das Remapping des System Memory auf Adresse 0 wie in meinem Code oben geschrieben:
1 | __DSB(); // memory access barrier |
2 | __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); // remap system memory to address 0: |
3 | __DSB(); |
Ohne das funktioniert es nicht. Es kann auch potenziell problematisch sein (sollte mit dem Fehler wsl. nichts zu tun haben), wenn Teile der HW initialisiert sind wenn man zum ST-Bootloader springt. Man weiß nicht, wie genau er initialisiert, also sollte vorher alles zurückgesetzt sein. Am einfachsten lässt sich das sicherstellen, wenn man vor dem Init von Hardware zum Bootloader springt. Ich mache das so, dass ich eben die Magic Number nach der Vektortabelle ganz am Anfang der main() prüfe und ggf. springe, noch bevor Takt usw. initialisiert wird. Dann kann man nichts vergessen zu de-initialisieren. Versuch mal testweise, ganz am Anfang der main() zu springen, um solche Probleme auszuschließen. Hochsitz C. schrieb: > Break at address "0x2050604" with no debug information available, or > outside of > program code. 0x2050604 ist wohl tatsächlich ungültiger Speicherbereich, siehe Memory Map im Datenblatt. Also springst du irgendwo falsch hin. Mit Assembler kann ich leider nicht weiterhelfen, aber im C-Code kannst du ja die Sprungadresse (Variable JumpAddress) im Debugger anschauen, bevor der Sprung ausgeführt wird. Dass nach dem Sprung das Debuggen nicht mehr geht, sollte normal sein, da dann ja der ST-Bootloader ausgeführt wird. https://www.st.com/resource/en/reference_manual/rm0091-stm32f0x1stm32f0x2stm32f0x8-advanced-armbased-32bit-mcus-stmicroelectronics.pdf Nachtrag: Denkbar wäre auch, dass noch Interrupts aktiviert sind, wenn du nicht alles sauber deinitialisierst. Wenn in der Vektortabelle des ST-Bootloaders dann kein gültiger Handler eingetragen ist, springt er evtl. in ungültigen Bereich. Also noch ein Argument, möglichst früh im Programm dorthin zu springen. (Oder einmal den Umweg über RESET zu gehen.)
:
Bearbeitet durch User
Chris R. schrieb: > du ja die Sprungadresse (Variable JumpAddress) im Debugger anschauen Die Adresse passt und das remap system memory to address 0 hatte ich auch gemacht. Interrupts deaktivieren auch. Direkt am Anfang der main() auch nicht. Ich glaub ich brauch erst mal ne Pause :-) Vielleicht probiere ich dann erst mal den BOOT0 PIN auf GND zu legen, ob der STCube Programmer dann die Verbindung hinbekommt... Gruß hochsitzcola
:
Bearbeitet durch User
An den Boot0 Pin ist nicht ranzukommen :-( Gibt es eigentlich einen Timeout, wie lange der Bootloader auf den Programmer wartet? Und was hat es mit dem Magic Number auf sich, von dem immer die Rede ist?! Gruß hochsitzcola
Vielleicht bringt mich das auf die richtige Spur?! https://community.st.com/t5/stm32-mcus/how-to-jump-to-system-bootloader-from-application-code-on-stm32/ta-p/49424 Lässt mich dieser empty-check ggf. stolpern: >except for the STM32F0 and some STM32L0 that have an empty check mechanism in place. Im reference manual steht: >Empty check On STM32F04x and STM32F09x devices only, internal empty check flag is implemented to allow easy programming of virgin devices by the boot loader Damit sollte der STM32F031C6 diesen empty check nicht haben?! Edit: ich habe das o.g. How-To so eingebaut, siehe letztes commit, wenn ich jetzt im Debug-Mode den Prozessor anhalte, tummelt er sich irgendwo im Adressbereich 0x1fffed72, 0x1fffed68, 0x1fffed7c, sollte also eigentlich passen. Aber warum reagiert er nicht auf den Verbindungsversuch vom Cube Programmer?!
:
Bearbeitet durch User
Hochsitz C. schrieb: > Vielleicht bringt mich das auf die richtige Spur?! Da geht's doch darum, wie man den Bootloader aus dem laufenden Hauptprogramm heraus aufruft. Das meiste davon ist überflüssig, wenn das Hauptprogramm garnicht läuft. Also wenn du diese Abfrage noch vor main() einbaust: Hochsitz C. schrieb: > Der Befehl kann zum Beispiel ein gezogener Bremhebel (GPIO Pin wird auf > 0 gezogen) beim Einschalten sein. Hochsitz C. schrieb: > Gibt es eigentlich einen Timeout, wie lange der Bootloader auf den > Programmer wartet? Der eingebaute wartet beliebig lange, bis zum nächsten Reset. > Und was hat es mit dem Magic Number auf sich, von dem > immer die Rede ist?! Der entscheidende Punkt: beim Start des Bootloaders müssen die Hardware-Register so aussehen, wie nach einem Reset. Dafür gibt es drei Möglichkeiten: a) man startet den Bootloader so früh wie möglich, bevor irgendwelche Hardware initialisiert wird b) man setzt alle einzeln zurück c) das Hauptprogramm erzeugt selbst einen Hardware-Reset per AIRCR. Nachdem das Programm wieder startet, muss es erkennen, ob das ein normaler Reset war oder der selbst erzeugte. Dafür kann man eine Magic Number ins RAM oder in ein Backup-Register schreiben. Wenn da die magische Bitkombination steht, wird zum Bootloader gesprungen, sonst zum Hauptprogramm. Man kann stattdessen auch das RCC.CSR Register auswerten. Das ist genau dafür da, um verschiedene Reset-Auslöser zu unterscheiden.
Bauform B. schrieb: > Also wenn du diese Abfrage noch vor main() > einbaust: habe ich ja auch probiert, vor jeder Hardwareinitialisierung zu springen: https://github.com/stancecoke/Lishui9FET/blob/92edff1ca3bb2cc05348b4964c219251c542f4e0/Core/Src/main.c#L163 der Prozessor tummelt sich ja anscheinend auch im richtigen Adressbereich. Nur er mag sich nicht mit dem Cube Programmer verbinden :-( Gruß hochsitzcola
:
Bearbeitet durch User
Hm, habe noch mal viel gelesen und probiert, hat immer noch nicht geklappt. Ich werde das Ganze als nächste an einem Bluepill-Board ausprobieren um zu schauen, ob es ggf. an einer Eigenart des STM32F031 liegt... Gruß hochsitzcola
Aaaahhh, ich bin so ein Depp! Die Hardware, die ich nutze, hat UART1 auf PB6/PB7 remapped. Dann kann das natürlich nicht gehen mit dem nativen Bootloader. :-) Gruß hochsitzcola
:
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.