Port qspi to PeripheralMutex
This commit is contained in:
parent
962fb95ff0
commit
7433dc1039
1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@ -6,6 +6,7 @@
|
|||||||
"rust-analyzer.checkOnSave.allTargets": false,
|
"rust-analyzer.checkOnSave.allTargets": false,
|
||||||
"rust-analyzer.procMacro.enable": true,
|
"rust-analyzer.procMacro.enable": true,
|
||||||
"rust-analyzer.cargo.loadOutDirsFromCheck": true,
|
"rust-analyzer.cargo.loadOutDirsFromCheck": true,
|
||||||
|
"rust-analyzer.cargo.target": "thumbv7em-none-eabi",
|
||||||
"files.watcherExclude": {
|
"files.watcherExclude": {
|
||||||
"**/.git/objects/**": true,
|
"**/.git/objects/**": true,
|
||||||
"**/.git/subtree-cache/**": true,
|
"**/.git/subtree-cache/**": true,
|
||||||
|
@ -17,13 +17,13 @@ defmt-error = []
|
|||||||
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] }
|
embassy = { version = "0.1.0", path = "../embassy", features = ["defmt"] }
|
||||||
embassy-nrf = { version = "0.1.0", path = "../embassy-nrf", features = ["defmt", "defmt-trace", "52840"] }
|
embassy-nrf = { version = "0.1.0", path = "../embassy-nrf", features = ["defmt", "52840"] }
|
||||||
|
|
||||||
defmt = "0.2.0"
|
defmt = "0.2.0"
|
||||||
defmt-rtt = "0.2.0"
|
defmt-rtt = "0.2.0"
|
||||||
|
|
||||||
cortex-m = "0.7.1"
|
cortex-m = { version = "0.7.1", features = ["inline-asm"] }
|
||||||
cortex-m-rt = "0.6.13"
|
cortex-m-rt = "0.6.13"
|
||||||
embedded-hal = { version = "0.2.4" }
|
embedded-hal = { version = "0.2.4" }
|
||||||
panic-probe = "0.1.0"
|
panic-probe = "0.1.0"
|
||||||
|
@ -8,6 +8,7 @@ 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 nrf52840_hal::gpio;
|
use nrf52840_hal::gpio;
|
||||||
|
|
||||||
use embassy::executor::{task, Executor};
|
use embassy::executor::{task, Executor};
|
||||||
@ -69,22 +70,32 @@ async fn run() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let irq = interrupt::take!(QSPI);
|
let irq = interrupt::take!(QSPI);
|
||||||
let mut q = qspi::Qspi::new(p.QSPI, irq, config);
|
let q = qspi::Qspi::new(p.QSPI, irq, config);
|
||||||
|
pin_mut!(q);
|
||||||
|
|
||||||
let mut id = [1; 3];
|
let mut id = [1; 3];
|
||||||
q.custom_instruction(0x9F, &[], &mut id).await.unwrap();
|
q.as_mut()
|
||||||
|
.custom_instruction(0x9F, &[], &mut id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
info!("id: {}", id);
|
info!("id: {}", id);
|
||||||
|
|
||||||
// Read status register
|
// Read status register
|
||||||
let mut status = [0; 1];
|
let mut status = [0; 1];
|
||||||
q.custom_instruction(0x05, &[], &mut status).await.unwrap();
|
q.as_mut()
|
||||||
|
.custom_instruction(0x05, &[], &mut status)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
info!("status: {:?}", status[0]);
|
info!("status: {:?}", status[0]);
|
||||||
|
|
||||||
if status[0] & 0x40 == 0 {
|
if status[0] & 0x40 == 0 {
|
||||||
status[0] |= 0x40;
|
status[0] |= 0x40;
|
||||||
|
|
||||||
q.custom_instruction(0x01, &status, &mut []).await.unwrap();
|
q.as_mut()
|
||||||
|
.custom_instruction(0x01, &status, &mut [])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
info!("enabled quad in status");
|
info!("enabled quad in status");
|
||||||
}
|
}
|
||||||
@ -95,19 +106,19 @@ async fn run() {
|
|||||||
|
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
info!("page {:?}: erasing... ", i);
|
info!("page {:?}: erasing... ", i);
|
||||||
q.erase(i * PAGE_SIZE).await.unwrap();
|
q.as_mut().erase(i * PAGE_SIZE).await.unwrap();
|
||||||
|
|
||||||
for j in 0..PAGE_SIZE {
|
for j in 0..PAGE_SIZE {
|
||||||
buf.0[j] = pattern((j + i * PAGE_SIZE) as u32);
|
buf.0[j] = pattern((j + i * PAGE_SIZE) as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("programming...");
|
info!("programming...");
|
||||||
q.write(i * PAGE_SIZE, &buf.0).await.unwrap();
|
q.as_mut().write(i * PAGE_SIZE, &buf.0).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
info!("page {:?}: reading... ", i);
|
info!("page {:?}: reading... ", i);
|
||||||
q.read(i * PAGE_SIZE, &mut buf.0).await.unwrap();
|
q.as_mut().read(i * PAGE_SIZE, &mut buf.0).await.unwrap();
|
||||||
|
|
||||||
info!("verifying...");
|
info!("verifying...");
|
||||||
for j in 0..PAGE_SIZE {
|
for j in 0..PAGE_SIZE {
|
||||||
|
@ -27,6 +27,7 @@ cortex-m-rt = "0.6.13"
|
|||||||
cortex-m = "0.7.1"
|
cortex-m = "0.7.1"
|
||||||
embedded-hal = { version = "0.2.4" }
|
embedded-hal = { version = "0.2.4" }
|
||||||
embedded-dma = { version = "0.1.2" }
|
embedded-dma = { version = "0.1.2" }
|
||||||
|
futures = { version = "0.3.5", default-features = false }
|
||||||
|
|
||||||
nrf52810-pac = { version = "0.9.0", optional = true }
|
nrf52810-pac = { version = "0.9.0", optional = true }
|
||||||
nrf52811-pac = { version = "0.9.1", optional = true }
|
nrf52811-pac = { version = "0.9.1", optional = true }
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
use crate::fmt::{assert, assert_eq, *};
|
|
||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
|
use core::pin::Pin;
|
||||||
|
use core::sync::atomic::{compiler_fence, Ordering};
|
||||||
|
use core::task::Poll;
|
||||||
|
|
||||||
|
use crate::fmt::{assert, assert_eq, *};
|
||||||
use crate::hal::gpio::{Output, Pin as GpioPin, Port as GpioPort, PushPull};
|
use crate::hal::gpio::{Output, Pin as GpioPin, Port as GpioPort, PushPull};
|
||||||
use crate::interrupt::{self, Interrupt};
|
use crate::interrupt::{self, Interrupt};
|
||||||
use crate::pac::QSPI;
|
use crate::pac::QSPI;
|
||||||
@ -9,6 +12,7 @@ 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;
|
||||||
pub use crate::pac::qspi::ifconfig0::READOC_A as ReadOpcode;
|
pub use crate::pac::qspi::ifconfig0::READOC_A as ReadOpcode;
|
||||||
pub use crate::pac::qspi::ifconfig0::WRITEOC_A as WriteOpcode;
|
pub use crate::pac::qspi::ifconfig0::WRITEOC_A as WriteOpcode;
|
||||||
|
use crate::util::peripheral::{PeripheralMutex, PeripheralState};
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// - config:
|
// - config:
|
||||||
@ -21,7 +25,8 @@ pub use crate::pac::qspi::ifconfig0::WRITEOC_A as WriteOpcode;
|
|||||||
// - set gpio in high drive
|
// - set gpio in high drive
|
||||||
|
|
||||||
use embassy::flash::{Error, Flash};
|
use embassy::flash::{Error, Flash};
|
||||||
use embassy::util::{DropBomb, Signal};
|
use embassy::util::{DropBomb, WakerRegistration};
|
||||||
|
use futures::future::poll_fn;
|
||||||
|
|
||||||
pub struct Pins {
|
pub struct Pins {
|
||||||
pub sck: GpioPin<Output<PushPull>>,
|
pub sck: GpioPin<Output<PushPull>>,
|
||||||
@ -46,8 +51,13 @@ pub struct Config {
|
|||||||
pub deep_power_down: Option<DeepPowerDownConfig>,
|
pub deep_power_down: Option<DeepPowerDownConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Qspi {
|
struct State {
|
||||||
inner: QSPI,
|
inner: QSPI,
|
||||||
|
waker: WakerRegistration,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Qspi {
|
||||||
|
inner: PeripheralMutex<State>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn port_bit(port: GpioPort) -> bool {
|
fn port_bit(port: GpioPort) -> bool {
|
||||||
@ -142,32 +152,34 @@ impl Qspi {
|
|||||||
while qspi.events_ready.read().bits() == 0 {}
|
while qspi.events_ready.read().bits() == 0 {}
|
||||||
qspi.events_ready.reset();
|
qspi.events_ready.reset();
|
||||||
|
|
||||||
// Enable READY interrupt
|
Self {
|
||||||
SIGNAL.reset();
|
inner: PeripheralMutex::new(
|
||||||
qspi.intenset.write(|w| w.ready().set());
|
State {
|
||||||
|
inner: qspi,
|
||||||
irq.set_handler(irq_handler);
|
waker: WakerRegistration::new(),
|
||||||
irq.unpend();
|
},
|
||||||
irq.enable();
|
irq,
|
||||||
|
),
|
||||||
Self { inner: qspi }
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sleep(&mut self) {
|
pub fn sleep(self: Pin<&mut Self>) {
|
||||||
info!("flash: sleeping");
|
self.inner().with(|s, _| {
|
||||||
info!("flash: state = {:?}", self.inner.status.read().bits());
|
info!("flash: sleeping");
|
||||||
self.inner.ifconfig1.modify(|_, w| w.dpmen().enter());
|
info!("flash: state = {:?}", s.inner.status.read().bits());
|
||||||
info!("flash: state = {:?}", self.inner.status.read().bits());
|
s.inner.ifconfig1.modify(|_, w| w.dpmen().enter());
|
||||||
cortex_m::asm::delay(1000000);
|
info!("flash: state = {:?}", s.inner.status.read().bits());
|
||||||
info!("flash: state = {:?}", self.inner.status.read().bits());
|
cortex_m::asm::delay(1000000);
|
||||||
|
info!("flash: state = {:?}", s.inner.status.read().bits());
|
||||||
|
|
||||||
self.inner
|
s.inner
|
||||||
.tasks_deactivate
|
.tasks_deactivate
|
||||||
.write(|w| w.tasks_deactivate().set_bit());
|
.write(|w| w.tasks_deactivate().set_bit());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn custom_instruction<'a>(
|
pub async fn custom_instruction<'a>(
|
||||||
&'a mut self,
|
mut self: Pin<&'a mut Self>,
|
||||||
opcode: u8,
|
opcode: u8,
|
||||||
req: &'a [u8],
|
req: &'a [u8],
|
||||||
resp: &'a mut [u8],
|
resp: &'a mut [u8],
|
||||||
@ -193,40 +205,68 @@ 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.inner.cinstrdat0.write(|w| unsafe { w.bits(dat0) });
|
self.as_mut().inner().with(|s, _| {
|
||||||
self.inner.cinstrdat1.write(|w| unsafe { w.bits(dat1) });
|
s.inner.cinstrdat0.write(|w| unsafe { w.bits(dat0) });
|
||||||
self.inner.events_ready.reset();
|
s.inner.cinstrdat1.write(|w| unsafe { w.bits(dat1) });
|
||||||
self.inner.cinstrconf.write(|w| {
|
|
||||||
let w = unsafe { w.opcode().bits(opcode) };
|
s.inner.events_ready.reset();
|
||||||
let w = unsafe { w.length().bits(len + 1) };
|
s.inner.intenset.write(|w| w.ready().set());
|
||||||
let w = w.lio2().bit(true);
|
|
||||||
let w = w.lio3().bit(true);
|
s.inner.cinstrconf.write(|w| {
|
||||||
let w = w.wipwait().bit(true);
|
let w = unsafe { w.opcode().bits(opcode) };
|
||||||
let w = w.wren().bit(true);
|
let w = unsafe { w.length().bits(len + 1) };
|
||||||
let w = w.lfen().bit(false);
|
let w = w.lio2().bit(true);
|
||||||
let w = w.lfstop().bit(false);
|
let w = w.lio3().bit(true);
|
||||||
w
|
let w = w.wipwait().bit(true);
|
||||||
|
let w = w.wren().bit(true);
|
||||||
|
let w = w.lfen().bit(false);
|
||||||
|
let w = w.lfstop().bit(false);
|
||||||
|
w
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
SIGNAL.wait().await;
|
self.as_mut().wait_ready().await;
|
||||||
|
|
||||||
let dat0 = self.inner.cinstrdat0.read().bits();
|
self.as_mut().inner().with(|s, _| {
|
||||||
let dat1 = self.inner.cinstrdat1.read().bits();
|
let dat0 = s.inner.cinstrdat0.read().bits();
|
||||||
for i in 0..4 {
|
let dat1 = s.inner.cinstrdat1.read().bits();
|
||||||
if i < resp.len() {
|
for i in 0..4 {
|
||||||
resp[i] = (dat0 >> (i * 8)) as u8;
|
if i < resp.len() {
|
||||||
|
resp[i] = (dat0 >> (i * 8)) as u8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
for i in 0..4 {
|
||||||
for i in 0..4 {
|
if i + 4 < resp.len() {
|
||||||
if i + 4 < resp.len() {
|
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>> {
|
||||||
|
unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn free(self: Pin<&mut Self>) -> (QSPI, interrupt::QSPI) {
|
||||||
|
let (state, irq) = self.inner().free();
|
||||||
|
(state.inner, irq)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wait_ready<'a>(mut self: Pin<&'a mut Self>) -> impl Future<Output = ()> + 'a {
|
||||||
|
poll_fn(move |cx| {
|
||||||
|
self.as_mut().inner().with(|s, irq| {
|
||||||
|
if s.inner.events_ready.read().bits() != 0 {
|
||||||
|
return Poll::Ready(());
|
||||||
|
}
|
||||||
|
s.waker.register(cx.waker());
|
||||||
|
Poll::Pending
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Flash for Qspi {
|
impl Flash for Qspi {
|
||||||
@ -234,7 +274,11 @@ impl Flash for Qspi {
|
|||||||
type WriteFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
|
type WriteFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
|
||||||
type ErasePageFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
|
type ErasePageFuture<'a> = impl Future<Output = Result<(), Error>> + 'a;
|
||||||
|
|
||||||
fn read<'a>(&'a mut self, address: usize, data: &'a mut [u8]) -> Self::ReadFuture<'a> {
|
fn read<'a>(
|
||||||
|
mut self: Pin<&'a mut Self>,
|
||||||
|
address: usize,
|
||||||
|
data: &'a mut [u8],
|
||||||
|
) -> Self::ReadFuture<'a> {
|
||||||
async move {
|
async move {
|
||||||
let bomb = DropBomb::new();
|
let bomb = DropBomb::new();
|
||||||
|
|
||||||
@ -242,25 +286,28 @@ 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.inner
|
self.as_mut().inner().with(|s, _| {
|
||||||
.read
|
s.inner
|
||||||
.src
|
.read
|
||||||
.write(|w| unsafe { w.src().bits(address as u32) });
|
.src
|
||||||
self.inner
|
.write(|w| unsafe { w.src().bits(address as u32) });
|
||||||
.read
|
s.inner
|
||||||
.dst
|
.read
|
||||||
.write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) });
|
.dst
|
||||||
self.inner
|
.write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) });
|
||||||
.read
|
s.inner
|
||||||
.cnt
|
.read
|
||||||
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
.cnt
|
||||||
|
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
||||||
|
|
||||||
self.inner.events_ready.reset();
|
s.inner.events_ready.reset();
|
||||||
self.inner
|
s.inner.intenset.write(|w| w.ready().set());
|
||||||
.tasks_readstart
|
s.inner
|
||||||
.write(|w| w.tasks_readstart().bit(true));
|
.tasks_readstart
|
||||||
|
.write(|w| w.tasks_readstart().bit(true));
|
||||||
|
});
|
||||||
|
|
||||||
SIGNAL.wait().await;
|
self.as_mut().wait_ready().await;
|
||||||
|
|
||||||
bomb.defuse();
|
bomb.defuse();
|
||||||
|
|
||||||
@ -268,7 +315,11 @@ impl Flash for Qspi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write<'a>(&'a mut self, address: usize, data: &'a [u8]) -> Self::WriteFuture<'a> {
|
fn write<'a>(
|
||||||
|
mut self: Pin<&'a mut Self>,
|
||||||
|
address: usize,
|
||||||
|
data: &'a [u8],
|
||||||
|
) -> Self::WriteFuture<'a> {
|
||||||
async move {
|
async move {
|
||||||
let bomb = DropBomb::new();
|
let bomb = DropBomb::new();
|
||||||
|
|
||||||
@ -276,25 +327,28 @@ 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.inner
|
self.as_mut().inner().with(|s, _| {
|
||||||
.write
|
s.inner
|
||||||
.src
|
.write
|
||||||
.write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
|
.src
|
||||||
self.inner
|
.write(|w| unsafe { w.src().bits(data.as_ptr() as u32) });
|
||||||
.write
|
s.inner
|
||||||
.dst
|
.write
|
||||||
.write(|w| unsafe { w.dst().bits(address as u32) });
|
.dst
|
||||||
self.inner
|
.write(|w| unsafe { w.dst().bits(address as u32) });
|
||||||
.write
|
s.inner
|
||||||
.cnt
|
.write
|
||||||
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
.cnt
|
||||||
|
.write(|w| unsafe { w.cnt().bits(data.len() as u32) });
|
||||||
|
|
||||||
self.inner.events_ready.reset();
|
s.inner.events_ready.reset();
|
||||||
self.inner
|
s.inner.intenset.write(|w| w.ready().set());
|
||||||
.tasks_writestart
|
s.inner
|
||||||
.write(|w| w.tasks_writestart().bit(true));
|
.tasks_writestart
|
||||||
|
.write(|w| w.tasks_writestart().bit(true));
|
||||||
|
});
|
||||||
|
|
||||||
SIGNAL.wait().await;
|
self.as_mut().wait_ready().await;
|
||||||
|
|
||||||
bomb.defuse();
|
bomb.defuse();
|
||||||
|
|
||||||
@ -302,23 +356,27 @@ impl Flash for Qspi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn erase<'a>(&'a mut self, address: usize) -> Self::ErasePageFuture<'a> {
|
fn erase<'a>(mut self: Pin<&'a mut Self>, address: usize) -> Self::ErasePageFuture<'a> {
|
||||||
async move {
|
async move {
|
||||||
let bomb = DropBomb::new();
|
let bomb = DropBomb::new();
|
||||||
|
|
||||||
assert_eq!(address as u32 % 4096, 0);
|
assert_eq!(address as u32 % 4096, 0);
|
||||||
|
|
||||||
self.inner
|
self.as_mut().inner().with(|s, _| {
|
||||||
.erase
|
s.inner
|
||||||
.ptr
|
.erase
|
||||||
.write(|w| unsafe { w.ptr().bits(address as u32) });
|
.ptr
|
||||||
self.inner.erase.len.write(|w| w.len()._4kb());
|
.write(|w| unsafe { w.ptr().bits(address as u32) });
|
||||||
self.inner.events_ready.reset();
|
s.inner.erase.len.write(|w| w.len()._4kb());
|
||||||
self.inner
|
|
||||||
.tasks_erasestart
|
|
||||||
.write(|w| w.tasks_erasestart().bit(true));
|
|
||||||
|
|
||||||
SIGNAL.wait().await;
|
s.inner.events_ready.reset();
|
||||||
|
s.inner.intenset.write(|w| w.ready().set());
|
||||||
|
s.inner
|
||||||
|
.tasks_erasestart
|
||||||
|
.write(|w| w.tasks_erasestart().bit(true));
|
||||||
|
});
|
||||||
|
|
||||||
|
self.as_mut().wait_ready().await;
|
||||||
|
|
||||||
bomb.defuse();
|
bomb.defuse();
|
||||||
|
|
||||||
@ -343,13 +401,13 @@ impl Flash for Qspi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static SIGNAL: Signal<()> = Signal::new();
|
impl PeripheralState for State {
|
||||||
|
type Interrupt = interrupt::QSPI;
|
||||||
|
|
||||||
unsafe fn irq_handler(_ctx: *mut ()) {
|
fn on_interrupt(&mut self) {
|
||||||
let p = crate::pac::Peripherals::steal().QSPI;
|
if self.inner.events_ready.read().bits() != 0 {
|
||||||
if p.events_ready.read().events_ready().bit_is_set() {
|
self.inner.intenclr.write(|w| w.ready().clear());
|
||||||
p.events_ready.reset();
|
self.waker.wake()
|
||||||
info!("qspi ready");
|
}
|
||||||
SIGNAL.signal(());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use core::future::Future;
|
use core::future::Future;
|
||||||
|
use core::pin::Pin;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
@ -18,18 +19,19 @@ pub trait Flash {
|
|||||||
///
|
///
|
||||||
/// address must be a multiple of self.read_size().
|
/// address must be a multiple of self.read_size().
|
||||||
/// buf.len() must be a multiple of self.read_size().
|
/// buf.len() must be a multiple of self.read_size().
|
||||||
fn read<'a>(&'a mut self, address: usize, buf: &'a mut [u8]) -> Self::ReadFuture<'a>;
|
fn read<'a>(self: Pin<&'a mut Self>, address: usize, buf: &'a mut [u8])
|
||||||
|
-> Self::ReadFuture<'a>;
|
||||||
|
|
||||||
/// Writes data to the flash device.
|
/// Writes data to the flash device.
|
||||||
///
|
///
|
||||||
/// address must be a multiple of self.write_size().
|
/// address must be a multiple of self.write_size().
|
||||||
/// buf.len() must be a multiple of self.write_size().
|
/// buf.len() must be a multiple of self.write_size().
|
||||||
fn write<'a>(&'a mut self, address: usize, buf: &'a [u8]) -> Self::WriteFuture<'a>;
|
fn write<'a>(self: Pin<&'a mut Self>, address: usize, buf: &'a [u8]) -> Self::WriteFuture<'a>;
|
||||||
|
|
||||||
/// Erases a single page from the flash device.
|
/// Erases a single page from the flash device.
|
||||||
///
|
///
|
||||||
/// address must be a multiple of self.erase_size().
|
/// address must be a multiple of self.erase_size().
|
||||||
fn erase<'a>(&'a mut self, address: usize) -> Self::ErasePageFuture<'a>;
|
fn erase<'a>(self: Pin<&'a mut Self>, address: usize) -> Self::ErasePageFuture<'a>;
|
||||||
|
|
||||||
/// Returns the total size, in bytes.
|
/// Returns the total size, in bytes.
|
||||||
/// This is not guaranteed to be a power of 2.
|
/// This is not guaranteed to be a power of 2.
|
||||||
|
Loading…
Reference in New Issue
Block a user