nrf/qspi: expose all functionality as inherent methods.
This commit is contained in:
parent
3e503e7335
commit
df00c83984
@ -1,11 +1,9 @@
|
|||||||
#![macro_use]
|
#![macro_use]
|
||||||
|
|
||||||
use core::future::Future;
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
use embassy::interrupt::{Interrupt, InterruptExt};
|
use embassy::interrupt::{Interrupt, InterruptExt};
|
||||||
use embassy::traits::flash::{Error, Flash};
|
|
||||||
use embassy::util::Unborrow;
|
use embassy::util::Unborrow;
|
||||||
use embassy_hal_common::drop::DropBomb;
|
use embassy_hal_common::drop::DropBomb;
|
||||||
use embassy_hal_common::unborrow;
|
use embassy_hal_common::unborrow;
|
||||||
@ -58,6 +56,13 @@ impl Default for Config {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum Error {
|
||||||
|
// TODO add "not in data memory" error and check for it
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Qspi<'d, T: Instance> {
|
pub struct Qspi<'d, T: Instance> {
|
||||||
dpm_enabled: bool,
|
dpm_enabled: bool,
|
||||||
phantom: PhantomData<&'d mut T>,
|
phantom: PhantomData<&'d mut T>,
|
||||||
@ -240,6 +245,87 @@ impl<'d, T: Instance> Qspi<'d, T> {
|
|||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn read(&mut self, address: usize, data: &mut [u8]) -> Result<(), Error> {
|
||||||
|
let bomb = DropBomb::new();
|
||||||
|
|
||||||
|
assert_eq!(data.as_ptr() as u32 % 4, 0);
|
||||||
|
assert_eq!(data.len() as u32 % 4, 0);
|
||||||
|
assert_eq!(address as u32 % 4, 0);
|
||||||
|
|
||||||
|
let r = T::regs();
|
||||||
|
|
||||||
|
r.read
|
||||||
|
.src
|
||||||
|
.write(|w| unsafe { w.src().bits(address as u32) });
|
||||||
|
r.read
|
||||||
|
.dst
|
||||||
|
.write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) });
|
||||||
|
r.read
|
||||||
|
.cnt
|
||||||
|
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
||||||
|
|
||||||
|
r.events_ready.reset();
|
||||||
|
r.intenset.write(|w| w.ready().set());
|
||||||
|
r.tasks_readstart.write(|w| w.tasks_readstart().bit(true));
|
||||||
|
|
||||||
|
self.wait_ready().await;
|
||||||
|
|
||||||
|
bomb.defuse();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn write(&mut self, address: usize, data: &[u8]) -> Result<(), Error> {
|
||||||
|
let bomb = DropBomb::new();
|
||||||
|
|
||||||
|
assert_eq!(data.as_ptr() as u32 % 4, 0);
|
||||||
|
assert_eq!(data.len() as u32 % 4, 0);
|
||||||
|
assert_eq!(address as u32 % 4, 0);
|
||||||
|
|
||||||
|
let r = T::regs();
|
||||||
|
r.write
|
||||||
|
.src
|
||||||
|
.write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
|
||||||
|
r.write
|
||||||
|
.dst
|
||||||
|
.write(|w| unsafe { w.dst().bits(address as u32) });
|
||||||
|
r.write
|
||||||
|
.cnt
|
||||||
|
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
||||||
|
|
||||||
|
r.events_ready.reset();
|
||||||
|
r.intenset.write(|w| w.ready().set());
|
||||||
|
r.tasks_writestart.write(|w| w.tasks_writestart().bit(true));
|
||||||
|
|
||||||
|
self.wait_ready().await;
|
||||||
|
|
||||||
|
bomb.defuse();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn erase(&mut self, address: usize) -> Result<(), Error> {
|
||||||
|
let bomb = DropBomb::new();
|
||||||
|
|
||||||
|
assert_eq!(address as u32 % 4096, 0);
|
||||||
|
|
||||||
|
let r = T::regs();
|
||||||
|
r.erase
|
||||||
|
.ptr
|
||||||
|
.write(|w| unsafe { w.ptr().bits(address as u32) });
|
||||||
|
r.erase.len.write(|w| w.len()._4kb());
|
||||||
|
|
||||||
|
r.events_ready.reset();
|
||||||
|
r.intenset.write(|w| w.ready().set());
|
||||||
|
r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true));
|
||||||
|
|
||||||
|
self.wait_ready().await;
|
||||||
|
|
||||||
|
bomb.defuse();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Drop for Qspi<'d, T> {
|
impl<'d, T: Instance> Drop for Qspi<'d, T> {
|
||||||
@ -285,124 +371,6 @@ impl<'d, T: Instance> Drop for Qspi<'d, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'d, T: Instance> Flash for Qspi<'d, T> {
|
|
||||||
type ReadFuture<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = Result<(), Error>> + 'a;
|
|
||||||
type WriteFuture<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = Result<(), Error>> + 'a;
|
|
||||||
type ErasePageFuture<'a>
|
|
||||||
where
|
|
||||||
Self: 'a,
|
|
||||||
= impl Future<Output = Result<(), Error>> + 'a;
|
|
||||||
|
|
||||||
fn read<'a>(&'a mut self, address: usize, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
|
||||||
async move {
|
|
||||||
let bomb = DropBomb::new();
|
|
||||||
|
|
||||||
assert_eq!(data.as_ptr() as u32 % 4, 0);
|
|
||||||
assert_eq!(data.len() as u32 % 4, 0);
|
|
||||||
assert_eq!(address as u32 % 4, 0);
|
|
||||||
|
|
||||||
let r = T::regs();
|
|
||||||
|
|
||||||
r.read
|
|
||||||
.src
|
|
||||||
.write(|w| unsafe { w.src().bits(address as u32) });
|
|
||||||
r.read
|
|
||||||
.dst
|
|
||||||
.write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) });
|
|
||||||
r.read
|
|
||||||
.cnt
|
|
||||||
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
|
||||||
|
|
||||||
r.events_ready.reset();
|
|
||||||
r.intenset.write(|w| w.ready().set());
|
|
||||||
r.tasks_readstart.write(|w| w.tasks_readstart().bit(true));
|
|
||||||
|
|
||||||
self.wait_ready().await;
|
|
||||||
|
|
||||||
bomb.defuse();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write<'a>(&'a mut self, address: usize, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
|
||||||
async move {
|
|
||||||
let bomb = DropBomb::new();
|
|
||||||
|
|
||||||
assert_eq!(data.as_ptr() as u32 % 4, 0);
|
|
||||||
assert_eq!(data.len() as u32 % 4, 0);
|
|
||||||
assert_eq!(address as u32 % 4, 0);
|
|
||||||
|
|
||||||
let r = T::regs();
|
|
||||||
r.write
|
|
||||||
.src
|
|
||||||
.write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
|
|
||||||
r.write
|
|
||||||
.dst
|
|
||||||
.write(|w| unsafe { w.dst().bits(address as u32) });
|
|
||||||
r.write
|
|
||||||
.cnt
|
|
||||||
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
|
||||||
|
|
||||||
r.events_ready.reset();
|
|
||||||
r.intenset.write(|w| w.ready().set());
|
|
||||||
r.tasks_writestart.write(|w| w.tasks_writestart().bit(true));
|
|
||||||
|
|
||||||
self.wait_ready().await;
|
|
||||||
|
|
||||||
bomb.defuse();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn erase<'a>(&'a mut self, address: usize) -> Self::ErasePageFuture<'a> {
|
|
||||||
async move {
|
|
||||||
let bomb = DropBomb::new();
|
|
||||||
|
|
||||||
assert_eq!(address as u32 % 4096, 0);
|
|
||||||
|
|
||||||
let r = T::regs();
|
|
||||||
r.erase
|
|
||||||
.ptr
|
|
||||||
.write(|w| unsafe { w.ptr().bits(address as u32) });
|
|
||||||
r.erase.len.write(|w| w.len()._4kb());
|
|
||||||
|
|
||||||
r.events_ready.reset();
|
|
||||||
r.intenset.write(|w| w.ready().set());
|
|
||||||
r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true));
|
|
||||||
|
|
||||||
self.wait_ready().await;
|
|
||||||
|
|
||||||
bomb.defuse();
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size(&self) -> usize {
|
|
||||||
256 * 4096 // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_size(&self) -> usize {
|
|
||||||
4 // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_size(&self) -> usize {
|
|
||||||
4 // TODO
|
|
||||||
}
|
|
||||||
|
|
||||||
fn erase_size(&self) -> usize {
|
|
||||||
4096 // TODO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) mod sealed {
|
pub(crate) mod sealed {
|
||||||
use embassy::waitqueue::AtomicWaker;
|
use embassy::waitqueue::AtomicWaker;
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ mod example_common;
|
|||||||
|
|
||||||
use defmt::assert_eq;
|
use defmt::assert_eq;
|
||||||
use embassy::executor::Spawner;
|
use embassy::executor::Spawner;
|
||||||
use embassy::traits::flash::Flash;
|
|
||||||
use embassy_nrf::Peripherals;
|
use embassy_nrf::Peripherals;
|
||||||
use embassy_nrf::{interrupt, qspi};
|
use embassy_nrf::{interrupt, qspi};
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
|
@ -8,7 +8,6 @@ mod example_common;
|
|||||||
use core::mem;
|
use core::mem;
|
||||||
use embassy::executor::Spawner;
|
use embassy::executor::Spawner;
|
||||||
use embassy::time::{Duration, Timer};
|
use embassy::time::{Duration, Timer};
|
||||||
use embassy::traits::flash::Flash;
|
|
||||||
use embassy_nrf::Peripherals;
|
use embassy_nrf::Peripherals;
|
||||||
use embassy_nrf::{interrupt, qspi};
|
use embassy_nrf::{interrupt, qspi};
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
|
Loading…
Reference in New Issue
Block a user