Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 64bd840

Browse filesBrowse files
committed
Finally get rid of volatile and use atomic thread fence memory barriers, great for ISR performance.
1 parent f1ac5c4 commit 64bd840
Copy full SHA for 64bd840

File tree

Expand file treeCollapse file tree

1 file changed

+12
-7
lines changed
Filter options
Expand file treeCollapse file tree

1 file changed

+12
-7
lines changed

‎cores/esp8266/core_esp8266_waveform.cpp

Copy file name to clipboardExpand all lines: cores/esp8266/core_esp8266_waveform.cpp
+12-7Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ namespace {
8787
static struct {
8888
Waveform pins[17]; // State of all possible pins
8989
uint32_t states = 0; // Is the pin high or low, updated in NMI so no access outside the NMI code
90-
volatile uint32_t enabled = 0; // Is it actively running, updated in NMI so no access outside the NMI code
90+
uint32_t enabled = 0; // Is it actively running, updated in NMI so no access outside the NMI code
9191

9292
// Enable lock-free by only allowing updates to waveform.states and waveform.enabled from IRQ service routine
93-
volatile int32_t toSet = -1; // Message to the NMI handler to start/modify exactly one waveform
94-
volatile int32_t toDisable = -1; // Message to the NMI handler to disable exactly one pin from waveform generation
93+
int32_t toSet = -1; // Message to the NMI handler to start/modify exactly one waveform
94+
int32_t toDisable = -1; // Message to the NMI handler to disable exactly one pin from waveform generation
9595

9696
uint32_t(*timer1CB)() = nullptr;
9797

@@ -112,6 +112,7 @@ static void initTimer() {
112112
ETS_FRC_TIMER1_NMI_INTR_ATTACH(timer1Interrupt);
113113
timer1_enable(TIM_DIV1, TIM_EDGE, TIM_SINGLE);
114114
waveform.timer1Running = true;
115+
timer1_write(microsecondsToClockCycles(1)); // Cause an interrupt post-haste
115116
}
116117

117118
static void ICACHE_RAM_ATTR deinitTimer() {
@@ -124,10 +125,9 @@ static void ICACHE_RAM_ATTR deinitTimer() {
124125
// Set a callback. Pass in NULL to stop it
125126
void setTimer1Callback(uint32_t (*fn)()) {
126127
waveform.timer1CB = fn;
127-
std::atomic_thread_fence(std::memory_order_release);
128+
std::atomic_thread_fence(std::memory_order_acq_rel);
128129
if (!waveform.timer1Running && fn) {
129130
initTimer();
130-
timer1_write(microsecondsToClockCycles(1)); // Cause an interrupt post-haste
131131
} else if (waveform.timer1Running && !fn && !waveform.enabled) {
132132
deinitTimer();
133133
}
@@ -164,6 +164,7 @@ int startWaveformClockCycles(uint8_t pin, uint32_t highCcys, uint32_t lowCcys,
164164
wave.periodCcys = periodCcys;
165165
wave.autoPwm = autoPwm;
166166

167+
std::atomic_thread_fence(std::memory_order_acquire);
167168
if (!(waveform.enabled & (1UL << pin))) {
168169
// wave.nextPeriodCcy and wave.endDutyCcy are initialized by the ISR
169170
wave.nextPeriodCcy = phaseOffsetCcys;
@@ -183,7 +184,6 @@ int startWaveformClockCycles(uint8_t pin, uint32_t highCcys, uint32_t lowCcys,
183184
waveform.toSet = pin;
184185
if (!waveform.timer1Running) {
185186
initTimer();
186-
timer1_write(microsecondsToClockCycles(1));
187187
}
188188
else if (T1L > IRQLATENCY + DELTAIRQ) {
189189
// Must not interfere if Timer is due shortly, cluster phases to reduce interrupt load
@@ -200,8 +200,10 @@ int startWaveformClockCycles(uint8_t pin, uint32_t highCcys, uint32_t lowCcys,
200200
waveform.toSet = pin;
201201
}
202202
}
203+
std::atomic_thread_fence(std::memory_order_acq_rel);
203204
while (waveform.toSet >= 0) {
204-
delay(0); // Wait for waveform to update
205+
delay(0); // Wait for waveform to update
206+
std::atomic_thread_fence(std::memory_order_acquire);
205207
}
206208
return true;
207209
}
@@ -214,14 +216,17 @@ int ICACHE_RAM_ATTR stopWaveform(uint8_t pin) {
214216
}
215217
// If user sends in a pin >16 but <32, this will always point to a 0 bit
216218
// If they send >=32, then the shift will result in 0 and it will also return false
219+
std::atomic_thread_fence(std::memory_order_acquire);
217220
if (waveform.enabled & (1UL << pin)) {
218221
waveform.toDisable = pin;
219222
// Must not interfere if Timer is due shortly
220223
if (T1L > IRQLATENCY + DELTAIRQ) {
221224
timer1_write(microsecondsToClockCycles(1));
222225
}
226+
std::atomic_thread_fence(std::memory_order_acq_rel);
223227
while (waveform.toDisable >= 0) {
224228
/* no-op */ // Can't delay() since stopWaveform may be called from an IRQ
229+
std::atomic_thread_fence(std::memory_order_acquire);
225230
}
226231
}
227232
if (!waveform.enabled && !waveform.timer1CB) {

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.