This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

disable interrupts and enable interrupts if they where enabled

Hello,

I'm not sure if this was already asked before. I didn’t found a similar question, so here it is: When I have a function that manipulates a data structure to communicate with an interrupt service routine and if that manipulation can not be done atomically, an usual approach is to disable all interrupts, do the manipulation and enable all interrupts again (`__disable_irq(); manipulation(); __enable_irq() ).

The problem with this approach is that it would enable interrupts, if interrupts where already disabled. Is there a disable function, that returns the previous irq disable status?

bool was_enabled = __disable_irq();
manipulation();
if ( was_enabled )
    __enable_irq();

I don’t ask this in the context of a soft device. I’m aware that disabling interrupts is not reasonable, when using one of the soft devices.

Cheers, Torsten

Parents
  • You should be able to use __get_PRIMASK() and __set_PRIMASK() like so

    uint32_t old_primask = __get_PRIMASK();
    __disable_irq();
    manipulation();
    __set_PRIMASK( old_primask );
    

    This looks like it might have a race condition but doesn't. If interrupts were enabled and something interrupts you between the __get_PRIMASK() and the __disable_irq() and disables IRQs itself, it will restore them before it finishes so your 'old_primask' variable will still be valid.

Reply
  • You should be able to use __get_PRIMASK() and __set_PRIMASK() like so

    uint32_t old_primask = __get_PRIMASK();
    __disable_irq();
    manipulation();
    __set_PRIMASK( old_primask );
    

    This looks like it might have a race condition but doesn't. If interrupts were enabled and something interrupts you between the __get_PRIMASK() and the __disable_irq() and disables IRQs itself, it will restore them before it finishes so your 'old_primask' variable will still be valid.

Children
Related