| _prev->_next = this; | _prev->_next = this; | ||||
| lastYield = this; | lastYield = this; | ||||
| } | } | ||||
| _pending = true; | |||||
| } else if (_type == EventTypeInterrupt) { | } else if (_type == EventTypeInterrupt) { | ||||
| // interrupt, called from software interrupt | // interrupt, called from software interrupt | ||||
| if (firstInterrupt == nullptr) { | if (firstInterrupt == nullptr) { | ||||
| _prev->_next = this; | _prev->_next = this; | ||||
| lastInterrupt = this; | lastInterrupt = this; | ||||
| } | } | ||||
| // TODO set interrupt pending | |||||
| _pending = true; | |||||
| SCB_ICSR = SCB_ICSR_PENDSVSET; // set PendSV interrupt | |||||
| } else { | } else { | ||||
| // detached, easy :-) | // detached, easy :-) | ||||
| _pending = true; | |||||
| } | } | ||||
| _pending = true; | |||||
| } | } | ||||
| void pendablesrvreq_isr(void) | void pendablesrvreq_isr(void) | ||||
| void EventResponder::runFromInterrupt() | 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() | bool EventResponder::clearEvent() |
| detach(); | detach(); | ||||
| _function = function; | _function = function; | ||||
| _type = EventTypeInterrupt; | _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 | // Attach a function to be called as its own thread. Boards not running | ||||
| static void runFromYield() { | static void runFromYield() { | ||||
| EventResponder *first = firstYield; | EventResponder *first = firstYield; | ||||
| // FIXME: also check if yield() called from an interrupt | |||||
| // never run these functions from any interrupt context | |||||
| if (first && !runningFromYield) { | if (first && !runningFromYield) { | ||||
| runningFromYield = true; | runningFromYield = true; | ||||
| firstYield = first->_next; | firstYield = first->_next; |
| // System Control Space (SCS), ARMv7 ref manual, B3.2, page 708 | // System Control Space (SCS), ARMv7 ref manual, B3.2, page 708 | ||||
| #define SCB_CPUID (*(const uint32_t *)0xE000ED00) // CPUID Base Register | #define SCB_CPUID (*(const uint32_t *)0xE000ED00) // CPUID Base Register | ||||
| #define SCB_ICSR (*(volatile uint32_t *)0xE000ED04) // Interrupt Control and State | #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_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_VTOR (*(volatile uint32_t *)0xE000ED08) // Vector Table Offset | ||||
| #define SCB_AIRCR (*(volatile uint32_t *)0xE000ED0C) // Application Interrupt and Reset Control | #define SCB_AIRCR (*(volatile uint32_t *)0xE000ED0C) // Application Interrupt and Reset Control | ||||
| #define SCB_SCR (*(volatile uint32_t *)0xE000ED10) // System Control Register | #define SCB_SCR (*(volatile uint32_t *)0xE000ED10) // System Control Register |