Browse Source

Disable interrupts in EventResponder critical sections

main
PaulStoffregen 7 years ago
parent
commit
07ac3cb4ea
2 changed files with 62 additions and 37 deletions
  1. +42
    -35
      teensy3/EventResponder.cpp
  2. +20
    -2
      teensy3/EventResponder.h

+ 42
- 35
teensy3/EventResponder.cpp View File



void EventResponder::triggerEventNotImmediate() void EventResponder::triggerEventNotImmediate()
{ {
if (_triggered) {
// already triggered
return;
}
if (_type == EventTypeYield) {
// normal type, called from yield()
if (firstYield == nullptr) {
_next = nullptr;
_prev = nullptr;
firstYield = this;
lastYield = this;
} else {
_next = nullptr;
_prev = lastYield;
_prev->_next = this;
lastYield = this;
}
_triggered = true;
} else if (_type == EventTypeInterrupt) {
// interrupt, called from software interrupt
if (firstInterrupt == nullptr) {
_next = nullptr;
_prev = nullptr;
firstInterrupt = this;
lastInterrupt = this;
bool irq = disableInterrupts();
if (_triggered == false) {
// not already triggered
if (_type == EventTypeYield) {
// normal type, called from yield()
if (firstYield == nullptr) {
_next = nullptr;
_prev = nullptr;
firstYield = this;
lastYield = this;
} else {
_next = nullptr;
_prev = lastYield;
_prev->_next = this;
lastYield = this;
}
} else if (_type == EventTypeInterrupt) {
// interrupt, called from software interrupt
if (firstInterrupt == nullptr) {
_next = nullptr;
_prev = nullptr;
firstInterrupt = this;
lastInterrupt = this;
} else {
_next = nullptr;
_prev = lastInterrupt;
_prev->_next = this;
lastInterrupt = this;
}
SCB_ICSR = SCB_ICSR_PENDSVSET; // set PendSV interrupt
} else { } else {
_next = nullptr;
_prev = lastInterrupt;
_prev->_next = this;
lastInterrupt = this;
// detached, easy :-)
} }
_triggered = true; _triggered = true;
SCB_ICSR = SCB_ICSR_PENDSVSET; // set PendSV interrupt
} else {
// detached, easy :-)
_triggered = true;
} }
enableInterrupts(irq);
} }


void pendablesrvreq_isr(void) void pendablesrvreq_isr(void)
void EventResponder::runFromInterrupt() void EventResponder::runFromInterrupt()
{ {
while (1) { while (1) {
bool irq = disableInterrupts();
EventResponder *first = firstInterrupt; EventResponder *first = firstInterrupt;
if (first) { if (first) {
firstInterrupt = first->_next; firstInterrupt = first->_next;
} else { } else {
lastInterrupt = nullptr; lastInterrupt = nullptr;
} }
enableInterrupts(irq);
first->_triggered = false; first->_triggered = false;
(*(first->_function))(*first); (*(first->_function))(*first);
} else { } else {
enableInterrupts(irq);
break; break;
} }
} }


bool EventResponder::clearEvent() bool EventResponder::clearEvent()
{ {
bool ret = false;
bool irq = disableInterrupts();
if (_triggered) { if (_triggered) {
if (_type == EventTypeYield) { if (_type == EventTypeYield) {
if (_prev) { if (_prev) {
} }
} }
_triggered = false; _triggered = false;
return true;
ret = true;
} }
return false;
enableInterrupts(irq);
return ret;
} }


void EventResponder::detach() void EventResponder::detach()
{ {
bool irq = disableInterrupts();
if (_type == EventTypeYield) { if (_type == EventTypeYield) {
if (_triggered) { if (_triggered) {
if (_prev) { if (_prev) {
} }
_type = EventTypeDetached; _type = EventTypeDetached;
} }
enableInterrupts(irq);
} }





+ 20
- 2
teensy3/EventResponder.h View File

__asm__ volatile("mrs %0, ipsr\n" : "=r" (ipsr)::); __asm__ volatile("mrs %0, ipsr\n" : "=r" (ipsr)::);
if (ipsr != 0) return; if (ipsr != 0) return;
// Next, check if any events have been triggered // Next, check if any events have been triggered
bool irq = disableInterrupts();
EventResponder *first = firstYield; EventResponder *first = firstYield;
if (first == nullptr) return;
if (first == nullptr) {
enableInterrupts(irq);
return;
}
// Finally, make sure we're not being recursively called, // Finally, make sure we're not being recursively called,
// which can happen if the user's function does anything // which can happen if the user's function does anything
// that calls yield. // that calls yield.
if (runningFromYield) return;
if (runningFromYield) {
enableInterrupts(irq);
return;
}
// Ok, update the runningFromYield flag and process event // Ok, update the runningFromYield flag and process event
runningFromYield = true; runningFromYield = true;
firstYield = first->_next; firstYield = first->_next;
} else { } else {
lastYield = nullptr; lastYield = nullptr;
} }
enableInterrupts(irq);
first->_triggered = false; first->_triggered = false;
(*(first->_function))(*first); (*(first->_function))(*first);
runningFromYield = false; runningFromYield = false;
static EventResponder *firstInterrupt; static EventResponder *firstInterrupt;
static EventResponder *lastInterrupt; static EventResponder *lastInterrupt;
static bool runningFromYield; static bool runningFromYield;
private:
static bool disableInterrupts() {
uint32_t primask;
__asm__ volatile("mrs %0, primask\n" : "=r" (primask)::);
__disable_irq();
return (primask == 0) ? false : true;
}
static void enableInterrupts(bool doit) {
if (doit) __enable_irq();
}
}; };


class MillisTimer class MillisTimer

Loading…
Cancel
Save