aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf-examples/src/bin/qspi.rs25
-rw-r--r--embassy-nrf/src/qspi.rs99
-rw-r--r--embassy-traits/src/flash.rs7
3 files changed, 66 insertions, 65 deletions
diff --git a/embassy-nrf-examples/src/bin/qspi.rs b/embassy-nrf-examples/src/bin/qspi.rs
index 27dd28d72..28cde6e51 100644
--- a/embassy-nrf-examples/src/bin/qspi.rs
+++ b/embassy-nrf-examples/src/bin/qspi.rs
@@ -14,7 +14,6 @@ use embassy::traits::flash::Flash;
14use embassy_nrf::Peripherals; 14use embassy_nrf::Peripherals;
15use embassy_nrf::{interrupt, qspi}; 15use embassy_nrf::{interrupt, qspi};
16use example_common::*; 16use example_common::*;
17use futures::pin_mut;
18 17
19const PAGE_SIZE: usize = 4096; 18const PAGE_SIZE: usize = 4096;
20 19
@@ -36,32 +35,22 @@ async fn main(spawner: Spawner) {
36 35
37 let config = qspi::Config::default(); 36 let config = qspi::Config::default();
38 let irq = interrupt::take!(QSPI); 37 let irq = interrupt::take!(QSPI);
39 let q = qspi::Qspi::new(p.QSPI, irq, sck, csn, io0, io1, io2, io3, config); 38 let mut q = qspi::Qspi::new(p.QSPI, irq, sck, csn, io0, io1, io2, io3, config);
40 pin_mut!(q);
41 39
42 let mut id = [1; 3]; 40 let mut id = [1; 3];
43 q.as_mut() 41 q.custom_instruction(0x9F, &[], &mut id).await.unwrap();
44 .custom_instruction(0x9F, &[], &mut id)
45 .await
46 .unwrap();
47 info!("id: {}", id); 42 info!("id: {}", id);
48 43
49 // Read status register 44 // Read status register
50 let mut status = [4; 1]; 45 let mut status = [4; 1];
51 q.as_mut() 46 q.custom_instruction(0x05, &[], &mut status).await.unwrap();
52 .custom_instruction(0x05, &[], &mut status)
53 .await
54 .unwrap();
55 47
56 info!("status: {:?}", status[0]); 48 info!("status: {:?}", status[0]);
57 49
58 if status[0] & 0x40 == 0 { 50 if status[0] & 0x40 == 0 {
59 status[0] |= 0x40; 51 status[0] |= 0x40;
60 52
61 q.as_mut() 53 q.custom_instruction(0x01, &status, &mut []).await.unwrap();
62 .custom_instruction(0x01, &status, &mut [])
63 .await
64 .unwrap();
65 54
66 info!("enabled quad in status"); 55 info!("enabled quad in status");
67 } 56 }
@@ -72,19 +61,19 @@ async fn main(spawner: Spawner) {
72 61
73 for i in 0..8 { 62 for i in 0..8 {
74 info!("page {:?}: erasing... ", i); 63 info!("page {:?}: erasing... ", i);
75 q.as_mut().erase(i * PAGE_SIZE).await.unwrap(); 64 q.erase(i * PAGE_SIZE).await.unwrap();
76 65
77 for j in 0..PAGE_SIZE { 66 for j in 0..PAGE_SIZE {
78 buf.0[j] = pattern((j + i * PAGE_SIZE) as u32); 67 buf.0[j] = pattern((j + i * PAGE_SIZE) as u32);
79 } 68 }
80 69
81 info!("programming..."); 70 info!("programming...");
82 q.as_mut().write(i * PAGE_SIZE, &buf.0).await.unwrap(); 71 q.write(i * PAGE_SIZE, &buf.0).await.unwrap();
83 } 72 }
84 73
85 for i in 0..8 { 74 for i in 0..8 {
86 info!("page {:?}: reading... ", i); 75 info!("page {:?}: reading... ", i);
87 q.as_mut().read(i * PAGE_SIZE, &mut buf.0).await.unwrap(); 76 q.read(i * PAGE_SIZE, &mut buf.0).await.unwrap();
88 77
89 info!("verifying..."); 78 info!("verifying...");
90 for j in 0..PAGE_SIZE { 79 for j in 0..PAGE_SIZE {
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs
index 033c9e012..d682c1b8c 100644
--- a/embassy-nrf/src/qspi.rs
+++ b/embassy-nrf/src/qspi.rs
@@ -1,11 +1,11 @@
1use core::future::Future; 1use core::future::Future;
2use core::marker::PhantomData; 2use core::marker::PhantomData;
3use core::pin::Pin;
4use core::task::Poll; 3use core::task::Poll;
5 4use embassy::interrupt::{Interrupt, InterruptExt};
6use embassy::interrupt::Interrupt; 5use embassy::traits::flash::{Error, Flash};
7use embassy_extras::peripheral::{PeripheralMutex, PeripheralState}; 6use embassy::util::{AtomicWaker, DropBomb, PeripheralBorrow};
8use embassy_extras::unborrow; 7use embassy_extras::unborrow;
8use futures::future::poll_fn;
9 9
10use crate::fmt::{assert, assert_eq, *}; 10use crate::fmt::{assert, assert_eq, *};
11use crate::gpio::Pin as GpioPin; 11use crate::gpio::Pin as GpioPin;
@@ -27,10 +27,6 @@ pub use crate::pac::qspi::ifconfig0::WRITEOC_A as WriteOpcode;
27// - activate/deactivate 27// - activate/deactivate
28// - set gpio in high drive 28// - set gpio in high drive
29 29
30use embassy::traits::flash::{Error, Flash};
31use embassy::util::{wake_on_interrupt, DropBomb, PeripheralBorrow, WakerRegistration};
32use futures::future::poll_fn;
33
34pub struct DeepPowerDownConfig { 30pub struct DeepPowerDownConfig {
35 pub enter_time: u16, 31 pub enter_time: u16,
36 pub exit_time: u16, 32 pub exit_time: u16,
@@ -77,7 +73,7 @@ impl<'d, T: Instance> Qspi<'d, T> {
77 ) -> Self { 73 ) -> Self {
78 unborrow!(qspi, irq, sck, csn, io0, io1, io2, io3); 74 unborrow!(qspi, irq, sck, csn, io0, io1, io2, io3);
79 75
80 let r = qspi.regs(); 76 let r = T::regs();
81 77
82 for cnf in &[ 78 for cnf in &[
83 sck.conf(), 79 sck.conf(),
@@ -137,6 +133,10 @@ impl<'d, T: Instance> Qspi<'d, T> {
137 while r.events_ready.read().bits() == 0 {} 133 while r.events_ready.read().bits() == 0 {}
138 r.events_ready.reset(); 134 r.events_ready.reset();
139 135
136 irq.set_handler(Self::on_interrupt);
137 irq.unpend();
138 irq.enable();
139
140 Self { 140 Self {
141 peri: qspi, 141 peri: qspi,
142 irq, 142 irq,
@@ -144,8 +144,18 @@ impl<'d, T: Instance> Qspi<'d, T> {
144 } 144 }
145 } 145 }
146 146
147 pub fn sleep(mut self: Pin<&mut Self>) { 147 fn on_interrupt(_: *mut ()) {
148 let r = unsafe { self.as_mut().get_unchecked_mut() }.peri.regs(); 148 let r = T::regs();
149 let s = T::state();
150
151 if r.events_ready.read().bits() != 0 {
152 s.ready_waker.wake();
153 r.intenclr.write(|w| w.ready().clear());
154 }
155 }
156
157 pub fn sleep(&mut self) {
158 let r = T::regs();
149 159
150 info!("flash: sleeping"); 160 info!("flash: sleeping");
151 info!("flash: state = {:?}", r.status.read().bits()); 161 info!("flash: state = {:?}", r.status.read().bits());
@@ -158,7 +168,7 @@ impl<'d, T: Instance> Qspi<'d, T> {
158 } 168 }
159 169
160 pub async fn custom_instruction( 170 pub async fn custom_instruction(
161 mut self: Pin<&mut Self>, 171 &mut self,
162 opcode: u8, 172 opcode: u8,
163 req: &[u8], 173 req: &[u8],
164 resp: &mut [u8], 174 resp: &mut [u8],
@@ -184,7 +194,7 @@ impl<'d, T: Instance> Qspi<'d, T> {
184 194
185 let len = core::cmp::max(req.len(), resp.len()) as u8; 195 let len = core::cmp::max(req.len(), resp.len()) as u8;
186 196
187 let r = unsafe { self.as_mut().get_unchecked_mut() }.peri.regs(); 197 let r = T::regs();
188 r.cinstrdat0.write(|w| unsafe { w.bits(dat0) }); 198 r.cinstrdat0.write(|w| unsafe { w.bits(dat0) });
189 r.cinstrdat1.write(|w| unsafe { w.bits(dat1) }); 199 r.cinstrdat1.write(|w| unsafe { w.bits(dat1) });
190 200
@@ -203,9 +213,9 @@ impl<'d, T: Instance> Qspi<'d, T> {
203 w 213 w
204 }); 214 });
205 215
206 self.as_mut().wait_ready().await; 216 self.wait_ready().await;
207 217
208 let r = unsafe { self.as_mut().get_unchecked_mut() }.peri.regs(); 218 let r = T::regs();
209 219
210 let dat0 = r.cinstrdat0.read().bits(); 220 let dat0 = r.cinstrdat0.read().bits();
211 let dat1 = r.cinstrdat1.read().bits(); 221 let dat1 = r.cinstrdat1.read().bits();
@@ -225,19 +235,14 @@ impl<'d, T: Instance> Qspi<'d, T> {
225 Ok(()) 235 Ok(())
226 } 236 }
227 237
228 async fn wait_ready(self: Pin<&mut Self>) { 238 async fn wait_ready(&mut self) {
229 let this = unsafe { self.get_unchecked_mut() };
230
231 poll_fn(move |cx| { 239 poll_fn(move |cx| {
232 let r = this.peri.regs(); 240 let r = T::regs();
233 241 let s = T::state();
242 s.ready_waker.register(cx.waker());
234 if r.events_ready.read().bits() != 0 { 243 if r.events_ready.read().bits() != 0 {
235 r.events_ready.reset();
236 return Poll::Ready(()); 244 return Poll::Ready(());
237 } 245 }
238
239 wake_on_interrupt(&mut this.irq, cx.waker());
240
241 Poll::Pending 246 Poll::Pending
242 }) 247 })
243 .await 248 .await
@@ -252,11 +257,7 @@ impl<'d, T: Instance> Flash for Qspi<'d, T> {
252 #[rustfmt::skip] 257 #[rustfmt::skip]
253 type ErasePageFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; 258 type ErasePageFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a;
254 259
255 fn read<'a>( 260 fn read<'a>(&'a mut self, address: usize, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
256 mut self: Pin<&'a mut Self>,
257 address: usize,
258 data: &'a mut [u8],
259 ) -> Self::ReadFuture<'a> {
260 async move { 261 async move {
261 let bomb = DropBomb::new(); 262 let bomb = DropBomb::new();
262 263
@@ -264,7 +265,7 @@ impl<'d, T: Instance> Flash for Qspi<'d, T> {
264 assert_eq!(data.len() as u32 % 4, 0); 265 assert_eq!(data.len() as u32 % 4, 0);
265 assert_eq!(address as u32 % 4, 0); 266 assert_eq!(address as u32 % 4, 0);
266 267
267 let r = unsafe { self.as_mut().get_unchecked_mut() }.peri.regs(); 268 let r = T::regs();
268 269
269 r.read 270 r.read
270 .src 271 .src
@@ -280,7 +281,7 @@ impl<'d, T: Instance> Flash for Qspi<'d, T> {
280 r.intenset.write(|w| w.ready().set()); 281 r.intenset.write(|w| w.ready().set());
281 r.tasks_readstart.write(|w| w.tasks_readstart().bit(true)); 282 r.tasks_readstart.write(|w| w.tasks_readstart().bit(true));
282 283
283 self.as_mut().wait_ready().await; 284 self.wait_ready().await;
284 285
285 bomb.defuse(); 286 bomb.defuse();
286 287
@@ -288,11 +289,7 @@ impl<'d, T: Instance> Flash for Qspi<'d, T> {
288 } 289 }
289 } 290 }
290 291
291 fn write<'a>( 292 fn write<'a>(&'a mut self, address: usize, data: &'a [u8]) -> Self::WriteFuture<'a> {
292 mut self: Pin<&'a mut Self>,
293 address: usize,
294 data: &'a [u8],
295 ) -> Self::WriteFuture<'a> {
296 async move { 293 async move {
297 let bomb = DropBomb::new(); 294 let bomb = DropBomb::new();
298 295
@@ -300,7 +297,7 @@ impl<'d, T: Instance> Flash for Qspi<'d, T> {
300 assert_eq!(data.len() as u32 % 4, 0); 297 assert_eq!(data.len() as u32 % 4, 0);
301 assert_eq!(address as u32 % 4, 0); 298 assert_eq!(address as u32 % 4, 0);
302 299
303 let r = unsafe { self.as_mut().get_unchecked_mut() }.peri.regs(); 300 let r = T::regs();
304 r.write 301 r.write
305 .src 302 .src
306 .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) }); 303 .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
@@ -315,7 +312,7 @@ impl<'d, T: Instance> Flash for Qspi<'d, T> {
315 r.intenset.write(|w| w.ready().set()); 312 r.intenset.write(|w| w.ready().set());
316 r.tasks_writestart.write(|w| w.tasks_writestart().bit(true)); 313 r.tasks_writestart.write(|w| w.tasks_writestart().bit(true));
317 314
318 self.as_mut().wait_ready().await; 315 self.wait_ready().await;
319 316
320 bomb.defuse(); 317 bomb.defuse();
321 318
@@ -323,13 +320,13 @@ impl<'d, T: Instance> Flash for Qspi<'d, T> {
323 } 320 }
324 } 321 }
325 322
326 fn erase<'a>(mut self: Pin<&'a mut Self>, address: usize) -> Self::ErasePageFuture<'a> { 323 fn erase<'a>(&'a mut self, address: usize) -> Self::ErasePageFuture<'a> {
327 async move { 324 async move {
328 let bomb = DropBomb::new(); 325 let bomb = DropBomb::new();
329 326
330 assert_eq!(address as u32 % 4096, 0); 327 assert_eq!(address as u32 % 4096, 0);
331 328
332 let r = unsafe { self.as_mut().get_unchecked_mut() }.peri.regs(); 329 let r = T::regs();
333 r.erase 330 r.erase
334 .ptr 331 .ptr
335 .write(|w| unsafe { w.ptr().bits(address as u32) }); 332 .write(|w| unsafe { w.ptr().bits(address as u32) });
@@ -339,7 +336,7 @@ impl<'d, T: Instance> Flash for Qspi<'d, T> {
339 r.intenset.write(|w| w.ready().set()); 336 r.intenset.write(|w| w.ready().set());
340 r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true)); 337 r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true));
341 338
342 self.as_mut().wait_ready().await; 339 self.wait_ready().await;
343 340
344 bomb.defuse(); 341 bomb.defuse();
345 342
@@ -367,8 +364,20 @@ impl<'d, T: Instance> Flash for Qspi<'d, T> {
367mod sealed { 364mod sealed {
368 use super::*; 365 use super::*;
369 366
367 pub struct State {
368 pub ready_waker: AtomicWaker,
369 }
370 impl State {
371 pub const fn new() -> Self {
372 Self {
373 ready_waker: AtomicWaker::new(),
374 }
375 }
376 }
377
370 pub trait Instance { 378 pub trait Instance {
371 fn regs(&self) -> &pac::qspi::RegisterBlock; 379 fn regs() -> &'static pac::qspi::RegisterBlock;
380 fn state() -> &'static State;
372 } 381 }
373} 382}
374 383
@@ -379,9 +388,13 @@ pub trait Instance: sealed::Instance + 'static {
379macro_rules! impl_instance { 388macro_rules! impl_instance {
380 ($type:ident, $irq:ident) => { 389 ($type:ident, $irq:ident) => {
381 impl sealed::Instance for peripherals::$type { 390 impl sealed::Instance for peripherals::$type {
382 fn regs(&self) -> &pac::qspi::RegisterBlock { 391 fn regs() -> &'static pac::qspi::RegisterBlock {
383 unsafe { &*pac::$type::ptr() } 392 unsafe { &*pac::$type::ptr() }
384 } 393 }
394 fn state() -> &'static sealed::State {
395 static STATE: sealed::State = sealed::State::new();
396 &STATE
397 }
385 } 398 }
386 impl Instance for peripherals::$type { 399 impl Instance for peripherals::$type {
387 type Interrupt = interrupt::$irq; 400 type Interrupt = interrupt::$irq;
diff --git a/embassy-traits/src/flash.rs b/embassy-traits/src/flash.rs
index 3adaa3a0a..c9b14a390 100644
--- a/embassy-traits/src/flash.rs
+++ b/embassy-traits/src/flash.rs
@@ -27,19 +27,18 @@ pub trait Flash {
27 /// 27 ///
28 /// address must be a multiple of self.read_size(). 28 /// address must be a multiple of self.read_size().
29 /// buf.len() must be a multiple of self.read_size(). 29 /// buf.len() must be a multiple of self.read_size().
30 fn read<'a>(self: Pin<&'a mut Self>, address: usize, buf: &'a mut [u8]) 30 fn read<'a>(&'a mut self, address: usize, buf: &'a mut [u8]) -> Self::ReadFuture<'a>;
31 -> Self::ReadFuture<'a>;
32 31
33 /// Writes data to the flash device. 32 /// Writes data to the flash device.
34 /// 33 ///
35 /// address must be a multiple of self.write_size(). 34 /// address must be a multiple of self.write_size().
36 /// buf.len() must be a multiple of self.write_size(). 35 /// buf.len() must be a multiple of self.write_size().
37 fn write<'a>(self: Pin<&'a mut Self>, address: usize, buf: &'a [u8]) -> Self::WriteFuture<'a>; 36 fn write<'a>(&'a mut self, address: usize, buf: &'a [u8]) -> Self::WriteFuture<'a>;
38 37
39 /// Erases a single page from the flash device. 38 /// Erases a single page from the flash device.
40 /// 39 ///
41 /// address must be a multiple of self.erase_size(). 40 /// address must be a multiple of self.erase_size().
42 fn erase<'a>(self: Pin<&'a mut Self>, address: usize) -> Self::ErasePageFuture<'a>; 41 fn erase<'a>(&'a mut self, address: usize) -> Self::ErasePageFuture<'a>;
43 42
44 /// Returns the total size, in bytes. 43 /// Returns the total size, in bytes.
45 /// This is not guaranteed to be a power of 2. 44 /// This is not guaranteed to be a power of 2.