@@ -87,11 +87,11 @@ namespace {
87
87
static struct {
88
88
Waveform pins[17 ]; // State of all possible pins
89
89
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
91
91
92
92
// 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
95
95
96
96
uint32_t (*timer1CB)() = nullptr ;
97
97
@@ -112,6 +112,7 @@ static void initTimer() {
112
112
ETS_FRC_TIMER1_NMI_INTR_ATTACH (timer1Interrupt);
113
113
timer1_enable (TIM_DIV1, TIM_EDGE, TIM_SINGLE);
114
114
waveform.timer1Running = true ;
115
+ timer1_write (microsecondsToClockCycles (1 )); // Cause an interrupt post-haste
115
116
}
116
117
117
118
static void ICACHE_RAM_ATTR deinitTimer () {
@@ -124,10 +125,9 @@ static void ICACHE_RAM_ATTR deinitTimer() {
124
125
// Set a callback. Pass in NULL to stop it
125
126
void setTimer1Callback (uint32_t (*fn)()) {
126
127
waveform.timer1CB = fn;
127
- std::atomic_thread_fence (std::memory_order_release );
128
+ std::atomic_thread_fence (std::memory_order_acq_rel );
128
129
if (!waveform.timer1Running && fn) {
129
130
initTimer ();
130
- timer1_write (microsecondsToClockCycles (1 )); // Cause an interrupt post-haste
131
131
} else if (waveform.timer1Running && !fn && !waveform.enabled ) {
132
132
deinitTimer ();
133
133
}
@@ -164,6 +164,7 @@ int startWaveformClockCycles(uint8_t pin, uint32_t highCcys, uint32_t lowCcys,
164
164
wave.periodCcys = periodCcys;
165
165
wave.autoPwm = autoPwm;
166
166
167
+ std::atomic_thread_fence (std::memory_order_acquire);
167
168
if (!(waveform.enabled & (1UL << pin))) {
168
169
// wave.nextPeriodCcy and wave.endDutyCcy are initialized by the ISR
169
170
wave.nextPeriodCcy = phaseOffsetCcys;
@@ -183,7 +184,6 @@ int startWaveformClockCycles(uint8_t pin, uint32_t highCcys, uint32_t lowCcys,
183
184
waveform.toSet = pin;
184
185
if (!waveform.timer1Running ) {
185
186
initTimer ();
186
- timer1_write (microsecondsToClockCycles (1 ));
187
187
}
188
188
else if (T1L > IRQLATENCY + DELTAIRQ) {
189
189
// 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,
200
200
waveform.toSet = pin;
201
201
}
202
202
}
203
+ std::atomic_thread_fence (std::memory_order_acq_rel);
203
204
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);
205
207
}
206
208
return true ;
207
209
}
@@ -214,14 +216,17 @@ int ICACHE_RAM_ATTR stopWaveform(uint8_t pin) {
214
216
}
215
217
// If user sends in a pin >16 but <32, this will always point to a 0 bit
216
218
// 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);
217
220
if (waveform.enabled & (1UL << pin)) {
218
221
waveform.toDisable = pin;
219
222
// Must not interfere if Timer is due shortly
220
223
if (T1L > IRQLATENCY + DELTAIRQ) {
221
224
timer1_write (microsecondsToClockCycles (1 ));
222
225
}
226
+ std::atomic_thread_fence (std::memory_order_acq_rel);
223
227
while (waveform.toDisable >= 0 ) {
224
228
/* no-op */ // Can't delay() since stopWaveform may be called from an IRQ
229
+ std::atomic_thread_fence (std::memory_order_acquire);
225
230
}
226
231
}
227
232
if (!waveform.enabled && !waveform.timer1CB ) {
0 commit comments