Part Number: TMS320F28379D
Tool/software:
Hi
My question
Please see the chapter Background below for extended context.
There are three intrinsics for handling global en-/dis-able of interrupts
- __disable_interrupts
- __enable_interrupts
- __restore_interrupts
#3. sounds like the obvious candidate when you want to restore the interrupt after having disabled them.
But sifting through the docs and the forum, it appears that 90% uses #1. and #2., only calling #2. if bit 0 (INTM) in the returned value from #1. was 1.
Also driverlib only provides functions that uses #1. and #2.
I wondered why that was the case, as the #3. (restore( seams to much more simple and straightforward to use.
Looking at the assembly instructions from those intrinsics as documented in SPRU514Y, I see that #3. (restore) restores the entire St1 register, as opposed to #1 and #2 that calls SETC and CLRC to only affect DNGM and INTM.
So my question is:
Is there a reason why most sources uses the more cumbersome __disable_interrupts / __enable_interrupts.?
Is there an unexpected side-effect of using __restore_interrupts and its complete retore of ST1?
Background
To protect a critical part of the code from interrupts either because of timing or access to shared objects, i have used this construct.
bool irqWasEnabled = ! Interrupt_disableGlobal();
// Critical
// code
// lines
// ...
if( irqWasEnabled )
{
Interrupt_enableGlobal();
}
// ...
The last part can be refactored into a one-liner
if( irqWasEnabled ) Interrupt_enableGlobal();
but that is not allowed in many coding-standards.
So i looked at other constructs the obvious solution was to make a pair of functions So I get
NoInterrupt_start(); // Critical // code // lines // ... NoInterrupt_end(); // ...
Those functions then use a file-static variable to carry the state, from _start to _end. Thus I had to look into if there could be a race condition around that variable if two locations in the code would call those functions, one being in interrupt context.
For reference the functions is implemented as
typedef unsigned int irqStatus_t;
static irqStatus_t irqStatus = False;
static void NoInterrupt_start( void )
{
IrqWasEnabled = ! Interrupt_disableGlobal();
}
static void NoInterrupt_end( void )
{
if( IrqWasEnabled )
{
Interrupt_enableGlobal();
}
}
But during this search I found this intrinsic
void __restore_interrupts( irqStatus_t val );
This looks like a way more simple solution, as I can then just use
irqStatus_t irqState = __disable_interrupts(); // Critical // code // lines // ... __restore_interrupts( irqState ); // ...
But as stated in the beginning of this post, I am not sure if the __restore_interrupts might have other side effects.