aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-03-05 20:50:45 +0100
committerDario Nieuwenhuis <[email protected]>2023-03-06 00:17:51 +0100
commitf8f1d3bcf09045616f5b63a08a9623cd14acd045 (patch)
tree4510489b071c37638f3f8805d0b3d4b5543d2696
parent34563b74aa48c53622344541153266b0227fc9bf (diff)
nrf/pdm: make available on all chips, use Instance trait, switch to new interrupt binding.
-rw-r--r--embassy-nrf/src/chips/nrf52810.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52811.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52832.rs5
-rw-r--r--embassy-nrf/src/chips/nrf52833.rs2
-rw-r--r--embassy-nrf/src/chips/nrf52840.rs2
-rw-r--r--embassy-nrf/src/chips/nrf5340_app.rs7
-rw-r--r--embassy-nrf/src/chips/nrf9160.rs2
-rw-r--r--embassy-nrf/src/lib.rs2
-rw-r--r--embassy-nrf/src/pdm.rs131
-rw-r--r--examples/nrf52840/src/bin/pdm.rs10
10 files changed, 116 insertions, 49 deletions
diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs
index 6b5c134b8..c6ccb6a0e 100644
--- a/embassy-nrf/src/chips/nrf52810.rs
+++ b/embassy-nrf/src/chips/nrf52810.rs
@@ -148,6 +148,8 @@ impl_twis!(TWI0, TWIS0, TWIM0_TWIS0_TWI0);
148 148
149impl_pwm!(PWM0, PWM0, PWM0); 149impl_pwm!(PWM0, PWM0, PWM0);
150 150
151impl_pdm!(PDM, PDM, PDM);
152
151impl_timer!(TIMER0, TIMER0, TIMER0); 153impl_timer!(TIMER0, TIMER0, TIMER0);
152impl_timer!(TIMER1, TIMER1, TIMER1); 154impl_timer!(TIMER1, TIMER1, TIMER1);
153impl_timer!(TIMER2, TIMER2, TIMER2); 155impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs
index c5de9a447..7d1bce1c0 100644
--- a/embassy-nrf/src/chips/nrf52811.rs
+++ b/embassy-nrf/src/chips/nrf52811.rs
@@ -150,6 +150,8 @@ impl_twis!(TWISPI0, TWIS0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0);
150 150
151impl_pwm!(PWM0, PWM0, PWM0); 151impl_pwm!(PWM0, PWM0, PWM0);
152 152
153impl_pdm!(PDM, PDM, PDM);
154
153impl_timer!(TIMER0, TIMER0, TIMER0); 155impl_timer!(TIMER0, TIMER0, TIMER0);
154impl_timer!(TIMER1, TIMER1, TIMER1); 156impl_timer!(TIMER1, TIMER1, TIMER1);
155impl_timer!(TIMER2, TIMER2, TIMER2); 157impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs
index c2b23fc5b..ce19a18e8 100644
--- a/embassy-nrf/src/chips/nrf52832.rs
+++ b/embassy-nrf/src/chips/nrf52832.rs
@@ -146,6 +146,9 @@ embassy_hal_common::peripherals! {
146 146
147 // I2S 147 // I2S
148 I2S, 148 I2S,
149
150 // PDM
151 PDM,
149} 152}
150 153
151impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); 154impl_uarte!(UARTE0, UARTE0, UARTE0_UART0);
@@ -168,6 +171,8 @@ impl_pwm!(PWM0, PWM0, PWM0);
168impl_pwm!(PWM1, PWM1, PWM1); 171impl_pwm!(PWM1, PWM1, PWM1);
169impl_pwm!(PWM2, PWM2, PWM2); 172impl_pwm!(PWM2, PWM2, PWM2);
170 173
174impl_pdm!(PDM, PDM, PDM);
175
171impl_timer!(TIMER0, TIMER0, TIMER0); 176impl_timer!(TIMER0, TIMER0, TIMER0);
172impl_timer!(TIMER1, TIMER1, TIMER1); 177impl_timer!(TIMER1, TIMER1, TIMER1);
173impl_timer!(TIMER2, TIMER2, TIMER2); 178impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs
index 95f71ade7..08b82021d 100644
--- a/embassy-nrf/src/chips/nrf52833.rs
+++ b/embassy-nrf/src/chips/nrf52833.rs
@@ -197,6 +197,8 @@ impl_pwm!(PWM1, PWM1, PWM1);
197impl_pwm!(PWM2, PWM2, PWM2); 197impl_pwm!(PWM2, PWM2, PWM2);
198impl_pwm!(PWM3, PWM3, PWM3); 198impl_pwm!(PWM3, PWM3, PWM3);
199 199
200impl_pdm!(PDM, PDM, PDM);
201
200impl_timer!(TIMER0, TIMER0, TIMER0); 202impl_timer!(TIMER0, TIMER0, TIMER0);
201impl_timer!(TIMER1, TIMER1, TIMER1); 203impl_timer!(TIMER1, TIMER1, TIMER1);
202impl_timer!(TIMER2, TIMER2, TIMER2); 204impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs
index 5e7479e88..4e8b6d9ee 100644
--- a/embassy-nrf/src/chips/nrf52840.rs
+++ b/embassy-nrf/src/chips/nrf52840.rs
@@ -208,6 +208,8 @@ impl_timer!(TIMER4, TIMER4, TIMER4, extended);
208 208
209impl_qspi!(QSPI, QSPI, QSPI); 209impl_qspi!(QSPI, QSPI, QSPI);
210 210
211impl_pdm!(PDM, PDM, PDM);
212
211impl_pin!(P0_00, 0, 0); 213impl_pin!(P0_00, 0, 0);
212impl_pin!(P0_01, 0, 1); 214impl_pin!(P0_01, 0, 1);
213impl_pin!(P0_02, 0, 2); 215impl_pin!(P0_02, 0, 2);
diff --git a/embassy-nrf/src/chips/nrf5340_app.rs b/embassy-nrf/src/chips/nrf5340_app.rs
index 9c7b738e6..050612b1c 100644
--- a/embassy-nrf/src/chips/nrf5340_app.rs
+++ b/embassy-nrf/src/chips/nrf5340_app.rs
@@ -34,7 +34,7 @@ pub mod pac {
34 nvmc_ns as nvmc, 34 nvmc_ns as nvmc,
35 oscillators_ns as oscillators, 35 oscillators_ns as oscillators,
36 p0_ns as p0, 36 p0_ns as p0,
37 pdm0_ns as pdm0, 37 pdm0_ns as pdm,
38 power_ns as power, 38 power_ns as power,
39 pwm0_ns as pwm0, 39 pwm0_ns as pwm0,
40 qdec0_ns as qdec0, 40 qdec0_ns as qdec0,
@@ -253,6 +253,9 @@ embassy_hal_common::peripherals! {
253 // QSPI 253 // QSPI
254 QSPI, 254 QSPI,
255 255
256 // PDM
257 PDM0,
258
256 // GPIOTE 259 // GPIOTE
257 GPIOTE_CH0, 260 GPIOTE_CH0,
258 GPIOTE_CH1, 261 GPIOTE_CH1,
@@ -398,6 +401,8 @@ impl_timer!(TIMER2, TIMER2, TIMER2);
398 401
399impl_qspi!(QSPI, QSPI, QSPI); 402impl_qspi!(QSPI, QSPI, QSPI);
400 403
404impl_pdm!(PDM0, PDM0, PDM0);
405
401impl_pin!(P0_00, 0, 0); 406impl_pin!(P0_00, 0, 0);
402impl_pin!(P0_01, 0, 1); 407impl_pin!(P0_01, 0, 1);
403#[cfg(feature = "nfc-pins-as-gpio")] 408#[cfg(feature = "nfc-pins-as-gpio")]
diff --git a/embassy-nrf/src/chips/nrf9160.rs b/embassy-nrf/src/chips/nrf9160.rs
index 385bd133d..d2b45114f 100644
--- a/embassy-nrf/src/chips/nrf9160.rs
+++ b/embassy-nrf/src/chips/nrf9160.rs
@@ -301,6 +301,8 @@ impl_pwm!(PWM1, PWM1, PWM1);
301impl_pwm!(PWM2, PWM2, PWM2); 301impl_pwm!(PWM2, PWM2, PWM2);
302impl_pwm!(PWM3, PWM3, PWM3); 302impl_pwm!(PWM3, PWM3, PWM3);
303 303
304impl_pdm!(PDM, PDM, PDM);
305
304impl_timer!(TIMER0, TIMER0, TIMER0); 306impl_timer!(TIMER0, TIMER0, TIMER0);
305impl_timer!(TIMER1, TIMER1, TIMER1); 307impl_timer!(TIMER1, TIMER1, TIMER1);
306impl_timer!(TIMER2, TIMER2, TIMER2); 308impl_timer!(TIMER2, TIMER2, TIMER2);
diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs
index 446b1f41a..17aa5ad15 100644
--- a/embassy-nrf/src/lib.rs
+++ b/embassy-nrf/src/lib.rs
@@ -47,8 +47,10 @@ pub mod nvmc;
47#[cfg(any( 47#[cfg(any(
48 feature = "nrf52810", 48 feature = "nrf52810",
49 feature = "nrf52811", 49 feature = "nrf52811",
50 feature = "nrf52832",
50 feature = "nrf52833", 51 feature = "nrf52833",
51 feature = "nrf52840", 52 feature = "nrf52840",
53 feature = "_nrf5340-app",
52 feature = "_nrf9160" 54 feature = "_nrf9160"
53))] 55))]
54pub mod pdm; 56pub mod pdm;
diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs
index 54feca4c1..8815bb316 100644
--- a/embassy-nrf/src/pdm.rs
+++ b/embassy-nrf/src/pdm.rs
@@ -1,25 +1,37 @@
1//! Pulse Density Modulation (PDM) mirophone driver. 1//! Pulse Density Modulation (PDM) mirophone driver.
2 2
3#![macro_use]
4
3use core::marker::PhantomData; 5use core::marker::PhantomData;
4use core::sync::atomic::{compiler_fence, Ordering}; 6use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::Poll; 7use core::task::Poll;
6 8
9use embassy_cortex_m::interrupt::Interrupt;
7use embassy_hal_common::drop::OnDrop; 10use embassy_hal_common::drop::OnDrop;
8use embassy_hal_common::{into_ref, PeripheralRef}; 11use embassy_hal_common::{into_ref, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker;
10use futures::future::poll_fn; 12use futures::future::poll_fn;
11 13
12use crate::chip::EASY_DMA_SIZE; 14use crate::chip::EASY_DMA_SIZE;
13use crate::gpio::sealed::Pin; 15use crate::gpio::sealed::Pin;
14use crate::gpio::{AnyPin, Pin as GpioPin}; 16use crate::gpio::{AnyPin, Pin as GpioPin};
15use crate::interrupt::{self, InterruptExt}; 17use crate::interrupt::{self, InterruptExt};
16use crate::peripherals::PDM; 18use crate::Peripheral;
17use crate::{pac, Peripheral}; 19
20/// Interrupt handler.
21pub struct InterruptHandler<T: Instance> {
22 _phantom: PhantomData<T>,
23}
24
25impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
26 unsafe fn on_interrupt() {
27 T::regs().intenclr.write(|w| w.end().clear());
28 T::state().waker.wake();
29 }
30}
18 31
19/// PDM microphone interface 32/// PDM microphone interface
20pub struct Pdm<'d> { 33pub struct Pdm<'d, T: Instance> {
21 irq: PeripheralRef<'d, interrupt::PDM>, 34 _peri: PeripheralRef<'d, T>,
22 phantom: PhantomData<&'d PDM>,
23} 35}
24 36
25/// PDM error. 37/// PDM error.
@@ -35,32 +47,30 @@ pub enum Error {
35 NotRunning, 47 NotRunning,
36} 48}
37 49
38static WAKER: AtomicWaker = AtomicWaker::new();
39static DUMMY_BUFFER: [i16; 1] = [0; 1]; 50static DUMMY_BUFFER: [i16; 1] = [0; 1];
40 51
41impl<'d> Pdm<'d> { 52impl<'d, T: Instance> Pdm<'d, T> {
42 /// Create PDM driver 53 /// Create PDM driver
43 pub fn new( 54 pub fn new(
44 pdm: impl Peripheral<P = PDM> + 'd, 55 pdm: impl Peripheral<P = T> + 'd,
45 irq: impl Peripheral<P = interrupt::PDM> + 'd, 56 _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
46 clk: impl Peripheral<P = impl GpioPin> + 'd, 57 clk: impl Peripheral<P = impl GpioPin> + 'd,
47 din: impl Peripheral<P = impl GpioPin> + 'd, 58 din: impl Peripheral<P = impl GpioPin> + 'd,
48 config: Config, 59 config: Config,
49 ) -> Self { 60 ) -> Self {
50 into_ref!(clk, din); 61 into_ref!(pdm, clk, din);
51 Self::new_inner(pdm, irq, clk.map_into(), din.map_into(), config) 62 Self::new_inner(pdm, clk.map_into(), din.map_into(), config)
52 } 63 }
53 64
54 fn new_inner( 65 fn new_inner(
55 _pdm: impl Peripheral<P = PDM> + 'd, 66 pdm: PeripheralRef<'d, T>,
56 irq: impl Peripheral<P = interrupt::PDM> + 'd,
57 clk: PeripheralRef<'d, AnyPin>, 67 clk: PeripheralRef<'d, AnyPin>,
58 din: PeripheralRef<'d, AnyPin>, 68 din: PeripheralRef<'d, AnyPin>,
59 config: Config, 69 config: Config,
60 ) -> Self { 70 ) -> Self {
61 into_ref!(irq); 71 into_ref!(pdm);
62 72
63 let r = Self::regs(); 73 let r = T::regs();
64 74
65 // setup gpio pins 75 // setup gpio pins
66 din.conf().write(|w| w.input().set_bit()); 76 din.conf().write(|w| w.input().set_bit());
@@ -84,26 +94,18 @@ impl<'d> Pdm<'d> {
84 r.gainr.write(|w| w.gainr().default_gain()); 94 r.gainr.write(|w| w.gainr().default_gain());
85 95
86 // IRQ 96 // IRQ
87 irq.disable(); 97 unsafe { T::Interrupt::steal() }.unpend();
88 irq.set_handler(|_| { 98 unsafe { T::Interrupt::steal() }.enable();
89 let r = Self::regs();
90 r.intenclr.write(|w| w.end().clear());
91 WAKER.wake();
92 });
93 irq.enable();
94 99
95 r.enable.write(|w| w.enable().set_bit()); 100 r.enable.write(|w| w.enable().set_bit());
96 101
97 Self { 102 Self { _peri: pdm }
98 phantom: PhantomData,
99 irq,
100 }
101 } 103 }
102 104
103 /// Start sampling microphon data into a dummy buffer 105 /// Start sampling microphon data into a dummy buffer
104 /// Usefull to start the microphon and keep it active between recording samples 106 /// Usefull to start the microphon and keep it active between recording samples
105 pub async fn start(&mut self) { 107 pub async fn start(&mut self) {
106 let r = Self::regs(); 108 let r = T::regs();
107 109
108 // start dummy sampling because microphon needs some setup time 110 // start dummy sampling because microphon needs some setup time
109 r.sample 111 r.sample
@@ -113,13 +115,13 @@ impl<'d> Pdm<'d> {
113 .maxcnt 115 .maxcnt
114 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); 116 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
115 117
116 r.tasks_start.write(|w| w.tasks_start().set_bit()); 118 r.tasks_start.write(|w| unsafe { w.bits(1) });
117 } 119 }
118 120
119 /// Stop sampling microphon data inta a dummy buffer 121 /// Stop sampling microphon data inta a dummy buffer
120 pub async fn stop(&mut self) { 122 pub async fn stop(&mut self) {
121 let r = Self::regs(); 123 let r = T::regs();
122 r.tasks_stop.write(|w| w.tasks_stop().set_bit()); 124 r.tasks_stop.write(|w| unsafe { w.bits(1) });
123 r.events_started.reset(); 125 r.events_started.reset();
124 } 126 }
125 127
@@ -132,9 +134,9 @@ impl<'d> Pdm<'d> {
132 return Err(Error::BufferTooLong); 134 return Err(Error::BufferTooLong);
133 } 135 }
134 136
135 let r = Self::regs(); 137 let r = T::regs();
136 138
137 if r.events_started.read().events_started().bit_is_clear() { 139 if r.events_started.read().bits() == 0 {
138 return Err(Error::NotRunning); 140 return Err(Error::NotRunning);
139 } 141 }
140 142
@@ -179,7 +181,7 @@ impl<'d> Pdm<'d> {
179 } 181 }
180 182
181 async fn wait_for_sample() { 183 async fn wait_for_sample() {
182 let r = Self::regs(); 184 let r = T::regs();
183 185
184 r.events_end.reset(); 186 r.events_end.reset();
185 r.intenset.write(|w| w.end().set()); 187 r.intenset.write(|w| w.end().set());
@@ -187,8 +189,8 @@ impl<'d> Pdm<'d> {
187 compiler_fence(Ordering::SeqCst); 189 compiler_fence(Ordering::SeqCst);
188 190
189 poll_fn(|cx| { 191 poll_fn(|cx| {
190 WAKER.register(cx.waker()); 192 T::state().waker.register(cx.waker());
191 if r.events_end.read().events_end().bit_is_set() { 193 if r.events_end.read().bits() != 0 {
192 return Poll::Ready(()); 194 return Poll::Ready(());
193 } 195 }
194 Poll::Pending 196 Poll::Pending
@@ -197,10 +199,6 @@ impl<'d> Pdm<'d> {
197 199
198 compiler_fence(Ordering::SeqCst); 200 compiler_fence(Ordering::SeqCst);
199 } 201 }
200
201 fn regs() -> &'static pac::pdm::RegisterBlock {
202 unsafe { &*pac::PDM::ptr() }
203 }
204} 202}
205 203
206/// PDM microphone driver Config 204/// PDM microphone driver Config
@@ -238,13 +236,11 @@ pub enum Edge {
238 LeftFalling, 236 LeftFalling,
239} 237}
240 238
241impl<'d> Drop for Pdm<'d> { 239impl<'d, T: Instance> Drop for Pdm<'d, T> {
242 fn drop(&mut self) { 240 fn drop(&mut self) {
243 let r = Self::regs(); 241 let r = T::regs();
244 242
245 r.tasks_stop.write(|w| w.tasks_stop().set_bit()); 243 r.tasks_stop.write(|w| unsafe { w.bits(1) });
246
247 self.irq.disable();
248 244
249 r.enable.write(|w| w.enable().disabled()); 245 r.enable.write(|w| w.enable().disabled());
250 246
@@ -252,3 +248,48 @@ impl<'d> Drop for Pdm<'d> {
252 r.psel.clk.reset(); 248 r.psel.clk.reset();
253 } 249 }
254} 250}
251
252pub(crate) mod sealed {
253 use embassy_sync::waitqueue::AtomicWaker;
254
255 /// Peripheral static state
256 pub struct State {
257 pub waker: AtomicWaker,
258 }
259
260 impl State {
261 pub const fn new() -> Self {
262 Self {
263 waker: AtomicWaker::new(),
264 }
265 }
266 }
267
268 pub trait Instance {
269 fn regs() -> &'static crate::pac::pdm::RegisterBlock;
270 fn state() -> &'static State;
271 }
272}
273
274/// PDM peripheral instance.
275pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
276 /// Interrupt for this peripheral.
277 type Interrupt: Interrupt;
278}
279
280macro_rules! impl_pdm {
281 ($type:ident, $pac_type:ident, $irq:ident) => {
282 impl crate::pdm::sealed::Instance for peripherals::$type {
283 fn regs() -> &'static crate::pac::pdm::RegisterBlock {
284 unsafe { &*pac::$pac_type::ptr() }
285 }
286 fn state() -> &'static crate::pdm::sealed::State {
287 static STATE: crate::pdm::sealed::State = crate::pdm::sealed::State::new();
288 &STATE
289 }
290 }
291 impl crate::pdm::Instance for peripherals::$type {
292 type Interrupt = crate::interrupt::$irq;
293 }
294 };
295}
diff --git a/examples/nrf52840/src/bin/pdm.rs b/examples/nrf52840/src/bin/pdm.rs
index 7388580fb..6b41320ca 100644
--- a/examples/nrf52840/src/bin/pdm.rs
+++ b/examples/nrf52840/src/bin/pdm.rs
@@ -4,16 +4,20 @@
4 4
5use defmt::info; 5use defmt::info;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_nrf::interrupt; 7use embassy_nrf::pdm::{self, Config, Pdm};
8use embassy_nrf::pdm::{Config, Pdm}; 8use embassy_nrf::{bind_interrupts, peripherals};
9use embassy_time::{Duration, Timer}; 9use embassy_time::{Duration, Timer};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 PDM => pdm::InterruptHandler<peripherals::PDM>;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_p: Spawner) { 17async fn main(_p: Spawner) {
14 let p = embassy_nrf::init(Default::default()); 18 let p = embassy_nrf::init(Default::default());
15 let config = Config::default(); 19 let config = Config::default();
16 let mut pdm = Pdm::new(p.PDM, interrupt::take!(PDM), p.P0_01, p.P0_00, config); 20 let mut pdm = Pdm::new(p.PDM, Irqs, p.P0_01, p.P0_00, config);
17 21
18 loop { 22 loop {
19 pdm.start().await; 23 pdm.start().await;