Skip to main content
SVasi.1
Associate
February 17, 2020
Solved

STM32F3xx - Hardfault_Handler due to failed vector table fetch

  • February 17, 2020
  • 6 replies
  • 4241 views

First I want to say that I am a newbie in this field. I am trying to upload and debug a code on a custom-made board based on STM32F303CB chip through a NUCLEO-F446RE board. I am using Eclipse IDE (2019-12), a GNU toolchain and a SEGGER J-Link debugging software.

The code builds successfully with no errors, anyway when starting to debug, a HardFault_handler is called. The code was not written by me. I doubt that the problem is in the code itself (it builds) and rather think that some setting of the tools is not right (correct me if I am wrong). I also tried the same procedure on several boards, so I would exclude a hardware issue as well.

The debugger hangs when initializing the USB in the function **MX_USB_Init()**, leading to a HardFault_handler. When debugging in single-step mode, most funcitons within MX_USB_init() execute successfully, except **USBD_Start(&hUsbDeviceFS)**. When stepping into USBD_Start(...), it arrives in the while(1) loop of the HardFault_handler. 

When debugging in resume mode (no single step), debugger would also hang at previous functions which work properly in single-step mode such as **HAL_PCD_Init(&hpcd_USB_FS)**, **HAL_PCDEx_PMAConfig**, **USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC)**, **USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS)** and again **USBD_Start(&hUsbDeviceFS)**.

I commented out the empty Hardfault_Handler() function in stm32f3xx_it.c generated by CubeMX and caused the calling of the default CMSIS Hardfault_Handler() function in exception_handlers.c. Doing that in the debug console I get the values of several registers:

   SEGGER J-Link GDB Server V6.60f - Terminal output channel

  [HardFault]

  Stack frame:

   R0 = 00000000

   R1 = 0000BF00

   R2 = 40005C00

   R3 = 00000001

   R12 = 0000E000

   LR = FFFFFFF9

   PC = F3EF8008

   PSR = 6000005B

  FSR/FAR:

   CFSR = 00000001

   HFSR = 40000000

   DFSR = 00000000

   AFSR = 00000000

  Misc

   LR/EXC_RETURN= FFFFFFF1

  Connection closed by the GDB server.

Then in the book "Mastering STM32" I read about the following meanings of the above register values:

LR = FFFF FFF9 - CPU has been running "regular code" (CPU was in thread mode) when the Hard Fault exception was called. It was not an interrupt. The stack used was MSP, FPU Unit disabled.

HFSR = 4000 0000 - the VECTBL bit is set which indicates that the Hard Fault is caused by **failed vector table fetch**. The explanation is as follows:

"Bus error received during a vector table fetch. This happens because the vector table is invalid (the most of the times we forgot to include the assembly file provided by ST or we forgot to modify its extension from lower .s to capital .S)."

In my project there is no .s or .S file and no function is referring to such a file. This makes me think that maybe the programmer is trying to write to a wrong address in the memory because there is no proper startup file. Does that make sense for you? Any help would be appreciated.

Thanks in advance!

This topic has been closed for replies.
Best answer by SVasi.1

SOLUTION:

It appeared that really the startup_stm32fXXXxX.S file was missing. I solved the problem by creating a new dummy project for my MCU using CubeMX and generating the code for Other IDEs (GPDSC). Then I copied the generated .s file (in my case startup_stm32f303xc.s) to the system->src->cmsis folder of the original project and deleted the files system_DEVICE.c and vectors_DEVICE.c. I changed the file extension from small .s to capital .S, compiled the project and then I was able to flash and debug the microcontroller successfully.

Thank you!

6 replies

waclawek.jan
Super User
February 17, 2020

Maybe you try to run your code from RAM and don't copy the vector table properly, or you use some kind of a bootloader and again don't change VTOR properly.

Check the location of the vector table in disasm, and in debugger check value of SCB->VTOR.

JW

SVasi.1
SVasi.1Author
Associate
February 18, 2020

Hi Jan,

not sure if I'm doing the right thing but here are the results:

SCB->VTOR is being updated twice:

  • First in the SystemInit() routine in system_stm32f3xx.c:
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */

Where FLASH_BASE is 0x08000000 and VECT_TAB_OFFSET is 0x0. Here is the disassembly:

203 SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
0000135a: mov.w r2, #134217728 ; 0x8000000
0000135e: ldr r3, [pc, #16] ; (0x1370 <SystemInit+88>)
00001360: str r2, [r3, #8]
00001362: bx lr
00001364: asrs r0, r0, #32
00001366: ands r2, r0
00001368: stmia r0!, {r2, r3}
0000136a: ldr??.w pc, [pc, #-3276] ; 0x6a0 <ADPD105_setLedCurrent+184>
0000136e: vpadd.f32 d14, d0, d0
00001372: b.n 0x1376 <SystemCoreClockUpdate+2>

After this operation the value of SCB->VTOR is 0x08000000.

  • Just after SystemInit() the following line is executed from _initialize_hardware.c:
 SCB->VTOR = (uint32_t)(&__vectors_start);

The value of __vectors_start ist 0x2000a000 and apparently the &__vectors_start is 0x0 because SCB->VTOR becomes 0 after this iteration. Here is the disassembly:

 65 SCB->VTOR = (uint32_t)(&__vectors_start);
000003ba: ldr r3, [pc, #8] ; (0x3c4 <__initialize_hardware_early+16>)
000003bc: ldr r2, [pc, #8] ; (0x3c8 <__initialize_hardware_early+20>)
000003be: str r2, [r3, #8]
000003c0: pop {r3, pc}
000003c2: nop 
000003c4: stc 0, cr14, [r0, #-0]
000003c8: movs r0, r0
000003ca: movs r0, r0

Is this what you mean?

SV

waclawek.jan
Super User
February 18, 2020

I meant, look into disasm to find out where the vector table actually is - I don't doubt a simple C line which assigns a value to a register would translate into anything unexpected... (But yes, finding the table alone does not mean there is no code which would copy it into RAM somewhere.)

> _initialize_hardware.c:

> &__vectors_start is 0x0 because SCB->VTOR becomes 0 after this iteration

This is unusual and probably points towards the problem. Find out, what is the purpose of that pointer in that file - I'd guess it's part of some framework, maybe a company framework? There surely must be some documentation accompanying it, if not, well then it's up to you to hack out its purpose and how its value is supposed to be filled in.

JW

SVasi.1
SVasi.1Author
Associate
February 20, 2020

Hi JW,

as I couldn't find what disasm exactly you refer to, I used a tool called readelf to show the .elf file disassembly. Here are the lines that are related to __vectors_start and __vector_start__:

Section Headers:
 [Nr] Name Type Addr Off Size ES Flg Lk Inf Al
 [ 0] NULL 00000000 000000 000000 00 0 0 0
 [ 1] .isr_vector PROGBITS 00000000 010000 00028c 00 AX 0 0 4
...
Symbol table '.symtab' contains 931 entries:
...
 622: 00000000 0 NOTYPE GLOBAL DEFAULT ABS __vectors_start__
...
 809: 00000000 0 NOTYPE GLOBAL DEFAULT ABS __vectors_start

Actually __vector_start and __vector_start__ are defined in the linker script (sections.ld):

SECTIONS
{
 /*
 * For Cortex-M devices, the beginning of the startup code is stored in
 * the .isr_vector section, which goes to FLASH. 
 */
 .isr_vector : ALIGN(4)
 {
 FILL(0xFF)
 
 __vectors_start = ABSOLUTE(.) ;
 __vectors_start__ = ABSOLUTE(.) ; /* STM specific definition */
 KEEP(*(.isr_vector)) 	/* Interrupt vectors */
 
		KEEP(*(.cfmconfig))			/* Freescale configuration words */ 
		 
 /* 
 * This section is here for convenience, to store the
 * startup code at the beginning of the flash area, hoping that
 * this will increase the readability of the listing.
 */
 *(.after_vectors .after_vectors.*)	/* Startup code and ISR */
 
 } >FLASH

And here are the lines in the .map file related to them:

 0x00000000 __vectors_start = ABSOLUTE (.)
 0x00000000 __vectors_start__ = ABSOLUTE (.)
 *(.isr_vector)
 .isr_vector 0x00000000 0x44 ./system/src/cmsis/vectors_DEVICE.o
 0x00000000 __isr_vectors

As the project was created with an older version of Eclipse and the GNU ARM toolchain and used to work, could it be possible that the issue is due to the newer versions, libraries etc.?

SVasi.1
SVasi.1AuthorBest answer
Associate
February 28, 2020

SOLUTION:

It appeared that really the startup_stm32fXXXxX.S file was missing. I solved the problem by creating a new dummy project for my MCU using CubeMX and generating the code for Other IDEs (GPDSC). Then I copied the generated .s file (in my case startup_stm32f303xc.s) to the system->src->cmsis folder of the original project and deleted the files system_DEVICE.c and vectors_DEVICE.c. I changed the file extension from small .s to capital .S, compiled the project and then I was able to flash and debug the microcontroller successfully.

Thank you!

waclawek.jan
Super User
February 28, 2020

Thanks for coming back with the solution.

Please chose your post as Best, so that the thread is marked as solved.

JW