在PIC32上的HiTech C中设置功能指针的中断安全方法

时间:2010-01-28 07:37:26

标签: c embedded

我定义了一个ISR来触发外部中断。外部中断可能并不总是被启用,但在某些情况下,我希望能够在主代码中注册一个在中断内调用ONCE的函数。在下一次中断之前,该函数可能被另一个函数替换或删除。

我对PIC32上的同步技术了解不多,但我想出了以下内容:

volatile BOOL callbackInterrupted = FALSE;
volatile BOOL callbackWritten = FALSE;
void (*myCallback)() = NULL;

void RegisterCallback(void (*callback)())
{
    do
    {
        callbackWritten = FALSE;
        myCallback = callback;
    }
    while(callbackInterrupted);

    callbackWritten = (callback != NULL);
}

void interrupt MyExternalInterrupt() @EXTERNAL_1_VCTR
{
    // Do a bunch of other things here...

    if(callbackWritten)
    {
        myCallback();
        myCallback = NULL;
        callbackInterrupted = TRUE;
        callbackWritten = FALSE;
    }
}

虽然我无法推理它。这实际上是否符合我的期望,即。防止ISR调用半集函数指针,或者调用函数两次? do ... while循环是多余的吗?还有更好的方法吗?

已添加:禁用此中断是不可能的。它用于计时。

flag = TRUE生成的说明:

lui         s1,0x0
ori         s1,s1,0x1
addiu       at,s1,0
or          t0,at,zero

fnc1 = &testfunc生成的说明:

lui         a2,0x9d00
ori         a2,a2,0x50
or          a1,a2,zero
sw          a1,16376(gp)

3 个答案:

答案 0 :(得分:2)

假设设置bool是一个原子操作(反汇编和读取手册以确定) - 我会使用一个标志来设置函数指针,但这个标志只能由ISR读取,并且只能由普通代码,给你一个简单的信号量。如果写入函数指针是原子的(再次通过反汇编检查),则可以使用它而不是标志。

像这样(在我的头顶)

void (*myCallback)() = NULL;        

void RegisterCallback(void (*callback)())        
{        
   myCallback = callback;
}        

void interrupt MyExternalInterrupt() @EXTERNAL_1_VCTR        
{        
   // Do a bunch of other things here...        

   if (myCallback!=NULL)
      myCallback();        
   myCallback = NULL;        
}  

修改的 在看到反汇编指令后,使用函数指针作为标志将起作用。修改后的代码以显示用法。

答案 1 :(得分:1)

鉴于ISR存在于时间脉冲的事实,为什么要在ISR中调用该函数呢?为什么不在主代码中调用它,主代码检查脉冲时序的结果?

如果你的答案是关键的代码是在ISR的火上执行的,那么我认为你也有机会在每次执行中断之前设置一个函数来调用。在这种情况下,您唯一的选择是确定在ISR中调用下一个中断的正确函数,或者在确定在代码中的其他地方调用的正确函数时禁用中断。如果时序很关键,你还应该确保这个ISR不会受到更高优先级中断的影响。

答案 2 :(得分:0)

我只使用一个函数指针并检查中断中的非null,调用并将其设置为null。在设置指针的地方,标准解决方案是禁用中断。