[信息] 判断函数是否在中断中运行

[复制链接]
160|0
Zhiniaocun 发表于 2025-11-7 14:22 | 显示全部楼层 |阅读模式
1. 通过 portENTER_CRITICAL() 和 portEXIT_CRITICAL() 检查中断嵌套
在 FreeRTOS 中,操作系统使用中断嵌套来实现任务调度。当发生中断时,FreeRTOS 通过禁用中断来保护临界区。因此,你可以使用这些函数来判断当前是否处于中断上下文中。

portENTER_CRITICAL() 和 portEXIT_CRITICAL() 是 FreeRTOS 提供的保护临界区的宏,它们会禁用/恢复中断。如果当前正在执行中断,调用这些函数时会影响中断优先级。

你可以通过检查这些宏是否影响当前上下文来推测当前代码是否在中断中执行。

2. 通过 xPortIsInsideInterrupt() 函数
FreeRTOS 提供了一个名为 xPortIsInsideInterrupt() 的函数(对于不同的移植,它可能有不同的名字),它可以用来判断当前代码是否在中断上下文中。

if (xPortIsInsideInterrupt()) {

    // 当前代码在中断上下文中执行

} else {

    // 当前代码在任务上下文中执行

}


3. 通过检查中断标志
在一些嵌入式系统中,MCU 通常会有标志位或寄存器来表示当前是否处于中断上下文。例如,ARM Cortex-M 系列处理器可以通过 PRIMASK 寄存器来判断当前是否处于中断上下文。

uint32_t primask = __get_PRIMASK();

if (primask == 0) {

    // 当前处于中断上下文

} else {

    // 当前处于任务上下文

}



        PRIMASK 为 0 时表示中断已被禁用,通常表示代码处于中断上下文。为 1 时表示中断已被允许,通常表示代码处于任务上下文。

4. 通过 FreeRTOS 任务调度器状态
        FreeRTOS 内部有任务调度器的状态可以判断是否在任务上下文中执行。如果任务调度器正在运行,当前代码就是在任务上下文中执行。你可以通过特定的 FreeRTOS 内部函数来检查当前是否在任务中运行。

        例如,可以检查 uxTaskGetTaskNumber(NULL) 返回的值(或其他 FreeRTOS 内部 API),但这些方法较为复杂且依赖于特定的 FreeRTOS 实现。

5. 通过 STM32 特定寄存器(如果是 STM32)
        对于 STM32 等嵌入式平台,可以通过查看中断相关的寄存器来判断。例如,对于 ARM Cortex-M 系列的 STM32 处理器,可以通过以下寄存器来判断:

// 检查是否处于中断上下文

if (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) {

    // 当前是中断上下文

} else {

    // 当前是任务上下文

}



        SCB->ICSR 寄存器中的 VECTACTIVE 位表示当前正在执行的中断向量的编号。如果值大于 0,说明当前是中断上下文。

可以通过以下几种方式来判断一个函数是否在中断中运行:
使用 xPortIsInsideInterrupt()(如果是 FreeRTOS)。

通过 PRIMASK 寄存器判断(对于 ARM Cortex-M 系列)。

通过 FreeRTOS 内部状态或任务调度器标志来判断。

检查特定硬件平台的中断控制寄存器(如 STM32 的 SCB->ICSR 寄存器)。

FreeRTOS下测试:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    switch (GPIO_Pin) {
        case KEY1_Pin:
            if (xPortIsInsideInterrupt()) {
                // 当前代码在中断上下文中执行
                printf("HAL_GPIO_EXTI_Callback 在中断上下文中执行\n");




            }else {
                // 当前代码在任务上下文中执行
                printf("HAL_GPIO_EXTI_Callback 任务上下文中执行\n");
            }
            break;
        default:
            break;
    }
}



/**
* 任务函数myTestTaskFunc
* 该函数是任务myTestTask的具体执行体,无限循环打印任务运行信息,并延迟1秒
* 参数argument:任务启动时传递的参数,本例中未使用
*/
void myTestTaskFunc(void const * argument) {
    while (1) {
        if (xPortIsInsideInterrupt()) {
            // 当前代码在中断上下文中执行
            printf("myTestTaskFunc 在中断上下文中执行...\r\n");
        } else {
            // 当前代码在任务上下文中执行
            printf("myTestTaskFunc 在任务上下文中执行...\r\n");
        }
        osDelay(1000);
    }
}



输出:

22002690c484ea61fc.png

正确。

CMSIS-RTOS自己实现的判断:

if (inHandlerMode()){    // 是否在中断中运行


}


/* Determine whether we are in thread mode or handler mode. 确定是处于线程模式还是处理程序模式 */
static int inHandlerMode (void)
{
  return __get_IPSR() != 0;
}

93559690c48453abe5.png

————————————————
版权声明:本文为CSDN博主「几个叶子」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44015616/article/details/154300948

您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

312

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部