问题描述
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 个,但在我的情况下,错过多个中断的可能性极小。