Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
21 years ago

Atomic Instruction Block

Is there a faster way to make a critical block of instructions atomic (not interruptible) than using the alt_irq_disable_all and alt_irq_enable_all HAL functions?

Chris

3 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I don't know exactly how the hal implements it, but in the legacy SDK, I use some macro's with a direct assembler instruction.

    Normaly, disbling and enabling interrupts take only one instruction.

    And if you want to store the status from before disabling (if you want to nest enables, disables) on the stack, you need some more.

    The macros look like this (DWORD is an unsigned long = 32 bit):

    /** Local stack space for processor status word.

    * Must be placed in the same scope where CRITICAL() and END_CRITICAL() is used

    * \hideinitializer

    */# define CONTAINS_CRITICAL DWORD stored_status;

    /** Begin critical section.

    * Interrupts will be disabled after this macro. \n

    * CRITICAL() must always be used in pair with END_CRITICAL().

    * \hideinitializer

    */# define CRITICAL { __asm__ volatile ("rdctl %0, status" : "=r" (stored_status));

    __asm__ volatile ("wrctl status, r0");

    }

    /** End critical section.

    * Interrupts will be enabled after this macro if they were enabled before CRITICAL(). \n

    * END_CRITICAL() must always be used in pair with CRITICAL().

    * \hideinitializer

    */# define END_CRITICAL { __asm__ volatile ("wrctl status, %0" :: "r" (stored_status)); }

    If you want to use, do this :

    void foo()

    {

    CONTAINS_CRITICAL

    // normal section

    CRITICAL

    //interrupts disabled here

    END_CRITICAL

    //normal section

    CRITICAL

    //interrupts disabled here

    END_CRITICAL

    }
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    If you find a more efficient way then I'd be interested to hear it.

    At optimisation level -O2 these functions compile up into exactly the same code as described above:

    rdctl rx, status
    wrctl status, zero

    at the start and

    wrctl status, rx

    at the end (where rx is a register between r2 and r23 chosen by the compiler).

    Please check your objdump file to see what the compiler has generated for you.