aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-01-24 21:42:01 +0000
committerGitHub <[email protected]>2022-01-24 21:42:01 +0000
commit0549a9dbaac8726e5d37d87f8f14b8524915c8c9 (patch)
tree4da1a85b0e259f16dc1d2e49da378d5d799f0349
parent917b0ea9b1bc70e2236e4d8b95d84af4141533b4 (diff)
parent48afef28a0c85d8296b0b984217350dad75daf46 (diff)
Merge #585
585: Permit many sequences to be passed r=huntc a=huntc Sequences are now passed in via the start method to avoid having to stop the PWM and restart it. Sequences continue to be constrained with the same lifetime of the Pwm struct itself. The pwm_sequence example has been extended to illustrate multiple sequences being passed around. Co-authored-by: huntc <[email protected]>
-rw-r--r--embassy-nrf/src/pwm.rs62
-rw-r--r--examples/nrf/src/bin/pwm_sequence.rs20
-rw-r--r--examples/nrf/src/bin/pwm_sequence_ppi.rs12
3 files changed, 45 insertions, 49 deletions
diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs
index 3fdc37ec0..61a282833 100644
--- a/embassy-nrf/src/pwm.rs
+++ b/embassy-nrf/src/pwm.rs
@@ -63,14 +63,7 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
63 ch2: impl Unborrow<Target = impl GpioOptionalPin> + 'd, 63 ch2: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
64 ch3: impl Unborrow<Target = impl GpioOptionalPin> + 'd, 64 ch3: impl Unborrow<Target = impl GpioOptionalPin> + 'd,
65 config: SequenceConfig, 65 config: SequenceConfig,
66 sequence: &'d [u16],
67 ) -> Result<Self, Error> { 66 ) -> Result<Self, Error> {
68 slice_in_ram_or(sequence, Error::DMABufferNotInDataMemory)?;
69
70 if sequence.len() > 32767 {
71 return Err(Error::SequenceTooLong);
72 }
73
74 unborrow!(ch0, ch1, ch2, ch3); 67 unborrow!(ch0, ch1, ch2, ch3);
75 68
76 let r = T::regs(); 69 let r = T::regs();
@@ -110,28 +103,6 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
110 r.events_seqstarted[0].reset(); 103 r.events_seqstarted[0].reset();
111 r.events_seqstarted[1].reset(); 104 r.events_seqstarted[1].reset();
112 105
113 r.seq0
114 .ptr
115 .write(|w| unsafe { w.bits(sequence.as_ptr() as u32) });
116 r.seq0
117 .cnt
118 .write(|w| unsafe { w.bits(sequence.len() as u32) });
119 r.seq0.refresh.write(|w| unsafe { w.bits(config.refresh) });
120 r.seq0
121 .enddelay
122 .write(|w| unsafe { w.bits(config.end_delay) });
123
124 r.seq1
125 .ptr
126 .write(|w| unsafe { w.bits(sequence.as_ptr() as u32) });
127 r.seq1
128 .cnt
129 .write(|w| unsafe { w.bits(sequence.len() as u32) });
130 r.seq1.refresh.write(|w| unsafe { w.bits(config.refresh) });
131 r.seq1
132 .enddelay
133 .write(|w| unsafe { w.bits(config.end_delay) });
134
135 r.decoder.write(|w| { 106 r.decoder.write(|w| {
136 w.load().bits(config.sequence_load as u8); 107 w.load().bits(config.sequence_load as u8);
137 w.mode().refresh_count() 108 w.mode().refresh_count()
@@ -146,6 +117,16 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
146 r.countertop 117 r.countertop
147 .write(|w| unsafe { w.countertop().bits(config.max_duty) }); 118 .write(|w| unsafe { w.countertop().bits(config.max_duty) });
148 119
120 r.seq0.refresh.write(|w| unsafe { w.bits(config.refresh) });
121 r.seq0
122 .enddelay
123 .write(|w| unsafe { w.bits(config.end_delay) });
124
125 r.seq1.refresh.write(|w| unsafe { w.bits(config.refresh) });
126 r.seq1
127 .enddelay
128 .write(|w| unsafe { w.bits(config.end_delay) });
129
149 Ok(Self { 130 Ok(Self {
150 phantom: PhantomData, 131 phantom: PhantomData,
151 ch0: ch0.degrade_optional(), 132 ch0: ch0.degrade_optional(),
@@ -157,12 +138,33 @@ impl<'d, T: Instance> SequencePwm<'d, T> {
157 138
158 /// Start or restart playback 139 /// Start or restart playback
159 #[inline(always)] 140 #[inline(always)]
160 pub fn start(&self, times: SequenceMode) -> Result<(), Error> { 141 pub fn start(&mut self, sequence: &'d [u16], times: SequenceMode) -> Result<(), Error> {
142 slice_in_ram_or(sequence, Error::DMABufferNotInDataMemory)?;
143
144 if sequence.len() > 32767 {
145 return Err(Error::SequenceTooLong);
146 }
147
161 if let SequenceMode::Times(0) = times { 148 if let SequenceMode::Times(0) = times {
162 return Err(Error::SequenceTimesAtLeastOne); 149 return Err(Error::SequenceTimesAtLeastOne);
163 } 150 }
151
164 let r = T::regs(); 152 let r = T::regs();
165 153
154 r.seq0
155 .ptr
156 .write(|w| unsafe { w.bits(sequence.as_ptr() as u32) });
157 r.seq0
158 .cnt
159 .write(|w| unsafe { w.bits(sequence.len() as u32) });
160
161 r.seq1
162 .ptr
163 .write(|w| unsafe { w.bits(sequence.as_ptr() as u32) });
164 r.seq1
165 .cnt
166 .write(|w| unsafe { w.bits(sequence.len() as u32) });
167
166 self.stop(); 168 self.stop();
167 169
168 r.enable.write(|w| w.enable().enabled()); 170 r.enable.write(|w| w.enable().enabled());
diff --git a/examples/nrf/src/bin/pwm_sequence.rs b/examples/nrf/src/bin/pwm_sequence.rs
index 8f57b5245..561bc1dd1 100644
--- a/examples/nrf/src/bin/pwm_sequence.rs
+++ b/examples/nrf/src/bin/pwm_sequence.rs
@@ -13,7 +13,8 @@ use embassy_nrf::Peripherals;
13 13
14#[embassy::main] 14#[embassy::main]
15async fn main(_spawner: Spawner, p: Peripherals) { 15async fn main(_spawner: Spawner, p: Peripherals) {
16 let seq_values: [u16; 5] = [1000, 250, 100, 50, 0]; 16 let seq_values_1: [u16; 5] = [1000, 250, 100, 50, 0];
17 let seq_values_2: [u16; 5] = [0, 50, 100, 250, 1000];
17 18
18 let mut config = SequenceConfig::default(); 19 let mut config = SequenceConfig::default();
19 config.prescaler = Prescaler::Div128; 20 config.prescaler = Prescaler::Div128;
@@ -24,19 +25,18 @@ async fn main(_spawner: Spawner, p: Peripherals) {
24 config.refresh = 624; 25 config.refresh = 624;
25 // thus our sequence takes 5 * 5000ms or 25 seconds 26 // thus our sequence takes 5 * 5000ms or 25 seconds
26 27
27 let pwm = unwrap!(SequencePwm::new( 28 let mut pwm = unwrap!(SequencePwm::new(
28 p.PWM0, 29 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config,
29 p.P0_13,
30 NoPin,
31 NoPin,
32 NoPin,
33 config,
34 &seq_values
35 )); 30 ));
36 let _ = pwm.start(SequenceMode::Infinite); 31 let _ = pwm.start(&seq_values_1, SequenceMode::Infinite);
37 32
38 info!("pwm started!"); 33 info!("pwm started!");
39 34
35 Timer::after(Duration::from_millis(20000)).await;
36 info!("pwm starting with another sequence!");
37
38 let _ = pwm.start(&seq_values_2, SequenceMode::Infinite);
39
40 // we can abort a sequence if we need to before its complete with pwm.stop() 40 // we can abort a sequence if we need to before its complete with pwm.stop()
41 // or stop is also implicitly called when the pwm peripheral is dropped 41 // or stop is also implicitly called when the pwm peripheral is dropped
42 // when it goes out of scope 42 // when it goes out of scope
diff --git a/examples/nrf/src/bin/pwm_sequence_ppi.rs b/examples/nrf/src/bin/pwm_sequence_ppi.rs
index aaea9ff00..213ef5ed7 100644
--- a/examples/nrf/src/bin/pwm_sequence_ppi.rs
+++ b/examples/nrf/src/bin/pwm_sequence_ppi.rs
@@ -26,17 +26,11 @@ async fn main(_spawner: Spawner, p: Peripherals) {
26 // thus our sequence takes 5 * 250ms or 1.25 seconds 26 // thus our sequence takes 5 * 250ms or 1.25 seconds
27 config.refresh = 30; 27 config.refresh = 30;
28 28
29 let pwm = unwrap!(SequencePwm::new( 29 let mut pwm = unwrap!(SequencePwm::new(
30 p.PWM0, 30 p.PWM0, p.P0_13, NoPin, NoPin, NoPin, config,
31 p.P0_13,
32 NoPin,
33 NoPin,
34 NoPin,
35 config,
36 &seq_values
37 )); 31 ));
38 32
39 let _ = pwm.start(SequenceMode::Times(1)); 33 let _ = pwm.start(&seq_values, SequenceMode::Times(1));
40 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work 34 // pwm.stop() deconfigures pins, and then the task_start_seq0 task cant work
41 // so its going to have to start running in order load the configuration 35 // so its going to have to start running in order load the configuration
42 36