diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-03-05 21:37:21 +0100 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-03-06 00:17:51 +0100 |
| commit | 96788ac93a1e98ef8d9d5e8d80d5102aef34d45d (patch) | |
| tree | 0c8f5a4bc0364f6abfa5de47bae59ca4978cbf54 /embassy-nrf | |
| parent | c66b28e759dc42c5f802336385a66eb8a82dab9a (diff) | |
nrf/qspi: switch to new interrupt binding.
Diffstat (limited to 'embassy-nrf')
| -rw-r--r-- | embassy-nrf/src/qspi.rs | 65 |
1 files changed, 35 insertions, 30 deletions
diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index d514e0274..7f004b9fc 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #![macro_use] | 3 | #![macro_use] |
| 4 | 4 | ||
| 5 | use core::future::poll_fn; | 5 | use core::future::poll_fn; |
| 6 | use core::marker::PhantomData; | ||
| 6 | use core::ptr; | 7 | use core::ptr; |
| 7 | use core::task::Poll; | 8 | use core::task::Poll; |
| 8 | 9 | ||
| @@ -11,12 +12,12 @@ use embassy_hal_common::{into_ref, PeripheralRef}; | |||
| 11 | use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; | 12 | use embedded_storage::nor_flash::{ErrorType, NorFlash, NorFlashError, NorFlashErrorKind, ReadNorFlash}; |
| 12 | 13 | ||
| 13 | use crate::gpio::{self, Pin as GpioPin}; | 14 | use crate::gpio::{self, Pin as GpioPin}; |
| 14 | use crate::interrupt::{Interrupt, InterruptExt}; | 15 | use crate::interrupt::{self, Interrupt, InterruptExt}; |
| 15 | pub use crate::pac::qspi::ifconfig0::{ | 16 | pub use crate::pac::qspi::ifconfig0::{ |
| 16 | ADDRMODE_A as AddressMode, PPSIZE_A as WritePageSize, READOC_A as ReadOpcode, WRITEOC_A as WriteOpcode, | 17 | ADDRMODE_A as AddressMode, PPSIZE_A as WritePageSize, READOC_A as ReadOpcode, WRITEOC_A as WriteOpcode, |
| 17 | }; | 18 | }; |
| 18 | pub use crate::pac::qspi::ifconfig1::SPIMODE_A as SpiMode; | 19 | pub use crate::pac::qspi::ifconfig1::SPIMODE_A as SpiMode; |
| 19 | use crate::{pac, Peripheral}; | 20 | use crate::Peripheral; |
| 20 | 21 | ||
| 21 | /// Deep power-down config. | 22 | /// Deep power-down config. |
| 22 | pub struct DeepPowerDownConfig { | 23 | pub struct DeepPowerDownConfig { |
| @@ -114,9 +115,26 @@ pub enum Error { | |||
| 114 | // TODO add "not in data memory" error and check for it | 115 | // TODO add "not in data memory" error and check for it |
| 115 | } | 116 | } |
| 116 | 117 | ||
| 118 | /// Interrupt handler. | ||
| 119 | pub struct InterruptHandler<T: Instance> { | ||
| 120 | _phantom: PhantomData<T>, | ||
| 121 | } | ||
| 122 | |||
| 123 | impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> { | ||
| 124 | unsafe fn on_interrupt() { | ||
| 125 | let r = T::regs(); | ||
| 126 | let s = T::state(); | ||
| 127 | |||
| 128 | if r.events_ready.read().bits() != 0 { | ||
| 129 | s.waker.wake(); | ||
| 130 | r.intenclr.write(|w| w.ready().clear()); | ||
| 131 | } | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 117 | /// QSPI flash driver. | 135 | /// QSPI flash driver. |
| 118 | pub struct Qspi<'d, T: Instance> { | 136 | pub struct Qspi<'d, T: Instance> { |
| 119 | irq: PeripheralRef<'d, T::Interrupt>, | 137 | _peri: PeripheralRef<'d, T>, |
| 120 | dpm_enabled: bool, | 138 | dpm_enabled: bool, |
| 121 | capacity: u32, | 139 | capacity: u32, |
| 122 | } | 140 | } |
| @@ -124,8 +142,8 @@ pub struct Qspi<'d, T: Instance> { | |||
| 124 | impl<'d, T: Instance> Qspi<'d, T> { | 142 | impl<'d, T: Instance> Qspi<'d, T> { |
| 125 | /// Create a new QSPI driver. | 143 | /// Create a new QSPI driver. |
| 126 | pub fn new( | 144 | pub fn new( |
| 127 | _qspi: impl Peripheral<P = T> + 'd, | 145 | qspi: impl Peripheral<P = T> + 'd, |
| 128 | irq: impl Peripheral<P = T::Interrupt> + 'd, | 146 | _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 129 | sck: impl Peripheral<P = impl GpioPin> + 'd, | 147 | sck: impl Peripheral<P = impl GpioPin> + 'd, |
| 130 | csn: impl Peripheral<P = impl GpioPin> + 'd, | 148 | csn: impl Peripheral<P = impl GpioPin> + 'd, |
| 131 | io0: impl Peripheral<P = impl GpioPin> + 'd, | 149 | io0: impl Peripheral<P = impl GpioPin> + 'd, |
| @@ -134,7 +152,7 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 134 | io3: impl Peripheral<P = impl GpioPin> + 'd, | 152 | io3: impl Peripheral<P = impl GpioPin> + 'd, |
| 135 | config: Config, | 153 | config: Config, |
| 136 | ) -> Self { | 154 | ) -> Self { |
| 137 | into_ref!(irq, sck, csn, io0, io1, io2, io3); | 155 | into_ref!(qspi, sck, csn, io0, io1, io2, io3); |
| 138 | 156 | ||
| 139 | let r = T::regs(); | 157 | let r = T::regs(); |
| 140 | 158 | ||
| @@ -189,16 +207,15 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 189 | w | 207 | w |
| 190 | }); | 208 | }); |
| 191 | 209 | ||
| 192 | irq.set_handler(Self::on_interrupt); | 210 | unsafe { T::Interrupt::steal() }.unpend(); |
| 193 | irq.unpend(); | 211 | unsafe { T::Interrupt::steal() }.enable(); |
| 194 | irq.enable(); | ||
| 195 | 212 | ||
| 196 | // Enable it | 213 | // Enable it |
| 197 | r.enable.write(|w| w.enable().enabled()); | 214 | r.enable.write(|w| w.enable().enabled()); |
| 198 | 215 | ||
| 199 | let res = Self { | 216 | let res = Self { |
| 217 | _peri: qspi, | ||
| 200 | dpm_enabled: config.deep_power_down.is_some(), | 218 | dpm_enabled: config.deep_power_down.is_some(), |
| 201 | irq, | ||
| 202 | capacity: config.capacity, | 219 | capacity: config.capacity, |
| 203 | }; | 220 | }; |
| 204 | 221 | ||
| @@ -212,16 +229,6 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 212 | res | 229 | res |
| 213 | } | 230 | } |
| 214 | 231 | ||
| 215 | fn on_interrupt(_: *mut ()) { | ||
| 216 | let r = T::regs(); | ||
| 217 | let s = T::state(); | ||
| 218 | |||
| 219 | if r.events_ready.read().bits() != 0 { | ||
| 220 | s.ready_waker.wake(); | ||
| 221 | r.intenclr.write(|w| w.ready().clear()); | ||
| 222 | } | ||
| 223 | } | ||
| 224 | |||
| 225 | /// Do a custom QSPI instruction. | 232 | /// Do a custom QSPI instruction. |
| 226 | pub async fn custom_instruction(&mut self, opcode: u8, req: &[u8], resp: &mut [u8]) -> Result<(), Error> { | 233 | pub async fn custom_instruction(&mut self, opcode: u8, req: &[u8], resp: &mut [u8]) -> Result<(), Error> { |
| 227 | let ondrop = OnDrop::new(Self::blocking_wait_ready); | 234 | let ondrop = OnDrop::new(Self::blocking_wait_ready); |
| @@ -310,7 +317,7 @@ impl<'d, T: Instance> Qspi<'d, T> { | |||
| 310 | poll_fn(move |cx| { | 317 | poll_fn(move |cx| { |
| 311 | let r = T::regs(); | 318 | let r = T::regs(); |
| 312 | let s = T::state(); | 319 | let s = T::state(); |
| 313 | s.ready_waker.register(cx.waker()); | 320 | s.waker.register(cx.waker()); |
| 314 | if r.events_ready.read().bits() != 0 { | 321 | if r.events_ready.read().bits() != 0 { |
| 315 | return Poll::Ready(()); | 322 | return Poll::Ready(()); |
| 316 | } | 323 | } |
| @@ -525,8 +532,6 @@ impl<'d, T: Instance> Drop for Qspi<'d, T> { | |||
| 525 | 532 | ||
| 526 | r.enable.write(|w| w.enable().disabled()); | 533 | r.enable.write(|w| w.enable().disabled()); |
| 527 | 534 | ||
| 528 | self.irq.disable(); | ||
| 529 | |||
| 530 | // Note: we do NOT deconfigure CSN here. If DPM is in use and we disconnect CSN, | 535 | // Note: we do NOT deconfigure CSN here. If DPM is in use and we disconnect CSN, |
| 531 | // leaving it floating, the flash chip might read it as zero which would cause it to | 536 | // leaving it floating, the flash chip might read it as zero which would cause it to |
| 532 | // spuriously exit DPM. | 537 | // spuriously exit DPM. |
| @@ -624,27 +629,27 @@ mod _eh1 { | |||
| 624 | pub(crate) mod sealed { | 629 | pub(crate) mod sealed { |
| 625 | use embassy_sync::waitqueue::AtomicWaker; | 630 | use embassy_sync::waitqueue::AtomicWaker; |
| 626 | 631 | ||
| 627 | use super::*; | 632 | /// Peripheral static state |
| 628 | |||
| 629 | pub struct State { | 633 | pub struct State { |
| 630 | pub ready_waker: AtomicWaker, | 634 | pub waker: AtomicWaker, |
| 631 | } | 635 | } |
| 636 | |||
| 632 | impl State { | 637 | impl State { |
| 633 | pub const fn new() -> Self { | 638 | pub const fn new() -> Self { |
| 634 | Self { | 639 | Self { |
| 635 | ready_waker: AtomicWaker::new(), | 640 | waker: AtomicWaker::new(), |
| 636 | } | 641 | } |
| 637 | } | 642 | } |
| 638 | } | 643 | } |
| 639 | 644 | ||
| 640 | pub trait Instance { | 645 | pub trait Instance { |
| 641 | fn regs() -> &'static pac::qspi::RegisterBlock; | 646 | fn regs() -> &'static crate::pac::qspi::RegisterBlock; |
| 642 | fn state() -> &'static State; | 647 | fn state() -> &'static State; |
| 643 | } | 648 | } |
| 644 | } | 649 | } |
| 645 | 650 | ||
| 646 | /// QSPI peripheral instance. | 651 | /// QSPI peripheral instance. |
| 647 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static { | 652 | pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static + Send { |
| 648 | /// Interrupt for this peripheral. | 653 | /// Interrupt for this peripheral. |
| 649 | type Interrupt: Interrupt; | 654 | type Interrupt: Interrupt; |
| 650 | } | 655 | } |
| @@ -652,7 +657,7 @@ pub trait Instance: Peripheral<P = Self> + sealed::Instance + 'static { | |||
| 652 | macro_rules! impl_qspi { | 657 | macro_rules! impl_qspi { |
| 653 | ($type:ident, $pac_type:ident, $irq:ident) => { | 658 | ($type:ident, $pac_type:ident, $irq:ident) => { |
| 654 | impl crate::qspi::sealed::Instance for peripherals::$type { | 659 | impl crate::qspi::sealed::Instance for peripherals::$type { |
| 655 | fn regs() -> &'static pac::qspi::RegisterBlock { | 660 | fn regs() -> &'static crate::pac::qspi::RegisterBlock { |
| 656 | unsafe { &*pac::$pac_type::ptr() } | 661 | unsafe { &*pac::$pac_type::ptr() } |
| 657 | } | 662 | } |
| 658 | fn state() -> &'static crate::qspi::sealed::State { | 663 | fn state() -> &'static crate::qspi::sealed::State { |
