AnsweredAssumed Answered

Jump to bootloader from main app (loop) on STM32F417

Question asked by Gordon Madden on Mar 1, 2017

Hi everyone!

My project is to upgrade (replace) the program running on a STM32F417. It has to be accomplished by plugging in a serial cable to the device and running a Windows app to start the upgrade. The customer performing the upgrade will choose the COM port through a menu of the Windows app. They will then press a button to start the upgrade.

 

Right now, I have this code in the main loop of the program running on the device:

if( charIn == 'B' )
            {
                JumpMemory();
            }

 

I can type in a 'B' in the terminal of my C# program and get have the JumpMemory() function run. This will not be the actual trigger, but for testing, I'm just trying to get all the actions necessary to be performed.

 

So, now that I can trigger a jump out of the main loop of the devices program. I want to reset and enter the bootloader. This is where my knowledge is weak as I have never work with ARM or the bootloader previously.

 

From posts on this site, I have use the following code snippets:

1) At the top of main.c (function declaration):

       JumpMemory();     (and the call to this function listed above)

        extern void SystemReset(void);

I'm not sure what this is referring to. There is a SystemReset  process in the assembly noted below. Is that what is being called?

 

2) When JumpMemory() is called a number is written to RAM and then reset is invoked.

      void JumpMemory(void)
{    
        *((unsigned long *)0x2001FFF0) = 0xDEADBEEF;
        NVIC_SystemReset();
}

 

The above and following code is from https://community.st.com/thread/16678?commentID=112864#comment-112864 

 

3) I created a new assembly (.s) file and put in this code. I can see that this Reset Handler will be run instead of the [WEAK] one specified in the startup.s file. It then loads the contents of the address where we place DEADBEEF into a register and then compares it to DEADBEEF we have loaded into another register. They are equal so it jumps to Reboot_Loader instead performing a normal startup.

;*******************************************************************************

; Write a known word into SRAM and use it for the 417 to boot into bootloader

 

;SystemReset();

 

Reset_Handler   PROC
                EXPORT  Reset_Handler
                IMPORT  __main
 
;...
                LDR     R0, =0x2001FFF0 ; Address for RAM signature
                LDR     R1, =0xDEADBEEF
                B        .
                LDR     R2, [R0, #0] ; Read current
                STR     R0, [R0, #0] ; Invalidate
                CMP     R2, R1
                BEQ     Reboot_Loader
 
; Normal startup path
                LDR     R0, =SystemInit
                BLX     R0
                LDR     R0, =__main
                BX      R0
                ENDP
;...
 
; Vector into System Loader
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
                ENDP
 
SystemReset     PROC
                EXPORT  SystemReset
                ldr     r1, =0xE000ED0C ; NVIC Application Interrupt and Controller
                ldr     r0, =0x05FA0004 ; Magic
                str     r0, [r1, #0]    ; Reset
                b       .
                ENDP
 
;...

 

I was hoping that this would place the operation of the program at the start of the bootloader and would wait for the baud rate byte (0x7F) to be sent. Instead, it skips back into the main loop. I assume that upon reset, it is performing a normal startup.

 

How do I get the process to stop at the beginning of the bootloader?

Do I have the system reset set up properly?

Should the assembly be in a separate file, as I have it, or somewhere else?

Is the NVIC reset the proper one to use?

 

Thank you for helping!

Outcomes