XCore DevInt

Files CCore/inc/dev/DevInt.h CCore/src/dev/DevInt.cpp CCore/src/dev/DevInt.s

This part implements one of the key class: IntLock class.


/* DevInt.h */

#ifndef CCore_inc_dev_DevInt_h
#define CCore_inc_dev_DevInt_h

#include <CCore/inc/Gadget.h>

namespace CCore {
namespace Dev {

/* functions */

bool IsIntContext() noexcept;

/* classes */

class IntLock;

/* class IntLock */

class IntLock : NoCopy
 {
   bool enable;

  public:

   IntLock() { enable=Internal::Disable(); }

   ~IntLock() { if( enable ) Internal::Enable(); }

   struct Internal
    {
     static bool Disable() noexcept;

     static void Enable() noexcept;
    };
 };

} // namespace Dev
} // namespace CCore

#endif

IntLock class disables interrupts in its constructor and enables in the destructor. But if interrupts was already disabled it does nothing. This class is used to create an interrupt protected scope. All instructions inside such scope are performed without any interventions. An IntLock scope must be efficient: i.e. must be quick and cannot perform any blocking calls. The interrupt context has already interrupts disabled, so using this class in the interrupt context is safe (but useless).

IsIntContext() returns true if called in the interrupt context and false otherwise.

IntLock::Internal::Disable() disables interrupts and return true, if they has been enabled.

IntLock::Internal::Enable() enables interrupts.

All these functions are CPU specific and implemented using an assembler. For example, here is an implementation for ARMv7:


@ DevInt.s

        .text
        .align 2

        .global _ZN5CCore3Dev12IsIntContextEv
        .global _ZN5CCore3Dev7IntLock8Internal6EnableEv
        .global _ZN5CCore3Dev7IntLock8Internal7DisableEv

_ZN5CCore3Dev12IsIntContextEv:                   @ CCore::Dev::IsIntContext

        mrs     r0, CPSR          @ r0 <- CPSR
        and     r0, r0, #31       @ mask CPU mode field
        cmp     r0, #18           @ compare with IRQ mode value

        movne   r0, #0            @ convert cmp result to bool value
        moveq   r0, #1

        bx      lr

_ZN5CCore3Dev7IntLock8Internal6EnableEv:         @ CCore::Dev::IntLock::Internal::Enable

        cpsie   i                 @ enable interrupts, changing bit I in CPSR

        bx      lr

_ZN5CCore3Dev7IntLock8Internal7DisableEv:        @ CCore::Dev::IntLock::Internal::Disable

        mrs     r0, CPSR          @ r0 <- CPSR
        tst     r0, #128          @ mask bit I

        movne   r0, #0            @ if bit I is set, just return false

        bxne    lr

        cpsid   i                 @ disable interrupts, changing bit I in CPSR

        mov     r0, #1            @ return true

        bx      lr