@@ -60,6 +60,7 @@ void EventResponder::triggerEventNotImmediate() | |||
_prev->_next = this; | |||
lastYield = this; | |||
} | |||
_pending = true; | |||
} else if (_type == EventTypeInterrupt) { | |||
// interrupt, called from software interrupt | |||
if (firstInterrupt == nullptr) { | |||
@@ -73,11 +74,12 @@ void EventResponder::triggerEventNotImmediate() | |||
_prev->_next = this; | |||
lastInterrupt = this; | |||
} | |||
// TODO set interrupt pending | |||
_pending = true; | |||
SCB_ICSR = SCB_ICSR_PENDSVSET; // set PendSV interrupt | |||
} else { | |||
// detached, easy :-) | |||
_pending = true; | |||
} | |||
_pending = true; | |||
} | |||
void pendablesrvreq_isr(void) | |||
@@ -87,15 +89,21 @@ void pendablesrvreq_isr(void) | |||
void EventResponder::runFromInterrupt() | |||
{ | |||
// FIXME: this will fail if the handler function triggers | |||
// its own or other EventResponder instances. The list will | |||
// change while we're holding a pointers to it. | |||
for (EventResponder *first=firstInterrupt; first; first = first->_next) { | |||
first->_pending = false; | |||
(*(first->_function))(*first); | |||
while (1) { | |||
EventResponder *first = firstInterrupt; | |||
if (first) { | |||
firstInterrupt = first->_next; | |||
if (firstInterrupt) { | |||
firstInterrupt->_prev = nullptr; | |||
} else { | |||
lastInterrupt = nullptr; | |||
} | |||
first->_pending = false; | |||
(*(first->_function))(*first); | |||
} else { | |||
break; | |||
} | |||
} | |||
firstInterrupt = nullptr; | |||
lastInterrupt = nullptr; | |||
} | |||
bool EventResponder::clearEvent() |
@@ -106,7 +106,7 @@ public: | |||
detach(); | |||
_function = function; | |||
_type = EventTypeInterrupt; | |||
// TODO: configure PendSV | |||
SCB_SHPR3 |= 0x00FF0000; // configure PendSV, lowest priority | |||
} | |||
// Attach a function to be called as its own thread. Boards not running | |||
@@ -161,6 +161,8 @@ public: | |||
static void runFromYield() { | |||
EventResponder *first = firstYield; | |||
// FIXME: also check if yield() called from an interrupt | |||
// never run these functions from any interrupt context | |||
if (first && !runningFromYield) { | |||
runningFromYield = true; | |||
firstYield = first->_next; |
@@ -5664,7 +5664,14 @@ typedef struct __attribute__((packed)) { | |||
// System Control Space (SCS), ARMv7 ref manual, B3.2, page 708 | |||
#define SCB_CPUID (*(const uint32_t *)0xE000ED00) // CPUID Base Register | |||
#define SCB_ICSR (*(volatile uint32_t *)0xE000ED04) // Interrupt Control and State | |||
#define SCB_ICSR_NMIPENDSET ((uint32_t)0x80000000) | |||
#define SCB_ICSR_PENDSVSET ((uint32_t)0x10000000) | |||
#define SCB_ICSR_PENDSVCLR ((uint32_t)0x08000000) | |||
#define SCB_ICSR_PENDSTSET ((uint32_t)0x04000000) | |||
#define SCB_ICSR_PENDSTCLR ((uint32_t)0x02000000) | |||
#define SCB_ICSR_ISRPREEMPT ((uint32_t)0x00800000) | |||
#define SCB_ICSR_ISRPENDING ((uint32_t)0x00400000) | |||
#define SCB_ICSR_RETTOBASE ((uint32_t)0x00000800) | |||
#define SCB_VTOR (*(volatile uint32_t *)0xE000ED08) // Vector Table Offset | |||
#define SCB_AIRCR (*(volatile uint32_t *)0xE000ED0C) // Application Interrupt and Reset Control | |||
#define SCB_SCR (*(volatile uint32_t *)0xE000ED10) // System Control Register |