2014-10-15 01:32 PM
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:2014-10-15 01:43 PM
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?2014-10-16 12:09 AM
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.2014-10-16 01:43 AM
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;2014-10-16 06:21 AM
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.
2014-10-16 06:22 AM
Thanks for answering. I tried the code you suggested but I couldn't get it to compile with my M4 core.
2014-10-16 06:25 AM
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.2014-10-16 06:47 AM
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!2014-10-16 06:53 AM
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.2014-10-16 10:15 AM
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.