STM32VLDiscovery开发板Timer3中断启用NVIC触发HardFault问题求助
Hey there, let's dig into this HardFault issue you're hitting with Timer3 and NVIC on your STM32VLDiscovery (STM32F100RBT6). I've wrestled with similar quirks on STM32F1 series chips before, so here are targeted checks and fixes to get your timer interrupt working:
1. Fix NVIC Priority Group Configuration First
The STM32F1 series requires you to set the NVIC priority group before configuring individual IRQ priorities. Skipping this step leads to invalid priority values, which almost always triggers a HardFault.
Add this line at the start of your initTimer3 function (or early in your program setup):
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // Example group: 2 bits for preemption, 2 for sub-priority
Make sure the preemption/sub-priority values you set in NVIC_InitStruct match the group you choose. For Group 2, preemption priority can be 0-3, sub-priority 0-3.
2. Verify Timer3 Clock Enable Order
You must enable the Timer3 peripheral clock before writing to any of its registers. Writing to an unclocked peripheral causes a bus error, which cascades into a HardFault.
Add this line right after enabling the NVIC priority group:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
Double-check that you're enabling the correct APB bus (TIM3 is on APB1 for STM32F100).
3. Validate Your TIM3_IRQHandler Implementation
A misnamed or incomplete interrupt handler can cause immediate crashes:
- Ensure the function name is exactly
void TIM3_IRQHandler(void)(no typos, likeTIM3_IRQ_HandlerorTIM2_IRQHandler). - Always clear the interrupt flag at the end of the handler to prevent infinite interrupt loops (which will overflow the stack and trigger HardFault):
void TIM3_IRQHandler(void) { if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { // Your logic here: write to GPIOC, toggle a pin, etc. GPIOC->ODR |= (TIM3->CNT & 0xFF); // Example: write lower 8 bits of timer count to GPIOC // Critical: clear the interrupt flag TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } }
4. Check Stack Size in the Startup File
The default stack size (usually 0x400 in startup_stm32f10x_md.s) might be too small if your interrupt handler uses local variables or has nested calls. Try increasing it to 0x800 or higher:
Stack_Size EQU 0x00000800 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp
5. Debug the HardFault Root Cause
To pinpoint exactly what's triggering the fault, use your debugger to read the system control block (SCB) registers:
SCB->HFSR: Checks for hard fault source (look for theFORCEDbit set)SCB->CFSR: Breaks down the fault type:BUSERR: Bus error (likely unclocked peripheral access)USGERR: Usage error (invalid priority configuration or misaligned memory access)
Here's a polished version of your timer initialization that addresses all the above points:
void initTimer3(void) { // 1. Set NVIC priority group first NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); // 2. Enable Timer3 clock RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // Don't forget to enable GPIOC clock if you're using it! RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // 3. Configure Timer3 base settings TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct; TIM_TimeBaseStruct.TIM_Prescaler = 7199; // 72MHz / (7199+1) = 10kHz timer clock TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStruct.TIM_Period = 9999; // Overflow every 1 second TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseStruct.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct); // 4. Enable Timer3 update interrupt TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE); // 5. Configure NVIC for TIM3 NVIC_InitTypeDef NVIC_InitStruct; NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); // 6. Start the timer TIM_Cmd(TIM3, ENABLE); }
内容的提问来源于stack exchange,提问作者Alexander Daum

