Files CCore/inc/dev/DevIntHandle.h CCore/src/dev/DevIntHandle.cpp
This part provides an interrupt control. There is no particular way how it should be implemented. This part is used strictly inside Target code, XCore code don't use it directly. So target is free to define it as convenient. Yet there is a proposed pattern. All interrupts are handled in a special interrupt context. In this context interrupts are disabled. Each interrupt source may have an associated interrupt handler. This handler is called once the source is asserted and interrupts are enabled. CPU stops the current task execution, saves the current task context and goes to the interrupt context, where interrupt sources are examined and appropriate interrupt handlers are called. During the interrupt processing the current task may be changed. If so a new task is started after the interrupt context is finished. The interrupt context has the own stack and the own language support context.
Here is the proposed interrupt control pattern:
/* DevIntHandle.h */ #ifndef CCore_inc_dev_DevIntHandle_h #define CCore_inc_dev_DevIntHandle_h #include <CCore/inc/PlanInit.h> namespace CCore { namespace Dev { /* GetPlanInitNode_...() */ PlanInitNode * GetPlanInitNode_DevIntHandle(); /* enum IntSource */ enum IntSource { Int_TINTx = 92, Int_TableLen = 128 }; /* functions */ void SetupIntHandler(IntSource int_source,Function<void (void)> handle_int); void CleanupIntHandler(IntSource int_source); void EnableInt(IntSource int_source); void DisableInt(IntSource int_source); } // namespace Dev } // namespace CCore #endif
It has the PlanInit node function GetPlanInitNode_DevIntHandle(). The enumeration IntSource defines interrupt sources as numbers. And the following four functions are used to control interrupt processing.
SetupIntHandler() sets up the given function as the interrupt handler for the given source. Interrupts are enabled.
CleanupIntHandler() clears the interrupt handler for the given source and disables interrupts.
EnableInt() enables interrupts from the given source.
DisableInt() disables interrupts from the given source.
/* DevIntHandle.cpp */ #include <CCore/inc/dev/DevIntHandle.h> #include <CCore/inc/dev/DevInt.h> #include <CCore/inc/task/TaskMonitor.h> #include <CCore/inc/task/TaskEvent.h> #include <__std_init.h> namespace CCore { namespace Dev { /* GetPlanInitNode_...() */ namespace Private_DevIntHandle { class IntTable : NoCopy { Function<void (void)> table[Int_TableLen]; public: IntTable() { } ~IntTable() { } void set(uint32 int_source,Function<void (void)> handle_int) { // TODO table[int_source]=handle_int; } void clear(uint32 int_source) { table[int_source]=Nothing; } void enable(uint32 int_source) { Used(int_source); // TODO } void disable(uint32 int_source) { Used(int_source); // TODO } void dispatch(uint32 int_source) { table[int_source](); } };
This class is a table of interrupt handlers. It is also responsible for the turning on/off interrupts from the particular source. Usually it is done by the changing the interrupt controller interrupt enable registers.
class IntEngine : public IntTable { public: IntEngine(); ~IntEngine(); static const char * GetTag() { return "DevIntHandle"; } }; PlanInitObject<IntEngine> Object CCORE_INITPRI_1 ;
This class is responsible for the interrupt controller initialization/deinitialization.
extern "C" { void IRQ_main() { TaskEventHost.add<TaskSwitchEvent>(TaskNumber::EnterInt); TaskMonitor::Internal::BeginInt(); // TODO uint32 int_source=0; Object->dispatch(int_source); TaskMonitor::Internal::EndInt(); TaskEventHost.add<TaskSwitchEvent>(TaskNumber::LeaveInt); } } // extern "C"
This function is a main interrupt entry. You must implement it according the provided pattern. It must start from the two defined calls and finished with two another calls. In the middle this function determines the interrupt source and dispatches to the correspondent handler. It may process only one source each time or several ones as desired.
IntEngine::IntEngine() { // TODO __std_intsetup(IRQ_main); } IntEngine::~IntEngine() { // TODO __std_intcleanup(); } } // namespace Private_DevIntHandle using namespace Private_DevIntHandle; PlanInitNode * GetPlanInitNode_DevIntHandle() { return &Object; } /* functions */ void SetupIntHandler(IntSource int_source,Function<void (void)> handle_int) { IntLock lock; Object->set(int_source,handle_int); Object->enable(int_source); } void CleanupIntHandler(IntSource int_source) { IntLock lock; Object->disable(int_source); Object->clear(int_source); } void EnableInt(IntSource int_source) { IntLock lock; Object->enable(int_source); } void DisableInt(IntSource int_source) { IntLock lock; Object->disable(int_source); } } // namespace Dev } // namespace CCore