stm32keilstm32f1

stm32f103c8 jump to application doesn't work


i write a programmer for boot stm32f103c8 by uart when submit app.bin file via MCS bootloader(media uart) and in to stm32f103c8 give successful data and then run app.bin by jumpToApp() function. but jumpToApp() doesn't correctly work .

bootloader code (write to flash) :

#define APP1_START (0x08005000)         //Origin + Bootloader size (20kB)
#define FLASH_BANK_SIZE (0XB000)        //44kB
#define FLASH_PAGE_SIZE_USER (0x400)    //1kB

     unlockFlashAndEraseMemory();
    for(iloop=0 ; iloop < 128; iloop+=4)
    {
      if(Buf[iloop]!=0x1a)
      { 
        flashWord((Buf[iloop+3]<<24)|(Buf[iloop+2]<<16)|(Buf[iloop+1]<<8)|(Buf[iloop]));
      }
    }

bootloader code (jump to app function):

typedef struct
{
    uint32_t        stack_addr;     // Stack Pointer
    application_t*  func_p;        // Program Counter
} JumpStruct;

    void jumpToApp(const uint32_t address)
    {
        //application_t jump_to_app;
        const JumpStruct* vector_p = (JumpStruct*)address;
        deinitEverything();
      __set_MSP(*(volatile uint32_t*)vector_p->stack_addr);
      vector_p->func_p();
    }
app code:

  MX_GPIO_Init();
  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_9, GPIO_PIN_RESET);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5|GPIO_PIN_7, GPIO_PIN_SET);
  while (1)
  {
      HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_4|GPIO_PIN_6|GPIO_PIN_9);
        HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_5|GPIO_PIN_7);
        HAL_Delay(500);
  }
app setting

#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS   SRAM_BASE       
#define VECT_TAB_OFFSET         0x00000000U                                                      
#else
#define VECT_TAB_BASE_ADDRESS   FLASH_BASE      
#define VECT_TAB_OFFSET         0x00005000U   

  

#define FLASH_BASE 0x08005000

app.bin file correctly get and write on flash micro but But it doesn't run. i use some code in this link and work keil ide


Solution

  • One possible problem is that in jumpToApp you set the stack pointer, and then call the reset handler as a function from C.

    Calling a function from C almost always involves adjusting the stack pointer, which will make it incorrect. You need to atomically set the stack pointer and then jump to the function with no possibility of doing anything in between.

    Do it from assembly with a function like this:

    Header:

    void __attribute__((noreturn)) jumpToApp(uint32_t vector);
    

    Source:

    jumpToApp:
      ldr r1, [r0]
      ldr r2, [r0, 4]
      msr msp, r1
      mov lr, r2
      bx lr
    

    I assume that your VECT_TAB_OFFSET setting causes the target application to set its own vector table into SCB-VTOR. If not then jumpToApp needs to do that too.