Hallo allerseits,
ich sitzt hier gerade vor einer STM32 Black Pill, bestückt mit einem
STM32F411CE.
Auf diesem läuft meine leere Testapplikation, die nur auf die Eingabe
durch einen Button wartet.
Sinn und Zweck der Übung ist es, ein Firmware Update via USB durchführen
zu können (z.B mit dem STMCubeProgrammer) ohne auf dem PCB den BOOT0
Jumper zu ändern oder die entsprechende Tasten zu drücken.
Wenn ich jetzt den UserButton an A0 drücke (im CODE = "KEY", so sollte
der STM32 in den Bootloader springen, ohne das ich physisch etwas an dem
BOOT0 Pin ändere.
Tut er aber nicht. Laut ST AN2606 ist die Adresse 0x1FFF0000, zu der man
springen soll.
Das Beispiel habe ich hier gemobst, der Kollege scheint bei ST zu
arbeiten.
https://stm32f4-discovery.net/2017/04/tutorial-jump-system-memory-software-stm32/
1
voidJumpToBootloader(void){
2
void(*SysMemBootJump)(void);
3
4
/**
5
* Step: Set system memory address.
6
*
7
* For STM32F429, system memory is on 0x1FFF 0000
8
* For other families, check AN2606 document table 110 with descriptions of memory addresses
9
*/
10
volatileuint32_taddr=0x1FFF0000;
11
12
/**
13
* Step: Disable RCC, set it to default (after reset) settings
14
* Internal clock, no PLL, etc.
15
*/
16
HAL_RCC_DeInit();
17
18
/**
19
* Step: Disable systick timer and reset it to default values
20
*/
21
SysTick->CTRL=0;
22
SysTick->LOAD=0;
23
SysTick->VAL=0;
24
25
/**
26
* Step: Disable all interrupts
27
*/
28
__disable_irq();
29
30
/**
31
* Step: Remap system memory to address 0x0000 0000 in address space
32
* For each family registers may be different.
33
* Check reference manual for each family.
34
*
35
* For STM32F4xx, MEMRMP register in SYSCFG is used (bits[1:0])
36
* For STM32F0xx, CFGR1 register in SYSCFG is used (bits[1:0])
37
* For others, check family reference manual
38
*/
39
40
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();//Call HAL macro to do this for you
41
42
/**
43
* Step: Set jump memory location for system memory
44
* Use address with 4 bytes offset which specifies jump location where program starts
* This step must be done last otherwise local variables in this function
51
* don't have proper value since stack pointer is located on different position
52
*
53
* Set direct address location which specifies stack pointer in SRAM location
54
*/
55
__set_MSP(*(uint32_t*)addr);
56
57
/**
58
* Step: Actually call our function to jump to set location
59
* This will start system memory execution
60
*/
61
SysMemBootJump();
62
63
/**
64
* Step: Connect USB<->UART converter to dedicated USART pins and test
65
* and test with bootloader works with STM32 Flash Loader Demonstrator software
66
*/
67
}
Hier noch der Aufruf aus der while Schleife raus, testweise via
UserButton A0, in der realen Applikation komtm der Sprungbefehl via USB.
Der Sprung in die Funktion "JumpToBootloaer" klappt, nur der Bootloader
wird nicht aktiviert.
1
/* USER CODE BEGIN WHILE */
2
while(1)
3
{
4
/* USER CODE END WHILE */
5
6
/* USER CODE BEGIN 3 */
7
8
HAL_Delay(500);
9
if(HAL_GPIO_ReadPin(KEY_GPIO_Port,KEY_Pin)==0)
10
{
11
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,RESET);
12
JumpToBootloader();
13
}
14
else
15
{
16
HAL_GPIO_WritePin(LED_GPIO_Port,LED_Pin,SET);
17
}
18
}
19
/* USER CODE END 3 */
Was mache ich falsch, was übersehe ich?
Viele Grüße
pegel schrieb:> Und funktioniert.
Du kannst dann mit dem CubeProgrammer via USB ein Update einspielen?
Das wäre ja genau das, was ich will.
Habe den Code getestet, den du verlinkt hast, leider ohne Erflog :(.
Aber dafür habe ich das hier gefunden, es ist eine Anfrage an ST, die
sich genau mit dem Problem beschäftigt und die Antwort ist nicht schön:
I can reproduce your issue on a DiscoveryF4 that uses STM32F407VGT that
has same bootloader as STM32F405.
WhatI can see is that, when jumping to bootloader from application, the
clocks are not setup properly. The RCC is not actually using the HSE. As
USB cannot work with HSI, the behaviour we see is normal.
Unfortunately, as supporter I don't have access to the bootloader code.
I need to ask to our R&D people. I will now send them the description of
this issue and ask for workaround.
Now, I must warn you that there is a risk that there is no possible
solution.
I will come back to you as soon as I get some feedback,
So we will wait and see...
Da muss ich mir wohl was anderes einfallen lassen, aber danke für deine
Unterstützung!
VG
Jumper schrieb:> Du kannst dann mit dem CubeProgrammer via USB ein Update einspielen?
Ja, kann ich.
Dein F411 BlackPill hat doch auch 25MHz HSE, oder?
Sollte also auch funktionieren.
Was mir aufgefallen ist, an 0x1FFF0000 steht 0x20002560.
Ich habe MSP auf 0x20010000 gesetzt.
Ich habe noch nie mit dem Bootloader über USB gearbeitet, aber im
Kommentarbereich schreibt Markus Gritsch, dass (entgegen der Aussage von
ST) für den USB-Bootloader Interrupts benötigt werden. Kommentiere mal
die Zeile __disable_irq() aus und versuche es dann noch einmal.
pegel schrieb:> Ist wie deiner, nur vor1 __set_MSP(0x20001000);> steht noch1 __set_PRIMASK(1); // Disable interrupts> 2 __set_PRIMASK(0x20001000); // Set the main stack pointer to its> default value>> Und funktioniert.
__set_PRIMASK(1) macht genau dasselbe wie __disable_irq().In beiden
Fällen wird das PRIMASK-Bit auf 1 gesetzt. Wenn dieses Bit gesetzt ist,
werden alle Interrupts (mit Ausnahme von NMI und HardFault) deaktiviert.
Der Aufruf von __disable_irq() sollte deshalb ausreichen.
Die Zeile __set_PRIMASK(0x20001000) macht für mich keinen Sinn. Das
PRIMASK-Register beinhaltet nur ein einzelnes Bit. Laut dem Kommentar
wird durch diese Zeile der Main Stack Pointer eingestellt, hierfür wird
jedoch __set_MSP benötigt.
Hier mal ein Link zur CMSIS-Dokumentation, wo der Effekt von PRIMASK
beschrieben wird:
https://www.keil.com/pack/doc/CMSIS/Core/html/group__Core__Register__gr.html#ga70b4e1a6c1c86eb913fb9d6e8400156f
Habs grad noch mal probiert mit meiner F411er Black Pill, leider wieder
ohne Erfolg. Ich kann mir auch nicht erklären wieso es bei dir klappt,
da für USB ja HSE benötigt wird, die aber beim RCC_DeInit deaktivert
wird.
Entweder hast du ne super HSI, mit der es auch so geht aber bei mir ist
da nichts zu holen.
Aber auf jeden Fall danke für deine Hilfe!
VG
Hast du es auch mal mit auskommentiertem __disable_irq() versucht? Wie
gesagt, im Kommentarbereich hat es einer hierdurch zum Laufen bekommen.
Wäre einen Versuch wert.