12. April 2014 · Categories: Software

On the Cortex-M processors, you typically use critical sections to isolate accesses of interrupt handlers from the main program. The assembler needed for this is pretty straightforward, the question is how do we best implement it in C++? First a version for Gnu C++:

Here we do a few things to ensure the compiler generates correct and optimal code for us:

  • The saved interrupt status is accessed directly as a register. This allows the compiler to keep the status in a register if beneficial, and since you need to move it into a register for access anyways, no performance is lost.
  • The fake dependency on line 5 ensures lines 4 and 5 are never swapped. We could do this in one __asm statement, but splitting it into two allows the compiler to insert a store between the two of them, if needed, which minimizes the time spent blocking interrupts.
  • Lines 6 and 9 are memory barriers which prevent the compiler from moving any memory accesses outside the lock.
  • The volatile keyword is needed to ensure that the compiler does not optimize these statements away, as they appear to him to have no effect.
  • Be careful when calling it, it must be InterruptLock var;

If you are using the Keil compiler, the lock would look pretty much the same. Here the intrinsic __schedule_barrier() is used to ensure that the compiler does not reorder code across the lock.