nrf/qspi: update to new api
This commit is contained in:
parent
16bb6fd6ac
commit
ec7309962a
@ -6,12 +6,12 @@
|
|||||||
|
|
||||||
#[path = "../example_common.rs"]
|
#[path = "../example_common.rs"]
|
||||||
mod example_common;
|
mod example_common;
|
||||||
|
use embassy_nrf::peripherals::Peripherals;
|
||||||
use example_common::*;
|
use example_common::*;
|
||||||
|
|
||||||
use cortex_m_rt::entry;
|
use cortex_m_rt::entry;
|
||||||
use defmt::{assert_eq, panic};
|
use defmt::{assert_eq, panic};
|
||||||
use futures::pin_mut;
|
use futures::pin_mut;
|
||||||
use nrf52840_hal::gpio;
|
|
||||||
|
|
||||||
use embassy::executor::{task, Executor};
|
use embassy::executor::{task, Executor};
|
||||||
use embassy::traits::flash::Flash;
|
use embassy::traits::flash::Flash;
|
||||||
@ -27,43 +27,16 @@ struct AlignedBuf([u8; 4096]);
|
|||||||
|
|
||||||
#[task]
|
#[task]
|
||||||
async fn run() {
|
async fn run() {
|
||||||
let p = unwrap!(embassy_nrf::pac::Peripherals::take());
|
let p = unsafe { Peripherals::steal() };
|
||||||
|
|
||||||
let port0 = gpio::p0::Parts::new(p.P0);
|
let csn = p.p0_17;
|
||||||
|
let sck = p.p0_19;
|
||||||
let pins = qspi::Pins {
|
let io0 = p.p0_20;
|
||||||
csn: port0
|
let io1 = p.p0_21;
|
||||||
.p0_17
|
let io2 = p.p0_22;
|
||||||
.into_push_pull_output(gpio::Level::High)
|
let io3 = p.p0_23;
|
||||||
.degrade(),
|
|
||||||
sck: port0
|
|
||||||
.p0_19
|
|
||||||
.into_push_pull_output(gpio::Level::High)
|
|
||||||
.degrade(),
|
|
||||||
io0: port0
|
|
||||||
.p0_20
|
|
||||||
.into_push_pull_output(gpio::Level::High)
|
|
||||||
.degrade(),
|
|
||||||
io1: port0
|
|
||||||
.p0_21
|
|
||||||
.into_push_pull_output(gpio::Level::High)
|
|
||||||
.degrade(),
|
|
||||||
io2: Some(
|
|
||||||
port0
|
|
||||||
.p0_22
|
|
||||||
.into_push_pull_output(gpio::Level::High)
|
|
||||||
.degrade(),
|
|
||||||
),
|
|
||||||
io3: Some(
|
|
||||||
port0
|
|
||||||
.p0_23
|
|
||||||
.into_push_pull_output(gpio::Level::High)
|
|
||||||
.degrade(),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
let config = qspi::Config {
|
let config = qspi::Config {
|
||||||
pins,
|
|
||||||
read_opcode: qspi::ReadOpcode::READ4IO,
|
read_opcode: qspi::ReadOpcode::READ4IO,
|
||||||
write_opcode: qspi::WriteOpcode::PP4IO,
|
write_opcode: qspi::WriteOpcode::PP4IO,
|
||||||
xip_offset: 0,
|
xip_offset: 0,
|
||||||
@ -72,7 +45,7 @@ async fn run() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let irq = interrupt::take!(QSPI);
|
let irq = interrupt::take!(QSPI);
|
||||||
let q = qspi::Qspi::new(p.QSPI, irq, config);
|
let q = qspi::Qspi::new(p.qspi, irq, sck, csn, io0, io1, io2, io3, config);
|
||||||
pin_mut!(q);
|
pin_mut!(q);
|
||||||
|
|
||||||
let mut id = [1; 3];
|
let mut id = [1; 3];
|
||||||
@ -83,7 +56,7 @@ async fn run() {
|
|||||||
info!("id: {}", id);
|
info!("id: {}", id);
|
||||||
|
|
||||||
// Read status register
|
// Read status register
|
||||||
let mut status = [0; 1];
|
let mut status = [4; 1];
|
||||||
q.as_mut()
|
q.as_mut()
|
||||||
.custom_instruction(0x05, &[], &mut status)
|
.custom_instruction(0x05, &[], &mut status)
|
||||||
.await
|
.await
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
|
use core::marker::PhantomData;
|
||||||
use core::pin::Pin;
|
use core::pin::Pin;
|
||||||
use core::task::Poll;
|
use core::task::Poll;
|
||||||
|
|
||||||
|
use embassy::interrupt::Interrupt;
|
||||||
use embassy_extras::peripheral::{PeripheralMutex, PeripheralState};
|
use embassy_extras::peripheral::{PeripheralMutex, PeripheralState};
|
||||||
|
|
||||||
use crate::fmt::{assert, assert_eq, *};
|
use crate::fmt::{assert, assert_eq, *};
|
||||||
use crate::hal::gpio::{Output, Pin as GpioPin, PushPull};
|
use crate::gpio::Pin as GpioPin;
|
||||||
use crate::interrupt::{self};
|
use crate::interrupt::{self};
|
||||||
use crate::pac::QSPI;
|
use crate::{pac, peripherals};
|
||||||
|
|
||||||
pub use crate::pac::qspi::ifconfig0::ADDRMODE_A as AddressMode;
|
pub use crate::pac::qspi::ifconfig0::ADDRMODE_A as AddressMode;
|
||||||
pub use crate::pac::qspi::ifconfig0::PPSIZE_A as WritePageSize;
|
pub use crate::pac::qspi::ifconfig0::PPSIZE_A as WritePageSize;
|
||||||
@ -25,25 +27,15 @@ pub use crate::pac::qspi::ifconfig0::WRITEOC_A as WriteOpcode;
|
|||||||
// - set gpio in high drive
|
// - set gpio in high drive
|
||||||
|
|
||||||
use embassy::traits::flash::{Error, Flash};
|
use embassy::traits::flash::{Error, Flash};
|
||||||
use embassy::util::{DropBomb, WakerRegistration};
|
use embassy::util::{wake_on_interrupt, DropBomb, PeripheralBorrow, WakerRegistration};
|
||||||
use futures::future::poll_fn;
|
use futures::future::poll_fn;
|
||||||
|
|
||||||
pub struct Pins {
|
|
||||||
pub sck: GpioPin<Output<PushPull>>,
|
|
||||||
pub csn: GpioPin<Output<PushPull>>,
|
|
||||||
pub io0: GpioPin<Output<PushPull>>,
|
|
||||||
pub io1: GpioPin<Output<PushPull>>,
|
|
||||||
pub io2: Option<GpioPin<Output<PushPull>>>,
|
|
||||||
pub io3: Option<GpioPin<Output<PushPull>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DeepPowerDownConfig {
|
pub struct DeepPowerDownConfig {
|
||||||
pub enter_time: u16,
|
pub enter_time: u16,
|
||||||
pub exit_time: u16,
|
pub exit_time: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub pins: Pins,
|
|
||||||
pub xip_offset: u32,
|
pub xip_offset: u32,
|
||||||
pub read_opcode: ReadOpcode,
|
pub read_opcode: ReadOpcode,
|
||||||
pub write_opcode: WriteOpcode,
|
pub write_opcode: WriteOpcode,
|
||||||
@ -51,55 +43,54 @@ pub struct Config {
|
|||||||
pub deep_power_down: Option<DeepPowerDownConfig>,
|
pub deep_power_down: Option<DeepPowerDownConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct State {
|
pub struct Qspi<'d, T: Instance> {
|
||||||
inner: QSPI,
|
qspi: T,
|
||||||
waker: WakerRegistration,
|
irq: T::Interrupt,
|
||||||
|
phantom: PhantomData<&'d mut T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Qspi {
|
impl<'d, T: Instance> Qspi<'d, T> {
|
||||||
inner: PeripheralMutex<State>,
|
pub fn new(
|
||||||
|
qspi: impl PeripheralBorrow<Target = T> + 'd,
|
||||||
|
irq: impl PeripheralBorrow<Target = T::Interrupt> + 'd,
|
||||||
|
sck: impl PeripheralBorrow<Target = impl GpioPin> + 'd,
|
||||||
|
csn: impl PeripheralBorrow<Target = impl GpioPin> + 'd,
|
||||||
|
io0: impl PeripheralBorrow<Target = impl GpioPin> + 'd,
|
||||||
|
io1: impl PeripheralBorrow<Target = impl GpioPin> + 'd,
|
||||||
|
io2: impl PeripheralBorrow<Target = impl GpioPin> + 'd,
|
||||||
|
io3: impl PeripheralBorrow<Target = impl GpioPin> + 'd,
|
||||||
|
config: Config,
|
||||||
|
) -> Self {
|
||||||
|
let mut qspi = unsafe { qspi.unborrow() };
|
||||||
|
let irq = unsafe { irq.unborrow() };
|
||||||
|
let sck = unsafe { sck.unborrow() };
|
||||||
|
let csn = unsafe { csn.unborrow() };
|
||||||
|
let io0 = unsafe { io0.unborrow() };
|
||||||
|
let io1 = unsafe { io1.unborrow() };
|
||||||
|
let io2 = unsafe { io2.unborrow() };
|
||||||
|
let io3 = unsafe { io3.unborrow() };
|
||||||
|
|
||||||
|
let r = qspi.regs();
|
||||||
|
|
||||||
|
for cnf in &[
|
||||||
|
sck.conf(),
|
||||||
|
csn.conf(),
|
||||||
|
io0.conf(),
|
||||||
|
io1.conf(),
|
||||||
|
io2.conf(),
|
||||||
|
io3.conf(),
|
||||||
|
] {
|
||||||
|
cnf.write(|w| w.dir().output().drive().h0h1());
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Qspi {
|
r.psel.sck.write(|w| unsafe { w.bits(sck.psel_bits()) });
|
||||||
pub fn new(qspi: QSPI, irq: interrupt::QSPI, config: Config) -> Self {
|
r.psel.csn.write(|w| unsafe { w.bits(csn.psel_bits()) });
|
||||||
qspi.psel.sck.write(|w| {
|
r.psel.io0.write(|w| unsafe { w.bits(io0.psel_bits()) });
|
||||||
let pin = &config.pins.sck;
|
r.psel.io1.write(|w| unsafe { w.bits(io1.psel_bits()) });
|
||||||
unsafe { w.bits(pin.psel_bits()) };
|
r.psel.io2.write(|w| unsafe { w.bits(io2.psel_bits()) });
|
||||||
w.connect().connected()
|
r.psel.io3.write(|w| unsafe { w.bits(io3.psel_bits()) });
|
||||||
});
|
|
||||||
qspi.psel.csn.write(|w| {
|
|
||||||
let pin = &config.pins.csn;
|
|
||||||
unsafe { w.bits(pin.psel_bits()) };
|
|
||||||
w.connect().connected()
|
|
||||||
});
|
|
||||||
qspi.psel.io0.write(|w| {
|
|
||||||
let pin = &config.pins.io0;
|
|
||||||
unsafe { w.bits(pin.psel_bits()) };
|
|
||||||
w.connect().connected()
|
|
||||||
});
|
|
||||||
qspi.psel.io1.write(|w| {
|
|
||||||
let pin = &config.pins.io1;
|
|
||||||
unsafe { w.bits(pin.psel_bits()) };
|
|
||||||
w.connect().connected()
|
|
||||||
});
|
|
||||||
qspi.psel.io2.write(|w| {
|
|
||||||
if let Some(ref pin) = config.pins.io2 {
|
|
||||||
unsafe { w.bits(pin.psel_bits()) };
|
|
||||||
w.connect().connected()
|
|
||||||
} else {
|
|
||||||
w.connect().disconnected()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
qspi.psel.io3.write(|w| {
|
|
||||||
if let Some(ref pin) = config.pins.io3 {
|
|
||||||
unsafe { w.bits(pin.psel_bits()) };
|
|
||||||
w.connect().connected()
|
|
||||||
} else {
|
|
||||||
w.connect().disconnected()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
qspi.ifconfig0.write(|mut w| {
|
r.ifconfig0.write(|mut w| {
|
||||||
w = w.addrmode().variant(AddressMode::_24BIT);
|
w = w.addrmode().variant(AddressMode::_24BIT);
|
||||||
if config.deep_power_down.is_some() {
|
if config.deep_power_down.is_some() {
|
||||||
w = w.dpmenable().enable();
|
w = w.dpmenable().enable();
|
||||||
@ -113,14 +104,14 @@ impl Qspi {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if let Some(dpd) = &config.deep_power_down {
|
if let Some(dpd) = &config.deep_power_down {
|
||||||
qspi.dpmdur.write(|mut w| unsafe {
|
r.dpmdur.write(|mut w| unsafe {
|
||||||
w = w.enter().bits(dpd.enter_time);
|
w = w.enter().bits(dpd.enter_time);
|
||||||
w = w.exit().bits(dpd.exit_time);
|
w = w.exit().bits(dpd.exit_time);
|
||||||
w
|
w
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
qspi.ifconfig1.write(|w| {
|
r.ifconfig1.write(|w| {
|
||||||
let w = unsafe { w.sckdelay().bits(80) };
|
let w = unsafe { w.sckdelay().bits(80) };
|
||||||
let w = w.dpmen().exit();
|
let w = w.dpmen().exit();
|
||||||
let w = w.spimode().mode0();
|
let w = w.spimode().mode0();
|
||||||
@ -128,48 +119,42 @@ impl Qspi {
|
|||||||
w
|
w
|
||||||
});
|
});
|
||||||
|
|
||||||
qspi.xipoffset
|
r.xipoffset
|
||||||
.write(|w| unsafe { w.xipoffset().bits(config.xip_offset) });
|
.write(|w| unsafe { w.xipoffset().bits(config.xip_offset) });
|
||||||
|
|
||||||
// Enable it
|
// Enable it
|
||||||
qspi.enable.write(|w| w.enable().enabled());
|
r.enable.write(|w| w.enable().enabled());
|
||||||
|
|
||||||
qspi.events_ready.reset();
|
r.events_ready.reset();
|
||||||
qspi.tasks_activate.write(|w| w.tasks_activate().bit(true));
|
r.tasks_activate.write(|w| w.tasks_activate().bit(true));
|
||||||
while qspi.events_ready.read().bits() == 0 {}
|
while r.events_ready.read().bits() == 0 {}
|
||||||
qspi.events_ready.reset();
|
r.events_ready.reset();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
inner: PeripheralMutex::new(
|
qspi,
|
||||||
State {
|
|
||||||
inner: qspi,
|
|
||||||
waker: WakerRegistration::new(),
|
|
||||||
},
|
|
||||||
irq,
|
irq,
|
||||||
),
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sleep(self: Pin<&mut Self>) {
|
pub fn sleep(mut self: Pin<&mut Self>) {
|
||||||
self.inner().with(|s, _| {
|
let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs();
|
||||||
|
|
||||||
info!("flash: sleeping");
|
info!("flash: sleeping");
|
||||||
info!("flash: state = {:?}", s.inner.status.read().bits());
|
info!("flash: state = {:?}", r.status.read().bits());
|
||||||
s.inner.ifconfig1.modify(|_, w| w.dpmen().enter());
|
r.ifconfig1.modify(|_, w| w.dpmen().enter());
|
||||||
info!("flash: state = {:?}", s.inner.status.read().bits());
|
info!("flash: state = {:?}", r.status.read().bits());
|
||||||
cortex_m::asm::delay(1000000);
|
cortex_m::asm::delay(1000000);
|
||||||
info!("flash: state = {:?}", s.inner.status.read().bits());
|
info!("flash: state = {:?}", r.status.read().bits());
|
||||||
|
|
||||||
s.inner
|
r.tasks_deactivate.write(|w| w.tasks_deactivate().set_bit());
|
||||||
.tasks_deactivate
|
|
||||||
.write(|w| w.tasks_deactivate().set_bit());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn custom_instruction<'a>(
|
pub async fn custom_instruction(
|
||||||
mut self: Pin<&'a mut Self>,
|
mut self: Pin<&mut Self>,
|
||||||
opcode: u8,
|
opcode: u8,
|
||||||
req: &'a [u8],
|
req: &[u8],
|
||||||
resp: &'a mut [u8],
|
resp: &mut [u8],
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let bomb = DropBomb::new();
|
let bomb = DropBomb::new();
|
||||||
|
|
||||||
@ -192,14 +177,14 @@ impl Qspi {
|
|||||||
|
|
||||||
let len = core::cmp::max(req.len(), resp.len()) as u8;
|
let len = core::cmp::max(req.len(), resp.len()) as u8;
|
||||||
|
|
||||||
self.as_mut().inner().with(|s, _| {
|
let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs();
|
||||||
s.inner.cinstrdat0.write(|w| unsafe { w.bits(dat0) });
|
r.cinstrdat0.write(|w| unsafe { w.bits(dat0) });
|
||||||
s.inner.cinstrdat1.write(|w| unsafe { w.bits(dat1) });
|
r.cinstrdat1.write(|w| unsafe { w.bits(dat1) });
|
||||||
|
|
||||||
s.inner.events_ready.reset();
|
r.events_ready.reset();
|
||||||
s.inner.intenset.write(|w| w.ready().set());
|
r.intenset.write(|w| w.ready().set());
|
||||||
|
|
||||||
s.inner.cinstrconf.write(|w| {
|
r.cinstrconf.write(|w| {
|
||||||
let w = unsafe { w.opcode().bits(opcode) };
|
let w = unsafe { w.opcode().bits(opcode) };
|
||||||
let w = unsafe { w.length().bits(len + 1) };
|
let w = unsafe { w.length().bits(len + 1) };
|
||||||
let w = w.lio2().bit(true);
|
let w = w.lio2().bit(true);
|
||||||
@ -210,13 +195,13 @@ impl Qspi {
|
|||||||
let w = w.lfstop().bit(false);
|
let w = w.lfstop().bit(false);
|
||||||
w
|
w
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
self.as_mut().wait_ready().await;
|
self.as_mut().wait_ready().await;
|
||||||
|
|
||||||
self.as_mut().inner().with(|s, _| {
|
let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs();
|
||||||
let dat0 = s.inner.cinstrdat0.read().bits();
|
|
||||||
let dat1 = s.inner.cinstrdat1.read().bits();
|
let dat0 = r.cinstrdat0.read().bits();
|
||||||
|
let dat1 = r.cinstrdat1.read().bits();
|
||||||
for i in 0..4 {
|
for i in 0..4 {
|
||||||
if i < resp.len() {
|
if i < resp.len() {
|
||||||
resp[i] = (dat0 >> (i * 8)) as u8;
|
resp[i] = (dat0 >> (i * 8)) as u8;
|
||||||
@ -227,34 +212,38 @@ impl Qspi {
|
|||||||
resp[i] = (dat1 >> (i * 8)) as u8;
|
resp[i] = (dat1 >> (i * 8)) as u8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
bomb.defuse();
|
bomb.defuse();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State>> {
|
async fn wait_ready(self: Pin<&mut Self>) {
|
||||||
unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
|
let this = unsafe { self.get_unchecked_mut() };
|
||||||
}
|
|
||||||
|
|
||||||
fn wait_ready<'a>(mut self: Pin<&'a mut Self>) -> impl Future<Output = ()> + 'a {
|
|
||||||
poll_fn(move |cx| {
|
poll_fn(move |cx| {
|
||||||
self.as_mut().inner().with(|s, _irq| {
|
let r = this.qspi.regs();
|
||||||
if s.inner.events_ready.read().bits() != 0 {
|
|
||||||
|
if r.events_ready.read().bits() != 0 {
|
||||||
|
r.events_ready.reset();
|
||||||
return Poll::Ready(());
|
return Poll::Ready(());
|
||||||
}
|
}
|
||||||
s.waker.register(cx.waker());
|
|
||||||
|
wake_on_interrupt(&mut this.irq, cx.waker());
|
||||||
|
|
||||||
Poll::Pending
|
Poll::Pending
|
||||||
})
|
})
|
||||||
})
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Flash for Qspi {
|
impl<'d, T: Instance> Flash for Qspi<'d, T> {
|
||||||
type ReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
|
#[rustfmt::skip]
|
||||||
type WriteFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
|
type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a;
|
||||||
type ErasePageFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
|
#[rustfmt::skip]
|
||||||
|
type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a;
|
||||||
|
#[rustfmt::skip]
|
||||||
|
type ErasePageFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a;
|
||||||
|
|
||||||
fn read<'a>(
|
fn read<'a>(
|
||||||
mut self: Pin<&'a mut Self>,
|
mut self: Pin<&'a mut Self>,
|
||||||
@ -268,26 +257,21 @@ impl Flash for Qspi {
|
|||||||
assert_eq!(data.len() as u32 % 4, 0);
|
assert_eq!(data.len() as u32 % 4, 0);
|
||||||
assert_eq!(address as u32 % 4, 0);
|
assert_eq!(address as u32 % 4, 0);
|
||||||
|
|
||||||
self.as_mut().inner().with(|s, _| {
|
let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs();
|
||||||
s.inner
|
|
||||||
.read
|
r.read
|
||||||
.src
|
.src
|
||||||
.write(|w| unsafe { w.src().bits(address as u32) });
|
.write(|w| unsafe { w.src().bits(address as u32) });
|
||||||
s.inner
|
r.read
|
||||||
.read
|
|
||||||
.dst
|
.dst
|
||||||
.write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) });
|
.write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) });
|
||||||
s.inner
|
r.read
|
||||||
.read
|
|
||||||
.cnt
|
.cnt
|
||||||
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
||||||
|
|
||||||
s.inner.events_ready.reset();
|
r.events_ready.reset();
|
||||||
s.inner.intenset.write(|w| w.ready().set());
|
r.intenset.write(|w| w.ready().set());
|
||||||
s.inner
|
r.tasks_readstart.write(|w| w.tasks_readstart().bit(true));
|
||||||
.tasks_readstart
|
|
||||||
.write(|w| w.tasks_readstart().bit(true));
|
|
||||||
});
|
|
||||||
|
|
||||||
self.as_mut().wait_ready().await;
|
self.as_mut().wait_ready().await;
|
||||||
|
|
||||||
@ -309,26 +293,20 @@ impl Flash for Qspi {
|
|||||||
assert_eq!(data.len() as u32 % 4, 0);
|
assert_eq!(data.len() as u32 % 4, 0);
|
||||||
assert_eq!(address as u32 % 4, 0);
|
assert_eq!(address as u32 % 4, 0);
|
||||||
|
|
||||||
self.as_mut().inner().with(|s, _| {
|
let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs();
|
||||||
s.inner
|
r.write
|
||||||
.write
|
|
||||||
.src
|
.src
|
||||||
.write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
|
.write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
|
||||||
s.inner
|
r.write
|
||||||
.write
|
|
||||||
.dst
|
.dst
|
||||||
.write(|w| unsafe { w.dst().bits(address as u32) });
|
.write(|w| unsafe { w.dst().bits(address as u32) });
|
||||||
s.inner
|
r.write
|
||||||
.write
|
|
||||||
.cnt
|
.cnt
|
||||||
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
||||||
|
|
||||||
s.inner.events_ready.reset();
|
r.events_ready.reset();
|
||||||
s.inner.intenset.write(|w| w.ready().set());
|
r.intenset.write(|w| w.ready().set());
|
||||||
s.inner
|
r.tasks_writestart.write(|w| w.tasks_writestart().bit(true));
|
||||||
.tasks_writestart
|
|
||||||
.write(|w| w.tasks_writestart().bit(true));
|
|
||||||
});
|
|
||||||
|
|
||||||
self.as_mut().wait_ready().await;
|
self.as_mut().wait_ready().await;
|
||||||
|
|
||||||
@ -344,19 +322,15 @@ impl Flash for Qspi {
|
|||||||
|
|
||||||
assert_eq!(address as u32 % 4096, 0);
|
assert_eq!(address as u32 % 4096, 0);
|
||||||
|
|
||||||
self.as_mut().inner().with(|s, _| {
|
let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs();
|
||||||
s.inner
|
r.erase
|
||||||
.erase
|
|
||||||
.ptr
|
.ptr
|
||||||
.write(|w| unsafe { w.ptr().bits(address as u32) });
|
.write(|w| unsafe { w.ptr().bits(address as u32) });
|
||||||
s.inner.erase.len.write(|w| w.len()._4kb());
|
r.erase.len.write(|w| w.len()._4kb());
|
||||||
|
|
||||||
s.inner.events_ready.reset();
|
r.events_ready.reset();
|
||||||
s.inner.intenset.write(|w| w.ready().set());
|
r.intenset.write(|w| w.ready().set());
|
||||||
s.inner
|
r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true));
|
||||||
.tasks_erasestart
|
|
||||||
.write(|w| w.tasks_erasestart().bit(true));
|
|
||||||
});
|
|
||||||
|
|
||||||
self.as_mut().wait_ready().await;
|
self.as_mut().wait_ready().await;
|
||||||
|
|
||||||
@ -383,13 +357,29 @@ impl Flash for Qspi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PeripheralState for State {
|
mod sealed {
|
||||||
type Interrupt = interrupt::QSPI;
|
use super::*;
|
||||||
|
|
||||||
fn on_interrupt(&mut self) {
|
pub trait Instance {
|
||||||
if self.inner.events_ready.read().bits() != 0 {
|
fn regs(&mut self) -> &pac::qspi::RegisterBlock;
|
||||||
self.inner.intenclr.write(|w| w.ready().clear());
|
|
||||||
self.waker.wake()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Instance: sealed::Instance + 'static {
|
||||||
|
type Interrupt: Interrupt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! make_impl {
|
||||||
|
($type:ident, $irq:ident) => {
|
||||||
|
impl sealed::Instance for peripherals::$type {
|
||||||
|
fn regs(&mut self) -> &pac::qspi::RegisterBlock {
|
||||||
|
unsafe { &*pac::$type::ptr() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Instance for peripherals::$type {
|
||||||
|
type Interrupt = interrupt::$irq;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
make_impl!(QSPI, QSPI);
|
||||||
|
@ -11,9 +11,17 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Flash {
|
pub trait Flash {
|
||||||
type ReadFuture<'a>: Future<Output = Result<(), Error>>;
|
type ReadFuture<'a>: Future<Output = Result<(), Error>>
|
||||||
type WriteFuture<'a>: Future<Output = Result<(), Error>>;
|
where
|
||||||
type ErasePageFuture<'a>: Future<Output = Result<(), Error>>;
|
Self: 'a;
|
||||||
|
|
||||||
|
type WriteFuture<'a>: Future<Output = Result<(), Error>>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
|
type ErasePageFuture<'a>: Future<Output = Result<(), Error>>
|
||||||
|
where
|
||||||
|
Self: 'a;
|
||||||
|
|
||||||
/// Reads data from the flash device.
|
/// Reads data from the flash device.
|
||||||
///
|
///
|
||||||
|
Loading…
Reference in New Issue
Block a user