STM32 µC:SysTick 延迟在中断处理程序中不起作用

STM32 µC: SysTick delay doesn't work inside interrupt handler

所以我用 C 语言为 STM32F103C8T6 微控制器编写了一个程序,使用了 RTC(实时时钟)和一个显示模块。

RTC 和显示器都工作正常,但是当我尝试从 RTC 中断处理程序内部更新显示器时,它不起作用。

当我从 main() 中向显示器写入内容时,它工作得很好。

中断处理程序也能正常工作,所以我认为问题出在写入显示器的函数中。

此函数使用小延迟来对与显示控制器的通信进行位爆炸。

我之前使用 SysTick 生成这样的延迟:

void delay(uint32_t n){
    uint32_t start =  systick_count;
    while (systick_count - start < n);
    return;
}

但不知何故,在 RTC 的中断处理程序中它不起作用。所以我用这个替换了我的延迟函数,而不是使用 SysTick:

for (; i>0; i--) {
    for (int j = 0; j < 72; ++j) {
        __asm__ __volatile__("nop\n\t":::"memory");
    }
}

现在一切正常。

我试图理解为什么 SysTick 显然在 RTC 中断处理程序中不起作用。

我想可能是中断优先级引起的,但根据数据表,默认情况下 SysTick Interrupt 的优先级高于 RTC 中断优先级。

也许有人可以解释,为什么会这样?

EDIT1:好的,所以我已经阅读了更多关于中断优先级的内容,看来我需要正确配置 NVIC_IRQChannelPreemptionPriority。我会尽快尝试这个...

关于中断内部的延迟,我知道这不是正确的做法,但我仍然想了解程序的行为

EDIT2:我刚刚尝试通过以下方式更改中断优先级:

// set RTC interrupt priority to 15 (lowest)
NVIC_SetPriority(RTC_IRQn, 15);
// set interrupt priority of SysTick to 0 (highest)
NVIC_SetPriority(SysTick_IRQn, 0);

现在 SysTick 延迟在 RTC 中断处理程序中起作用。

您使用SysTick 实现延迟的方式与来自ST 的HAL 库中的HAL_Delay 相同。它的工作方式是 SysTick 不断递增(通常以 1 毫秒为间隔)一个变量 - systick_count 在你的例子中 - 与延迟函数内部的局部变量进行比较 - start 在你的例子中。

这里要注意两点:

  1. systick_count 需要设置为 volatile 以强制在每次比较之前重新读取其值。它是由中断修改的,而不是在该函数内部修改的。您的编译器可能会选择优化这部分代码。

  2. SysTick中断在调用delay函数时需要"running"。如果不是,例如因为您处于更高优先级(数值较低)的中断中,所以您处于死锁状态并且延迟功能将永远不会完成,因为计数器永远不会被从未发生过的 SysTick 递增。关于这一点——不要假设,只依赖数据表。继续并在延迟时实际验证它是 运行ning。要么在调用延迟函数时检查 NVIC 寄存器值,要么在 RTC 中断时简单地在 SysTick 中设置一个断点——当你在延迟函数中时,它应该会到达该断点。如果不是-您可能需要调整中断优先级。

关于延迟中断的整个想法 - 它通常被认为是不好的做法。中断应该用于非常快速地完成非常小的部分工作,例如设置一个标志,表明需要在主程序代码中完成某些事情,或者将接收到的字节放入队列中以供以后处理。虽然这在一个只有一个中断(如果算上 Systick 的话是两个)的简单程序中可能看起来并不明显,但一旦添加更多中断,它很快就会出现问题,并且 运行 会出现丢失信息等问题,因为您的中断相互阻塞,并且调用速度不够快。