aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Rosenthal <[email protected]>2021-11-10 12:34:41 -0700
committerJacob Rosenthal <[email protected]>2021-11-10 12:34:41 -0700
commit903b8f032fa36fb1bf8cd6f1d1b3c14ce7caa0dd (patch)
treec79ad6da5de5c45bb93473c2fae2d3d796f9647d
parent4751dbddc6466c30cd1bdd387adb9513ec19b3d2 (diff)
defensive dma
-rw-r--r--embassy-nrf/src/pwm.rs32
1 files changed, 30 insertions, 2 deletions
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs
index 077a27cd0..e4ddda395 100644
--- a/embassy-nrf/src/pwm.rs
+++ b/embassy-nrf/src/pwm.rs
@@ -3,7 +3,7 @@
3use core::marker::PhantomData; 3use core::marker::PhantomData;
4use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
5use embassy::util::Unborrow; 5use embassy::util::Unborrow;
6use embassy_hal_common::unborrow; 6use embassy_hal_common::{low_power_wait_until, unborrow};
7 7
8use crate::gpio::sealed::Pin as _; 8use crate::gpio::sealed::Pin as _;
9use crate::gpio::{AnyPin, OptionalPin as GpioOptionalPin}; 9use crate::gpio::{AnyPin, OptionalPin as GpioOptionalPin};
@@ -157,12 +157,19 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
157 157
158 r.enable.write(|w| w.enable().enabled()); 158 r.enable.write(|w| w.enable().enabled());
159 159
160 // defensive before seqstart
161 compiler_fence(Ordering::SeqCst);
162
160 match times { 163 match times {
161 // just the one time, no loop count 164 // just the one time, no loop count
162 SequenceMode::Times(1) => { 165 SequenceMode::Times(1) => {
163 r.loop_.write(|w| w.cnt().disabled()); 166 r.loop_.write(|w| w.cnt().disabled());
164 // tasks_seqstart() doesn't exist in all svds so write its bit instead 167 // tasks_seqstart() doesn't exist in all svds so write its bit instead
165 r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) }); 168 r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) });
169
170 // defensive wait until waveform is loaded after seqstart
171 low_power_wait_until(|| r.events_seqend[0].read().bits() == 1);
172 r.events_seqend[0].write(|w| w);
166 } 173 }
167 // loop count is how many times to play BOTH sequences 174 // loop count is how many times to play BOTH sequences
168 // 2 total (1 x 2) 175 // 2 total (1 x 2)
@@ -177,17 +184,30 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
177 if odd { 184 if odd {
178 // tasks_seqstart() doesn't exist in all svds so write its bit instead 185 // tasks_seqstart() doesn't exist in all svds so write its bit instead
179 r.tasks_seqstart[1].write(|w| unsafe { w.bits(0x01) }); 186 r.tasks_seqstart[1].write(|w| unsafe { w.bits(0x01) });
187
188 // defensive wait until waveform is loaded after seqstart
189 low_power_wait_until(|| r.events_seqend[1].read().bits() == 1);
190 r.events_seqend[1].write(|w| w);
180 } else { 191 } else {
181 // tasks_seqstart() doesn't exist in all svds so write its bit instead 192 // tasks_seqstart() doesn't exist in all svds so write its bit instead
182 r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) }); 193 r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) });
194
195 // defensive wait until waveform is loaded after seqstart
196 low_power_wait_until(|| r.events_seqend[0].read().bits() == 1);
197 r.events_seqend[0].write(|w| w);
183 } 198 }
184 } 199 }
185 // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again 200 // to play infinitely, repeat the sequence one time, then have loops done self trigger seq0 again
186 SequenceMode::Infinite => { 201 SequenceMode::Infinite => {
187 r.loop_.write(|w| unsafe { w.cnt().bits(0x1) }); 202 r.loop_.write(|w| unsafe { w.cnt().bits(0x1) });
188 r.shorts.write(|w| w.loopsdone_seqstart0().enabled()); 203 r.shorts.write(|w| w.loopsdone_seqstart0().enabled());
204
189 // tasks_seqstart() doesn't exist in all svds so write its bit instead 205 // tasks_seqstart() doesn't exist in all svds so write its bit instead
190 r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) }); 206 r.tasks_seqstart[0].write(|w| unsafe { w.bits(0x01) });
207
208 // defensive wait until waveform is loaded after seqstart
209 low_power_wait_until(|| r.events_seqend[0].read().bits() == 1);
210 r.events_seqend[0].write(|w| w);
191 } 211 }
192 } 212 }
193 213
@@ -201,6 +221,8 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
201 221
202 r.shorts.reset(); 222 r.shorts.reset();
203 223
224 compiler_fence(Ordering::SeqCst);
225
204 // tasks_stop() doesn't exist in all svds so write its bit instead 226 // tasks_stop() doesn't exist in all svds so write its bit instead
205 r.tasks_stop.write(|w| unsafe { w.bits(0x01) }); 227 r.tasks_stop.write(|w| unsafe { w.bits(0x01) });
206 } 228 }
@@ -404,6 +426,8 @@ impl<'d, T: Instance> SimplePwm<'d, T> {
404 426
405 r.shorts.reset(); 427 r.shorts.reset();
406 428
429 compiler_fence(Ordering::SeqCst);
430
407 // tasks_stop() doesn't exist in all svds so write its bit instead 431 // tasks_stop() doesn't exist in all svds so write its bit instead
408 r.tasks_stop.write(|w| unsafe { w.bits(0x01) }); 432 r.tasks_stop.write(|w| unsafe { w.bits(0x01) });
409 } 433 }
@@ -432,11 +456,15 @@ impl<'d, T: Instance> SimplePwm<'d, T> {
432 .ptr 456 .ptr
433 .write(|w| unsafe { w.bits(&self.duty as *const _ as u32) }); 457 .write(|w| unsafe { w.bits(&self.duty as *const _ as u32) });
434 458
435 // todo justify? should i fence elsehwere we task start? or 459 // defensive before seqstart
436 compiler_fence(Ordering::SeqCst); 460 compiler_fence(Ordering::SeqCst);
437 461
438 // tasks_seqstart() doesn't exist in all svds so write its bit instead 462 // tasks_seqstart() doesn't exist in all svds so write its bit instead
439 r.tasks_seqstart[0].write(|w| unsafe { w.bits(1) }); 463 r.tasks_seqstart[0].write(|w| unsafe { w.bits(1) });
464
465 // defensive wait until waveform is loaded after seqstart
466 low_power_wait_until(|| r.events_seqend[0].read().bits() == 1);
467 r.events_seqend[0].write(|w| w);
440 } 468 }
441 469
442 /// Sets the PWM clock prescaler. 470 /// Sets the PWM clock prescaler.