cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L412: When I turn the reset (physical) switch, the µC jumps into the DFU bootloader, although it isn't supposed to

WhereDidFrankGo
Associate II

Hi there!

I have a weird problem, where I'm a bit lost, probably also due to my limited knowledge of assembly. So I am trying to write a function (which is called using a very secret pattern) which sets a magic number and soft resets the microcontroller. On startup, a comparison to the magic number is made, and it either jumps into the DFU bootloader, or continues regular startup.

But somehow even when I press the physical reset switch, it goes into the bootloader, although it shouldn't. And I'd like to ask for your advice why.

Here's the reset handler. Line 3 to line 8 is what I have added. It loads the bootloader_flag address, reads out bootloader_flag, loads magic number 0x00C0FFEE, and clears bootloader_flag. Then it compares the dereferenced bootloader_flag in r2 to the magic number in r1 and decides whether to jump or to continue.

Reset_Handler:
  /*Check for bootloader*/
  ldr r0, =_bootloader_flag // Load bootloader flag address
  ldr r1, =0x00C0FFEE // Load magic number
  ldr r2, [r0, #0] // Dereference flag
  str r0, [r0, #0] // Clear
  cmp r2, r1 // Check flag
  beq Reboot_Loader // Flag detected? Go to loader
 
  ldr   sp, =_estack    /* Set stack pointer */
 
/* Copy the data segment initializers from flash to SRAM */
  movs	r1, #0
  b	LoopCopyDataInit

Here's the code of Reboot_Loader:

Reboot_Loader:
	ldr r0, =0x1FFF0000 // Load bootloader address
	ldr r1, [r0, #0] // Load default stack pointer
	mov sp, r1 // Set stack pointer to default
	ldr r0, [r0, #4] // Load bootloader +4
	bx r0 // Go to bootloader +4

And finally the code piece that triggers the dirty reset:

volatile uint32_t _bootloader_flag = 0x00000001;
 
/**
 * @brief Write dirty bit and go into DFU mode bootloader
 * @param bootloader_status 
 */
void activate_bootloader(uint32_t bootloader_status) {
	if(bootloader_status == 1) {
		// Write DFU message
		NVIC_DisableIRQ(TIM1_UP_TIM16_IRQn);
		WriteSomeMessageToNotifyUser("");
		NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
		// Disable interrupts
		__disable_irq();
		// http://blog.fahhem.com/2017/12/jump-to-emb-bootloader/
		_bootloader_flag = 0x00C0FFEE; // Magic number flag set
		// See you latte
		NVIC_SystemReset();
	  while(1);
	}
}

Thank you for your help.

I'm using STM32CubeMX, everything HAL, SystemWorkbench, macOS Catalina and the microcontroller is an STM32L412KB.

Stay safe and cheers.

5 REPLIES 5

The state of the boot pins, and if the flash looks like it has valid SP/PC values, will impact if the loader will run or jump back into flash.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Thanks for your reply. Could you please elaborate on what you mean by

  1. the state of boot pins: You mean BOOT0 pin, and nSWBOOT0 and BOOT1 option bits?
  2. How is a valid SP/PC determined - where to check or implement in code?

+1

Toggle some pin to see if it went to bootloader through your code or directly due to some of the bootloader entry mechanisms Clive said above.

Note, that for AN2606/pattern6 (as is L412), the "flash empty" detection in fact only checks the very first word of FLASH against 0xFFFFFFFF; and also that once this is detected true, it won't go away using "ordinary" reset even if the FLASH is reprogrammed, you need either poweron reset or forced reloading of the option bytes.

JW

Thanks. I've found the (pretty obvious) mistake I have made.

I'm using BOOT0 as GPIO and the Option Bits are set so that nSWBOOT0 == 1, which means that reset would take value from the BOOT0 pin.

Now that nSWBOOT0 == 0, the device resets and DFUs just as expected.

Sorry I tend to be a bit terse, often using a phone, and not looking to write an essay.

Yes, the BOOTx pins or their proxy, which are changing the mapping of the zero page memory, ie ROM, FLASH, RAM, and is the default vector table when SCB->VTOR == 0 at reset.

I haven't pulled the specific loader apart here, but the typical approach is to check the SP (word at 0) is not 0xFFFFFFFF, and ideally in the 0x200xxxxx type range representing RAM, 32-bit aligned, and the PC (word at 4) is not 0xFFFFFFFF, and is at 0x080xxxxxx range and ODD, indicating a Thumb subroutine within the FLASH.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..