Disable-Enable Interrupts

The easiest and fastest way to gain exclusive access to a shared resource is by disabling and enabling interrupts, as shown in the pseudo-code in the listing below.


Disabling and Enabling Interrupts
              Disable Interrupts;
              Access the resource;
              Enable  Interrupts;


µC/OS-III uses this technique (as do most, if not all, kernels) to access certain internal variables and data structures, ensuring that these variables and data structures are manipulated atomically. However, disabling and enabling interrupts are actually CPU-related functions rather than OS-related functions and functions in CPU-specific files are provided to accomplish this (see the cpu.h file of the processor being used). The services provided in the CPU module are called µC/CPU. Each different target CPU architecture has its own set of µC/CPU-related files.


Using CPU Macros to disable and enable interrupts
          void YourFunction (void) 
          {
              CPU_SR_ALLOC();                 (1)
           
           
              CPU_CRITICAL_ENTER();           (2) 
              Access the resource;            (3) 
              CPU_CRITICAL_EXIT();            (4) 
          }

(1) The CPU_SR_ALLOC() macro is required when the other two macros that disable/enable interrupts are used. This macro simply allocates storage for a local variable to hold the value of the current interrupt disable status of the CPU. If interrupts are already disabled we do not want to enable them upon exiting the critical section.

(2) CPU_CRITICAL_ENTER() saves the current state of the CPU interrupt disable flag(s) in the local variable allocated by CPU_SR_ALLOC() and disables all maskable interrupts.

(3) The critical section of code is then accessed without fear of being changed by either an ISR or another task because interrupts are disabled. In other words, this operation is now atomic.

(4) CPU_CRITICAL_EXIT() restores the previously saved interrupt disable status of the CPU from the local variable.

CPU_CRITICAL_ENTER() and CPU_CRITICAL_EXIT() are always used in pairs. Interrupts should be disabled for as short a time as possible as disabling interrupts impacts the response of the system to interrupts. This is known as interrupt latency. Disabling and enabling is used only when changing or copying a few variables.

Note that this is the only way that a task can share variables or data structures with an ISR.

µC/CPU provides a way to actually measure interrupt latency.

When using µC/OS-III, interrupts may be disabled for as much time as µC/OS-III does, without affecting interrupt latency. Obviously, it is important to know how long µC/OS-III disables interrupts, which depends on the CPU used.

Although this method works, you should avoid disabling interrupts as it affects the responsiveness of the system to real-time events.