aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-nrf/src/qspi.rs208
-rw-r--r--examples/nrf/src/bin/qspi.rs1
-rw-r--r--examples/nrf/src/bin/qspi_lowpower.rs1
3 files changed, 88 insertions, 122 deletions
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs
index 6afba4931..89262ac05 100644
--- a/embassy-nrf/src/qspi.rs
+++ b/embassy-nrf/src/qspi.rs
@@ -1,11 +1,9 @@
1#![macro_use] 1#![macro_use]
2 2
3use core::future::Future;
4use core::marker::PhantomData; 3use core::marker::PhantomData;
5use core::ptr; 4use core::ptr;
6use core::task::Poll; 5use core::task::Poll;
7use embassy::interrupt::{Interrupt, InterruptExt}; 6use embassy::interrupt::{Interrupt, InterruptExt};
8use embassy::traits::flash::{Error, Flash};
9use embassy::util::Unborrow; 7use embassy::util::Unborrow;
10use embassy_hal_common::drop::DropBomb; 8use embassy_hal_common::drop::DropBomb;
11use embassy_hal_common::unborrow; 9use embassy_hal_common::unborrow;
@@ -58,6 +56,13 @@ impl Default for Config {
58 } 56 }
59} 57}
60 58
59#[derive(Debug, Copy, Clone, Eq, PartialEq)]
60#[cfg_attr(feature = "defmt", derive(defmt::Format))]
61#[non_exhaustive]
62pub enum Error {
63 // TODO add "not in data memory" error and check for it
64}
65
61pub struct Qspi<'d, T: Instance> { 66pub struct Qspi<'d, T: Instance> {
62 dpm_enabled: bool, 67 dpm_enabled: bool,
63 phantom: PhantomData<&'d mut T>, 68 phantom: PhantomData<&'d mut T>,
@@ -240,6 +245,87 @@ impl<'d, T: Instance> Qspi<'d, T> {
240 }) 245 })
241 .await 246 .await
242 } 247 }
248
249 pub async fn read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> {
250 let bomb = DropBomb::new();
251
252 assert_eq!(data.as_ptr() as u32 % 4, 0);
253 assert_eq!(data.len() as u32 % 4, 0);
254 assert_eq!(address as u32 % 4, 0);
255
256 let r = T::regs();
257
258 r.read
259 .src
260 .write(|w| unsafe { w.src().bits(address as u32) });
261 r.read
262 .dst
263 .write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) });
264 r.read
265 .cnt
266 .write(|w| unsafe { w.cnt().bits(data.len() as u32) });
267
268 r.events_ready.reset();
269 r.intenset.write(|w| w.ready().set());
270 r.tasks_readstart.write(|w| w.tasks_readstart().bit(true));
271
272 self.wait_ready().await;
273
274 bomb.defuse();
275
276 Ok(())
277 }
278
279 pub async fn write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> {
280 let bomb = DropBomb::new();
281
282 assert_eq!(data.as_ptr() as u32 % 4, 0);
283 assert_eq!(data.len() as u32 % 4, 0);
284 assert_eq!(address as u32 % 4, 0);
285
286 let r = T::regs();
287 r.write
288 .src
289 .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
290 r.write
291 .dst
292 .write(|w| unsafe { w.dst().bits(address as u32) });
293 r.write
294 .cnt
295 .write(|w| unsafe { w.cnt().bits(data.len() as u32) });
296
297 r.events_ready.reset();
298 r.intenset.write(|w| w.ready().set());
299 r.tasks_writestart.write(|w| w.tasks_writestart().bit(true));
300
301 self.wait_ready().await;
302
303 bomb.defuse();
304
305 Ok(())
306 }
307
308 pub async fn erase(&mut self, address: usize) -> Result<(), Error> {
309 let bomb = DropBomb::new();
310
311 assert_eq!(address as u32 % 4096, 0);
312
313 let r = T::regs();
314 r.erase
315 .ptr
316 .write(|w| unsafe { w.ptr().bits(address as u32) });
317 r.erase.len.write(|w| w.len()._4kb());
318
319 r.events_ready.reset();
320 r.intenset.write(|w| w.ready().set());
321 r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true));
322
323 self.wait_ready().await;
324
325 bomb.defuse();
326
327 Ok(())
328 }
243} 329}
244 330
245impl<'d, T: Instance> Drop for Qspi<'d, T> { 331impl<'d, T: Instance> Drop for Qspi<'d, T> {
@@ -285,124 +371,6 @@ impl<'d, T: Instance> Drop for Qspi<'d, T> {
285 } 371 }
286} 372}
287 373
288impl<'d, T: Instance> Flash for Qspi<'d, T> {
289 type ReadFuture<'a>
290 where
291 Self: 'a,
292 = impl Future<Output = Result<(), Error>> + 'a;
293 type WriteFuture<'a>
294 where
295 Self: 'a,
296 = impl Future<Output = Result<(), Error>> + 'a;
297 type ErasePageFuture<'a>
298 where
299 Self: 'a,
300 = impl Future<Output = Result<(), Error>> + 'a;
301
302 fn read<'a>(&'a mut self, address: usize, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
303 async move {
304 let bomb = DropBomb::new();
305
306 assert_eq!(data.as_ptr() as u32 % 4, 0);
307 assert_eq!(data.len() as u32 % 4, 0);
308 assert_eq!(address as u32 % 4, 0);
309
310 let r = T::regs();
311
312 r.read
313 .src
314 .write(|w| unsafe { w.src().bits(address as u32) });
315 r.read
316 .dst
317 .write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) });
318 r.read
319 .cnt
320 .write(|w| unsafe { w.cnt().bits(data.len() as u32) });
321
322 r.events_ready.reset();
323 r.intenset.write(|w| w.ready().set());
324 r.tasks_readstart.write(|w| w.tasks_readstart().bit(true));
325
326 self.wait_ready().await;
327
328 bomb.defuse();
329
330 Ok(())
331 }
332 }
333
334 fn write<'a>(&'a mut self, address: usize, data: &'a [u8]) -> Self::WriteFuture<'a> {
335 async move {
336 let bomb = DropBomb::new();
337
338 assert_eq!(data.as_ptr() as u32 % 4, 0);
339 assert_eq!(data.len() as u32 % 4, 0);
340 assert_eq!(address as u32 % 4, 0);
341
342 let r = T::regs();
343 r.write
344 .src
345 .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
346 r.write
347 .dst
348 .write(|w| unsafe { w.dst().bits(address as u32) });
349 r.write
350 .cnt
351 .write(|w| unsafe { w.cnt().bits(data.len() as u32) });
352
353 r.events_ready.reset();
354 r.intenset.write(|w| w.ready().set());
355 r.tasks_writestart.write(|w| w.tasks_writestart().bit(true));
356
357 self.wait_ready().await;
358
359 bomb.defuse();
360
361 Ok(())
362 }
363 }
364
365 fn erase<'a>(&'a mut self, address: usize) -> Self::ErasePageFuture<'a> {
366 async move {
367 let bomb = DropBomb::new();
368
369 assert_eq!(address as u32 % 4096, 0);
370
371 let r = T::regs();
372 r.erase
373 .ptr
374 .write(|w| unsafe { w.ptr().bits(address as u32) });
375 r.erase.len.write(|w| w.len()._4kb());
376
377 r.events_ready.reset();
378 r.intenset.write(|w| w.ready().set());
379 r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true));
380
381 self.wait_ready().await;
382
383 bomb.defuse();
384
385 Ok(())
386 }
387 }
388
389 fn size(&self) -> usize {
390 256 * 4096 // TODO
391 }
392
393 fn read_size(&self) -> usize {
394 4 // TODO
395 }
396
397 fn write_size(&self) -> usize {
398 4 // TODO
399 }
400
401 fn erase_size(&self) -> usize {
402 4096 // TODO
403 }
404}
405
406pub(crate) mod sealed { 374pub(crate) mod sealed {
407 use embassy::waitqueue::AtomicWaker; 375 use embassy::waitqueue::AtomicWaker;
408 376
diff --git a/examples/nrf/src/bin/qspi.rs b/examples/nrf/src/bin/qspi.rs
index c7f9503bb..b2e6bfc15 100644
--- a/examples/nrf/src/bin/qspi.rs
+++ b/examples/nrf/src/bin/qspi.rs
@@ -7,7 +7,6 @@ mod example_common;
7 7
8use defmt::assert_eq; 8use defmt::assert_eq;
9use embassy::executor::Spawner; 9use embassy::executor::Spawner;
10use embassy::traits::flash::Flash;
11use embassy_nrf::Peripherals; 10use embassy_nrf::Peripherals;
12use embassy_nrf::{interrupt, qspi}; 11use embassy_nrf::{interrupt, qspi};
13use example_common::*; 12use example_common::*;
diff --git a/examples/nrf/src/bin/qspi_lowpower.rs b/examples/nrf/src/bin/qspi_lowpower.rs
index e9e1bac42..4e264ef2f 100644
--- a/examples/nrf/src/bin/qspi_lowpower.rs
+++ b/examples/nrf/src/bin/qspi_lowpower.rs
@@ -8,7 +8,6 @@ mod example_common;
8use core::mem; 8use core::mem;
9use embassy::executor::Spawner; 9use embassy::executor::Spawner;
10use embassy::time::{Duration, Timer}; 10use embassy::time::{Duration, Timer};
11use embassy::traits::flash::Flash;
12use embassy_nrf::Peripherals; 11use embassy_nrf::Peripherals;
13use embassy_nrf::{interrupt, qspi}; 12use embassy_nrf::{interrupt, qspi};
14use example_common::*; 13use example_common::*;