引入需求
中断是 MCU 开发的重点和难点,在一些临界关键代码段(经常是 ISR 和 进程共享的硬件和变量)需要禁止和使能中断。
这本来是一件容易的事情,因为编译器提供了原始语句
禁止中断 __disable_interrupt();
使能中断 __enable_interrupt();
然而,有 2 种特殊情况的引入需要特别小心设计。
嵌套调用 :禁止中断后,第 2,3 ... N 次禁止中断,仅当最后一次使能中断时才生效。
恢复初始值:禁止中断时,保存当下中断寄存器状态;使能中断时,恢复保存的中断寄存器状态。
实现代码
/*!
* Nested interrupt counter.
*
* \remark Interrupt should only be fully revert once the value is 0
*/
static uint8_t s_byIrqNestLevel = 0;
static halIntState_t s_intState;
void BoardDisableIrq( void )
{
if (0 == s_byIrqNestLevel)
{
s_intState = __get_interrupt_state();
__disable_interrupt();
}
s_byIrqNestLevel++;
}
void BoardEnableIrq( void )
{
s_byIrqNestLevel--;
if (0 == s_byIrqNestLevel)
{
__set_interrupt_state(s_intState);
}
}
单元测试
初始值,IRQ=Enable,嵌套=1层
HAL_ENABLE_INTERRUPTS();
BoardDisableIrq();
BoardEnableIrq();
初始值,IRQ=Enable,嵌套=2层
HAL_ENABLE_INTERRUPTS();
BoardDisableIrq();
BoardDisableIrq();
BoardEnableIrq();
BoardEnableIrq();
初始值,IRQ=Disable,嵌套=1层
HAL_DISABLE_INTERRUPTS();
BoardDisableIrq();
BoardEnableIrq();
初始值,IRQ=Disable,嵌套=3层
HAL_DISABLE_INTERRUPTS();
BoardDisableIrq();
BoardDisableIrq();
BoardDisableIrq();
BoardEnableIrq();
BoardEnableIrq();
BoardEnableIrq();
上面的 4 种单元测试结果说明这 2 个函数达到目标:既允许嵌套调用,又能恢复初始值。