Jumping from one firmware to another in MCU internal FLASH

一曲冷凌霜 提交于 2019-11-30 16:05:13

You have to jump to "the application address + 4" because the base address of the application holds the initial stack pointer position. So jumping to this address means jumping to the address of stack base. Under the app address + 4 (+4B because of 32-bit architecture) there's the address of reset handler procedure.

In file 'startup_stm32f03xx.s', make sure that you have the following piece of code:

EXTERN  HardFault_Handler_C        ; this declaration is probably missing

__tx_vectors                       ; this declaration is probably there
    DCD     HardFault_Handler

Then, in the same file, add the following interrupt handler (where all other handlers are located):

    PUBWEAK HardFault_Handler
    SECTION .text:CODE:REORDER(1)
HardFault_Handler
    TST LR, #4
    ITE EQ
    MRSEQ R0, MSP
    MRSNE R0, PSP
    B HardFault_Handler_C

Then, in file 'stm32f03xx.c', add the following ISR:

void HardFault_Handler_C(unsigned int* hardfault_args)
{
    printf("R0    = 0x%.8X\r\n",hardfault_args[0]);         
    printf("R1    = 0x%.8X\r\n",hardfault_args[1]);         
    printf("R2    = 0x%.8X\r\n",hardfault_args[2]);         
    printf("R3    = 0x%.8X\r\n",hardfault_args[3]);         
    printf("R12   = 0x%.8X\r\n",hardfault_args[4]);         
    printf("LR    = 0x%.8X\r\n",hardfault_args[5]);         
    printf("PC    = 0x%.8X\r\n",hardfault_args[6]);         
    printf("PSR   = 0x%.8X\r\n",hardfault_args[7]);         
    printf("BFAR  = 0x%.8X\r\n",*(unsigned int*)0xE000ED38);
    printf("CFSR  = 0x%.8X\r\n",*(unsigned int*)0xE000ED28);
    printf("HFSR  = 0x%.8X\r\n",*(unsigned int*)0xE000ED2C);
    printf("DFSR  = 0x%.8X\r\n",*(unsigned int*)0xE000ED30);
    printf("AFSR  = 0x%.8X\r\n",*(unsigned int*)0xE000ED3C);
    printf("SHCSR = 0x%.8X\r\n",SCB->SHCSR);                
    while (1);
}

If you can't use printf at the point in the execution when this specific Hard-Fault interrupt occurs, then save all the above data in a global buffer instead, so you can view it after reaching the while (1).

Then, refer to the 'Cortex-M Fault Exceptions and Registers' section at http://www.keil.com/appnotes/files/apnt209.pdf in order to understand the problem, or publish the output here if you want further assistance.

The Hard Fault ISR indicated to me where the fault was. R0 had __initial_sp which is the top of the stack. It made me realise that I had to initialise my application's Stack pointer in the bootloader before jumping to the app. After doing that I can now successfully jump to the app from the bootloader. The jump address also has to be (for some reason I do not quite understand) the application address + 4.

Also, note that you need to modify the main application RAM allocation to start from 0x200000C0 with size 0x00001FD0. This is done so you can relocate the vector table to the internal SRAM at 0x20000000 in the main application "main" function as follows:

/* Private macro -------------------------------------------------------------*/
__IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));

/************************************************************//**
* \brief Main application application entry point
*
* At this stage the microcontroller clock setting is already configured, 
* this is done through SystemInit() function which is called from startup
* file (startup_stm32f030x8.s) before to branch to application main.
* To reconfigure the default setting of SystemInit() function, refer to
* startup_stm32f030x8.c file
*****************************************************************/
int main( void )
{
    uint32_t i = 0;
    uint8_t status;

/* Relocate by software the vector table to the internal SRAM at 0x20000000 ***/  
  /* Copy the vector table from the Flash (mapped at the base of the application
     load address 0x08003000) to the base address of the SRAM at 0x20000000. */
  for(i = 0; i < 48; i++)
  {
    VectorTable[i] = *(__IO uint32_t*)(IAP_BTLUPG_ADDRESS + (i<<2));
  }

    RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;   /* Enable the SYSCFG peripheral clock*/

    SYSCFG->CFGR1 = SYSCFG_CFGR1_MEM_MODE;  /* Remap SRAM at 0x00000000 */

/***************** Application code starts below ***************************/       
}

See my new bootloader INTFLASH_execute_main_app function below:

void INTFLASH_execute_main_app(const char mode)
{
  MyFunc_ptr Jump_To_Application;
  uint32_t JumpAddress;

//  __disable_irq();

    JumpAddress = *(__IO uint32_t*) (IAP_APP_ADDRESS + 4);
  Jump_To_Application = (MyFunc_ptr) JumpAddress;

  if( mode || intflash_check_main_app() )
  {
    App_ptr = (uint8_t*)Jump_To_Application;
    if( (*App_ptr != 0xFF) &&  (App_ptr) )
    {                  
    __set_MSP( *(__IO uint32_t*)IAP_APP_ADDRESS );  // Initialise app's Stack Pointer
    Jump_To_Application();
    }
  }          
//  __enable_irq();
}

Many Thanks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!