aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes41
-rwxr-xr-x.github/ci/crlf.sh17
-rw-r--r--embassy-nrf/src/pdm.rs588
-rw-r--r--embassy-stm32/src/qspi/mod.rs664
4 files changed, 684 insertions, 626 deletions
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..4db9edae7
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,41 @@
1* text=auto
2
3*.adoc text
4*.html text
5*.in text
6*.json text
7*.md text
8*.proto text
9*.py text
10*.rs text
11*.service text
12*.sh text
13*.toml text
14*.txt text
15*.x text
16*.yml text
17
18*.raw binary
19*.bin binary
20*.png binary
21*.jpg binary
22*.jpeg binary
23*.gif binary
24*.ico binary
25*.mov binary
26*.mp4 binary
27*.mp3 binary
28*.flv binary
29*.fla binary
30*.swf binary
31*.gz binary
32*.zip binary
33*.7z binary
34*.ttf binary
35*.eot binary
36*.woff binary
37*.pyc binary
38*.pdf binary
39*.ez binary
40*.bz2 binary
41*.swp binary \ No newline at end of file
diff --git a/.github/ci/crlf.sh b/.github/ci/crlf.sh
new file mode 100755
index 000000000..457510407
--- /dev/null
+++ b/.github/ci/crlf.sh
@@ -0,0 +1,17 @@
1#!/bin/bash
2## on push branch~=gh-readonly-queue/main/.*
3## on pull_request
4
5set -euo pipefail
6
7FILES_WITH_CRLF=$(find ! -path "./.git/*" -not -type d | xargs file -N | (grep " CRLF " || true))
8
9if [ -z "$FILES_WITH_CRLF" ]; then
10 echo -e "No files with CRLF endings found."
11 exit 0
12else
13 NR_FILES=$(echo "$FILES_WITH_CRLF" | wc -l)
14 echo -e "ERROR: Found ${NR_FILES} files with CRLF endings."
15 echo "$FILES_WITH_CRLF"
16 exit "$NR_FILES"
17fi \ No newline at end of file
diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs
index 0e30f7002..efa1fbccc 100644
--- a/embassy-nrf/src/pdm.rs
+++ b/embassy-nrf/src/pdm.rs
@@ -1,294 +1,294 @@
1//! Pulse Density Modulation (PDM) mirophone driver. 1//! Pulse Density Modulation (PDM) mirophone driver.
2 2
3#![macro_use] 3#![macro_use]
4 4
5use core::marker::PhantomData; 5use core::marker::PhantomData;
6use core::sync::atomic::{compiler_fence, Ordering}; 6use core::sync::atomic::{compiler_fence, Ordering};
7use core::task::Poll; 7use core::task::Poll;
8 8
9use embassy_hal_common::drop::OnDrop; 9use embassy_hal_common::drop::OnDrop;
10use embassy_hal_common::{into_ref, PeripheralRef}; 10use embassy_hal_common::{into_ref, PeripheralRef};
11use futures::future::poll_fn; 11use futures::future::poll_fn;
12 12
13use crate::chip::EASY_DMA_SIZE; 13use crate::chip::EASY_DMA_SIZE;
14use crate::gpio::sealed::Pin; 14use crate::gpio::sealed::Pin;
15use crate::gpio::{AnyPin, Pin as GpioPin}; 15use crate::gpio::{AnyPin, Pin as GpioPin};
16use crate::interrupt::typelevel::Interrupt; 16use crate::interrupt::typelevel::Interrupt;
17use crate::{interrupt, Peripheral}; 17use crate::{interrupt, Peripheral};
18 18
19/// Interrupt handler. 19/// Interrupt handler.
20pub struct InterruptHandler<T: Instance> { 20pub struct InterruptHandler<T: Instance> {
21 _phantom: PhantomData<T>, 21 _phantom: PhantomData<T>,
22} 22}
23 23
24impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { 24impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> {
25 unsafe fn on_interrupt() { 25 unsafe fn on_interrupt() {
26 T::regs().intenclr.write(|w| w.end().clear()); 26 T::regs().intenclr.write(|w| w.end().clear());
27 T::state().waker.wake(); 27 T::state().waker.wake();
28 } 28 }
29} 29}
30 30
31/// PDM microphone interface 31/// PDM microphone interface
32pub struct Pdm<'d, T: Instance> { 32pub struct Pdm<'d, T: Instance> {
33 _peri: PeripheralRef<'d, T>, 33 _peri: PeripheralRef<'d, T>,
34} 34}
35 35
36/// PDM error. 36/// PDM error.
37#[derive(Debug, Clone, Copy, PartialEq, Eq)] 37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38#[cfg_attr(feature = "defmt", derive(defmt::Format))] 38#[cfg_attr(feature = "defmt", derive(defmt::Format))]
39#[non_exhaustive] 39#[non_exhaustive]
40pub enum Error { 40pub enum Error {
41 /// Buffer is too long. 41 /// Buffer is too long.
42 BufferTooLong, 42 BufferTooLong,
43 /// Buffer is empty 43 /// Buffer is empty
44 BufferZeroLength, 44 BufferZeroLength,
45 /// PDM is not running 45 /// PDM is not running
46 NotRunning, 46 NotRunning,
47} 47}
48 48
49static DUMMY_BUFFER: [i16; 1] = [0; 1]; 49static DUMMY_BUFFER: [i16; 1] = [0; 1];
50 50
51impl<'d, T: Instance> Pdm<'d, T> { 51impl<'d, T: Instance> Pdm<'d, T> {
52 /// Create PDM driver 52 /// Create PDM driver
53 pub fn new( 53 pub fn new(
54 pdm: impl Peripheral<P = T> + 'd, 54 pdm: impl Peripheral<P = T> + 'd,
55 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, 55 _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd,
56 clk: impl Peripheral<P = impl GpioPin> + 'd, 56 clk: impl Peripheral<P = impl GpioPin> + 'd,
57 din: impl Peripheral<P = impl GpioPin> + 'd, 57 din: impl Peripheral<P = impl GpioPin> + 'd,
58 config: Config, 58 config: Config,
59 ) -> Self { 59 ) -> Self {
60 into_ref!(pdm, clk, din); 60 into_ref!(pdm, clk, din);
61 Self::new_inner(pdm, clk.map_into(), din.map_into(), config) 61 Self::new_inner(pdm, clk.map_into(), din.map_into(), config)
62 } 62 }
63 63
64 fn new_inner( 64 fn new_inner(
65 pdm: PeripheralRef<'d, T>, 65 pdm: PeripheralRef<'d, T>,
66 clk: PeripheralRef<'d, AnyPin>, 66 clk: PeripheralRef<'d, AnyPin>,
67 din: PeripheralRef<'d, AnyPin>, 67 din: PeripheralRef<'d, AnyPin>,
68 config: Config, 68 config: Config,
69 ) -> Self { 69 ) -> Self {
70 into_ref!(pdm); 70 into_ref!(pdm);
71 71
72 let r = T::regs(); 72 let r = T::regs();
73 73
74 // setup gpio pins 74 // setup gpio pins
75 din.conf().write(|w| w.input().set_bit()); 75 din.conf().write(|w| w.input().set_bit());
76 r.psel.din.write(|w| unsafe { w.bits(din.psel_bits()) }); 76 r.psel.din.write(|w| unsafe { w.bits(din.psel_bits()) });
77 clk.set_low(); 77 clk.set_low();
78 clk.conf().write(|w| w.dir().output()); 78 clk.conf().write(|w| w.dir().output());
79 r.psel.clk.write(|w| unsafe { w.bits(clk.psel_bits()) }); 79 r.psel.clk.write(|w| unsafe { w.bits(clk.psel_bits()) });
80 80
81 // configure 81 // configure
82 // use default for 82 // use default for
83 // - gain right 83 // - gain right
84 // - gain left 84 // - gain left
85 // - clk 85 // - clk
86 // - ratio 86 // - ratio
87 r.mode.write(|w| { 87 r.mode.write(|w| {
88 w.edge().bit(config.edge == Edge::LeftRising); 88 w.edge().bit(config.edge == Edge::LeftRising);
89 w.operation().bit(config.operation_mode == OperationMode::Mono); 89 w.operation().bit(config.operation_mode == OperationMode::Mono);
90 w 90 w
91 }); 91 });
92 r.gainl.write(|w| w.gainl().default_gain()); 92 r.gainl.write(|w| w.gainl().default_gain());
93 r.gainr.write(|w| w.gainr().default_gain()); 93 r.gainr.write(|w| w.gainr().default_gain());
94 94
95 // IRQ 95 // IRQ
96 T::Interrupt::unpend(); 96 T::Interrupt::unpend();
97 unsafe { T::Interrupt::enable() }; 97 unsafe { T::Interrupt::enable() };
98 98
99 r.enable.write(|w| w.enable().set_bit()); 99 r.enable.write(|w| w.enable().set_bit());
100 100
101 Self { _peri: pdm } 101 Self { _peri: pdm }
102 } 102 }
103 103
104 /// Start sampling microphon data into a dummy buffer 104 /// Start sampling microphon data into a dummy buffer
105 /// Usefull to start the microphon and keep it active between recording samples 105 /// Usefull to start the microphon and keep it active between recording samples
106 pub async fn start(&mut self) { 106 pub async fn start(&mut self) {
107 let r = T::regs(); 107 let r = T::regs();
108 108
109 // start dummy sampling because microphon needs some setup time 109 // start dummy sampling because microphon needs some setup time
110 r.sample 110 r.sample
111 .ptr 111 .ptr
112 .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); 112 .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
113 r.sample 113 r.sample
114 .maxcnt 114 .maxcnt
115 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); 115 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
116 116
117 r.tasks_start.write(|w| unsafe { w.bits(1) }); 117 r.tasks_start.write(|w| unsafe { w.bits(1) });
118 } 118 }
119 119
120 /// Stop sampling microphon data inta a dummy buffer 120 /// Stop sampling microphon data inta a dummy buffer
121 pub async fn stop(&mut self) { 121 pub async fn stop(&mut self) {
122 let r = T::regs(); 122 let r = T::regs();
123 r.tasks_stop.write(|w| unsafe { w.bits(1) }); 123 r.tasks_stop.write(|w| unsafe { w.bits(1) });
124 r.events_started.reset(); 124 r.events_started.reset();
125 } 125 }
126 126
127 /// Sample data into the given buffer. 127 /// Sample data into the given buffer.
128 pub async fn sample(&mut self, buffer: &mut [i16]) -> Result<(), Error> { 128 pub async fn sample(&mut self, buffer: &mut [i16]) -> Result<(), Error> {
129 if buffer.len() == 0 { 129 if buffer.len() == 0 {
130 return Err(Error::BufferZeroLength); 130 return Err(Error::BufferZeroLength);
131 } 131 }
132 if buffer.len() > EASY_DMA_SIZE { 132 if buffer.len() > EASY_DMA_SIZE {
133 return Err(Error::BufferTooLong); 133 return Err(Error::BufferTooLong);
134 } 134 }
135 135
136 let r = T::regs(); 136 let r = T::regs();
137 137
138 if r.events_started.read().bits() == 0 { 138 if r.events_started.read().bits() == 0 {
139 return Err(Error::NotRunning); 139 return Err(Error::NotRunning);
140 } 140 }
141 141
142 let drop = OnDrop::new(move || { 142 let drop = OnDrop::new(move || {
143 r.intenclr.write(|w| w.end().clear()); 143 r.intenclr.write(|w| w.end().clear());
144 r.events_stopped.reset(); 144 r.events_stopped.reset();
145 145
146 // reset to dummy buffer 146 // reset to dummy buffer
147 r.sample 147 r.sample
148 .ptr 148 .ptr
149 .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); 149 .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
150 r.sample 150 r.sample
151 .maxcnt 151 .maxcnt
152 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); 152 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
153 153
154 while r.events_stopped.read().bits() == 0 {} 154 while r.events_stopped.read().bits() == 0 {}
155 }); 155 });
156 156
157 // setup user buffer 157 // setup user buffer
158 let ptr = buffer.as_ptr(); 158 let ptr = buffer.as_ptr();
159 let len = buffer.len(); 159 let len = buffer.len();
160 r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(ptr as u32) }); 160 r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(ptr as u32) });
161 r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(len as _) }); 161 r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(len as _) });
162 162
163 // wait till the current sample is finished and the user buffer sample is started 163 // wait till the current sample is finished and the user buffer sample is started
164 Self::wait_for_sample().await; 164 Self::wait_for_sample().await;
165 165
166 // reset the buffer back to the dummy buffer 166 // reset the buffer back to the dummy buffer
167 r.sample 167 r.sample
168 .ptr 168 .ptr
169 .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); 169 .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) });
170 r.sample 170 r.sample
171 .maxcnt 171 .maxcnt
172 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); 172 .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) });
173 173
174 // wait till the user buffer is sampled 174 // wait till the user buffer is sampled
175 Self::wait_for_sample().await; 175 Self::wait_for_sample().await;
176 176
177 drop.defuse(); 177 drop.defuse();
178 178
179 Ok(()) 179 Ok(())
180 } 180 }
181 181
182 async fn wait_for_sample() { 182 async fn wait_for_sample() {
183 let r = T::regs(); 183 let r = T::regs();
184 184
185 r.events_end.reset(); 185 r.events_end.reset();
186 r.intenset.write(|w| w.end().set()); 186 r.intenset.write(|w| w.end().set());
187 187
188 compiler_fence(Ordering::SeqCst); 188 compiler_fence(Ordering::SeqCst);
189 189
190 poll_fn(|cx| { 190 poll_fn(|cx| {
191 T::state().waker.register(cx.waker()); 191 T::state().waker.register(cx.waker());
192 if r.events_end.read().bits() != 0 { 192 if r.events_end.read().bits() != 0 {
193 return Poll::Ready(()); 193 return Poll::Ready(());
194 } 194 }
195 Poll::Pending 195 Poll::Pending
196 }) 196 })
197 .await; 197 .await;
198 198
199 compiler_fence(Ordering::SeqCst); 199 compiler_fence(Ordering::SeqCst);
200 } 200 }
201} 201}
202 202
203/// PDM microphone driver Config 203/// PDM microphone driver Config
204pub struct Config { 204pub struct Config {
205 /// Use stero or mono operation 205 /// Use stero or mono operation
206 pub operation_mode: OperationMode, 206 pub operation_mode: OperationMode,
207 /// On which edge the left channel should be samples 207 /// On which edge the left channel should be samples
208 pub edge: Edge, 208 pub edge: Edge,
209} 209}
210 210
211impl Default for Config { 211impl Default for Config {
212 fn default() -> Self { 212 fn default() -> Self {
213 Self { 213 Self {
214 operation_mode: OperationMode::Mono, 214 operation_mode: OperationMode::Mono,
215 edge: Edge::LeftFalling, 215 edge: Edge::LeftFalling,
216 } 216 }
217 } 217 }
218} 218}
219 219
220/// PDM operation mode. 220/// PDM operation mode.
221#[derive(PartialEq)] 221#[derive(PartialEq)]
222pub enum OperationMode { 222pub enum OperationMode {
223 /// Mono (1 channel) 223 /// Mono (1 channel)
224 Mono, 224 Mono,
225 /// Stereo (2 channels) 225 /// Stereo (2 channels)
226 Stereo, 226 Stereo,
227} 227}
228 228
229/// PDM edge polarity 229/// PDM edge polarity
230#[derive(PartialEq)] 230#[derive(PartialEq)]
231pub enum Edge { 231pub enum Edge {
232 /// Left edge is rising 232 /// Left edge is rising
233 LeftRising, 233 LeftRising,
234 /// Left edge is falling 234 /// Left edge is falling
235 LeftFalling, 235 LeftFalling,
236} 236}
237 237
238impl<'d, T: Instance> Drop for Pdm<'d, T> { 238impl<'d, T: Instance> Drop for Pdm<'d, T> {
239 fn drop(&mut self) { 239 fn drop(&mut self) {
240 let r = T::regs(); 240 let r = T::regs();
241 241
242 r.tasks_stop.write(|w| unsafe { w.bits(1) }); 242 r.tasks_stop.write(|w| unsafe { w.bits(1) });
243 243
244 r.enable.write(|w| w.enable().disabled()); 244 r.enable.write(|w| w.enable().disabled());
245 245
246 r.psel.din.reset(); 246 r.psel.din.reset();
247 r.psel.clk.reset(); 247 r.psel.clk.reset();
248 } 248 }
249} 249}
250 250
251pub(crate) mod sealed { 251pub(crate) mod sealed {
252 use embassy_sync::waitqueue::AtomicWaker; 252 use embassy_sync::waitqueue::AtomicWaker;
253 253
254 /// Peripheral static state 254 /// Peripheral static state
255 pub struct State { 255 pub struct State {
256 pub waker: AtomicWaker, 256 pub waker: AtomicWaker,
257 } 257 }
258 258
259 impl State { 259 impl State {
260 pub const fn new() -> Self { 260 pub const fn new() -> Self {
261 Self { 261 Self {
262 waker: AtomicWaker::new(), 262 waker: AtomicWaker::new(),
263 } 263 }
264 } 264 }
265 } 265 }
266 266
267 pub trait Instance { 267 pub trait Instance {
268 fn regs() -> &'static crate::pac::pdm::RegisterBlock; 268 fn regs() -> &'static crate::pac::pdm::RegisterBlock;
269 fn state() -> &'static State; 269 fn state() -> &'static State;
270 } 270 }
271} 271}
272 272
273/// PDM peripheral instance. 273/// PDM peripheral instance.
274pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send { 274pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send {
275 /// Interrupt for this peripheral. 275 /// Interrupt for this peripheral.
276 type Interrupt: interrupt::typelevel::Interrupt; 276 type Interrupt: interrupt::typelevel::Interrupt;
277} 277}
278 278
279macro_rules! impl_pdm { 279macro_rules! impl_pdm {
280 ($type:ident, $pac_type:ident, $irq:ident) => { 280 ($type:ident, $pac_type:ident, $irq:ident) => {
281 impl crate::pdm::sealed::Instance for peripherals::$type { 281 impl crate::pdm::sealed::Instance for peripherals::$type {
282 fn regs() -> &'static crate::pac::pdm::RegisterBlock { 282 fn regs() -> &'static crate::pac::pdm::RegisterBlock {
283 unsafe { &*pac::$pac_type::ptr() } 283 unsafe { &*pac::$pac_type::ptr() }
284 } 284 }
285 fn state() -> &'static crate::pdm::sealed::State { 285 fn state() -> &'static crate::pdm::sealed::State {
286 static STATE: crate::pdm::sealed::State = crate::pdm::sealed::State::new(); 286 static STATE: crate::pdm::sealed::State = crate::pdm::sealed::State::new();
287 &STATE 287 &STATE
288 } 288 }
289 } 289 }
290 impl crate::pdm::Instance for peripherals::$type { 290 impl crate::pdm::Instance for peripherals::$type {
291 type Interrupt = crate::interrupt::typelevel::$irq; 291 type Interrupt = crate::interrupt::typelevel::$irq;
292 } 292 }
293 }; 293 };
294} 294}
diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs
index e9db934bf..31b676088 100644
--- a/embassy-stm32/src/qspi/mod.rs
+++ b/embassy-stm32/src/qspi/mod.rs
@@ -1,332 +1,332 @@
1#![macro_use] 1#![macro_use]
2 2
3pub mod enums; 3pub mod enums;
4 4
5use embassy_hal_common::{into_ref, PeripheralRef}; 5use embassy_hal_common::{into_ref, PeripheralRef};
6use enums::*; 6use enums::*;
7 7
8use crate::dma::Transfer; 8use crate::dma::Transfer;
9use crate::gpio::sealed::AFType; 9use crate::gpio::sealed::AFType;
10use crate::gpio::AnyPin; 10use crate::gpio::AnyPin;
11use crate::pac::quadspi::Quadspi as Regs; 11use crate::pac::quadspi::Quadspi as Regs;
12use crate::rcc::RccPeripheral; 12use crate::rcc::RccPeripheral;
13use crate::{peripherals, Peripheral}; 13use crate::{peripherals, Peripheral};
14 14
15pub struct TransferConfig { 15pub struct TransferConfig {
16 /// Instraction width (IMODE) 16 /// Instraction width (IMODE)
17 pub iwidth: QspiWidth, 17 pub iwidth: QspiWidth,
18 /// Address width (ADMODE) 18 /// Address width (ADMODE)
19 pub awidth: QspiWidth, 19 pub awidth: QspiWidth,
20 /// Data width (DMODE) 20 /// Data width (DMODE)
21 pub dwidth: QspiWidth, 21 pub dwidth: QspiWidth,
22 /// Instruction Id 22 /// Instruction Id
23 pub instruction: u8, 23 pub instruction: u8,
24 /// Flash memory address 24 /// Flash memory address
25 pub address: Option<u32>, 25 pub address: Option<u32>,
26 /// Number of dummy cycles (DCYC) 26 /// Number of dummy cycles (DCYC)
27 pub dummy: DummyCycles, 27 pub dummy: DummyCycles,
28 /// Length of data 28 /// Length of data
29 pub data_len: Option<usize>, 29 pub data_len: Option<usize>,
30} 30}
31 31
32impl Default for TransferConfig { 32impl Default for TransferConfig {
33 fn default() -> Self { 33 fn default() -> Self {
34 Self { 34 Self {
35 iwidth: QspiWidth::NONE, 35 iwidth: QspiWidth::NONE,
36 awidth: QspiWidth::NONE, 36 awidth: QspiWidth::NONE,
37 dwidth: QspiWidth::NONE, 37 dwidth: QspiWidth::NONE,
38 instruction: 0, 38 instruction: 0,
39 address: None, 39 address: None,
40 dummy: DummyCycles::_0, 40 dummy: DummyCycles::_0,
41 data_len: None, 41 data_len: None,
42 } 42 }
43 } 43 }
44} 44}
45 45
46pub struct Config { 46pub struct Config {
47 /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen. 47 /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen.
48 /// If you need other value the whose predefined use `Other` variant. 48 /// If you need other value the whose predefined use `Other` variant.
49 pub memory_size: MemorySize, 49 pub memory_size: MemorySize,
50 /// Address size (8/16/24/32-bit) 50 /// Address size (8/16/24/32-bit)
51 pub address_size: AddressSize, 51 pub address_size: AddressSize,
52 /// Scalar factor for generating CLK [0-255] 52 /// Scalar factor for generating CLK [0-255]
53 pub prescaler: u8, 53 pub prescaler: u8,
54 /// Number of bytes to trigger FIFO threshold flag. 54 /// Number of bytes to trigger FIFO threshold flag.
55 pub fifo_threshold: FIFOThresholdLevel, 55 pub fifo_threshold: FIFOThresholdLevel,
56 /// Minimum number of cycles that chip select must be high between issued commands 56 /// Minimum number of cycles that chip select must be high between issued commands
57 pub cs_high_time: ChipSelectHightTime, 57 pub cs_high_time: ChipSelectHightTime,
58} 58}
59 59
60impl Default for Config { 60impl Default for Config {
61 fn default() -> Self { 61 fn default() -> Self {
62 Self { 62 Self {
63 memory_size: MemorySize::Other(0), 63 memory_size: MemorySize::Other(0),
64 address_size: AddressSize::_24bit, 64 address_size: AddressSize::_24bit,
65 prescaler: 128, 65 prescaler: 128,
66 fifo_threshold: FIFOThresholdLevel::_17Bytes, 66 fifo_threshold: FIFOThresholdLevel::_17Bytes,
67 cs_high_time: ChipSelectHightTime::_5Cycle, 67 cs_high_time: ChipSelectHightTime::_5Cycle,
68 } 68 }
69 } 69 }
70} 70}
71 71
72#[allow(dead_code)] 72#[allow(dead_code)]
73pub struct Qspi<'d, T: Instance, Dma> { 73pub struct Qspi<'d, T: Instance, Dma> {
74 _peri: PeripheralRef<'d, T>, 74 _peri: PeripheralRef<'d, T>,
75 sck: Option<PeripheralRef<'d, AnyPin>>, 75 sck: Option<PeripheralRef<'d, AnyPin>>,
76 d0: Option<PeripheralRef<'d, AnyPin>>, 76 d0: Option<PeripheralRef<'d, AnyPin>>,
77 d1: Option<PeripheralRef<'d, AnyPin>>, 77 d1: Option<PeripheralRef<'d, AnyPin>>,
78 d2: Option<PeripheralRef<'d, AnyPin>>, 78 d2: Option<PeripheralRef<'d, AnyPin>>,
79 d3: Option<PeripheralRef<'d, AnyPin>>, 79 d3: Option<PeripheralRef<'d, AnyPin>>,
80 nss: Option<PeripheralRef<'d, AnyPin>>, 80 nss: Option<PeripheralRef<'d, AnyPin>>,
81 dma: PeripheralRef<'d, Dma>, 81 dma: PeripheralRef<'d, Dma>,
82 config: Config, 82 config: Config,
83} 83}
84 84
85impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { 85impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> {
86 pub fn new( 86 pub fn new(
87 peri: impl Peripheral<P = T> + 'd, 87 peri: impl Peripheral<P = T> + 'd,
88 d0: impl Peripheral<P = impl D0Pin<T>> + 'd, 88 d0: impl Peripheral<P = impl D0Pin<T>> + 'd,
89 d1: impl Peripheral<P = impl D1Pin<T>> + 'd, 89 d1: impl Peripheral<P = impl D1Pin<T>> + 'd,
90 d2: impl Peripheral<P = impl D2Pin<T>> + 'd, 90 d2: impl Peripheral<P = impl D2Pin<T>> + 'd,
91 d3: impl Peripheral<P = impl D3Pin<T>> + 'd, 91 d3: impl Peripheral<P = impl D3Pin<T>> + 'd,
92 sck: impl Peripheral<P = impl SckPin<T>> + 'd, 92 sck: impl Peripheral<P = impl SckPin<T>> + 'd,
93 nss: impl Peripheral<P = impl NSSPin<T>> + 'd, 93 nss: impl Peripheral<P = impl NSSPin<T>> + 'd,
94 dma: impl Peripheral<P = Dma> + 'd, 94 dma: impl Peripheral<P = Dma> + 'd,
95 config: Config, 95 config: Config,
96 ) -> Self { 96 ) -> Self {
97 into_ref!(peri, d0, d1, d2, d3, sck, nss); 97 into_ref!(peri, d0, d1, d2, d3, sck, nss);
98 98
99 sck.set_as_af(sck.af_num(), AFType::OutputPushPull); 99 sck.set_as_af(sck.af_num(), AFType::OutputPushPull);
100 sck.set_speed(crate::gpio::Speed::VeryHigh); 100 sck.set_speed(crate::gpio::Speed::VeryHigh);
101 nss.set_as_af(nss.af_num(), AFType::OutputPushPull); 101 nss.set_as_af(nss.af_num(), AFType::OutputPushPull);
102 nss.set_speed(crate::gpio::Speed::VeryHigh); 102 nss.set_speed(crate::gpio::Speed::VeryHigh);
103 d0.set_as_af(d0.af_num(), AFType::OutputPushPull); 103 d0.set_as_af(d0.af_num(), AFType::OutputPushPull);
104 d0.set_speed(crate::gpio::Speed::VeryHigh); 104 d0.set_speed(crate::gpio::Speed::VeryHigh);
105 d1.set_as_af(d1.af_num(), AFType::OutputPushPull); 105 d1.set_as_af(d1.af_num(), AFType::OutputPushPull);
106 d1.set_speed(crate::gpio::Speed::VeryHigh); 106 d1.set_speed(crate::gpio::Speed::VeryHigh);
107 d2.set_as_af(d2.af_num(), AFType::OutputPushPull); 107 d2.set_as_af(d2.af_num(), AFType::OutputPushPull);
108 d2.set_speed(crate::gpio::Speed::VeryHigh); 108 d2.set_speed(crate::gpio::Speed::VeryHigh);
109 d3.set_as_af(d3.af_num(), AFType::OutputPushPull); 109 d3.set_as_af(d3.af_num(), AFType::OutputPushPull);
110 d3.set_speed(crate::gpio::Speed::VeryHigh); 110 d3.set_speed(crate::gpio::Speed::VeryHigh);
111 111
112 Self::new_inner( 112 Self::new_inner(
113 peri, 113 peri,
114 Some(d0.map_into()), 114 Some(d0.map_into()),
115 Some(d1.map_into()), 115 Some(d1.map_into()),
116 Some(d2.map_into()), 116 Some(d2.map_into()),
117 Some(d3.map_into()), 117 Some(d3.map_into()),
118 Some(sck.map_into()), 118 Some(sck.map_into()),
119 Some(nss.map_into()), 119 Some(nss.map_into()),
120 dma, 120 dma,
121 config, 121 config,
122 ) 122 )
123 } 123 }
124 124
125 fn new_inner( 125 fn new_inner(
126 peri: impl Peripheral<P = T> + 'd, 126 peri: impl Peripheral<P = T> + 'd,
127 d0: Option<PeripheralRef<'d, AnyPin>>, 127 d0: Option<PeripheralRef<'d, AnyPin>>,
128 d1: Option<PeripheralRef<'d, AnyPin>>, 128 d1: Option<PeripheralRef<'d, AnyPin>>,
129 d2: Option<PeripheralRef<'d, AnyPin>>, 129 d2: Option<PeripheralRef<'d, AnyPin>>,
130 d3: Option<PeripheralRef<'d, AnyPin>>, 130 d3: Option<PeripheralRef<'d, AnyPin>>,
131 sck: Option<PeripheralRef<'d, AnyPin>>, 131 sck: Option<PeripheralRef<'d, AnyPin>>,
132 nss: Option<PeripheralRef<'d, AnyPin>>, 132 nss: Option<PeripheralRef<'d, AnyPin>>,
133 dma: impl Peripheral<P = Dma> + 'd, 133 dma: impl Peripheral<P = Dma> + 'd,
134 config: Config, 134 config: Config,
135 ) -> Self { 135 ) -> Self {
136 into_ref!(peri, dma); 136 into_ref!(peri, dma);
137 137
138 T::enable(); 138 T::enable();
139 T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); 139 T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into()));
140 140
141 while T::REGS.sr().read().busy() {} 141 while T::REGS.sr().read().busy() {}
142 142
143 T::REGS.cr().write(|w| { 143 T::REGS.cr().write(|w| {
144 w.set_prescaler(config.prescaler); 144 w.set_prescaler(config.prescaler);
145 w.set_en(true); 145 w.set_en(true);
146 }); 146 });
147 T::REGS.dcr().write(|w| { 147 T::REGS.dcr().write(|w| {
148 w.set_fsize(config.memory_size.into()); 148 w.set_fsize(config.memory_size.into());
149 w.set_csht(config.cs_high_time.into()); 149 w.set_csht(config.cs_high_time.into());
150 w.set_ckmode(false); 150 w.set_ckmode(false);
151 }); 151 });
152 152
153 Self { 153 Self {
154 _peri: peri, 154 _peri: peri,
155 sck, 155 sck,
156 d0, 156 d0,
157 d1, 157 d1,
158 d2, 158 d2,
159 d3, 159 d3,
160 nss, 160 nss,
161 dma, 161 dma,
162 config, 162 config,
163 } 163 }
164 } 164 }
165 165
166 pub fn command(&mut self, transaction: TransferConfig) { 166 pub fn command(&mut self, transaction: TransferConfig) {
167 T::REGS.cr().modify(|v| v.set_dmaen(false)); 167 T::REGS.cr().modify(|v| v.set_dmaen(false));
168 self.setup_transaction(QspiMode::IndirectWrite, &transaction); 168 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
169 169
170 while !T::REGS.sr().read().tcf() {} 170 while !T::REGS.sr().read().tcf() {}
171 T::REGS.fcr().modify(|v| v.set_ctcf(true)); 171 T::REGS.fcr().modify(|v| v.set_ctcf(true));
172 } 172 }
173 173
174 pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { 174 pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) {
175 T::REGS.cr().modify(|v| v.set_dmaen(false)); 175 T::REGS.cr().modify(|v| v.set_dmaen(false));
176 self.setup_transaction(QspiMode::IndirectWrite, &transaction); 176 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
177 177
178 if let Some(len) = transaction.data_len { 178 if let Some(len) = transaction.data_len {
179 let current_ar = T::REGS.ar().read().address(); 179 let current_ar = T::REGS.ar().read().address();
180 T::REGS.ccr().modify(|v| { 180 T::REGS.ccr().modify(|v| {
181 v.set_fmode(QspiMode::IndirectRead.into()); 181 v.set_fmode(QspiMode::IndirectRead.into());
182 }); 182 });
183 T::REGS.ar().write(|v| { 183 T::REGS.ar().write(|v| {
184 v.set_address(current_ar); 184 v.set_address(current_ar);
185 }); 185 });
186 186
187 for idx in 0..len { 187 for idx in 0..len {
188 while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} 188 while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {}
189 buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() }; 189 buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() };
190 } 190 }
191 } 191 }
192 192
193 while !T::REGS.sr().read().tcf() {} 193 while !T::REGS.sr().read().tcf() {}
194 T::REGS.fcr().modify(|v| v.set_ctcf(true)); 194 T::REGS.fcr().modify(|v| v.set_ctcf(true));
195 } 195 }
196 196
197 pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { 197 pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) {
198 T::REGS.cr().modify(|v| v.set_dmaen(false)); 198 T::REGS.cr().modify(|v| v.set_dmaen(false));
199 self.setup_transaction(QspiMode::IndirectWrite, &transaction); 199 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
200 200
201 if let Some(len) = transaction.data_len { 201 if let Some(len) = transaction.data_len {
202 T::REGS.ccr().modify(|v| { 202 T::REGS.ccr().modify(|v| {
203 v.set_fmode(QspiMode::IndirectWrite.into()); 203 v.set_fmode(QspiMode::IndirectWrite.into());
204 }); 204 });
205 205
206 for idx in 0..len { 206 for idx in 0..len {
207 while !T::REGS.sr().read().ftf() {} 207 while !T::REGS.sr().read().ftf() {}
208 unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) }; 208 unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) };
209 } 209 }
210 } 210 }
211 211
212 while !T::REGS.sr().read().tcf() {} 212 while !T::REGS.sr().read().tcf() {}
213 T::REGS.fcr().modify(|v| v.set_ctcf(true)); 213 T::REGS.fcr().modify(|v| v.set_ctcf(true));
214 } 214 }
215 215
216 pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) 216 pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig)
217 where 217 where
218 Dma: QuadDma<T>, 218 Dma: QuadDma<T>,
219 { 219 {
220 self.setup_transaction(QspiMode::IndirectWrite, &transaction); 220 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
221 221
222 T::REGS.ccr().modify(|v| { 222 T::REGS.ccr().modify(|v| {
223 v.set_fmode(QspiMode::IndirectRead.into()); 223 v.set_fmode(QspiMode::IndirectRead.into());
224 }); 224 });
225 let current_ar = T::REGS.ar().read().address(); 225 let current_ar = T::REGS.ar().read().address();
226 T::REGS.ar().write(|v| { 226 T::REGS.ar().write(|v| {
227 v.set_address(current_ar); 227 v.set_address(current_ar);
228 }); 228 });
229 229
230 let request = self.dma.request(); 230 let request = self.dma.request();
231 let transfer = unsafe { 231 let transfer = unsafe {
232 Transfer::new_read( 232 Transfer::new_read(
233 &mut self.dma, 233 &mut self.dma,
234 request, 234 request,
235 T::REGS.dr().as_ptr() as *mut u8, 235 T::REGS.dr().as_ptr() as *mut u8,
236 buf, 236 buf,
237 Default::default(), 237 Default::default(),
238 ) 238 )
239 }; 239 };
240 240
241 T::REGS.cr().modify(|v| v.set_dmaen(true)); 241 T::REGS.cr().modify(|v| v.set_dmaen(true));
242 242
243 transfer.blocking_wait(); 243 transfer.blocking_wait();
244 } 244 }
245 245
246 pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) 246 pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig)
247 where 247 where
248 Dma: QuadDma<T>, 248 Dma: QuadDma<T>,
249 { 249 {
250 self.setup_transaction(QspiMode::IndirectWrite, &transaction); 250 self.setup_transaction(QspiMode::IndirectWrite, &transaction);
251 251
252 T::REGS.ccr().modify(|v| { 252 T::REGS.ccr().modify(|v| {
253 v.set_fmode(QspiMode::IndirectWrite.into()); 253 v.set_fmode(QspiMode::IndirectWrite.into());
254 }); 254 });
255 255
256 let request = self.dma.request(); 256 let request = self.dma.request();
257 let transfer = unsafe { 257 let transfer = unsafe {
258 Transfer::new_write( 258 Transfer::new_write(
259 &mut self.dma, 259 &mut self.dma,
260 request, 260 request,
261 buf, 261 buf,
262 T::REGS.dr().as_ptr() as *mut u8, 262 T::REGS.dr().as_ptr() as *mut u8,
263 Default::default(), 263 Default::default(),
264 ) 264 )
265 }; 265 };
266 266
267 T::REGS.cr().modify(|v| v.set_dmaen(true)); 267 T::REGS.cr().modify(|v| v.set_dmaen(true));
268 268
269 transfer.blocking_wait(); 269 transfer.blocking_wait();
270 } 270 }
271 271
272 fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) { 272 fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) {
273 T::REGS.fcr().modify(|v| { 273 T::REGS.fcr().modify(|v| {
274 v.set_csmf(true); 274 v.set_csmf(true);
275 v.set_ctcf(true); 275 v.set_ctcf(true);
276 v.set_ctef(true); 276 v.set_ctef(true);
277 v.set_ctof(true); 277 v.set_ctof(true);
278 }); 278 });
279 279
280 while T::REGS.sr().read().busy() {} 280 while T::REGS.sr().read().busy() {}
281 281
282 if let Some(len) = transaction.data_len { 282 if let Some(len) = transaction.data_len {
283 T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); 283 T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1));
284 } 284 }
285 285
286 T::REGS.ccr().write(|v| { 286 T::REGS.ccr().write(|v| {
287 v.set_fmode(fmode.into()); 287 v.set_fmode(fmode.into());
288 v.set_imode(transaction.iwidth.into()); 288 v.set_imode(transaction.iwidth.into());
289 v.set_instruction(transaction.instruction); 289 v.set_instruction(transaction.instruction);
290 v.set_admode(transaction.awidth.into()); 290 v.set_admode(transaction.awidth.into());
291 v.set_adsize(self.config.address_size.into()); 291 v.set_adsize(self.config.address_size.into());
292 v.set_dmode(transaction.dwidth.into()); 292 v.set_dmode(transaction.dwidth.into());
293 v.set_abmode(QspiWidth::NONE.into()); 293 v.set_abmode(QspiWidth::NONE.into());
294 v.set_dcyc(transaction.dummy.into()); 294 v.set_dcyc(transaction.dummy.into());
295 }); 295 });
296 296
297 if let Some(addr) = transaction.address { 297 if let Some(addr) = transaction.address {
298 T::REGS.ar().write(|v| { 298 T::REGS.ar().write(|v| {
299 v.set_address(addr); 299 v.set_address(addr);
300 }); 300 });
301 } 301 }
302 } 302 }
303} 303}
304 304
305pub(crate) mod sealed { 305pub(crate) mod sealed {
306 use super::*; 306 use super::*;
307 307
308 pub trait Instance { 308 pub trait Instance {
309 const REGS: Regs; 309 const REGS: Regs;
310 } 310 }
311} 311}
312 312
313pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {} 313pub trait Instance: Peripheral<P = Self> + sealed::Instance + RccPeripheral {}
314 314
315pin_trait!(SckPin, Instance); 315pin_trait!(SckPin, Instance);
316pin_trait!(D0Pin, Instance); 316pin_trait!(D0Pin, Instance);
317pin_trait!(D1Pin, Instance); 317pin_trait!(D1Pin, Instance);
318pin_trait!(D2Pin, Instance); 318pin_trait!(D2Pin, Instance);
319pin_trait!(D3Pin, Instance); 319pin_trait!(D3Pin, Instance);
320pin_trait!(NSSPin, Instance); 320pin_trait!(NSSPin, Instance);
321 321
322dma_trait!(QuadDma, Instance); 322dma_trait!(QuadDma, Instance);
323 323
324foreach_peripheral!( 324foreach_peripheral!(
325 (quadspi, $inst:ident) => { 325 (quadspi, $inst:ident) => {
326 impl sealed::Instance for peripherals::$inst { 326 impl sealed::Instance for peripherals::$inst {
327 const REGS: Regs = crate::pac::$inst; 327 const REGS: Regs = crate::pac::$inst;
328 } 328 }
329 329
330 impl Instance for peripherals::$inst {} 330 impl Instance for peripherals::$inst {}
331 }; 331 };
332); 332);