I’m building some of the ST example projects using gcc, which work pretty well, except that after a hard reset, I almost immediately hit a hard fault exception. When the part (STM32F103) jumps to the hardfault handler, I can manually (with GDB) go place it at the location of the reset handler, and the examples run fine, but I’d like to get the cause of the hard fault resolved.
Doing some reading, and chatting with some of the folks on this forum, I’ve realized that in order for vector table entries to work properly in the cortex micros, they have to have their least significant bit set to 1, to signify that the ISR is thumb code. (All code for the cortex-m3s is thumb-2 code, so all vectors should have this bit set)
Ok. So when I actually compile my code using gcc, the startup code provided by ST appears not to compile correctly. The vector table is generated, but the entry for the Reset_Handler does not have that bit set correctly. Here’s some of the startup code:
.syntax unified
.cpu cortex-m3
.fpu softvfp
.thumb
.global g_pfnVectors
.global SystemInit_ExtMemCtl_Dummy
.global Default_Handler
/* start address for the initialization values of the .data section.
defined in linker script */
.word _sidata
/* start address for the .data section. defined in linker script */
.word _sdata
/* end address for the .data section. defined in linker script */
.word _edata
/* start address for the .bss section. defined in linker script */
.word _sbss
/* end address for the .bss section. defined in linker script */
.word _ebss
.equ BootRAM, 0xF1E0F85F
/**
* @brief This is the code that gets called when the processor first
* starts execution following a reset event. Only the absolutely
* necessary set is performed, after which the application
* supplied main() routine is called.
* @param None
* @retval : None
*/
.section .text.Reset_Handler
.weak Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Copy the data segment initializers from flash to SRAM */
movs r1, #0
b LoopCopyDataInit
CopyDataInit:
ldr r3, =_sidata
ldr r3, [r3, r1]
str r3, [r0, r1]
adds r1, r1, #4
...
etc… and then the vector table:
.section .isr_vector,"a",%progbits
.type g_pfnVectors, %object
.size g_pfnVectors, .-g_pfnVectors
g_pfnVectors:
.word _estack /* defined in linker script */
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word MemManage_Handler
.word BusFault_Handler
.word UsageFault_Handler
...
So that looks fine to me, but the vector table output, that I read from my listing file is thus:
Disassembly of section .isr_vector:
08000000 <g_pfnVectors>:
8000000: 20010000 andcs r0, r1, r0
8000004: 0800b6f0 stmdaeq r0, {r4, r5, r6, r7, r9, sl, ip, sp, pc}
8000008: 08000a29 stmdaeq r0, {r0, r3, r5, r9, fp}
800000c: 08000a35 stmdaeq r0, {r0, r2, r4, r5, r9, fp}
8000010: 08000a3d stmdaeq r0, {r0, r2, r3, r4, r5, r9, fp}
8000014: 08000a45 stmdaeq r0, {r0, r2, r6, r9, fp}
8000018: 08000a4d stmdaeq r0, {r0, r2, r3, r6, r9, fp}
The thing is, the address for the Reset_Handler (which should be stored at 0x8000004) is correct, it’s just that that lowest bit isn’t set. When I define other ISRs (in my C code) and their addresses are placed in the table, the LSB in their vector table entry is set correctly.
I guess the big question is… what gives? followed by … how do I fix it? I’ve tried this with several versions of gcc, all with essentially the same behavior.
Any thoughts?