cancel
Showing results for 
Search instead for 
Did you mean: 

Custom Bootloader HardFault

johncarroll9
Associate II
Posted on October 15, 2014 at 22:32

Hi Folks,

I wrote a custom bootloader at work and I'm getting a hard fault right at the instruction to jump to the Reset_Handler of the Application. This bootloader worked fine for 6 months but suddenly it started getting hard faults. I have done the following:

  • Verified the stack pointer was moved to the start of the stack of the application.
  • Verified that the address i'm jumping to is in fact the reset handler.
  • Shut down all interrupts except for system tick since it cannot be shut down.
  • Disabled all ports and peripherals I used in the bootloader prior to the jump.

I am using IAR 7.3 to develop on a STM32F303. Any help would be appreciated. I've been battling this for several days.

Thank you,

John

9 REPLIES 9
Posted on October 15, 2014 at 22:43

Not much to work with here.

You'd need to step through the transition in assembler mode, and pay attention to the registers. If the jump itself fails you need to make sure the address is ODD to reflect THUMB code.

Does the OLD code still work? What did you change in your code, or development environment?
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
stm32forum
Associate II
Posted on October 16, 2014 at 09:09

Try adding this

http://blog.frankvh.com/2011/12/07/cortex-m3-m4-hard-fault-handler/

handler to get some more info about the fault.

chen
Associate II
Posted on October 16, 2014 at 10:43

Hi

1. Is the hardfault happen in the bootloader OR the application ?

2. What do you mean by ''jump to the Reset_Handler of the Application''

Technically, to jump to the Application 2 things must be done :

i. The stack pointer register must be set (so the SP will use the correct address for the application)

ii. The program counter must be loaded with the start address of the init routine in the application.

Both MUST be read from the Vector table of the application,

1st entry in vector table is the Stack pointer address,

2nd entry in vector table is the address for the init routine

(I think I have got that right)

3. ''Shut down all interrupts except for system tick since it cannot be shut down.''

Not true, the SysTick can be stopped, it must be done in Supervisor mode. If you have not done anything to change mode in your bootloader, then the booloader is probably running in supervisor mode.

Try :

portNVIC_SYSTICK_CTRL_REG = portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT;

johncarroll9
Associate II
Posted on October 16, 2014 at 15:21

Thanks for answering. The development environment is unchanged. The bootloader has not changed since April this year. What happened was I made changes to the application and suddenly my bootloader would hardfault when performing the jump to the application.

johncarroll9
Associate II
Posted on October 16, 2014 at 15:22

Thanks for answering. I tried the code you suggested but I couldn't get it to compile with my M4 core.

johncarroll9
Associate II
Posted on October 16, 2014 at 15:25

Thanks for answering.

1. The hardfault is within the bootloader.

2. The address for the 2nd entry in the vector table is the Reset_Handler. My old application code and new application code both point to their respective reset handler addresses. I do set the stack pointer and obtain it from the 1st entry in the vector table.

3. I tried the code you suggested but I couldn't resolve the symbols. I couldn't find them in the standard peripheral library nor CMSIS. Right now I'm trying to find a global ''Shut down all interrupts'' command just to be safe.

johncarroll9
Associate II
Posted on October 16, 2014 at 15:47

I figured it out. I called __disable_irq(); from core_cmFunc.h in the  bootloader before making the jump. In the application I call _enable_irq(). I still can't explain why this suddenly started failing. My only guess is that I was on the hairy edge of an interrupt this entire time and my new application code, which takes longer to download, was buying enough time for the interrupt to fire.

Thank you all for your kind help. It did give me the ideas required to reach this point!

chen
Associate II
Posted on October 16, 2014 at 15:53

Hi

''1. The hardfault is within the bootloader.''

You say that the bootloader has not changed.

Must be as clive1 suggested - the addresses are not aligned correctly.

What kind of Hardfault is it?

Check the map file generated by the application, check that the address of the stack and 'reset handler' are 32bit aligned.

''3. I tried the code you suggested but I couldn't resolve the symbols. I couldn't find them in the standard peripheral library nor CMSIS. Right now I'm trying to find a global ''Shut down all interrupts'' command just to be safe.''

Yes, sorry about that. The defines are from FreeRTOS.

All it is doing is going straight to the SysTick timer register in the ARM core and disabling the SysTick Timer. There should be the defines for it in CMSIS.

Posted on October 16, 2014 at 19:15

There's quite a significant distance between the jump to the application, and where the vector table is relocated, and then the C run time environment is properly stood up, before main() is called and any IRQHandler()s have a valid context to work within.

Boot Loaders should avoid leaving interrupts firing (SysTick, TIM, whatever) by turning them off rather than simply telling the processor to mask them temporarily. If they are expected to be handled there needs to be some careful hand-off between the loader and application.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..