FreeRTOS如何判断当前上下文是在中断还是在线程环境中

  • Post author:
  • Post category:其他


一、目的

很多小伙伴在使用FreeRTOS API时,肯定看到过类似这样的接口:

xSemaphoreGiveFromISR
      (
        SemaphoreHandle_t xSemaphore,
        signed BaseType_t *pxHigherPriorityTaskWoken
      );

xSemaphoreGive( SemaphoreHandle_t xSemaphore );

上图是释放信号量接口,这两个接口的区别:中断上下文中只能调用带FromISR后缀的接口 ;线程上下文中只能调用不带FromISR后缀的接口。存在这样的区别是因为FreeRTOS线程调度在线程中的实现与在中断中的实现方式不同,这个在以后的博文再解释。

有时候我们封装接口时可能需要判断当前上下文是在中断还是线程中,那如何判断呢?

由于跟硬件芯片平台强相关,所以FreeRTOS以xPortIsInsideInterrupt这个接口来适配不同平台,但是在Cortex-M系列的MCU上基本上实现方式都是一样的。

第一种:

    portFORCE_INLINE static BaseType_t xPortIsInsideInterrupt( void )
    {
        uint32_t ulCurrentInterrupt;
        BaseType_t xReturn;
 
        /* Obtain the number of the currently executing interrupt. */
        __asm volatile ( "mrs %0, ipsr" : "=r" ( ulCurrentInterrupt )::"memory" );
 
        if( ulCurrentInterrupt == 0 )
        {
            xReturn = pdFALSE;
        }
        else
        {
            xReturn = pdTRUE;
        }
 
        return xReturn;
    }

第二种:

/**
  \brief   Get IPSR Register
  \details Returns the content of the IPSR Register.
  \return               IPSR Register value
 */
__STATIC_INLINE uint32_t __get_IPSR(void)
{
  register uint32_t __regIPSR          __ASM("ipsr");
  return(__regIPSR);
}

其实无论是哪种方式,关键的代码都是


获取IPSR寄存器的值


,那IPSR是什么寄存器呢?

二、原理

从Cortex-M权威手册上我们可以找到准确的答案




Arm Cortex-M7 Devices Generic User Guide r1p2



https://developer.arm.com/documentation/dui0646/c/The-Cortex-M7-Processor/Programmers-model/Core-registers?lang=en


IPSR寄存器记录着当前处理的异常/中断的中断号,如果为0,就说明当前不在中断上下文中。



需要注意的是IPSR寄存器只能在特权级下访问。

下图就是寄存器组中关于IPSR的状态信息

OK,本篇内容到此结束。



版权声明:本文为tianizimark原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。