2024-02-22 03:55 AM
It has been asked several times, however I can not find a working solution for me.
With STM32L486RGT6 I achieved to implement jump to bootloader, entering DFU mode successfully. All fine!
Doing it similar for STM32L071CZY6TR and STM32F469VE it does not remain in bootloader, but starts the application from flash.
Environment: Boot0 = 0 fixed. Application is stored in Bank1.
Debugging STM32L071 I see the jump to 0x1ff0’0510. Stepping forward ends up in a small loop. Disconnecting the debugger, the application starts from flash. I don’t see any Hardfault message.
Do I miss something to reset or should this anyway not be used to update the FW in Flash?
Below the code I use.
void Jump2StInternalBootloader(void)
{
volatile uint32_t addr = 0x1FF00000;
HAL_UART_DeInit(&huart1);
HAL_UART_DeInit(&huart5);
HAL_ADC_DeInit(&hadc);
HAL_I2C_DeInit(&hi2c1);
HAL_TIM_Base_DeInit(&htim2);
HAL_LPTIM_DeInit(&hlptim1);
HAL_StatusTypeDef s = HAL_RCC_DeInit();
if (s != HAL_OK){
while(1){;}
}
HAL_SuspendTick();
SysTick->CTRL = 0;
SysTick->LOAD = 0;
SysTick->VAL = 0;
HAL_DeInit();
__disable_irq();
HAL_RCCEx_DisableLSECSS();
__HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
/* Clear Interrupt Enable Register & Interrupt Pending Register. TODO check code */
for (uint8_t i = 0; i < (MCU_IRQS + 31u) / 32; i++) {
NVIC->ICER[i] = 0xFFFFFFFF;
NVIC->ICPR[i] = 0xFFFFFFFF;
}
for (IRQn_Type i = WWDG_IRQn; i <= LPUART1_IRQn; i++) {
HAL_NVIC_DisableIRQ(i);
}
void (*jumpFuncPtr)(void);
jumpFuncPtr = (void (*)(void))(*((uint32_t *)(addr + 4)));
__set_MSP(*(uint32_t *)addr);
jumpFuncPtr();
}
Thanks in advance.
Led
2024-02-22 04:10 AM
I think, the best way is to set some magic in RAM, do a system reset, in the startup process check for that magic and either jump to the application or the bootloader. But maybe in your case it can help to disable all IRQs at startup and double check the bootloader address.
2024-02-22 05:41 AM - edited 2024-02-22 05:43 AM
Assuming I want to implement this solution, using the magic in the RAM, then I could call the function shown in my first post as the very first thing in the main(). Expecting, that the application would always to go bootloader immediately.
void main(void)
{
Jump2StInternalBootloader();
I gave it a short try (commenting out the *_DeInit() function). Unfortunately it does not stop in bootloader, as I cannot connect via Uart and the debugging shows that the application is started again.
As bootloader address I use the system memory address according datasheet.
By the way: I can successfully enter bootloader by erasing the chip and set BFB2 Option Byte Flag.
2024-02-22 05:53 AM
Is a watchdog running?
Disconnecting debugger shouldn't have an effect on code being ran if you're not debugging.
Interrupts need enabled for the DFU bootloader. You're not enabling them. General working jump to bootloader code can be seen here:
2024-02-22 10:08 AM
main() is too late. A lot of initialization has already been done on system initialization. You must put it in the startup code.
2024-02-22 10:17 AM - edited 2024-02-22 10:19 AM
You can't disable IRQ's at a system level, nothing reenables them, that's not how the processor starts.
You're expected to stop / teardown whatever your app has running, cause that's not going to be running any more.
Some of the newer System Loaders may try and check if your firmware is present and jump to it. It may look at the mapping based on the BOOTx pins, and these may be sticky. This was done to limit several vectors of attack on design.
The ROM can be patched on CM3,CM4 and CM7, and I've demonstrated this previously, if it doesn't do what you want out-of-the-box.
Disassemble and Debug if you're not getting the behaviour you want.
It will really help to have a solid understanding of the Cortex-Mx MCU's and debugging / tracing code
Check Zero Memory Mapping, and setting SCB->VTOR to the Vectors that will be in use.
For updating your OWN application, implement your OWN boot loader. The System Boot Loader is primarily for initial programming or unbricking, not for your best end-user experience.
2024-02-22 10:44 AM
Even if you implement your own bootloader, having the system bootloader switch in the startup code and triggering a software reset is easier. No need to tear down anything. Only gracefull application shutdwon is needed.
2024-02-22 11:39 PM
Thank you TDK for the proposal. Watchdog is not running. I've tried with interrupts enabled according the link you added. But did not make any difference.
(Actually I based my code on the first reply in this chat. But as the first reply states 'is full of errors and unnecessary actions' and later I read from the author 'I will update', but nothing has changed, ... I don't put confidence into it. )
2024-02-22 11:42 PM
Thanks a lot Uwe for the proposal.As I'm not too familiar with the functionality of startup code, and because the device is already in mass production (high risk and costs if it does not work properly), I prefer writing the own bootloader.
2024-02-22 11:47 PM
Thanks Tesla for the valuable input. Your statement simplifies the decision to give up and go back to write an own bootloder. Even though with the working device STM32L4, it is such a great solution, making the handling so easy.
You wrote 'I've demonstrated this previously'. Can you provide the link what post you mean?