diff options
| author | Dario Nieuwenhuis <[email protected]> | 2021-03-21 20:54:09 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2021-03-29 00:58:57 +0200 |
| commit | ec7309962a8f427732a0c6fc7c29713923b39028 (patch) | |
| tree | a45096b7309e2660cb8749b5e459f97312896870 | |
| parent | 16bb6fd6ac34646f498424459b8eb6863635b119 (diff) | |
nrf/qspi: update to new api
| -rw-r--r-- | embassy-nrf-examples/src/bin/qspi.rs | 49 | ||||
| -rw-r--r-- | embassy-nrf/src/qspi.rs | 378 | ||||
| -rw-r--r-- | embassy-traits/src/flash.rs | 14 |
3 files changed, 206 insertions, 235 deletions
diff --git a/embassy-nrf-examples/src/bin/qspi.rs b/embassy-nrf-examples/src/bin/qspi.rs index 7d8a45f78..a08969881 100644 --- a/embassy-nrf-examples/src/bin/qspi.rs +++ b/embassy-nrf-examples/src/bin/qspi.rs | |||
| @@ -6,12 +6,12 @@ | |||
| 6 | 6 | ||
| 7 | #[path = "../example_common.rs"] | 7 | #[path = "../example_common.rs"] |
| 8 | mod example_common; | 8 | mod example_common; |
| 9 | use embassy_nrf::peripherals::Peripherals; | ||
| 9 | use example_common::*; | 10 | use example_common::*; |
| 10 | 11 | ||
| 11 | use cortex_m_rt::entry; | 12 | use cortex_m_rt::entry; |
| 12 | use defmt::{assert_eq, panic}; | 13 | use defmt::{assert_eq, panic}; |
| 13 | use futures::pin_mut; | 14 | use futures::pin_mut; |
| 14 | use nrf52840_hal::gpio; | ||
| 15 | 15 | ||
| 16 | use embassy::executor::{task, Executor}; | 16 | use embassy::executor::{task, Executor}; |
| 17 | use embassy::traits::flash::Flash; | 17 | use embassy::traits::flash::Flash; |
| @@ -27,43 +27,16 @@ struct AlignedBuf([u8; 4096]); | |||
| 27 | 27 | ||
| 28 | #[task] | 28 | #[task] |
| 29 | async fn run() { | 29 | async fn run() { |
| 30 | let p = unwrap!(embassy_nrf::pac::Peripherals::take()); | 30 | let p = unsafe { Peripherals::steal() }; |
| 31 | 31 | ||
| 32 | let port0 = gpio::p0::Parts::new(p.P0); | 32 | let csn = p.p0_17; |
| 33 | 33 | let sck = p.p0_19; | |
| 34 | let pins = qspi::Pins { | 34 | let io0 = p.p0_20; |
| 35 | csn: port0 | 35 | let io1 = p.p0_21; |
| 36 | .p0_17 | 36 | let io2 = p.p0_22; |
| 37 | .into_push_pull_output(gpio::Level::High) | 37 | let io3 = p.p0_23; |
| 38 | .degrade(), | ||
| 39 | sck: port0 | ||
| 40 | .p0_19 | ||
| 41 | .into_push_pull_output(gpio::Level::High) | ||
| 42 | .degrade(), | ||
| 43 | io0: port0 | ||
| 44 | .p0_20 | ||
| 45 | .into_push_pull_output(gpio::Level::High) | ||
| 46 | .degrade(), | ||
| 47 | io1: port0 | ||
| 48 | .p0_21 | ||
| 49 | .into_push_pull_output(gpio::Level::High) | ||
| 50 | .degrade(), | ||
| 51 | io2: Some( | ||
| 52 | port0 | ||
| 53 | .p0_22 | ||
| 54 | .into_push_pull_output(gpio::Level::High) | ||
| 55 | .degrade(), | ||
| 56 | ), | ||
| 57 | io3: Some( | ||
| 58 | port0 | ||
| 59 | .p0_23 | ||
| 60 | .into_push_pull_output(gpio::Level::High) | ||
| 61 | .degrade(), | ||
| 62 | ), | ||
| 63 | }; | ||
| 64 | 38 | ||
| 65 | let config = qspi::Config { | 39 | let config = qspi::Config { |
| 66 | pins, | ||
| 67 | read_opcode: qspi::ReadOpcode::READ4IO, | 40 | read_opcode: qspi::ReadOpcode::READ4IO, |
| 68 | write_opcode: qspi::WriteOpcode::PP4IO, | 41 | write_opcode: qspi::WriteOpcode::PP4IO, |
| 69 | xip_offset: 0, | 42 | xip_offset: 0, |
| @@ -72,7 +45,7 @@ async fn run() { | |||
| 72 | }; | 45 | }; |
| 73 | 46 | ||
| 74 | let irq = interrupt::take!(QSPI); | 47 | let irq = interrupt::take!(QSPI); |
| 75 | let q = qspi::Qspi::new(p.QSPI, irq, config); | 48 | let q = qspi::Qspi::new(p.qspi, irq, sck, csn, io0, io1, io2, io3, config); |
| 76 | pin_mut!(q); | 49 | pin_mut!(q); |
| 77 | 50 | ||
| 78 | let mut id = [1; 3]; | 51 | let mut id = [1; 3]; |
| @@ -83,7 +56,7 @@ async fn run() { | |||
| 83 | info!("id: {}", id); | 56 | info!("id: {}", id); |
| 84 | 57 | ||
| 85 | // Read status register | 58 | // Read status register |
| 86 | let mut status = [0; 1]; | 59 | let mut status = [4; 1]; |
| 87 | q.as_mut() | 60 | q.as_mut() |
| 88 | .custom_instruction(0x05, &[], &mut status) | 61 | .custom_instruction(0x05, &[], &mut status) |
| 89 | .await | 62 | .await |
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index 026660cba..39428c62c 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs | |||
| @@ -1,13 +1,15 @@ | |||
| 1 | use core::future::Future; | 1 | use core::future::Future; |
| 2 | use core::marker::PhantomData; | ||
| 2 | use core::pin::Pin; | 3 | use core::pin::Pin; |
| 3 | use core::task::Poll; | 4 | use core::task::Poll; |
| 4 | 5 | ||
| 6 | use embassy::interrupt::Interrupt; | ||
| 5 | use embassy_extras::peripheral::{PeripheralMutex, PeripheralState}; | 7 | use embassy_extras::peripheral::{PeripheralMutex, PeripheralState}; |
| 6 | 8 | ||
| 7 | use crate::fmt::{assert, assert_eq, *}; | 9 | use crate::fmt::{assert, assert_eq, *}; |
| 8 | use crate::hal::gpio::{Output, Pin as GpioPin, PushPull}; | 10 | use crate::gpio::Pin as GpioPin; |
| 9 | use crate::interrupt::{self}; | 11 | use crate::interrupt::{self}; |
| 10 | use crate::pac::QSPI; | 12 | use crate::{pac, peripherals}; |
| 11 | 13 | ||
| 12 | pub use crate::pac::qspi::ifconfig0::ADDRMODE_A as AddressMode; | 14 | pub use crate::pac::qspi::ifconfig0::ADDRMODE_A as AddressMode; |
| 13 | pub use crate::pac::qspi::ifconfig0::PPSIZE_A as WritePageSize; | 15 | pub use crate::pac::qspi::ifconfig0::PPSIZE_A as WritePageSize; |
| @@ -25,25 +27,15 @@ pub use crate::pac::qspi::ifconfig0::WRITEOC_A as WriteOpcode; | |||
| 25 | // - set gpio in high drive | 27 | // - set gpio in high drive |
| 26 | 28 | ||
| 27 | use embassy::traits::flash::{Error, Flash}; | 29 | use embassy::traits::flash::{Error, Flash}; |
| 28 | use embassy::util::{DropBomb, WakerRegistration}; | 30 | use embassy::util::{wake_on_interrupt, DropBomb, PeripheralBorrow, WakerRegistration}; |
| 29 | use futures::future::poll_fn; | 31 | use futures::future::poll_fn; |
| 30 | 32 | ||
| 31 | pub struct Pins { | ||
| 32 | pub sck: GpioPin<Output<PushPull>>, | ||
| 33 | pub csn: GpioPin<Output<PushPull>>, | ||
| 34 | pub io0: GpioPin<Output<PushPull>>, | ||
| 35 | pub io1: GpioPin<Output<PushPull>>, | ||
| 36 | pub io2: Option<GpioPin<Output<PushPull>>>, | ||
| 37 | pub io3: Option<GpioPin<Output<PushPull>>>, | ||
| 38 | } | ||
| 39 | |||
| 40 | pub struct DeepPowerDownConfig { | 33 | pub struct DeepPowerDownConfig { |
| 41 | pub enter_time: u16, | 34 | pub enter_time: u16, |
| 42 | pub exit_time: u16, | 35 | pub exit_time: u16, |
| 43 | } | 36 | } |
| 44 | 37 | ||
| 45 | pub struct Config { | 38 | pub struct Config { |
| 46 | pub pins: Pins, | ||
| 47 | pub xip_offset: u32, | 39 | pub xip_offset: u32, |
| 48 | pub read_opcode: ReadOpcode, | 40 | pub read_opcode: ReadOpcode, |
| 49 | pub write_opcode: WriteOpcode, | 41 | pub write_opcode: WriteOpcode, |
| @@ -51,55 +43,54 @@ pub struct Config { | |||
| 51 | pub deep_power_down: Option<DeepPowerDownConfig>, | 43 | pub deep_power_down: Option<DeepPowerDownConfig>, |
| 52 | } | 44 | } |
| 53 | 45 | ||
| 54 | struct State { | 46 | pub struct Qspi<'d, T: Instance> { |
| 55 | inner: QSPI, | 47 | qspi: T, |
| 56 | waker: WakerRegistration, | 48 | irq: T::Interrupt, |
| 49 | phantom: PhantomData<&'d mut T>, | ||
| 57 | } | 50 | } |
| 58 | 51 | ||
| 59 | pub struct Qspi { | 52 | impl<'d, T: Instance> Qspi<'d, T> { |
| 60 | inner: PeripheralMutex<State>, | 53 | pub fn new( |
| 61 | } | 54 | qspi: impl PeripheralBorrow<Target = T> + 'd, |
| 55 | irq: impl PeripheralBorrow<Target = T::Interrupt> + 'd, | ||
| 56 | sck: impl PeripheralBorrow<Target = impl GpioPin> + 'd, | ||
| 57 | csn: impl PeripheralBorrow<Target = impl GpioPin> + 'd, | ||
| 58 | io0: impl PeripheralBorrow<Target = impl GpioPin> + 'd, | ||
| 59 | io1: impl PeripheralBorrow<Target = impl GpioPin> + 'd, | ||
| 60 | io2: impl PeripheralBorrow<Target = impl GpioPin> + 'd, | ||
| 61 | io3: impl PeripheralBorrow<Target = impl GpioPin> + 'd, | ||
| 62 | config: Config, | ||
| 63 | ) -> Self { | ||
| 64 | let mut qspi = unsafe { qspi.unborrow() }; | ||
| 65 | let irq = unsafe { irq.unborrow() }; | ||
| 66 | let sck = unsafe { sck.unborrow() }; | ||
| 67 | let csn = unsafe { csn.unborrow() }; | ||
| 68 | let io0 = unsafe { io0.unborrow() }; | ||
| 69 | let io1 = unsafe { io1.unborrow() }; | ||
| 70 | let io2 = unsafe { io2.unborrow() }; | ||
| 71 | let io3 = unsafe { io3.unborrow() }; | ||
| 72 | |||
| 73 | let r = qspi.regs(); | ||
| 74 | |||
| 75 | for cnf in &[ | ||
| 76 | sck.conf(), | ||
| 77 | csn.conf(), | ||
| 78 | io0.conf(), | ||
| 79 | io1.conf(), | ||
| 80 | io2.conf(), | ||
| 81 | io3.conf(), | ||
| 82 | ] { | ||
| 83 | cnf.write(|w| w.dir().output().drive().h0h1()); | ||
| 84 | } | ||
| 62 | 85 | ||
| 63 | impl Qspi { | 86 | r.psel.sck.write(|w| unsafe { w.bits(sck.psel_bits()) }); |
| 64 | pub fn new(qspi: QSPI, irq: interrupt::QSPI, config: Config) -> Self { | 87 | r.psel.csn.write(|w| unsafe { w.bits(csn.psel_bits()) }); |
| 65 | qspi.psel.sck.write(|w| { | 88 | r.psel.io0.write(|w| unsafe { w.bits(io0.psel_bits()) }); |
| 66 | let pin = &config.pins.sck; | 89 | r.psel.io1.write(|w| unsafe { w.bits(io1.psel_bits()) }); |
| 67 | unsafe { w.bits(pin.psel_bits()) }; | 90 | r.psel.io2.write(|w| unsafe { w.bits(io2.psel_bits()) }); |
| 68 | w.connect().connected() | 91 | r.psel.io3.write(|w| unsafe { w.bits(io3.psel_bits()) }); |
| 69 | }); | ||
| 70 | qspi.psel.csn.write(|w| { | ||
| 71 | let pin = &config.pins.csn; | ||
| 72 | unsafe { w.bits(pin.psel_bits()) }; | ||
| 73 | w.connect().connected() | ||
| 74 | }); | ||
| 75 | qspi.psel.io0.write(|w| { | ||
| 76 | let pin = &config.pins.io0; | ||
| 77 | unsafe { w.bits(pin.psel_bits()) }; | ||
| 78 | w.connect().connected() | ||
| 79 | }); | ||
| 80 | qspi.psel.io1.write(|w| { | ||
| 81 | let pin = &config.pins.io1; | ||
| 82 | unsafe { w.bits(pin.psel_bits()) }; | ||
| 83 | w.connect().connected() | ||
| 84 | }); | ||
| 85 | qspi.psel.io2.write(|w| { | ||
| 86 | if let Some(ref pin) = config.pins.io2 { | ||
| 87 | unsafe { w.bits(pin.psel_bits()) }; | ||
| 88 | w.connect().connected() | ||
| 89 | } else { | ||
| 90 | w.connect().disconnected() | ||
| 91 | } | ||
| 92 | }); | ||
| 93 | qspi.psel.io3.write(|w| { | ||
| 94 | if let Some(ref pin) = config.pins.io3 { | ||
| 95 | unsafe { w.bits(pin.psel_bits()) }; | ||
| 96 | w.connect().connected() | ||
| 97 | } else { | ||
| 98 | w.connect().disconnected() | ||
| 99 | } | ||
| 100 | }); | ||
| 101 | 92 | ||
| 102 | qspi.ifconfig0.write(|mut w| { | 93 | r.ifconfig0.write(|mut w| { |
| 103 | w = w.addrmode().variant(AddressMode::_24BIT); | 94 | w = w.addrmode().variant(AddressMode::_24BIT); |
| 104 | if config.deep_power_down.is_some() { | 95 | if config.deep_power_down.is_some() { |
| 105 | w = w.dpmenable().enable(); | 96 | w = w.dpmenable().enable(); |
| @@ -113,14 +104,14 @@ impl Qspi { | |||
| 113 | }); | 104 | }); |
| 114 | 105 | ||
| 115 | if let Some(dpd) = &config.deep_power_down { | 106 | if let Some(dpd) = &config.deep_power_down { |
| 116 | qspi.dpmdur.write(|mut w| unsafe { | 107 | r.dpmdur.write(|mut w| unsafe { |
| 117 | w = w.enter().bits(dpd.enter_time); | 108 | w = w.enter().bits(dpd.enter_time); |
| 118 | w = w.exit().bits(dpd.exit_time); | 109 | w = w.exit().bits(dpd.exit_time); |
| 119 | w | 110 | w |
| 120 | }) | 111 | }) |
| 121 | } | 112 | } |
| 122 | 113 | ||
| 123 | qspi.ifconfig1.write(|w| { | 114 | r.ifconfig1.write(|w| { |
| 124 | let w = unsafe { w.sckdelay().bits(80) }; | 115 | let w = unsafe { w.sckdelay().bits(80) }; |
| 125 | let w = w.dpmen().exit(); | 116 | let w = w.dpmen().exit(); |
| 126 | let w = w.spimode().mode0(); | 117 | let w = w.spimode().mode0(); |
| @@ -128,48 +119,42 @@ impl Qspi { | |||
| 128 | w | 119 | w |
| 129 | }); | 120 | }); |
| 130 | 121 | ||
| 131 | qspi.xipoffset | 122 | r.xipoffset |
| 132 | .write(|w| unsafe { w.xipoffset().bits(config.xip_offset) }); | 123 | .write(|w| unsafe { w.xipoffset().bits(config.xip_offset) }); |
| 133 | 124 | ||
| 134 | // Enable it | 125 | // Enable it |
| 135 | qspi.enable.write(|w| w.enable().enabled()); | 126 | r.enable.write(|w| w.enable().enabled()); |
| 136 | 127 | ||
| 137 | qspi.events_ready.reset(); | 128 | r.events_ready.reset(); |
| 138 | qspi.tasks_activate.write(|w| w.tasks_activate().bit(true)); | 129 | r.tasks_activate.write(|w| w.tasks_activate().bit(true)); |
| 139 | while qspi.events_ready.read().bits() == 0 {} | 130 | while r.events_ready.read().bits() == 0 {} |
| 140 | qspi.events_ready.reset(); | 131 | r.events_ready.reset(); |
| 141 | 132 | ||
| 142 | Self { | 133 | Self { |
| 143 | inner: PeripheralMutex::new( | 134 | qspi, |
| 144 | State { | 135 | irq, |
| 145 | inner: qspi, | 136 | phantom: PhantomData, |
| 146 | waker: WakerRegistration::new(), | ||
| 147 | }, | ||
| 148 | irq, | ||
| 149 | ), | ||
| 150 | } | 137 | } |
| 151 | } | 138 | } |
| 152 | 139 | ||
| 153 | pub fn sleep(self: Pin<&mut Self>) { | 140 | pub fn sleep(mut self: Pin<&mut Self>) { |
| 154 | self.inner().with(|s, _| { | 141 | let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs(); |
| 155 | info!("flash: sleeping"); | 142 | |
| 156 | info!("flash: state = {:?}", s.inner.status.read().bits()); | 143 | info!("flash: sleeping"); |
| 157 | s.inner.ifconfig1.modify(|_, w| w.dpmen().enter()); | 144 | info!("flash: state = {:?}", r.status.read().bits()); |
| 158 | info!("flash: state = {:?}", s.inner.status.read().bits()); | 145 | r.ifconfig1.modify(|_, w| w.dpmen().enter()); |
| 159 | cortex_m::asm::delay(1000000); | 146 | info!("flash: state = {:?}", r.status.read().bits()); |
| 160 | info!("flash: state = {:?}", s.inner.status.read().bits()); | 147 | cortex_m::asm::delay(1000000); |
| 161 | 148 | info!("flash: state = {:?}", r.status.read().bits()); | |
| 162 | s.inner | 149 | |
| 163 | .tasks_deactivate | 150 | r.tasks_deactivate.write(|w| w.tasks_deactivate().set_bit()); |
| 164 | .write(|w| w.tasks_deactivate().set_bit()); | ||
| 165 | }); | ||
| 166 | } | 151 | } |
| 167 | 152 | ||
| 168 | pub async fn custom_instruction<'a>( | 153 | pub async fn custom_instruction( |
| 169 | mut self: Pin<&'a mut Self>, | 154 | mut self: Pin<&mut Self>, |
| 170 | opcode: u8, | 155 | opcode: u8, |
| 171 | req: &'a [u8], | 156 | req: &[u8], |
| 172 | resp: &'a mut [u8], | 157 | resp: &mut [u8], |
| 173 | ) -> Result<(), Error> { | 158 | ) -> Result<(), Error> { |
| 174 | let bomb = DropBomb::new(); | 159 | let bomb = DropBomb::new(); |
| 175 | 160 | ||
| @@ -192,69 +177,73 @@ impl Qspi { | |||
| 192 | 177 | ||
| 193 | let len = core::cmp::max(req.len(), resp.len()) as u8; | 178 | let len = core::cmp::max(req.len(), resp.len()) as u8; |
| 194 | 179 | ||
| 195 | self.as_mut().inner().with(|s, _| { | 180 | let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs(); |
| 196 | s.inner.cinstrdat0.write(|w| unsafe { w.bits(dat0) }); | 181 | r.cinstrdat0.write(|w| unsafe { w.bits(dat0) }); |
| 197 | s.inner.cinstrdat1.write(|w| unsafe { w.bits(dat1) }); | 182 | r.cinstrdat1.write(|w| unsafe { w.bits(dat1) }); |
| 198 | 183 | ||
| 199 | s.inner.events_ready.reset(); | 184 | r.events_ready.reset(); |
| 200 | s.inner.intenset.write(|w| w.ready().set()); | 185 | r.intenset.write(|w| w.ready().set()); |
| 201 | 186 | ||
| 202 | s.inner.cinstrconf.write(|w| { | 187 | r.cinstrconf.write(|w| { |
| 203 | let w = unsafe { w.opcode().bits(opcode) }; | 188 | let w = unsafe { w.opcode().bits(opcode) }; |
| 204 | let w = unsafe { w.length().bits(len + 1) }; | 189 | let w = unsafe { w.length().bits(len + 1) }; |
| 205 | let w = w.lio2().bit(true); | 190 | let w = w.lio2().bit(true); |
| 206 | let w = w.lio3().bit(true); | 191 | let w = w.lio3().bit(true); |
| 207 | let w = w.wipwait().bit(true); | 192 | let w = w.wipwait().bit(true); |
| 208 | let w = w.wren().bit(true); | 193 | let w = w.wren().bit(true); |
| 209 | let w = w.lfen().bit(false); | 194 | let w = w.lfen().bit(false); |
| 210 | let w = w.lfstop().bit(false); | 195 | let w = w.lfstop().bit(false); |
| 211 | w | 196 | w |
| 212 | }); | ||
| 213 | }); | 197 | }); |
| 214 | 198 | ||
| 215 | self.as_mut().wait_ready().await; | 199 | self.as_mut().wait_ready().await; |
| 216 | 200 | ||
| 217 | self.as_mut().inner().with(|s, _| { | 201 | let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs(); |
| 218 | let dat0 = s.inner.cinstrdat0.read().bits(); | 202 | |
| 219 | let dat1 = s.inner.cinstrdat1.read().bits(); | 203 | let dat0 = r.cinstrdat0.read().bits(); |
| 220 | for i in 0..4 { | 204 | let dat1 = r.cinstrdat1.read().bits(); |
| 221 | if i < resp.len() { | 205 | for i in 0..4 { |
| 222 | resp[i] = (dat0 >> (i * 8)) as u8; | 206 | if i < resp.len() { |
| 223 | } | 207 | resp[i] = (dat0 >> (i * 8)) as u8; |
| 224 | } | 208 | } |
| 225 | for i in 0..4 { | 209 | } |
| 226 | if i + 4 < resp.len() { | 210 | for i in 0..4 { |
| 227 | resp[i] = (dat1 >> (i * 8)) as u8; | 211 | if i + 4 < resp.len() { |
| 228 | } | 212 | resp[i] = (dat1 >> (i * 8)) as u8; |
| 229 | } | 213 | } |
| 230 | }); | 214 | } |
| 231 | 215 | ||
| 232 | bomb.defuse(); | 216 | bomb.defuse(); |
| 233 | 217 | ||
| 234 | Ok(()) | 218 | Ok(()) |
| 235 | } | 219 | } |
| 236 | 220 | ||
| 237 | fn inner(self: Pin<&mut Self>) -> Pin<&mut PeripheralMutex<State>> { | 221 | async fn wait_ready(self: Pin<&mut Self>) { |
| 238 | unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().inner) } | 222 | let this = unsafe { self.get_unchecked_mut() }; |
| 239 | } | ||
| 240 | 223 | ||
| 241 | fn wait_ready<'a>(mut self: Pin<&'a mut Self>) -> impl Future<Output = ()> + 'a { | ||
| 242 | poll_fn(move |cx| { | 224 | poll_fn(move |cx| { |
| 243 | self.as_mut().inner().with(|s, _irq| { | 225 | let r = this.qspi.regs(); |
| 244 | if s.inner.events_ready.read().bits() != 0 { | 226 | |
| 245 | return Poll::Ready(()); | 227 | if r.events_ready.read().bits() != 0 { |
| 246 | } | 228 | r.events_ready.reset(); |
| 247 | s.waker.register(cx.waker()); | 229 | return Poll::Ready(()); |
| 248 | Poll::Pending | 230 | } |
| 249 | }) | 231 | |
| 232 | wake_on_interrupt(&mut this.irq, cx.waker()); | ||
| 233 | |||
| 234 | Poll::Pending | ||
| 250 | }) | 235 | }) |
| 236 | .await | ||
| 251 | } | 237 | } |
| 252 | } | 238 | } |
| 253 | 239 | ||
| 254 | impl Flash for Qspi { | 240 | impl<'d, T: Instance> Flash for Qspi<'d, T> { |
| 255 | type ReadFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | 241 | #[rustfmt::skip] |
| 256 | type WriteFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | 242 | type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; |
| 257 | type ErasePageFuture<'a> = impl Future<Output = Result<(), Error>> + 'a; | 243 | #[rustfmt::skip] |
| 244 | type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; | ||
| 245 | #[rustfmt::skip] | ||
| 246 | type ErasePageFuture<'a> where Self: 'a = impl Future<Output = Result<(), Error>> + 'a; | ||
| 258 | 247 | ||
| 259 | fn read<'a>( | 248 | fn read<'a>( |
| 260 | mut self: Pin<&'a mut Self>, | 249 | mut self: Pin<&'a mut Self>, |
| @@ -268,26 +257,21 @@ impl Flash for Qspi { | |||
| 268 | assert_eq!(data.len() as u32 % 4, 0); | 257 | assert_eq!(data.len() as u32 % 4, 0); |
| 269 | assert_eq!(address as u32 % 4, 0); | 258 | assert_eq!(address as u32 % 4, 0); |
| 270 | 259 | ||
| 271 | self.as_mut().inner().with(|s, _| { | 260 | let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs(); |
| 272 | s.inner | 261 | |
| 273 | .read | 262 | r.read |
| 274 | .src | 263 | .src |
| 275 | .write(|w| unsafe { w.src().bits(address as u32) }); | 264 | .write(|w| unsafe { w.src().bits(address as u32) }); |
| 276 | s.inner | 265 | r.read |
| 277 | .read | 266 | .dst |
| 278 | .dst | 267 | .write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) }); |
| 279 | .write(|w| unsafe { w.dst().bits(data.as_ptr() as u32) }); | 268 | r.read |
| 280 | s.inner | 269 | .cnt |
| 281 | .read | 270 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); |
| 282 | .cnt | 271 | |
| 283 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | 272 | r.events_ready.reset(); |
| 284 | 273 | r.intenset.write(|w| w.ready().set()); | |
| 285 | s.inner.events_ready.reset(); | 274 | r.tasks_readstart.write(|w| w.tasks_readstart().bit(true)); |
| 286 | s.inner.intenset.write(|w| w.ready().set()); | ||
| 287 | s.inner | ||
| 288 | .tasks_readstart | ||
| 289 | .write(|w| w.tasks_readstart().bit(true)); | ||
| 290 | }); | ||
| 291 | 275 | ||
| 292 | self.as_mut().wait_ready().await; | 276 | self.as_mut().wait_ready().await; |
| 293 | 277 | ||
| @@ -309,26 +293,20 @@ impl Flash for Qspi { | |||
| 309 | assert_eq!(data.len() as u32 % 4, 0); | 293 | assert_eq!(data.len() as u32 % 4, 0); |
| 310 | assert_eq!(address as u32 % 4, 0); | 294 | assert_eq!(address as u32 % 4, 0); |
| 311 | 295 | ||
| 312 | self.as_mut().inner().with(|s, _| { | 296 | let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs(); |
| 313 | s.inner | 297 | r.write |
| 314 | .write | 298 | .src |
| 315 | .src | 299 | .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) }); |
| 316 | .write(|w| unsafe { w.src().bits(data.as_ptr() as u32) }); | 300 | r.write |
| 317 | s.inner | 301 | .dst |
| 318 | .write | 302 | .write(|w| unsafe { w.dst().bits(address as u32) }); |
| 319 | .dst | 303 | r.write |
| 320 | .write(|w| unsafe { w.dst().bits(address as u32) }); | 304 | .cnt |
| 321 | s.inner | 305 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); |
| 322 | .write | 306 | |
| 323 | .cnt | 307 | r.events_ready.reset(); |
| 324 | .write(|w| unsafe { w.cnt().bits(data.len() as u32) }); | 308 | r.intenset.write(|w| w.ready().set()); |
| 325 | 309 | r.tasks_writestart.write(|w| w.tasks_writestart().bit(true)); | |
| 326 | s.inner.events_ready.reset(); | ||
| 327 | s.inner.intenset.write(|w| w.ready().set()); | ||
| 328 | s.inner | ||
| 329 | .tasks_writestart | ||
| 330 | .write(|w| w.tasks_writestart().bit(true)); | ||
| 331 | }); | ||
| 332 | 310 | ||
| 333 | self.as_mut().wait_ready().await; | 311 | self.as_mut().wait_ready().await; |
| 334 | 312 | ||
| @@ -344,19 +322,15 @@ impl Flash for Qspi { | |||
| 344 | 322 | ||
| 345 | assert_eq!(address as u32 % 4096, 0); | 323 | assert_eq!(address as u32 % 4096, 0); |
| 346 | 324 | ||
| 347 | self.as_mut().inner().with(|s, _| { | 325 | let r = unsafe { self.as_mut().get_unchecked_mut() }.qspi.regs(); |
| 348 | s.inner | 326 | r.erase |
| 349 | .erase | 327 | .ptr |
| 350 | .ptr | 328 | .write(|w| unsafe { w.ptr().bits(address as u32) }); |
| 351 | .write(|w| unsafe { w.ptr().bits(address as u32) }); | 329 | r.erase.len.write(|w| w.len()._4kb()); |
| 352 | s.inner.erase.len.write(|w| w.len()._4kb()); | ||
| 353 | 330 | ||
| 354 | s.inner.events_ready.reset(); | 331 | r.events_ready.reset(); |
| 355 | s.inner.intenset.write(|w| w.ready().set()); | 332 | r.intenset.write(|w| w.ready().set()); |
| 356 | s.inner | 333 | r.tasks_erasestart.write(|w| w.tasks_erasestart().bit(true)); |
| 357 | .tasks_erasestart | ||
| 358 | .write(|w| w.tasks_erasestart().bit(true)); | ||
| 359 | }); | ||
| 360 | 334 | ||
| 361 | self.as_mut().wait_ready().await; | 335 | self.as_mut().wait_ready().await; |
| 362 | 336 | ||
| @@ -383,13 +357,29 @@ impl Flash for Qspi { | |||
| 383 | } | 357 | } |
| 384 | } | 358 | } |
| 385 | 359 | ||
| 386 | impl PeripheralState for State { | 360 | mod sealed { |
| 387 | type Interrupt = interrupt::QSPI; | 361 | use super::*; |
| 388 | 362 | ||
| 389 | fn on_interrupt(&mut self) { | 363 | pub trait Instance { |
| 390 | if self.inner.events_ready.read().bits() != 0 { | 364 | fn regs(&mut self) -> &pac::qspi::RegisterBlock; |
| 391 | self.inner.intenclr.write(|w| w.ready().clear()); | ||
| 392 | self.waker.wake() | ||
| 393 | } | ||
| 394 | } | 365 | } |
| 395 | } | 366 | } |
| 367 | |||
| 368 | pub trait Instance: sealed::Instance + 'static { | ||
| 369 | type Interrupt: Interrupt; | ||
| 370 | } | ||
| 371 | |||
| 372 | macro_rules! make_impl { | ||
| 373 | ($type:ident, $irq:ident) => { | ||
| 374 | impl sealed::Instance for peripherals::$type { | ||
| 375 | fn regs(&mut self) -> &pac::qspi::RegisterBlock { | ||
| 376 | unsafe { &*pac::$type::ptr() } | ||
| 377 | } | ||
| 378 | } | ||
| 379 | impl Instance for peripherals::$type { | ||
| 380 | type Interrupt = interrupt::$irq; | ||
| 381 | } | ||
| 382 | }; | ||
| 383 | } | ||
| 384 | |||
| 385 | make_impl!(QSPI, QSPI); | ||
diff --git a/embassy-traits/src/flash.rs b/embassy-traits/src/flash.rs index 145cc7684..3adaa3a0a 100644 --- a/embassy-traits/src/flash.rs +++ b/embassy-traits/src/flash.rs | |||
| @@ -11,9 +11,17 @@ pub enum Error { | |||
| 11 | } | 11 | } |
| 12 | 12 | ||
| 13 | pub trait Flash { | 13 | pub trait Flash { |
| 14 | type ReadFuture<'a>: Future<Output = Result<(), Error>>; | 14 | type ReadFuture<'a>: Future<Output = Result<(), Error>> |
| 15 | type WriteFuture<'a>: Future<Output = Result<(), Error>>; | 15 | where |
| 16 | type ErasePageFuture<'a>: Future<Output = Result<(), Error>>; | 16 | Self: 'a; |
| 17 | |||
| 18 | type WriteFuture<'a>: Future<Output = Result<(), Error>> | ||
| 19 | where | ||
| 20 | Self: 'a; | ||
| 21 | |||
| 22 | type ErasePageFuture<'a>: Future<Output = Result<(), Error>> | ||
| 23 | where | ||
| 24 | Self: 'a; | ||
| 17 | 25 | ||
| 18 | /// Reads data from the flash device. | 26 | /// Reads data from the flash device. |
| 19 | /// | 27 | /// |
