title: Interrupt-safe way to set function pointer in HiTech C on PIC32
body: <p>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.</p>
  
  <p>I don't know much about techniques for synchronisation on the PIC32, but I've come up with the following:</p>
  
  <pre><code>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;
      }
  }
  </code></pre>
  
  <p>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 <code>do ... while</code> loop superfluous? Is there a better way?</p>
  
  <p><b>Added:</b> disabling this interrupt is out of the question. It is used for timing.</p>
  
  <p>Instructions generated for <code>flag = TRUE</code>:</p>
  
  <pre><code>lui         s1,0x0
  ori         s1,s1,0x1
  addiu       at,s1,0
  or          t0,at,zero
  </code></pre>
  
  <p>Instructions generated for <code>fnc1 = &amp;testfunc</code>:</p>
  
  <pre><code>lui         a2,0x9d00
  ori         a2,a2,0x50
  or          a1,a2,zero
  sw          a1,16376(gp)
  </code></pre>