允许嵌套调用和恢复初始值,禁止和使能 MCU 中断的方法

引入需求

中断是 MCU 开发的重点和难点,在一些临界关键代码段(经常是 ISR 和 进程共享的硬件和变量)需要禁止和使能中断。
这本来是一件容易的事情,因为编译器提供了原始语句
禁止中断 __disable_interrupt();
使能中断 __enable_interrupt();

然而,有 2 种特殊情况的引入需要特别小心设计。
嵌套调用 :禁止中断后,第 2,3 ... N 次禁止中断,仅当最后一次使能中断时才生效。
恢复初始值:禁止中断时,保存当下中断寄存器状态;使能中断时,恢复保存的中断寄存器状态。

实现代码

/*!
 * Nested interrupt counter.
 *
 * 
emark 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 个函数达到目标:既允许嵌套调用,又能恢复初始值。

原文地址:https://www.cnblogs.com/rimelink/p/12617679.html