Ich versuche, es so zu machen, dass mein STM32L011 vom Benutzercode zum ST-Bootloader springen kann, mit dem Flash über USART2 neu programmiert werden kann. Dies ist hypothetisch dieselbe Frage wie STM32F091 Jump to Bootloader from application , aber ich habe kein Glück mit den Korrekturen zur Deaktivierung von Peripheriegeräten aus dieser Frage. ST hat ihre Foren neu gestaltet und alle alten Links zu Threads zerstört, also habe ich eine schreckliche Zeit damit, Hinweise auf andere mögliche Probleme zu finden, und ich bin ziemlich ratlos, wo ich als nächstes suchen soll.
Meine Sprungfunktion ist wie folgt (geändert von der obigen Frage für meine Anwendung und die Verwendung der ST LL-Bibliotheken). Mein Anwendungscode verwendet den LPUART auf PA2/PA3, der dann von USART2 für den Bootloader verwendet werden sollte. Auf dem LPUART wird ein Befehl im Benutzeranwendungscode empfangen, der die Sprungfunktion aufruft. Der Anwendungscode bestätigt den Befehl ordnungsgemäß gemäß meinem seriellen Protokoll, aber dann reagiert der USART-Bootloader nicht auf Flasher-Dienstprogramme. Sie senden das anfängliche 0x7F-Byte per AN2606, aber der Bootloader sendet das ACK nicht zurück.
#define STM32L01_SYSTEM_MEMORY 0x1FF00000
void jump_to_bootloader()
{
// Disable global interrupts
__disable_irq();
// Disable interrupt requests from peripherals
NVIC_DisableIRQ(SysTick_IRQn);
NVIC_DisableIRQ(LPUART1_IRQn);
NVIC_DisableIRQ(EXTI0_1_IRQn);
NVIC_DisableIRQ(DMA1_Channel2_3_IRQn);
NVIC_DisableIRQ(I2C1_IRQn);
typedef void (*pFunction)(void);
volatile uint32_t addr = STM32L01_SYSTEM_MEMORY;
uint32_t jumpaddr = *(__IO uint32_t*) (STM32L01_SYSTEM_MEMORY + 4);
pFunction jump_to_application;
// Application-specific shutdown of HSE and switch to MSI
clock_HSE_to_MSI();
// Reset ALL peripherals
LL_AHB1_GRP1_ForceReset(LL_AHB1_GRP1_PERIPH_ALL);
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_ALL);
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_ALL);
LL_mDelay(5);
LL_AHB1_GRP1_ReleaseReset(LL_AHB1_GRP1_PERIPH_ALL);
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_ALL);
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_ALL);
LL_mDelay(5);
// Fully reset RCC to power-up state
LL_RCC_DeInit();
// Zero out SysTick
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
// Remap memory to system flash
SYSCFG->CFGR1 = 0x01;
jump_to_application = (pFunction)jumpaddr;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) addr);
jump_to_application();
}
Diese Probleme habe ich ausgeschlossen:
Arbeitstheorien:
Vor __set_MSP():
Nach dem Springen zum Ende der Sprungfunktion (Debugger-Schrittschaltflächen nicht mehr aktiviert):
Wenn ich dann im Debugger auf Ausführung aussetzen klicke, bringt mich das zu einem von Eclipse generierten Haltepunkt am Anfang von main() zurück. Ich verstehe nicht, wie das der Fall sein kann, da mein Anwendungscode sowohl mit als auch ohne den vorhandenen Debugger nachweislich nicht mehr richtig funktioniert.
Sie könnten versuchen, zu 0x1FF00FFE anstelle von 0x1FF00000 zu springen. (eingebettete Bootloader-Adresse nach AN2606 Rev 35, S. 26)
Mein erster Kommentar war völlig falsch. Aber laut den Kommentaren oben hat der Themenstarter gefunden, was falsch war. Aufgrund des auf dem L011-Gerät präsentierten leeren Prüfmechanismus können Sie nicht vom Benutzercode zum Systemspeicher springen und dort bleiben. Ich bin auf meinem L07x-Gerät mit Dual-Banking-Mechanismus auf ähnliche Probleme gestoßen (ähnliches Problem https://stackoverflow.com/questions/42020893/stm32l073rz-rev-z-iap-jump-to-bootloader-system-memory ). Es stellte sich heraus, dass der Bootloader auf jeden Fall zum Benutzercode zurückspringt, solange ein gültiger Code in einer der Banken vorhanden ist. Natürlich ist es möglich, dies zu umgehen, indem man nach der Leerprüfung zur Adresse springt, aber es ist schwierig, die richtige Adresse zu finden, und es gibt keine Garantie, dass STM diese Adresse beim nächsten Drucken des Chips nicht ändert.
Chris Stratton
Benutzer72833
Filo
Joe Baker
Dewan