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