Skip to main content
Lukasz Przenioslo
Associate III
November 26, 2015
Question

STM32F4 jump to bootloader without boot0 pulled up

  • November 26, 2015
  • 11 replies
  • 2081 views
Posted on November 26, 2015 at 14:19

Hello there,

I am working on an application now, where I need to send a command to the mcu through USB in order to reset the mcu and jump to system memory bootloader. On my board boot1 is shorted to ground, that means if I reset the mcu with boot1 pulled up, the system starts from bootloader. User however wont have access to boot1 phisically, so before watchdog reset I need to set boot1 in software somehow. Is that possible? I would apreciate all help!
    This topic has been closed for replies.

    11 replies

    Tesla DeLorean
    Guru
    November 26, 2015
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Lukasz Przenioslo
    Associate III
    November 26, 2015
    Posted on November 26, 2015 at 15:36

    So if I understand correctly, I have to do something before I expire the watchdog and do something in the reset interrupt routine? How can I get the reset interrupt routine function in HAL?

    Tesla DeLorean
    Guru
    November 26, 2015
    Posted on November 26, 2015 at 15:58

    I presume the HAL still uses startup_stm32xxx.s? You add code there to react to the reset which recognizes a setting you have left in an agreed location in RAM. Ideally one outside of the linker's scope

    This is for the F1 but provides more context to the method.

    /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Threaded.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Jump%20to%20internal%20bootloader&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=1653

    To refactor for you

    In application.c
    // 1FFF0000 -> 2000xxxx -> SP
    // 1FFF0004 -> 1FFFxxxx -> PC
    printf(''Entering Boot Loader..
    
    '');
    *((unsigned long *)0x2001FFF0) = 0xDEADBEEF; // 128KB STM32F4xx
    // NVIC_GenerateSystemReset(); // Explicitly Reset (SPL/CMSIS)
    while(1); // Wait for Watchdog to fire
    In startup.s
    ; Reset Handler
    Reset_Handler PROC
    EXPORT Reset_Handler [WEAK]
    IMPORT SystemInit
    IMPORT __main
    LDR R0, =0x2001FFF0 ; Magic Location
    LDR R1, =0xDEADBEEF
    LDR R2, [R0, #0]
    STR R0, [R0, #0] ; Invalidate
    CMP R2, R1
    BEQ Reboot_Loader
    LDR R0, =SystemInit
    BLX R0
    LDR R0, =__main
    BX R0
    ENDP
    Reboot_Loader PROC
    EXPORT Reboot_Loader
    LDR R0, =0x40023844 ; RCC_APB2ENR
    LDR R1, =0x00004000 ; enable SYSCFG clock
    STR R1, [R0, #0]
    LDR R0, =0x40013800 ; SYSCFG_MEMRMP
    LDR R1, =0x00000001 ; remap ROM at zero
    STR R1, [R0, #0]
    LDR R0, =0x1FFF0000 ; load ROM base
    LDR SP,[R0, #0] ; assign main stack pointer
    LDR R0,[R0, #4] ; load bootloader address
    BX R0
    ENDP

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Lukasz Przenioslo
    Associate III
    November 26, 2015
    Posted on November 26, 2015 at 16:48

    Yes, In my project there is a file startup_stm32f407xx.s

    I think I understand the overal concept now. I need to place some value in ram and check it when reset in startup code. But what does this mean?

    // 1FFF0000 -> 2000xxxx -> SP
    // 1FFF0004 -> 1FFFxxxx -> PC

    Do you mean to save a value 1fff0000 to the address 2000xxxx? And what is SP and PC? This line saves the value right?

    *((unsigned long *)0x2001FFF0) = 0xDEADBEEF;

    The code provided for startup.s is supposed to be placed at the beginning of the file? Also, I need to change the addresses for my MCU that is 1 MB flash right, or did you do it already?
    Tesla DeLorean
    Guru
    November 26, 2015
    Posted on November 26, 2015 at 17:59

    You're using a Cortex-M4 processor, the two initial vector entries contain a Stack Pointer (SP) and a Program Counter (PC). The SP will be pointing into the RAM somewhere, and the PC will be pointing to some code deeper into the ROM image. When BOOT0 is High, the memory at 0x1FFF0000 maps at zero within the address space of the processor, as well as it's normal address. The Reboot_Loader effects this transfer of control, with the memory mapping/shadowing in this fashion.

    Yes, it writes a 32-bit word into the back end of the RAM which starts at 0x20000000. A pointer with an explicit address.

    Not sure what the size of the FLASH has to do with anything here, it's situated at 0x08000000

    You are placing the code in the RESET HANDLER, ie what it does immediate as the processor resets. Basically : Look I have a magic constant, redirect execution off into the ROM image, otherwise start as normal.

    http://infocenter.arm.com/help/topic/com.arm.doc.ddi0439b/DDI0439B_cortex_m4_r0p0_trm.pdf

    http://www.amazon.com/Definitive-Cortex%C2%AE-M3-Cortex%C2%AE-M4-Processors-Edition/dp/0124080820

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Lukasz Przenioslo
    Associate III
    November 26, 2015
    Posted on November 26, 2015 at 20:02

    Thank you for the links and explanation. I will try this tommorow morning.

    Lukasz Przenioslo
    Associate III
    November 26, 2015
    Posted on November 26, 2015 at 20:15

    I tried to insert the assembler code now, but all the symbols (I dont understand them as well) are unrocognised, like PROC, EXPORT, IMPORT etc.

    This is my startup file: https://pastebin.com/LuQvc3H0

    There is a label Reset_Handler already. Does the additional content replaces this ''function'' address? How to make the compiller understand the symbols?

    Tesla DeLorean
    Guru
    November 26, 2015
    Posted on November 26, 2015 at 23:57

    That would be because they are Keil assembler directives

    .section .text.Reset_Handler
    .weak Reset_Handler
    .type Reset_Handler, %function
    Reset_Handler: 
    /* <<<< ADD CODE HERE TO CHECK AND BRANCH TO REBOOT_HANDLER <<<< */
     LDR R0, =0x2001FFF0 ; Magic Location
     LDR R1, =0xDEADBEEF
     LDR R2, [R0, #0]
     STR R0, [R0, #0] ; Invalidate
     CMP R2, R1
     BEQ Reboot_Loader
    
    ldr sp, =_estack /* set stack pointer */

    After the Reset Handler
    Reboot_Loader:
    LDR R0, =0x40023844 ; RCC_APB2ENR
    LDR R1, =0x00004000 ; enable SYSCFG clock
    STR R1, [R0, #0]
    LDR R0, =0x40013800 ; SYSCFG_MEMRMP
    LDR R1, =0x00000001 ; remap ROM at zero
    STR R1, [R0, #0]
    LDR R0, =0x1FFF0000 ; load ROM base
    LDR SP,[R0, #0] ; assign main stack pointer
    LDR R0,[R0, #4] ; load bootloader address
    BX R0

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Lukasz Przenioslo
    Associate III
    November 27, 2015
    Posted on November 27, 2015 at 08:50

    Clive, your help is priceless! Thank you very much, I managed to get it working :)

    For now, I think it is great. However, after i slept with thinking about this application I think i found a flaw in it:

    In order to give the possibility of jumping to bootloader for the user, the application loaded has to be valid. If one puts garbage by accident in the user flash memory, pc will never jump to system memory. Am I right? 
    Tesla DeLorean
    Guru
    November 27, 2015
    Posted on November 27, 2015 at 11:57

    This would be why people separate their own loader/app code, and then avoid erasing the loader portion and bricking the device.

    Review the IAP examples, and related threads.

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