Go Down

Topic: Arduino Due - Saving and Restoring Interrupt Enable (Read 788 times) previous topic - next topic

RayLivingston

Oct 31, 2014, 07:59 pm Last Edit: Oct 31, 2014, 07:59 pm by RayLivingston
I have a project using a Due, which is very heavily interrupt-driven.  There are a few low-level classes that interact with external hardware (a custom FPGA that requires some pretty complex bit-banged I/O to communicate with it).  The methods in these classes that "talk" to the hardware cannot be interrupted, lest the bit-banged I/O sequence get broken, so they must run with interrupts disabled.  BUT, some of them can be called either from a foreground task or an interrupt handler, so they need to be able to save the current interrupt enable state, disable all interrupts, do their thing, then restore the interrupt enable state to what it was on entry. 

It appears to me the way to do this is by saving the ARM PRIMASK register, writing it to disable all maskable interrupts (writing 0x10 to PRIMASK if I'm understanding correctly), then restoring the saved value when done.  It also appears this code needs to be semaphored, since the register accesses are not atomic.  I have been unable to find existing code to do this, and my attempts at writing my own methods have been less than successful.

So, does anyone have code to do this safely and robustly?

Regards,
Ray L.

PaulS

You know, if I had a Due question, I think I just might post it in the Due section of the forum. YMMV.
The art of getting good answers lies in asking good questions.

RayLivingston

Nobody has had to deal with this issue??

Regards,
Ray L.

RayLivingston

Well, I think I have a solution, though not quite what I really wanted.  Under current conditions, I think it is safe, and certainly seems to work fine.

To mask interrupts:

__set_BASEPRI(1 << (8 - __NVIC_PRIO_BITS));

To unmask interrupts:

__set_BASEPRI(0);

This assumes, I believe correctly, that the Arduino code never modifies the PRIMASK register.  If it does, this will not work reliably under all conditions.

The more robust solution I'd prefer to have would involve a semaphore to control "ownership" of the PRIMASK register.  Once a task has the semaphore, it would save the current PRIMASK value, mask all interrupts, do what it needs to do, then restore PRIMASK to its entry state, and release the semaphore.

Regards,
Ray L.

Go Up