重新发出 SysTick 中断

问题描述

我有一个SysTick中断,每秒触发4次任务切换,如下图。

void SysTick_Handler(void) {
  SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; // Set PendSV 
}

main 中的任务偶尔会通过其中一个 UART 输出一些消息,并且为了确保它们具有独占的 I/O 访问权限,输出例程使用由 LDREX 和 STREX 设置的互斥锁保护。代码在 90% 以上的情况下都能正常运行。

但是,这种保护的一个副作用似乎是,在设置互斥锁期间发生 SysTick 时,不会发生任务切换,此时正在运行的任务将继续运行,直到下一个任务切换。

有没有办法再次触发 SysTick,比如说 10 毫秒后,然后一直执行直到当前正在运行的任务清除互斥锁?例如:

void SysTick_Handler(void) {
  if (mutex) {
    // set SysTick to trigger again in 10 ms 
  } else {
    SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; // Set PendSV 
  } 
}

如果是,如何。

TIA

解决方法

在互斥体释放函数中设置 SysTick、PendSV、SVCall 或其他一些待处理的中断。

如果您想避免不必要的中断成本,您可以在 systick 处理程序中设置一个原子标志,并在互斥体释放函数中检查它,以便只有在您错过预定运行时才触发中断。

,

我按照 Tom V 的建议实施了一个解决方案,它的效果非常好!!谢谢!!

关键部分:

void SysTick_Handler(void)
{
    if (mutex > 0) {
        sigint++; 
    } else {
        sigint = 0;
        SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; // Set PendSV to pending
    }
}

和:

// in mutex release
if (sigint) {
    __asm(" CPSID i");  
    sigint = 0; 
    (*systick_ptr)(); 
    __asm(" CPSIE i"); 
} 

但是,请注意,此解决方案确实至少有一个“功能”:如果此代码错过了 1 个以上的中断,它将仅构成 1 个,但在我的情况下,错过多个中断的可能性极小。