Ich versuche, von meiner Anwendung aus einen Sprung zum STM32F091 USART1-Bootloader zu implementieren.
Ich verwende die folgende Funktion (basierend auf https://community.st.com/thread/40238-stm32l476rg-jump-to-bootloader-from-software ):
void SB_SystemBootloaderJump()
{
typedef void (*pFunction)(void);
pFunction JumpToApplication;
HAL_RCC_DeInit();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/**
* Step: Disable all interrupts
*/
__disable_irq();
/* ARM Cortex-M Programming Guide to Memory Barrier Instructions.*/
__DSB();
// __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH()
// ;
// /* Remap is bot visible at once. Execute some unrelated command! */
// __DSB();
// __ISB();
JumpToApplication = (void (*)(void)) (*((uint32_t *) ((0x1FFFD800 + 4))));
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) 0x1FFFD800);
JumpToApplication();
}
Von APP Note AN2606: Systemspeicheradresse wie im Bild: https://i.imgur.com/nVcgoBg.png
Vom SWD-Dienstprogramm Speicherinhalte im Systemspeicher: https://i.imgur.com/PeepkrX.png
Von Debugger, SP und Reset-Handler als Bild: https://i.imgur.com/PagQng0.png
Programmausführung bis zum Haltepunkt an der Bootloader-Adresse: https://i.imgur.com/koKfObe.png
In Anbetracht: A - Mit einem Jumper zu VCC am BOOT0-Pin kann ich über die STM32 Flash Loader-Demo erfolgreich auf den System-Bootloader zugreifen. Das Gleiche gilt nicht, wenn ich von meiner App zum Bootloader springe. B - Ich verwende eine FTDI FT230x USBxSerial Bridge.
Fragen:
1 - Da ich die absolute Systemspeicheradresse verwende, muss __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH()
. Richtig?
2 - Übersehe ich etwas bei dieser Funktion?
3 - Gibt es eine Zeitüberschreitung zwischen dem Start des Bootloaders und dem Empfang des "0x7F"-Bytes auf USART1?
4 - Wirkt sich das Öffnen/Schließen der seriellen Schnittstelle auf den Bootloader aus? Muss ich die MCU zurücksetzen, wenn ich die serielle Schnittstelle schließe und wieder öffne?
Das Problem war mit dem USART1-Peripheriestatus. Die USART1-Konfigurationsregisterwerte wurden zur Bootloader-Ausführung übertragen, was möglicherweise Probleme für den proprietären Bootloader verursachte. Die Lösung war, USART1 über RCC_APB2RSTR zurückzusetzen.
Die Funktion lautet nun:
void SB_SystemBootloaderJump()
{
typedef void (*pFunction)(void);
pFunction JumpToApplication;
__HAL_RCC_USART1_FORCE_RESET();
HAL_Delay(5);
__HAL_RCC_USART1_RELEASE_RESET();
HAL_Delay(5);
HAL_RCC_DeInit();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
/**
* Step: Disable all interrupts
*/
__disable_irq();
/* ARM Cortex-M Programming Guide to Memory Barrier Instructions.*/
__DSB();
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH()
;
/* Remap is bot visible at once. Execute some unrelated command! */
__DSB();
__ISB();
JumpToApplication = (void (*)(void)) (*((uint32_t *) ((0x1FFFD800 + 4))));
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) 0x1FFFD800);
JumpToApplication();
}
Da ich die absolute Systemspeicheradresse verwende, muss __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH() nicht verwendet werden.
... wenn Ihr Programm definitiv nicht auf den "low" Speicher zugreift. Vergessen Sie nicht, die Interrupt-Tabelle neu zuzuordnen.
Wirkt sich das Öffnen/Schließen der seriellen Schnittstelle auf den Bootloader aus? Muss ich die MCU zurücksetzen, wenn ich die serielle Schnittstelle schließe und wieder öffne?
Wenn Sie wirklich die USART-Pins verwenden (nicht die serielle USB-Emulation): Das Öffnen/Schließen des seriellen Ports sollte nur die Steuerleitungen betreffen, nicht die Datenleitungen. In den meisten Fällen werden die Steuerleitungen nicht einmal mit der CPU verbunden.
"__enable_irq();" einfügen nach Ihrem "__ISB();". Es sollte gut funktionieren.
MarcelNubi