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)