| @@ -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 | |||