RTC警报中断(IRQ编号41)在我的开发板上使用STM32F411CEU MCU不断被调用,甚至没有初始化RTC。我有这个默认的中断处理程序(我在startup_stm32F411ceux.s中注释了Default_Handler):
void Default_Handler(void)
{
uint32_t irq_number = __get_IPSR() & IPSR_ISR_Msk;
for(int i=0; i<nf::HAL_IRQ_map::n_interrupts;i++)
{
if(nf::HAL_IRQ_map::map[i].irq == irq_number)
{
nf::HAL_IRQ_map::map[i].irq_handler(nf::HAL_IRQ_map::map[i].params);
break;
}
}
HAL_NVIC_ClearPendingIRQ((IRQn_Type) irq_number);
}
在第一行上,我得到了IRQ号,它始终是41,这意味着RTC警报中断。在最后一行,我尝试清除IRQ,但是处理程序被连续调用。我的堆栈如下所示:
Default_Handler() at hal_irq_map.cpp:15 0x801d3e0
<signal handler called>() at 0xfffffff9
HAL_TIM_Base_Start_IT() at stm32f4xx_hal_tim.c:447 0x8016eec
HAL_InitTick() at stm32f4xx_hal_timebase_tim.c:83 0x80131ea
HAL_Init() at stm32f4xx_hal.c:176 0x8013448
main() at main.c:95 0x8012696
中断被一遍又一遍地调用,并且堆栈始终看起来像这样(程序无法执行)。 HAL_Init()在main()的第一行。我有Stm32CubeIDE和ST-LINK V2。
问题:
尝试清除中断时我做错什么了吗?
为什么不初始化而调用RTC警报中断?
编辑:
我尝试过:
void Default_Handler(void)
{
//Check if we handle the interrupt
uint32_t irq_number = __get_IPSR() & IPSR_ISR_Msk;
bool handled = false;
for(int i=0; i<nf::HAL_IRQ_map::n_interrupts;i++)
{
if(nf::HAL_IRQ_map::map[i].irq == irq_number)
{
nf::HAL_IRQ_map::map[i].irq_handler(nf::HAL_IRQ_map::map[i].params);
handled = true;
break;
}
}
if(!handled)
HAL_NVIC_DisableIRQ((IRQn_Type) irq_number);
HAL_NVIC_ClearPendingIRQ((IRQn_Type) irq_number);
}
现在,我正在显式禁用该中断,但是同一中断仍在触发。
问题是“一半”解决了:
__ get_IPSR()&IPSR_ISR_Msk似乎没有返回正确的IRQ编号。我现在通过HAL_NVIC_GetActive获取IRQ号。我还是ARM编程的新手,并且对文档的阅读不够充分。 “活动” IRQ表示正在处理它,即当前正在执行其处理程序。 “挂起” IRQ意味着将尽快调用其处理程序。因此,当您处于默认处理程序中并且想知道是哪个中断导致了此调用时,您会寻找“活动的” IRQ。
但是,我仍然不知道为什么RTC警报中断待处理,为什么不能将其禁用或清除。我认为它甚至从未启用过。
现在我的Default_Handler看起来像这样:
void Default_Handler(void)
{
uint32_t irq_number;
for(int i=0; i<50; i++) // loop is for debugging only - comment out when not used
{
if(HAL_NVIC_GetActive((IRQn_Type) i))
{
irq_number = i;
break;
}
}
bool handled = false;
for(int i=0; i<nf::HAL_IRQ_map::n_interrupts;i++)
{
if(HAL_NVIC_GetActive(nf::HAL_IRQ_map::map[i].irq))
{
nf::HAL_IRQ_map::map[i].irq_handler(nf::HAL_IRQ_map::map[i].params);
handled = true;
HAL_NVIC_ClearPendingIRQ(nf::HAL_IRQ_map::map[i].irq);
break;
}
}
if(!handled)
for(;;); //sit here forever
}
当我遍历IRQ编号时,我发现actual活动IRQ编号是TIM1_UP_TIM10_IRQn。但是为什么要调用Default_Handler而不是(正确的处理程序)TIM1_UP_TIM10_IRQHandler?
我想可能是因为我自己定义了Default_Handler。 startup_stm32f411ceux.s:
中有两行.weak TIM1_UP_TIM10_IRQHandler
.thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
TIM1_UP_TIM10_IRQHandler定义为。weak,这意味着,如果您自己定义处理程序,则它是强定义,将被使用。第二行的含义对我来说有点模糊,但是我认为,如果未定义TIM1_UP_TIM10_IRQHandler,则将使用Default_Handler代替作为处理程序。在我的代码中,对于[[TIM1_UP_TIM10_IRQHandler和Default_Handler都有严格的定义。由于我不清楚的原因,链接器选择Default_Handler作为计时器1更新中断的处理程序。
尝试使用pragmaweak
或__ attribute __((weak))定义我自己的Default_Handler弱点没有帮助。因此,我只是在startup_stm32f411ceux.s中注释了。thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler,现在正确调用了[[TIM1_UP_TIM10_IRQHandler。