19

我正在为 ARM Cortex M3 (NXP LPC1769) 微控制器开发软件。目前我正在寻找一种机制来检测我的函数是否在 ISR 中被调用。我想我必须检查登记册。基于这些信息,我想调用困难的函数。

如果有包含必要信息的寄存器,我已经检查了参考手册。

例如,我尝试根据“中断活动位寄存器”(IABR)寄存器检测是否从 ISR(我使用 SysTick-ISR)调用了我。如果 ISR 处于活动状态,则该寄存器应为 != 0。但值是 0x00000000。这意味着没有中断处于活动状态。除了这个测试,我在参考手册中检查了 NVIC 和 SC 寄存器,寻找包含必要标志的寄存器,但我没有找到。

有人知道适合我的问题的寄存器/机制吗?

4

4 回答 4

29

您需要测试中断控制状态寄存器的VECTACTIVE字段。

我使用以下内容:

//! Test if in interrupt mode
inline bool isInterrupt()
{
    return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0 ;
}

SCM 和 SCB_ICSR_VECTACTIVE_Msk 是在 CMSIS (core_cm3.h) 中定义的,我想它会间接包含在您的部分特定标头中(我猜是 lpc17xx.h 或类似的)。我正在使用 C++,包括 C 中的 stdbool.h 将为您提供 bool 类型,或更改为您自己的 int 或 typedef。

然后使用它,例如:

void somefunction( char ch )
{
    if( isInterrupt() )
    {
        // Do not block if ISR
        send( ch, NO_WAIT ) ;
    }
    else
    {
        send( ch, TIMEOUT ) ;
    }
}

如果需要假设不了解架构的解决方案,请考虑以下事项:

volatile int interrupt_nest_count = 0 ;
#define ENTER_ISR() interrupt_nest_count++
#define EXIT_ISR()  interrupt_nest_count--
#define IN_ISR() (interrupt_nest_count != 0)

void isrA()
{
     ENTER_ISR() ;
     somefunction( 'a' ) ;
     EXIT_ISR() ;
}

void isrB()
{
     ENTER_ISR() ;
     somefunction( 'b' ) ;
     EXIT_ISR() ;
}

void somefunction( char ch )
{
    if( IN_ISR() )
    {
        // Do not block if ISR
        send( ch, NO_WAIT ) ;
    }
    else
    {
        send( ch, TIMEOUT ) ;
    }
}

然而,问题是指安全检测中断上下文,这依赖于添加到所有ISR 的进入/退出宏。

于 2013-05-21T13:42:24.110 回答
15

经过一番讨论和更多搜索,我找到了正确的寄存器:中断程序状态寄存器:IPSR包含当前中断服务程序(ISR)的异常类型号。有关其属性,请参见表 626 中的寄存器摘要。

如果没有从 isr 调用函数,则寄存器的值为 IPSR == 0

于 2013-05-20T20:30:18.663 回答
0

最简单的方法是将上下文作为参数传递给函数。它也是独立于平台的。

typedef enum _context {
    normal_context = 0,
    isr_context = 1
} context;

从 ISR 调用函数:

func(param1, param2, isr_context);

从普通代码调用函数:

func(param1, param2, normal_context);

如果 ISR 代码不受您的控制并且您只是传递一个函数指针,那么只需使用两个不同的包装函数。一个传递 isr_context,另一个传递 normal_context 作为函数的参数。

于 2013-05-20T20:07:31.783 回答
0

最好的方法可能是创建两个不同的函数:一个从 ISR 调用,另一个从程序的其余部分调用。

如果这不是一个选项,那么您可以使用纯标准 C 来确定调用者,不需要寄存器:

inline void my_func (const char* caller);

static void isr (void)
{
  my_func(__func__);
}


inline void my_func (const char* caller)
{
  if(strcmp(caller, "isr")==0)
  {
    // was called from isr
  }
  else
  {
    // called from elsewhere
  }
}

如果你给你的 ISR 起聪明的名字,上面的代码将足够快地从一个 isr 运行。

于 2013-05-21T08:40:25.817 回答