cancel
Showing results for 
Search instead for 
Did you mean: 

Auto STM32IDE generated code leaving VTOR at 0x00000000 causes unhandled interrupts

rclar.6
Senior

Trouble Report: STM32G474 FD CAN RX Interrupt Causes HardFault Due to VTOR Left at 0x00000000

Platform Details
----------------
- Microcontroller: STM32G474VETx
- IDE: STM32CubeIDE
- Version: 1.16.0
- Build: 21983_20240628_1741
- Startup project: Standard CubeMX-generated application with FDCAN peripheral using interrupt-based RX
- RTOS: None (bare metal)
- Debugger: ST-LINK / OpenOCD

Problem Summary
---------------
When enabling FDCAN RX FIFO0 interrupts via HAL_FDCAN_ActivateNotification() on STM32G474VETx,
the system crashes immediately with a hard fault (0xFFFFFFF9) on the first received CAN message.

After the fault, resetting via the debugger fails to return to main(). On inspection, SCB->VTOR is
found to be 0x00000000, which causes all vector table lookups to point to incorrect (and un-programmed)
memory, resulting in undefined interrupt dispatch.

Technical Findings
------------------
- FDCAN1_IT0_IRQHandler() is correctly defined and linked (nm confirms symbol is present and in vector table).
- HAL_FDCAN_ActivateNotification(...) returns HAL_OK.
- HAL_FDCAN_ConfigFilter(...) is used correctly with valid filter indexes (≤ ExtFiltersNbr - 1).
- Only extended ID messages are used.
- StdFiltersNbr = 0, ExtFiltersNbr = 4, as required.
- Interrupt is not handled; system faults without entering handler.
- Debugger shows return address 0xFFFFFFF9 — invalid exception return due to unhandled interrupt.
- After crash, SCB->VTOR is 0x00000000. This is incorrect — the vector table lives at 0x08000000.

Workaround
----------
Manually setting SCB->VTOR = 0x08000000; at the top of main() resolves the issue and restores correct interrupt behavior.
After applying this fix:
- The CAN interrupt is handled correctly
- Callback is invoked as expected
- System remains stable
- Debugger reset behaves correctly

Suggested Root Cause
---------------------
CubeMX-generated startup or system init code for STM32G474 may not explicitly set SCB->VTOR to the
correct Flash base (0x08000000). If the CPU starts with VTOR = 0x00000000 (e.g., after soft-reset or
via debugger), the vector table lookup fails, leading to:
- IRQs jumping to invalid addresses
- Crashes on first interrupt
- Unrecoverable core state even after reset

Recommended Actions by ST
-------------------------
1. Ensure that CubeMX and HAL startup code always initializes SCB->VTOR explicitly, even in single-image,
no-bootloader projects.
2. Consider adding a warning or assertion if SCB->VTOR is zero at main().
3. Update documentation for FDCAN usage to mention VTOR importance if not using a bootloader.
4. Provide CubeMX configuration option for VTOR setup under system settings.

Supporting Files Available on Request
-------------------------------------
- main.c, stm32g4xx_it.c, FDCAN_Config() source
- ELF map and nm dump confirming ISR linkage
- Screenshot or logs from debugger showing VTOR = 0x00000000

 

 

 

This resulted in a lot of re-coding the 'CANFD' and trying to fix this. With no interrupts enabled the code ran as expected and I could POLL and RX can . But as soon as the interrupts were enabled, on the first CAN message rxd it crashed. Nasty as well as the trashed vectors meant reset in debug did not work either

12 REPLIES 12

SYSCFG clock gets enabled by HAL_Init() by default, but if you want to access the registers prior to that, you just write 1 to that bit. There's also macro __HAL_RCC_SYSCFG_CLK_ENABLE() to do that.

OK I had BOOT0 floating (I thought this might have been the problem) but I have now 10k to ground on this. I still need to set SCB->VTOR to 0x08000000 to get the interrupts working. 

If you still need to set the VTOR then there is something wrong with your code. Do you use a custom bootloader in your app? Do you change the memory mapping? Do you use dual bank capability?

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice