Parcourir la source

Disable interrupts in EventResponder critical sections

main
PaulStoffregen il y a 7 ans
Parent
révision
07ac3cb4ea
2 fichiers modifiés avec 62 ajouts et 37 suppressions
  1. +42
    -35
      teensy3/EventResponder.cpp
  2. +20
    -2
      teensy3/EventResponder.h

+ 42
- 35
teensy3/EventResponder.cpp Voir le fichier

@@ -43,43 +43,42 @@ bool EventResponder::runningFromYield = false;

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 {
_next = nullptr;
_prev = lastInterrupt;
_prev->_next = this;
lastInterrupt = this;
// detached, easy :-)
}
_triggered = true;
SCB_ICSR = SCB_ICSR_PENDSVSET; // set PendSV interrupt
} else {
// detached, easy :-)
_triggered = true;
}
enableInterrupts(irq);
}

void pendablesrvreq_isr(void)
@@ -90,6 +89,7 @@ void pendablesrvreq_isr(void)
void EventResponder::runFromInterrupt()
{
while (1) {
bool irq = disableInterrupts();
EventResponder *first = firstInterrupt;
if (first) {
firstInterrupt = first->_next;
@@ -98,9 +98,11 @@ void EventResponder::runFromInterrupt()
} else {
lastInterrupt = nullptr;
}
enableInterrupts(irq);
first->_triggered = false;
(*(first->_function))(*first);
} else {
enableInterrupts(irq);
break;
}
}
@@ -108,6 +110,8 @@ void EventResponder::runFromInterrupt()

bool EventResponder::clearEvent()
{
bool ret = false;
bool irq = disableInterrupts();
if (_triggered) {
if (_type == EventTypeYield) {
if (_prev) {
@@ -133,13 +137,15 @@ bool EventResponder::clearEvent()
}
}
_triggered = false;
return true;
ret = true;
}
return false;
enableInterrupts(irq);
return ret;
}

void EventResponder::detach()
{
bool irq = disableInterrupts();
if (_type == EventTypeYield) {
if (_triggered) {
if (_prev) {
@@ -169,6 +175,7 @@ void EventResponder::detach()
}
_type = EventTypeDetached;
}
enableInterrupts(irq);
}



+ 20
- 2
teensy3/EventResponder.h Voir le fichier

@@ -166,12 +166,19 @@ public:
__asm__ volatile("mrs %0, ipsr\n" : "=r" (ipsr)::);
if (ipsr != 0) return;
// Next, check if any events have been triggered
bool irq = disableInterrupts();
EventResponder *first = firstYield;
if (first == nullptr) return;
if (first == nullptr) {
enableInterrupts(irq);
return;
}
// Finally, make sure we're not being recursively called,
// which can happen if the user's function does anything
// that calls yield.
if (runningFromYield) return;
if (runningFromYield) {
enableInterrupts(irq);
return;
}
// Ok, update the runningFromYield flag and process event
runningFromYield = true;
firstYield = first->_next;
@@ -180,6 +187,7 @@ public:
} else {
lastYield = nullptr;
}
enableInterrupts(irq);
first->_triggered = false;
(*(first->_function))(*first);
runningFromYield = false;
@@ -201,6 +209,16 @@ protected:
static EventResponder *firstInterrupt;
static EventResponder *lastInterrupt;
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

Chargement…
Annuler
Enregistrer