What are the equivalent of cli() and sei() in DUE.

Hi, guys . i am looking for a cli() and sei() equivalent for DUE except interrupts() and noInterrupts().

does anyone know?

What's wrong with interrupts() and noInterrupts() ? Those ARE the equivalents for sei/cli, and translate directly to ARM-specified __enable_irq compiler intrinsics, which in turn end up being single instructions.

nothing wrong. i just want to know. i want to learn core language. do u have answer Mr. wetfw.

The equivalent of sei() and cli() for ARM processors are __enable_irq() and __disable_irq().

For the Due, the definitions are contained in the core file: "wiring_constants.h".

#define interrupts() __enable_irq()
#define noInterrupts() __disable_irq()

Thanks MartinL.

On AVR, sei() and cli() control the global interrupt enable GIE bit. It has 3 purposes:

  • Enable interrupt for everything
  • Temporarily mask interrupts for critical sections of code
  • Prevent other interrupts from happening while running ISR code

People who are familiar with AVR and PIC are not accustomed to thinking of these 3 tasks distinctly. Mentally they just tend to get lumped together into a general notion of enable/disable interrupts, because the hardware is simple and rather limited.

On ARM, there are separate mechanisms for all 3 of these functions.

The PRIMASK bit is controlled by __enable_irq() and __disable_irq(). It's intended only for #2.

For #1, there are sets of interrupt enable/disable registers in the NVIC (ARM's Cortex-M interrupt controller) meant for enabling interrupts. PRIMASK is NOT meant for that function. In fact, at startup PRIMASK defaults to allowing all interrupts, because it's really only intended for function #2.

Probably the biggest improvement ARM offers and the place people only familiar with AVR & PIC misunderstand the most is function #3. On AVR, the hardware automatically disables the GIE bit when it runs your interrupt, and turns it back on when your interrupt returns. If you think of ARM's PRIMASK this way, you'll make mistakes. ARM does NOT change PRIMASK when entering an interrupt.

Instead, ARM Cortex-M supports priority nested interrupts. This is a really awesome feature, if used by software (priority levels properly configured). Suppose an interrupt runs with mid-level priority. All the other interrupts at the same or lower priority are blocked, like they would be on AVR with the hardware automatically disabling GIE. But all the higher priority interrupts remain able to interrupt. So if you've got some long-running interrupt, other interrupts like the SysTick for the millis timing can still interrupt it, so you don't lose timing counts. If the priorities are assigned well (on Teensy they are... so far not so well on Due) you get really wonderful compatibility where libraries that need low latency can get it, but other libs that don't still work without the interrupt compatibility problems that are so common on AVR.

Anyway, the takeaway is these ARM functions aren't meant to be exactly the same as AVR's. Use them for short critical sections in your code, but don't assume everything else about how interrupts works mirrors AVR. These ARM processors has so much better capability, and sadly it's usually wasted because people understand only the older, less capable 8 bit systems and don't take advantage of the great features ARM provides.

2 Likes

+1

See my post in a previous thread, reply #6 :
https://forum.arduino.cc/index.php?topic=443741.0

The interrupt management in Cortex M3 is one of the most awesome features, although the multiple priority numbering conventions used in managing the interrupt priorities are often counter-intuitive, inconsistent, and confusing, which can lead to bugs.

A short tutorial on this subject would greatly help beginners and even some advanced users. As a good starting point, I suggest the reading of this site:
http://embeddedgurus.com/state-space/2014/02/cutting-through-the-confusion-with-arm-cortex-m-interrupt-priorities/