cancel
Showing results for 
Search instead for 
Did you mean: 

hard fault when jumping to application from custom bootloader

gkovelman
Associate II
Posted on July 19, 2016 at 10:41

Hi,

I'm working on a STM32F401 MCU with custom bootloader and application. Compiler is GCC 5.2.1, not optimizations are running. I'm getting a hardfault after the first interrupt after the following jump sequence: bootloader -> application -> bootloader -> application. After the first jump to the application from the bootloader, the system is working properly. However, after jumping to the application after jumping back to the bootloader (I'm not resetting the board on purpose), the hardfault happens after the first interrupt that may be anything from SysTick to EXTI. What could be the reason for this? Anything that I'm not updating? Thanks. stubs of the code: jumping procedure (for both programs; application is at 0x08008000 and bootloader is at 0x08000000):

typedef
void
(*pFunction)(
void
);
uint32_t appStack;
pFunction appEntry;
//Jump to address
/* Get the application stack pointer */
appStack = (uint32_t) * ((__IO uint32_t*)address);
/* Get the application entry point */
appEntry = (pFunction) * (__IO uint32_t*) (address + 4);
/* Reconfigure vector table offset */
SCB->VTOR = address;
__set_MSP(appStack);
appEntry();

application cleanup before jumping:

osThreadSuspendAll();
__disable_irq();
SysTick->CTRL =0;
SysTick->LOAD=0;
SysTick->VAL=0;
__set_PRIMASK(1);
HAL_UART_DeInit(&huart2);
HAL_I2C_DeInit(&hi2c1);
HAL_RCC_DeInit();
HAL_DeInit(); 

3 REPLIES 3
jon239955_stm1_st
Associate II
Posted on July 19, 2016 at 14:41

If there are any interrupts pending, they will be actioned as soon as you enable interrupts in your new application.

I manually disable the interrupts and clear any pending ones before jumping (or early in code of new app)

  /* Disable all interrupts */

  NVIC->ICER[0] = 0xFFFFFFFF;

  NVIC->ICER[1] = 0xFFFFFFFF;

  NVIC->ICER[2] = 0xFFFFFFFF;

  /* Clear pendings */

  NVIC->ICPR[0] = 0xFFFFFFFF;

  NVIC->ICPR[1] = 0xFFFFFFFF;

  NVIC->ICPR[2] = 0xFFFFFFFF;

Note, the number of interrupts affects the number of registers to clear - this code will clear up to 96 interrupts as was for an F2.  Not sure if the F4 has more interrupts.

Posted on July 19, 2016 at 17:29

In an RTOS one must be conscious of whether the CPU is in user/system mode when the transfer is effected.

And more generally, you can't transfer control within an interrupt, as the return via LR action unstacks the NVIC's current state, failing to do that will preclude everything except preemption.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
gkovelman
Associate II
Posted on July 21, 2016 at 06:58

I'm doing the transfer from inside a task. How can I make sure that I'm in the correct mode (I'm guessing user mode?)?

I'm disabling interrupts before going to another application. I tried clearing NVIC pending interrupts, except for systick, as it's not in NVIC. Should I do more?