2021-08-19 07:24 AM
Hi all,
I'm creating a personnal board with an STM32L432 mcu, but I have a question about BOOT0. I'd like my futur to give the possibility at my futur clients to update the board. To do thaht I know I can use DFU mode and to enter to this mode BOOT0 should be high.
But I don't want to add a specific button beceause I don't have place and the board wouldn't be accessible so is it possible to active BOOT0 by software for example before reset the board ?
Solved! Go to Solution.
2021-08-19 08:36 AM
If you just need to jump to bootloader consider the below snippet from this post.
inline void launchBootloader(void)
{
typedef void (*pFunction)(void);
pFunction JumpToApplication;
// uint32_t JumpAddress;
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*)(SYSTEM_MEMORY
+ 4)));/* Initialize user application's
Stack Pointer */
__set_MSP(*(__IO uint32_t*)SYSTEM_MEMORY);
JumpToApplication();
}
2021-08-19 08:36 AM
If you just need to jump to bootloader consider the below snippet from this post.
inline void launchBootloader(void)
{
typedef void (*pFunction)(void);
pFunction JumpToApplication;
// uint32_t JumpAddress;
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*)(SYSTEM_MEMORY
+ 4)));/* Initialize user application's
Stack Pointer */
__set_MSP(*(__IO uint32_t*)SYSTEM_MEMORY);
JumpToApplication();
}
2021-08-19 08:37 AM
Generally, its possible to just enter the bootloader directly.
There are a few caveats though:
To do this, just do whatever the actual core does when the bootloader starts:
static __attribute__((noreturn)) inline void set_stackpointer_and_branch(
uint32_t sp, uint32_t exec_addr)
{
__asm__ volatile ("MSR msp, %0\n"
"BX %1\n"
: : "r" (sp),
"r" (exec_addr));
__builtin_unreachable();
}
void bootBuiltinUpdater(void)
{
// De-Init peripherals and clocks here
// System memory begin
uint32_t *baseaddr = (uint32_t*) 0x1FFF0000;
set_stackpointer_and_branch(baseaddr[0], baseaddr[1]);
}
This is untested, but it should work-- I have used the very same method on a number of STM controllers.
I would still advice against this in general; providing your own Updater will afford you more freedom and is more robust especially with heavy peripheral use.
2021-08-19 11:23 AM
Best is, have code early in startup that checks for some magic and trigger reset from your programm. That way, everything is reset.
2021-08-19 11:31 AM
Disabling the IRQ has consequences..
2021-08-19 12:10 PM
Which consequences @Community member ?
2021-08-20 05:56 AM
The most obvious one being them not being enabled again...
2023-05-24 08:03 AM
Hi,
I need help with this topic.
I tried to implement everything suggested here but it's not working.
I'm working with STM32L47 and I'm trying to add the option to update the FW via DFU without toggling BOOT0.
I tried to make the Stackpointer jump to the same address the BOOT0 as it's sent by the BOOT0 press (0x1FFF0000) but the only thing I get is a fast close on open of the USB port (as seen by Device manger of Windows) and then the Stackpointer is going back to address 0x08000000 and the application code is being executed.
My sequence is as follows:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
CB_BootLoaderCheck();
void CB_BootLoaderCheck(void)
{
if((*(__IO long *) (BK_SRAM_BASE + 0)) == SRAM_FLAG_SET_VAL)
{
(*(__IO long *) (BK_SRAM_BASE + 0)) = SRAM_FLAG_CLEAR_VAL; // Reset memory, if desired.
CB_JumpToBootLoader();
}
}
void CB_JumpToBootLoader(void)
{
volatile uint32_t SYSTEM_MEMORY = 0x1FFF0000;
typedef void (*pFunction)(void);
pFunction JumpToApplication;
// uint32_t JumpAddress;
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*)(SYSTEM_MEMORY
+ 4)));/* Initialize user application's
Stack Pointer */
__set_MSP(*(__IO uint32_t*)SYSTEM_MEMORY);
JumpToApplication();
}
case DFU_MODE:
printf("Logger__r: insert MCU into bootloader mode\r\n");
CB_SetDFU_FlagSRAM();
Logger_ResetMCU();
break;
The problem is that it's not working. The Stackpointer keeps returning to the application code.
What am I doing wrong?