Browse Source

Use PendSV for EventResponder attachInterrupt

main
PaulStoffregen 7 years ago
parent
commit
e77b120f7b
3 changed files with 28 additions and 11 deletions
  1. +18
    -10
      teensy3/EventResponder.cpp
  2. +3
    -1
      teensy3/EventResponder.h
  3. +7
    -0
      teensy3/kinetis.h

+ 18
- 10
teensy3/EventResponder.cpp View File

_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()

+ 3
- 1
teensy3/EventResponder.h View File

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;

+ 7
- 0
teensy3/kinetis.h View File

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

Loading…
Cancel
Save