ATMELStudio Included ASM Interrupt Enable/Disable Functions & Memory Barriers (interrupt.h and atomic.h)

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

 

I am wondering if any of you C/ASM gurus could help me answer some questions I have regarding some programming fundamentals.

 

Question #1:

Regarding the ATMELStudio include/avr interrupt.h SEI and CLI interrupt flag functions:

 

I noticed that the author of this file used "memory barriers" when using the assembly code instruction for setting (SEI) and clearing (CLI) the interrupt flags as follows:

//Enable interrupts:
# define sei() __asm__ __volatile__ ("sei" ::: "memory");

//Disable interrupts:
# define cli() __asm__ __volatile__ ("cli" ::: "memory");

From my understanding, these assembly instructions simply set the interrupt flag either to 0 or 1.  No memory is modified by the assembly code itself.  The __asm__ volatile statement will guarantee the assembly code is executed wherever it is called.  I don't however understand why the "::: memory" barrier was used in this case, being that we know only the interrupt register value is modified without affecting any memory.  It seems like for a simple task such as setting a register flag, the memory barrier will cause unnecessary processing overhead by forcing the storage of values in any cache before executing the asm code and reloading them after the asm code has executed.

 

Why would the author not simply use the following code to set the interrupt flags and reduce the processing overhead by removing the memory clobbers?:

//Enable interrupts: 
asm volatile("sei");
//Disable interrupts: 
asm volatile("cli");

 

Question #2:

In the atomic.h file, I understand the usefulness of ATOMIC_RESTORESTATE and NONATOMIC_RESTORESTATE since these store the SREG values on entry to memory and restore the SREG values on exit.  However, looking at the ATOMIC_FORCEON and NONATOMIC_FORCEOFF options, I am not understanding their usefulness.

 

How are these two any different from the following code where I manually control CLI on entry and SEI on exit?

 

 

What I believe is the equivalent to (ATOMIC_FORCEON):

//Disable interrupts: 
asm volatile("cli");

x = y+2;
    
//Enable interrupts: 
asm volatile("sei");

What I believe is the equivalent to (NONATOMIC_FORCEON):

//Enable interrupts: 
asm volatile("sei");

x = y+2; 

//Disable interrupts: 
asm volatile("cli"); 

 

Thanks, I appreciate the help!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The memory barrier is the force the compiler inti placing the code where you want it to be. Otherwise it is free to re-arrange your code so your cli() and sei() might not end up where you expect.
FYI There’s no cache in an AVR.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You probably want to google "sequence point". A memory barrier forces one.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

clawson wrote:

You probably want to google "sequence point". A memory barrier forces one.

That was an interesting read. Always assumed an expression was handled from left to right with braces handled first. But that does not automatically seems to be the case....