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