Skip to main content
chuck2
Associate
May 1, 2014
Question

Calling stm32429I-Eval Bootloader

  • May 1, 2014
  • 32 replies
  • 7106 views
Posted on May 02, 2014 at 01:26

Hello, we are wanting to call the built-in bootloader from our application without manipulating the BOOT0/BOOT1 pins. I am trying to use the EVAL board to validate our method. The Users Manual for the Eval board does state:  ''The RS-232 boot loader mechanism is not supported on the STM32429I-EVAL''. There is no explanation of this statement. However, if I move the Boot0 switch on the eval board to 1 and power cycle, I am able to at least connect to the bootloader over RS-232 using the ST demo flash loader program. If I can get that far by calling the bootloader on the Eval board with the BOOT pins both at 0, I will call it a success until our hardware is ready.

I have tried both calling the bootloader from C code, using the method posted on Youtube, and also calling it from my startup assemble code, using the method Clive has suggested in the forum, as follows (I am using IAR):

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;;

;; Default interrupt handlers.

;;

THUMB

PUBWEAK Reset_Handler

SECTION .text:CODE:REORDER:NOROOT(2)

Reset_Handler

LDR R0,=0x1FFF0000

LDR R1,[R0,#0]

MOV SP,R1

LDR R0,[R0,#4]

BX R0            ;debugger shows 0x1FFF4ABF in R0 at this point

Unfortunately, both methods display the same behavior - I cannot connect to the bootloader using the demo program. If I use the debugger, I can hit a breakpoint at the start of the bootloader (at 0x1FFF4ABE) , and can trace through it until I get bored, but as soon as I hit run, I hit a breakpoint back at the BX R0 line above, as if a reset is occurring, or the bootloader is jumping back to the start of the application. This made me suspect the dual boot mode of the 429, but I used ST-Link to verify the BFB2 bit in the options byte is cleared, so no dual boot should be taking place.

Any ideas?
    This topic has been closed for replies.

    32 replies

    mario239955_stm1
    Visitor II
    August 20, 2015
    Posted on August 20, 2015 at 03:49

    Hank, Clive,

    First of all, thanks for this post, its been helpful. Im trying to do exactly what hank is doing but i always get a ''hardfault''. Im using keil V5 and STM32F427 This is my code in the startup.s

    Reset_Handler PROC
    EXPORT Reset_Handler [WEAK]
    IMPORT __main
    LDR R0, =0x2000FFF0
    LDR R1, =0xDEADBEEF
    LDR R2, [R0, #0]
    STR R0, [R0, #0] ; Invalidate
    CMP R2, R1
    BEQ Reboot_Loader
    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 ; MAP ROM AT ZERO
    STR R1, [R0, #0]
    LDR R0, =0x1FFF0000 ; ROM BASE
    LDR SP,[R0, #0] ; SP @ +0
    LDR R0,[R0, #4] ; PC @ +4
    BX R0

    And in C main(): // executed by the program. HAL_RCC_DeInit(); SysTick->CTRL = 0x00; SysTick->LOAD = 0x00; SysTick->VAL = 0; //__set_PRIMASK(1); // JumpAddress = *(__IO uint32_t*) (0x1fff0004); // SysMemBootJump =(void *)JumpAddress; // __set_MSP(*(volatile unsigned int *)0x1FFF0000); // SysMemBootJump(); Reboot_Loader();
    Tesla DeLorean
    Guru
    August 20, 2015
    Posted on August 20, 2015 at 08:43

    The mechanism is not to call the routine directly, but via a tag in RAM and a reset. Pick a chip appropriate address in the C and Assembler routines.

                    printf(''Entering Boot Loader..\r\n'');

                    *((unsigned long *)0x2000FFF0) = 0xDEADBEEF; // 64KB STM32F103

                    NVIC_SystemReset();

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    mario239955_stm1
    Visitor II
    August 20, 2015
    Posted on August 20, 2015 at 09:33

    Thanks Clive! I made it work using an old post from you

    Reset_Handler PROC
    EXPORT Reset_Handler [WEAK]
    IMPORT SystemInit
    IMPORT __main
    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 ; MAP ROM AT ZERO
    STR R1, [R0, #0]
    LDR R0, =0x1FFF0000 ; ROM BASE
    LDR R0, =0x00000000 ; OR GENERICALLY MAPPED AT ZERO
    LDR SP,[R0, #0] ; SP @ +0
    LDR R0,[R0, #4] ; PC @ +4
    BX R0
    BX R0
    ENDP ;

    Its there and advantage of using the mark in the RAM? Whats the purpose of doing this? Now, im with the issue of disabling every module in the MCU, to jump to the bootloader. My current application uses the following modules: DCMI DMA FMC USB USART I2C SPI Do i need disable all modules that im using? Thanks a lot!!!
    mario239955_stm1
    Visitor II
    August 20, 2015
    Posted on August 20, 2015 at 09:42

    Clive! Never mind, im being redundant, i understood what you said to me in the previous post! 

    Thanks for the help!

    dthiffeault9
    Visitor II
    October 9, 2015
    Posted on October 10, 2015 at 00:07

    Hi,

    I've searched and analysed a lot of Clive1 posts (you're great!!). I did implement the 0xDEADBEEF in RAM and the .s. In the posts you have in this thread, I'm trying to understand this:

    LDR R0, =0x40013800 ; SYSCFG_MEMRMP
    LDR R1, =0x00000001 ; MAP ROM AT ZERO

    I don't have that in my code and maybe that's the reason I'm experiencing this behavior: - User App starts - Write 0xDEADBEEF in RAM - Soft Reset - Assembly reset code compares memory, 0xDEADBEEF is found - Reboot_Loader is called - Jumping to embedded bootloader - Some code executes - User App is recalled again - and so on. From what I understand, I'm not staying in the embedded bootloader, it's jumping back in my application. Then, since it's an infinite loop, the hard fault handler is called. Am I missing something? Thanks for your time, DT
    Tesla DeLorean
    Guru
    October 9, 2015
    Posted on October 10, 2015 at 00:55

    Ok, confirm what processor you're using, and the precise code sequences you have doing the reset, and in the reset handler.

    The two lines load immediate constants into the processor registers, the line afterward copies the ONE constant into the SYSCFG->MAPRMP register, whose address I hard-coded.

    The purpose here is to do the equivalent memory mapping (shadowing) caused by the BOOTx pins. ie the ROM also appears at 0x00000000 in the memory map, instead of your FLASH code.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    dthiffeault9
    Visitor II
    October 13, 2015
    Posted on October 13, 2015 at 14:38

    Hi,

    this is the code as it is currently. I changed it a little from the original post I saw from you because I was trying things to make it work. MCU is:STM32F427ZIT6, using IAR. My setup function:

    BOOL BSPResetBoard(BOOL bBootload)
    {
    if (bBootload)
    {
    *((unsigned long *)0x2001BFF0) = 0xDEADBEEF;
    }
    hal_BSPSoftwareReset();
    return TRUE;
    }

    Assembly code in startup_stm32f427xx.s:

    THUMB
    PUBWEAK Reset_Handler
    SECTION .text:CODE:REORDER:NOROOT(2)
    Reset_Handler
    LDR R0, =0x2001BFF0
    LDR R1, =0xDEADBEEF
    LDR R2, [R0]
    STR R0, [R0]
    CMP R2, R1
    BEQ Reboot_Loader
    LDR R0, =SystemInit
    BLX R0
    LDR R0, =__iar_program_start
    BX R0
    PUBWEAK Reboot_Loader
    SECTION .text:CODE:REORDER:NOROOT(2)
    Reboot_Loader
    LDR R0, =0x00000000
    LDR SP, [R0, #0]
    LDR R0, =0x1FFF0004
    BX R0

    (sorry for alignment, didn't paste well...) Thanks !! DT
    Tesla DeLorean
    Guru
    October 13, 2015
    Posted on October 13, 2015 at 18:29

    Ok, the thing you're not grasping here is that 0x1FFF0004 is not executable code you can jump too, but a pointer to some code. In fact if you jump to it, you'll get a Hard Fault.

    THUMB
    PUBWEAK Reset_Handler
    SECTION .text:CODE:REORDER:NOROOT(2)
    Reset_Handler
    LDR R0, =0x2001BFF0 
    LDR R1, =0xDEADBEEF
    LDR R2, [R0]
    STR R0, [R0]
    CMP R2, R1
    BEQ Reboot_Loader
    LDR R0, =SystemInit
    BLX R0
    LDR R0, =__iar_program_start
    BX R0
    PUBWEAK Reboot_Loader
    SECTION .text:CODE:REORDER:NOROOT(2)
    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 ; MAP ROM AT ZERO
    STR R1, [R0, #0]
    ; LDR R0, =0x1FFF0000 ; ROM BASE
    LDR R0, =0x00000000 ; OR GENERICALLY MAPPED AT ZERO
    LDR SP,[R0, #0] ; SP @ +0
    LDR R0,[R0, #4] ; PC @ +4
    BX R0
    ; sourcer32@gmail.com

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    dthiffeault9
    Visitor II
    October 13, 2015
    Posted on October 13, 2015 at 18:58

    alright thanks. I'll try that tomorrow (can't try it today).

    One question I have. How does the ST bootloader behave after that? Will it stay in Bootloader as long as there is no UART connection to it? Or will it try to jump again in User Code after a specific time (since the User App is still good)?

    I presume that when loading new data via the Bootloader, the RAM will be reset (so will the DEADBEEF flag)?

    Sorry for those questions. I usually play with a user bootloader, so not sure what to expect :)

    Thanks!

    dthiffeault9
    Visitor II
    October 13, 2015
    Posted on October 13, 2015 at 19:15

    one small question looking at the code you posted. Why this:

    LDR     R0, =0x00000000 ;  OR GENERICALLY MAPPED AT ZERO

    instead of this (commented out):

    LDR     R0, =0x1FFF0000 ; ROM BASE

    I was under the impression that for my MCU, the ST embedded bootloader was at 0x1FFF0000.

    Thanks!