diff options
| -rw-r--r-- | embassy-nrf/src/spim.rs | 59 | ||||
| -rw-r--r-- | examples/nrf52840/src/bin/lora_p2p_report.rs | 9 | ||||
| -rw-r--r-- | examples/nrf52840/src/bin/lora_p2p_sense.rs | 9 | ||||
| -rw-r--r-- | examples/nrf52840/src/bin/spim.rs | 9 |
4 files changed, 50 insertions, 36 deletions
diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 17e435787..89cbdfee9 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.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::sync::atomic::{compiler_fence, Ordering}; | 7 | use core::sync::atomic::{compiler_fence, Ordering}; |
| 7 | use core::task::Poll; | 8 | use core::task::Poll; |
| 8 | 9 | ||
| @@ -14,7 +15,7 @@ pub use pac::spim0::frequency::FREQUENCY_A as Frequency; | |||
| 14 | use crate::chip::FORCE_COPY_BUFFER_SIZE; | 15 | use crate::chip::FORCE_COPY_BUFFER_SIZE; |
| 15 | use crate::gpio::sealed::Pin as _; | 16 | use crate::gpio::sealed::Pin as _; |
| 16 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; | 17 | use crate::gpio::{self, AnyPin, Pin as GpioPin, PselBits}; |
| 17 | use crate::interrupt::{Interrupt, InterruptExt}; | 18 | use crate::interrupt::{self, Interrupt, InterruptExt}; |
| 18 | use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; | 19 | use crate::util::{slice_in_ram_or, slice_ptr_parts, slice_ptr_parts_mut}; |
| 19 | use crate::{pac, Peripheral}; | 20 | use crate::{pac, Peripheral}; |
| 20 | 21 | ||
| @@ -31,11 +32,6 @@ pub enum Error { | |||
| 31 | BufferNotInRAM, | 32 | BufferNotInRAM, |
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | /// SPIM driver. | ||
| 35 | pub struct Spim<'d, T: Instance> { | ||
| 36 | _p: PeripheralRef<'d, T>, | ||
| 37 | } | ||
| 38 | |||
| 39 | /// SPIM configuration. | 35 | /// SPIM configuration. |
| 40 | #[non_exhaustive] | 36 | #[non_exhaustive] |
| 41 | pub struct Config { | 37 | pub struct Config { |
| @@ -62,11 +58,33 @@ impl Default for Config { | |||
| 62 | } | 58 | } |
| 63 | } | 59 | } |
| 64 | 60 | ||
| 61 | /// Interrupt handler. | ||
| 62 | pub struct InterruptHandler<T: Instance> { | ||
| 63 | _phantom: PhantomData<T>, | ||
| 64 | } | ||
| 65 | |||
| 66 | impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> { | ||
| 67 | unsafe fn on_interrupt() { | ||
| 68 | let r = T::regs(); | ||
| 69 | let s = T::state(); | ||
| 70 | |||
| 71 | if r.events_end.read().bits() != 0 { | ||
| 72 | s.end_waker.wake(); | ||
| 73 | r.intenclr.write(|w| w.end().clear()); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | /// SPIM driver. | ||
| 79 | pub struct Spim<'d, T: Instance> { | ||
| 80 | _p: PeripheralRef<'d, T>, | ||
| 81 | } | ||
| 82 | |||
| 65 | impl<'d, T: Instance> Spim<'d, T> { | 83 | impl<'d, T: Instance> Spim<'d, T> { |
| 66 | /// Create a new SPIM driver. | 84 | /// Create a new SPIM driver. |
| 67 | pub fn new( | 85 | pub fn new( |
| 68 | spim: impl Peripheral<P = T> + 'd, | 86 | spim: impl Peripheral<P = T> + 'd, |
| 69 | irq: impl Peripheral<P = T::Interrupt> + 'd, | 87 | _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 70 | sck: impl Peripheral<P = impl GpioPin> + 'd, | 88 | sck: impl Peripheral<P = impl GpioPin> + 'd, |
| 71 | miso: impl Peripheral<P = impl GpioPin> + 'd, | 89 | miso: impl Peripheral<P = impl GpioPin> + 'd, |
| 72 | mosi: impl Peripheral<P = impl GpioPin> + 'd, | 90 | mosi: impl Peripheral<P = impl GpioPin> + 'd, |
| @@ -75,7 +93,6 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 75 | into_ref!(sck, miso, mosi); | 93 | into_ref!(sck, miso, mosi); |
| 76 | Self::new_inner( | 94 | Self::new_inner( |
| 77 | spim, | 95 | spim, |
| 78 | irq, | ||
| 79 | sck.map_into(), | 96 | sck.map_into(), |
| 80 | Some(miso.map_into()), | 97 | Some(miso.map_into()), |
| 81 | Some(mosi.map_into()), | 98 | Some(mosi.map_into()), |
| @@ -86,36 +103,35 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 86 | /// Create a new SPIM driver, capable of TX only (MOSI only). | 103 | /// Create a new SPIM driver, capable of TX only (MOSI only). |
| 87 | pub fn new_txonly( | 104 | pub fn new_txonly( |
| 88 | spim: impl Peripheral<P = T> + 'd, | 105 | spim: impl Peripheral<P = T> + 'd, |
| 89 | irq: impl Peripheral<P = T::Interrupt> + 'd, | 106 | _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 90 | sck: impl Peripheral<P = impl GpioPin> + 'd, | 107 | sck: impl Peripheral<P = impl GpioPin> + 'd, |
| 91 | mosi: impl Peripheral<P = impl GpioPin> + 'd, | 108 | mosi: impl Peripheral<P = impl GpioPin> + 'd, |
| 92 | config: Config, | 109 | config: Config, |
| 93 | ) -> Self { | 110 | ) -> Self { |
| 94 | into_ref!(sck, mosi); | 111 | into_ref!(sck, mosi); |
| 95 | Self::new_inner(spim, irq, sck.map_into(), None, Some(mosi.map_into()), config) | 112 | Self::new_inner(spim, sck.map_into(), None, Some(mosi.map_into()), config) |
| 96 | } | 113 | } |
| 97 | 114 | ||
| 98 | /// Create a new SPIM driver, capable of RX only (MISO only). | 115 | /// Create a new SPIM driver, capable of RX only (MISO only). |
| 99 | pub fn new_rxonly( | 116 | pub fn new_rxonly( |
| 100 | spim: impl Peripheral<P = T> + 'd, | 117 | spim: impl Peripheral<P = T> + 'd, |
| 101 | irq: impl Peripheral<P = T::Interrupt> + 'd, | 118 | _irq: impl interrupt::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 102 | sck: impl Peripheral<P = impl GpioPin> + 'd, | 119 | sck: impl Peripheral<P = impl GpioPin> + 'd, |
| 103 | miso: impl Peripheral<P = impl GpioPin> + 'd, | 120 | miso: impl Peripheral<P = impl GpioPin> + 'd, |
| 104 | config: Config, | 121 | config: Config, |
| 105 | ) -> Self { | 122 | ) -> Self { |
| 106 | into_ref!(sck, miso); | 123 | into_ref!(sck, miso); |
| 107 | Self::new_inner(spim, irq, sck.map_into(), Some(miso.map_into()), None, config) | 124 | Self::new_inner(spim, sck.map_into(), Some(miso.map_into()), None, config) |
| 108 | } | 125 | } |
| 109 | 126 | ||
| 110 | fn new_inner( | 127 | fn new_inner( |
| 111 | spim: impl Peripheral<P = T> + 'd, | 128 | spim: impl Peripheral<P = T> + 'd, |
| 112 | irq: impl Peripheral<P = T::Interrupt> + 'd, | ||
| 113 | sck: PeripheralRef<'d, AnyPin>, | 129 | sck: PeripheralRef<'d, AnyPin>, |
| 114 | miso: Option<PeripheralRef<'d, AnyPin>>, | 130 | miso: Option<PeripheralRef<'d, AnyPin>>, |
| 115 | mosi: Option<PeripheralRef<'d, AnyPin>>, | 131 | mosi: Option<PeripheralRef<'d, AnyPin>>, |
| 116 | config: Config, | 132 | config: Config, |
| 117 | ) -> Self { | 133 | ) -> Self { |
| 118 | into_ref!(spim, irq); | 134 | into_ref!(spim); |
| 119 | 135 | ||
| 120 | let r = T::regs(); | 136 | let r = T::regs(); |
| 121 | 137 | ||
| @@ -191,23 +207,12 @@ impl<'d, T: Instance> Spim<'d, T> { | |||
| 191 | // Disable all events interrupts | 207 | // Disable all events interrupts |
| 192 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); | 208 | r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); |
| 193 | 209 | ||
| 194 | irq.set_handler(Self::on_interrupt); | 210 | unsafe { T::Interrupt::steal() }.unpend(); |
| 195 | irq.unpend(); | 211 | unsafe { T::Interrupt::steal() }.enable(); |
| 196 | irq.enable(); | ||
| 197 | 212 | ||
| 198 | Self { _p: spim } | 213 | Self { _p: spim } |
| 199 | } | 214 | } |
| 200 | 215 | ||
| 201 | fn on_interrupt(_: *mut ()) { | ||
| 202 | let r = T::regs(); | ||
| 203 | let s = T::state(); | ||
| 204 | |||
| 205 | if r.events_end.read().bits() != 0 { | ||
| 206 | s.end_waker.wake(); | ||
| 207 | r.intenclr.write(|w| w.end().clear()); | ||
| 208 | } | ||
| 209 | } | ||
| 210 | |||
| 211 | fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { | 216 | fn prepare(&mut self, rx: *mut [u8], tx: *const [u8]) -> Result<(), Error> { |
| 212 | slice_in_ram_or(tx, Error::BufferNotInRAM)?; | 217 | slice_in_ram_or(tx, Error::BufferNotInRAM)?; |
| 213 | // NOTE: RAM slice check for rx is not necessary, as a mutable | 218 | // NOTE: RAM slice check for rx is not necessary, as a mutable |
diff --git a/examples/nrf52840/src/bin/lora_p2p_report.rs b/examples/nrf52840/src/bin/lora_p2p_report.rs index d512b83f6..e24f0db03 100644 --- a/examples/nrf52840/src/bin/lora_p2p_report.rs +++ b/examples/nrf52840/src/bin/lora_p2p_report.rs | |||
| @@ -11,11 +11,15 @@ use defmt::*; | |||
| 11 | use embassy_executor::Spawner; | 11 | use embassy_executor::Spawner; |
| 12 | use embassy_lora::sx126x::*; | 12 | use embassy_lora::sx126x::*; |
| 13 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; | 13 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; |
| 14 | use embassy_nrf::{interrupt, spim}; | 14 | use embassy_nrf::{bind_interrupts, peripherals, spim}; |
| 15 | use embassy_time::{Duration, Timer}; | 15 | use embassy_time::{Duration, Timer}; |
| 16 | use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor}; | 16 | use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor}; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 18 | ||
| 19 | bind_interrupts!(struct Irqs { | ||
| 20 | SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>; | ||
| 21 | }); | ||
| 22 | |||
| 19 | #[embassy_executor::main] | 23 | #[embassy_executor::main] |
| 20 | async fn main(_spawner: Spawner) { | 24 | async fn main(_spawner: Spawner) { |
| 21 | let p = embassy_nrf::init(Default::default()); | 25 | let p = embassy_nrf::init(Default::default()); |
| @@ -23,8 +27,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | spi_config.frequency = spim::Frequency::M16; | 27 | spi_config.frequency = spim::Frequency::M16; |
| 24 | 28 | ||
| 25 | let mut radio = { | 29 | let mut radio = { |
| 26 | let irq = interrupt::take!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); | 30 | let spim = spim::Spim::new(p.TWISPI1, Irqs, p.P1_11, p.P1_13, p.P1_12, spi_config); |
| 27 | let spim = spim::Spim::new(p.TWISPI1, irq, p.P1_11, p.P1_13, p.P1_12, spi_config); | ||
| 28 | 31 | ||
| 29 | let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard); | 32 | let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard); |
| 30 | let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard); | 33 | let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard); |
diff --git a/examples/nrf52840/src/bin/lora_p2p_sense.rs b/examples/nrf52840/src/bin/lora_p2p_sense.rs index b9768874b..b6f41ffcc 100644 --- a/examples/nrf52840/src/bin/lora_p2p_sense.rs +++ b/examples/nrf52840/src/bin/lora_p2p_sense.rs | |||
| @@ -12,13 +12,17 @@ use defmt::*; | |||
| 12 | use embassy_executor::Spawner; | 12 | use embassy_executor::Spawner; |
| 13 | use embassy_lora::sx126x::*; | 13 | use embassy_lora::sx126x::*; |
| 14 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; | 14 | use embassy_nrf::gpio::{Input, Level, Output, OutputDrive, Pin as _, Pull}; |
| 15 | use embassy_nrf::{interrupt, spim}; | 15 | use embassy_nrf::{bind_interrupts, peripherals, spim}; |
| 16 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; | 16 | use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; |
| 17 | use embassy_sync::pubsub::{PubSubChannel, Publisher}; | 17 | use embassy_sync::pubsub::{PubSubChannel, Publisher}; |
| 18 | use embassy_time::{Duration, Timer}; | 18 | use embassy_time::{Duration, Timer}; |
| 19 | use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor, TxConfig}; | 19 | use lorawan_device::async_device::radio::{Bandwidth, CodingRate, PhyRxTx, RfConfig, SpreadingFactor, TxConfig}; |
| 20 | use {defmt_rtt as _, panic_probe as _, panic_probe as _}; | 20 | use {defmt_rtt as _, panic_probe as _, panic_probe as _}; |
| 21 | 21 | ||
| 22 | bind_interrupts!(struct Irqs { | ||
| 23 | SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1 => spim::InterruptHandler<peripherals::TWISPI1>; | ||
| 24 | }); | ||
| 25 | |||
| 22 | // Message bus: queue of 2, 1 subscriber (Lora P2P), 2 publishers (temperature, motion detection) | 26 | // Message bus: queue of 2, 1 subscriber (Lora P2P), 2 publishers (temperature, motion detection) |
| 23 | static MESSAGE_BUS: PubSubChannel<CriticalSectionRawMutex, Message, 2, 1, 2> = PubSubChannel::new(); | 27 | static MESSAGE_BUS: PubSubChannel<CriticalSectionRawMutex, Message, 2, 1, 2> = PubSubChannel::new(); |
| 24 | 28 | ||
| @@ -58,8 +62,7 @@ async fn main(spawner: Spawner) { | |||
| 58 | spi_config.frequency = spim::Frequency::M16; | 62 | spi_config.frequency = spim::Frequency::M16; |
| 59 | 63 | ||
| 60 | let mut radio = { | 64 | let mut radio = { |
| 61 | let irq = interrupt::take!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); | 65 | let spim = spim::Spim::new(p.TWISPI1, Irqs, p.P1_11, p.P1_13, p.P1_12, spi_config); |
| 62 | let spim = spim::Spim::new(p.TWISPI1, irq, p.P1_11, p.P1_13, p.P1_12, spi_config); | ||
| 63 | 66 | ||
| 64 | let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard); | 67 | let cs = Output::new(p.P1_10.degrade(), Level::High, OutputDrive::Standard); |
| 65 | let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard); | 68 | let reset = Output::new(p.P1_06.degrade(), Level::High, OutputDrive::Standard); |
diff --git a/examples/nrf52840/src/bin/spim.rs b/examples/nrf52840/src/bin/spim.rs index 132e01660..9d1843a8f 100644 --- a/examples/nrf52840/src/bin/spim.rs +++ b/examples/nrf52840/src/bin/spim.rs | |||
| @@ -5,9 +5,13 @@ | |||
| 5 | use defmt::{info, unwrap}; | 5 | use defmt::{info, unwrap}; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; | 7 | use embassy_nrf::gpio::{Level, Output, OutputDrive}; |
| 8 | use embassy_nrf::{interrupt, spim}; | 8 | use embassy_nrf::{bind_interrupts, peripherals, spim}; |
| 9 | use {defmt_rtt as _, panic_probe as _}; | 9 | use {defmt_rtt as _, panic_probe as _}; |
| 10 | 10 | ||
| 11 | bind_interrupts!(struct Irqs { | ||
| 12 | SPIM3 => spim::InterruptHandler<peripherals::SPI3>; | ||
| 13 | }); | ||
| 14 | |||
| 11 | #[embassy_executor::main] | 15 | #[embassy_executor::main] |
| 12 | async fn main(_spawner: Spawner) { | 16 | async fn main(_spawner: Spawner) { |
| 13 | let p = embassy_nrf::init(Default::default()); | 17 | let p = embassy_nrf::init(Default::default()); |
| @@ -16,8 +20,7 @@ async fn main(_spawner: Spawner) { | |||
| 16 | let mut config = spim::Config::default(); | 20 | let mut config = spim::Config::default(); |
| 17 | config.frequency = spim::Frequency::M16; | 21 | config.frequency = spim::Frequency::M16; |
| 18 | 22 | ||
| 19 | let irq = interrupt::take!(SPIM3); | 23 | let mut spim = spim::Spim::new(p.SPI3, Irqs, p.P0_29, p.P0_28, p.P0_30, config); |
| 20 | let mut spim = spim::Spim::new(p.SPI3, irq, p.P0_29, p.P0_28, p.P0_30, config); | ||
| 21 | 24 | ||
| 22 | let mut ncs = Output::new(p.P0_31, Level::High, OutputDrive::Standard); | 25 | let mut ncs = Output::new(p.P0_31, Level::High, OutputDrive::Standard); |
| 23 | 26 | ||
