在 PIC32 上的 HiTech C 中设置函数指针的中断安全方法
我定义了一个 ISR 来触发外部中断。外部中断可能并不总是启用,但在某些情况下,我希望能够注册一个函数,以便在主代码内的中断内调用一次。在下一次中断之前,该函数可能会被另一个函数替换或删除。
我对 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)
I have an ISR defined to trigger on an external interrupt. The external interrupt may not always be enabled, but under certain circumstances I want to be able to register a function to be called ONCE within the interrupt from within the main code. The function might be replaced by another one, or removed, before the next interrupt.
I don't know much about techniques for synchronisation on the PIC32, but I've come up with the following:
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;
}
}
I'm having trouble reasoning about it though. Does this actually do what I hope, ie. prevent the ISR calling a half-set function pointer, or calling a function twice? Is the do ... while
loop superfluous? Is there a better way?
Added: disabling this interrupt is out of the question. It is used for timing.
Instructions generated for flag = TRUE
:
lui s1,0x0
ori s1,s1,0x1
addiu at,s1,0
or t0,at,zero
Instructions generated for fnc1 = &testfunc
:
lui a2,0x9d00
ori a2,a2,0x50
or a1,a2,zero
sw a1,16376(gp)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
假设设置 bool 是一个原子操作(反汇编并阅读手册以确保) - 我将使用一个标志来设置函数指针,但该标志只能由 ISR 读取,并且只能由普通代码写入,给你一个简单的信号量。如果编写函数指针是原子的(再次通过反汇编进行检查),则可以使用它而不是标志。
像这样(在我的脑海中)
编辑
看到反汇编指令后,使用函数指针作为标志就可以了。修改代码以显示用法。
Assuming setting the bool is an atomic operation (disassemble & read the manual to be sure) - I would use a flag to set the function pointer, but this flag shold only be read by the ISR, and only written by the normal code, giving you a simple semaphore. If writing the function pointer is atomic (again, check by disassembling), you can use it instead of the flag.
Like this (off the top of my head)
Edit
After seeing disassembled instructions, using the function pointer as a flag will work. Modified code to show usage.
考虑到 ISR 是用来对脉冲计时的,为什么还要调用 ISR 中的函数呢?为什么不在主代码中调用它来检查脉冲定时的结果呢?
如果您的答案是在 ISR 触发时执行代码很重要,那么我认为您有机会设置一个在每次执行中断之前调用的函数也很重要。在这种情况下,您唯一的选择是确定在 ISR 中调用下一个中断的正确函数,或者在确定在代码中其他地方调用的正确函数时禁用中断。如果时序很关键,您还应该确保此 ISR 不会被更高优先级的中断所影响。
Given the fact that the ISR is there to time pulses why call the function within the ISR at all? Why not call it in the main code where ever it is that the main code checks up on the results of the pulse timing?
If your answer is that its critical the code is executed on the fire of the ISR, then i assume its also critical that you have the opportunity to set a function to call prior to every execution of the interrupt. In this case your only options are to determine the proper function to call for the next interrupt within the ISR or to disable the interrupt while you determine the proper function to call elsewhere in the code. If timing is critical you should also make sure this ISR can't be bumped by a higher priority interrupt.
我将仅使用函数指针并检查中断中是否为非空,调用并将其设置为空。在设置指针的地方,标准解决方案是禁用中断。
I would use only a function pointer and check that for non-null in the interrupt, call and set it to null. Where you set the pointer the standard solution would be to disable interrupts.