diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-07-07 14:31:09 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-07-07 14:31:09 +0000 |
| commit | 7d68ca1f3b126ed0337eb32991858ad0c6ccc375 (patch) | |
| tree | cf45eb607ae5aaee38c1d221bb2bd83ac6d5e7ef | |
| parent | e196387e695da96b44609079a84ede77ef9ba7af (diff) | |
| parent | 4b63829110b8ef314d22d78c160f54e6ae98634c (diff) | |
Merge pull request #1627 from pennae/rp-pio-irq
rp/pio: use bind_interrupts for irqs
| -rw-r--r-- | embassy-rp/src/lib.rs | 1 | ||||
| -rw-r--r-- | embassy-rp/src/pio.rs | 78 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_async.rs | 9 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_dma.rs | 11 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_hd44780.rs | 15 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_ws2812.rs | 13 | ||||
| -rw-r--r-- | examples/rp/src/bin/wifi_ap_tcp_server.rs | 9 | ||||
| -rw-r--r-- | examples/rp/src/bin/wifi_blinky.rs | 9 | ||||
| -rw-r--r-- | examples/rp/src/bin/wifi_scan.rs | 9 | ||||
| -rw-r--r-- | examples/rp/src/bin/wifi_tcp_server.rs | 9 | ||||
| -rw-r--r-- | tests/rp/Cargo.toml | 2 | ||||
| -rw-r--r-- | tests/rp/src/bin/cyw43-perf.rs | 10 | ||||
| -rw-r--r-- | tests/rp/src/bin/pio_irq.rs | 55 |
13 files changed, 160 insertions, 70 deletions
diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 4fd3cb46a..4f205a16e 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs | |||
| @@ -252,7 +252,6 @@ pub fn init(config: config::Config) -> Peripherals { | |||
| 252 | #[cfg(feature = "time-driver")] | 252 | #[cfg(feature = "time-driver")] |
| 253 | timer::init(); | 253 | timer::init(); |
| 254 | dma::init(); | 254 | dma::init(); |
| 255 | pio::init(); | ||
| 256 | gpio::init(); | 255 | gpio::init(); |
| 257 | } | 256 | } |
| 258 | 257 | ||
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index 30648e8ea..72a2f44ed 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs | |||
| @@ -16,12 +16,12 @@ use pio::{SideSet, Wrap}; | |||
| 16 | use crate::dma::{Channel, Transfer, Word}; | 16 | use crate::dma::{Channel, Transfer, Word}; |
| 17 | use crate::gpio::sealed::Pin as SealedPin; | 17 | use crate::gpio::sealed::Pin as SealedPin; |
| 18 | use crate::gpio::{self, AnyPin, Drive, Level, Pull, SlewRate}; | 18 | use crate::gpio::{self, AnyPin, Drive, Level, Pull, SlewRate}; |
| 19 | use crate::interrupt::InterruptExt; | 19 | use crate::interrupt::typelevel::{Binding, Handler, Interrupt}; |
| 20 | use crate::pac::dma::vals::TreqSel; | 20 | use crate::pac::dma::vals::TreqSel; |
| 21 | use crate::relocate::RelocatedProgram; | 21 | use crate::relocate::RelocatedProgram; |
| 22 | use crate::{interrupt, pac, peripherals, pio_instr_util, RegExt}; | 22 | use crate::{pac, peripherals, pio_instr_util, RegExt}; |
| 23 | 23 | ||
| 24 | struct Wakers([AtomicWaker; 12]); | 24 | pub struct Wakers([AtomicWaker; 12]); |
| 25 | 25 | ||
| 26 | impl Wakers { | 26 | impl Wakers { |
| 27 | #[inline(always)] | 27 | #[inline(always)] |
| @@ -38,10 +38,6 @@ impl Wakers { | |||
| 38 | } | 38 | } |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | const NEW_AW: AtomicWaker = AtomicWaker::new(); | ||
| 42 | const PIO_WAKERS_INIT: Wakers = Wakers([NEW_AW; 12]); | ||
| 43 | static WAKERS: [Wakers; 2] = [PIO_WAKERS_INIT; 2]; | ||
| 44 | |||
| 45 | #[derive(Clone, Copy, PartialEq, Eq, Default, Debug)] | 41 | #[derive(Clone, Copy, PartialEq, Eq, Default, Debug)] |
| 46 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 42 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 47 | #[repr(u8)] | 43 | #[repr(u8)] |
| @@ -85,42 +81,20 @@ const RXNEMPTY_MASK: u32 = 1 << 0; | |||
| 85 | const TXNFULL_MASK: u32 = 1 << 4; | 81 | const TXNFULL_MASK: u32 = 1 << 4; |
| 86 | const SMIRQ_MASK: u32 = 1 << 8; | 82 | const SMIRQ_MASK: u32 = 1 << 8; |
| 87 | 83 | ||
| 88 | #[cfg(feature = "rt")] | 84 | pub struct InterruptHandler<PIO: Instance> { |
| 89 | #[interrupt] | 85 | _pio: PhantomData<PIO>, |
| 90 | fn PIO0_IRQ_0() { | ||
| 91 | use crate::pac; | ||
| 92 | let ints = pac::PIO0.irqs(0).ints().read().0; | ||
| 93 | for bit in 0..12 { | ||
| 94 | if ints & (1 << bit) != 0 { | ||
| 95 | WAKERS[0].0[bit].wake(); | ||
| 96 | } | ||
| 97 | } | ||
| 98 | pac::PIO0.irqs(0).inte().write_clear(|m| m.0 = ints); | ||
| 99 | } | 86 | } |
| 100 | 87 | ||
| 101 | #[cfg(feature = "rt")] | 88 | impl<PIO: Instance> Handler<PIO::Interrupt> for InterruptHandler<PIO> { |
| 102 | #[interrupt] | 89 | unsafe fn on_interrupt() { |
| 103 | fn PIO1_IRQ_0() { | 90 | let ints = PIO::PIO.irqs(0).ints().read().0; |
| 104 | use crate::pac; | 91 | for bit in 0..12 { |
| 105 | let ints = pac::PIO1.irqs(0).ints().read().0; | 92 | if ints & (1 << bit) != 0 { |
| 106 | for bit in 0..12 { | 93 | PIO::wakers().0[bit].wake(); |
| 107 | if ints & (1 << bit) != 0 { | 94 | } |
| 108 | WAKERS[1].0[bit].wake(); | ||
| 109 | } | 95 | } |
| 96 | PIO::PIO.irqs(0).inte().write_clear(|m| m.0 = ints); | ||
| 110 | } | 97 | } |
| 111 | pac::PIO1.irqs(0).inte().write_clear(|m| m.0 = ints); | ||
| 112 | } | ||
| 113 | |||
| 114 | pub(crate) unsafe fn init() { | ||
| 115 | interrupt::PIO0_IRQ_0.disable(); | ||
| 116 | interrupt::PIO0_IRQ_0.set_priority(interrupt::Priority::P3); | ||
| 117 | pac::PIO0.irqs(0).inte().write(|m| m.0 = 0); | ||
| 118 | interrupt::PIO0_IRQ_0.enable(); | ||
| 119 | |||
| 120 | interrupt::PIO1_IRQ_0.disable(); | ||
| 121 | interrupt::PIO1_IRQ_0.set_priority(interrupt::Priority::P3); | ||
| 122 | pac::PIO1.irqs(0).inte().write(|m| m.0 = 0); | ||
| 123 | interrupt::PIO1_IRQ_0.enable(); | ||
| 124 | } | 98 | } |
| 125 | 99 | ||
| 126 | /// Future that waits for TX-FIFO to become writable | 100 | /// Future that waits for TX-FIFO to become writable |
| @@ -144,7 +118,7 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoOutFuture<'a, 'd, PI | |||
| 144 | if self.get_mut().sm_tx.try_push(value) { | 118 | if self.get_mut().sm_tx.try_push(value) { |
| 145 | Poll::Ready(()) | 119 | Poll::Ready(()) |
| 146 | } else { | 120 | } else { |
| 147 | WAKERS[PIO::PIO_NO as usize].fifo_out()[SM].register(cx.waker()); | 121 | PIO::wakers().fifo_out()[SM].register(cx.waker()); |
| 148 | PIO::PIO.irqs(0).inte().write_set(|m| { | 122 | PIO::PIO.irqs(0).inte().write_set(|m| { |
| 149 | m.0 = TXNFULL_MASK << SM; | 123 | m.0 = TXNFULL_MASK << SM; |
| 150 | }); | 124 | }); |
| @@ -181,7 +155,7 @@ impl<'a, 'd, PIO: Instance, const SM: usize> Future for FifoInFuture<'a, 'd, PIO | |||
| 181 | if let Some(v) = self.sm_rx.try_pull() { | 155 | if let Some(v) = self.sm_rx.try_pull() { |
| 182 | Poll::Ready(v) | 156 | Poll::Ready(v) |
| 183 | } else { | 157 | } else { |
| 184 | WAKERS[PIO::PIO_NO as usize].fifo_in()[SM].register(cx.waker()); | 158 | PIO::wakers().fifo_in()[SM].register(cx.waker()); |
| 185 | PIO::PIO.irqs(0).inte().write_set(|m| { | 159 | PIO::PIO.irqs(0).inte().write_set(|m| { |
| 186 | m.0 = RXNEMPTY_MASK << SM; | 160 | m.0 = RXNEMPTY_MASK << SM; |
| 187 | }); | 161 | }); |
| @@ -217,7 +191,7 @@ impl<'a, 'd, PIO: Instance> Future for IrqFuture<'a, 'd, PIO> { | |||
| 217 | return Poll::Ready(()); | 191 | return Poll::Ready(()); |
| 218 | } | 192 | } |
| 219 | 193 | ||
| 220 | WAKERS[PIO::PIO_NO as usize].irq()[self.irq_no as usize].register(cx.waker()); | 194 | PIO::wakers().irq()[self.irq_no as usize].register(cx.waker()); |
| 221 | PIO::PIO.irqs(0).inte().write_set(|m| { | 195 | PIO::PIO.irqs(0).inte().write_set(|m| { |
| 222 | m.0 = SMIRQ_MASK << self.irq_no; | 196 | m.0 = SMIRQ_MASK << self.irq_no; |
| 223 | }); | 197 | }); |
| @@ -949,9 +923,11 @@ pub struct Pio<'d, PIO: Instance> { | |||
| 949 | } | 923 | } |
| 950 | 924 | ||
| 951 | impl<'d, PIO: Instance> Pio<'d, PIO> { | 925 | impl<'d, PIO: Instance> Pio<'d, PIO> { |
| 952 | pub fn new(_pio: impl Peripheral<P = PIO> + 'd) -> Self { | 926 | pub fn new(_pio: impl Peripheral<P = PIO> + 'd, _irq: impl Binding<PIO::Interrupt, InterruptHandler<PIO>>) -> Self { |
| 953 | PIO::state().users.store(5, Ordering::Release); | 927 | PIO::state().users.store(5, Ordering::Release); |
| 954 | PIO::state().used_pins.store(0, Ordering::Release); | 928 | PIO::state().used_pins.store(0, Ordering::Release); |
| 929 | PIO::Interrupt::unpend(); | ||
| 930 | unsafe { PIO::Interrupt::enable() }; | ||
| 955 | Self { | 931 | Self { |
| 956 | common: Common { | 932 | common: Common { |
| 957 | instructions_used: 0, | 933 | instructions_used: 0, |
| @@ -1017,6 +993,15 @@ mod sealed { | |||
| 1017 | const PIO_NO: u8; | 993 | const PIO_NO: u8; |
| 1018 | const PIO: &'static crate::pac::pio::Pio; | 994 | const PIO: &'static crate::pac::pio::Pio; |
| 1019 | const FUNCSEL: crate::pac::io::vals::Gpio0ctrlFuncsel; | 995 | const FUNCSEL: crate::pac::io::vals::Gpio0ctrlFuncsel; |
| 996 | type Interrupt: crate::interrupt::typelevel::Interrupt; | ||
| 997 | |||
| 998 | #[inline] | ||
| 999 | fn wakers() -> &'static Wakers { | ||
| 1000 | const NEW_AW: AtomicWaker = AtomicWaker::new(); | ||
| 1001 | static WAKERS: Wakers = Wakers([NEW_AW; 12]); | ||
| 1002 | |||
| 1003 | &WAKERS | ||
| 1004 | } | ||
| 1020 | 1005 | ||
| 1021 | #[inline] | 1006 | #[inline] |
| 1022 | fn state() -> &'static State { | 1007 | fn state() -> &'static State { |
| @@ -1033,18 +1018,19 @@ mod sealed { | |||
| 1033 | pub trait Instance: sealed::Instance + Sized + Unpin {} | 1018 | pub trait Instance: sealed::Instance + Sized + Unpin {} |
| 1034 | 1019 | ||
| 1035 | macro_rules! impl_pio { | 1020 | macro_rules! impl_pio { |
| 1036 | ($name:ident, $pio:expr, $pac:ident, $funcsel:ident) => { | 1021 | ($name:ident, $pio:expr, $pac:ident, $funcsel:ident, $irq:ident) => { |
| 1037 | impl sealed::Instance for peripherals::$name { | 1022 | impl sealed::Instance for peripherals::$name { |
| 1038 | const PIO_NO: u8 = $pio; | 1023 | const PIO_NO: u8 = $pio; |
| 1039 | const PIO: &'static pac::pio::Pio = &pac::$pac; | 1024 | const PIO: &'static pac::pio::Pio = &pac::$pac; |
| 1040 | const FUNCSEL: pac::io::vals::Gpio0ctrlFuncsel = pac::io::vals::Gpio0ctrlFuncsel::$funcsel; | 1025 | const FUNCSEL: pac::io::vals::Gpio0ctrlFuncsel = pac::io::vals::Gpio0ctrlFuncsel::$funcsel; |
| 1026 | type Interrupt = crate::interrupt::typelevel::$irq; | ||
| 1041 | } | 1027 | } |
| 1042 | impl Instance for peripherals::$name {} | 1028 | impl Instance for peripherals::$name {} |
| 1043 | }; | 1029 | }; |
| 1044 | } | 1030 | } |
| 1045 | 1031 | ||
| 1046 | impl_pio!(PIO0, 0, PIO0, PIO0_0); | 1032 | impl_pio!(PIO0, 0, PIO0, PIO0_0, PIO0_IRQ_0); |
| 1047 | impl_pio!(PIO1, 1, PIO1, PIO1_0); | 1033 | impl_pio!(PIO1, 1, PIO1, PIO1_0, PIO1_IRQ_0); |
| 1048 | 1034 | ||
| 1049 | pub trait PioPin: sealed::PioPin + gpio::Pin {} | 1035 | pub trait PioPin: sealed::PioPin + gpio::Pin {} |
| 1050 | 1036 | ||
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 79eda1a09..69034c92a 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs | |||
| @@ -3,13 +3,18 @@ | |||
| 3 | #![feature(type_alias_impl_trait)] | 3 | #![feature(type_alias_impl_trait)] |
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_rp::bind_interrupts; | ||
| 6 | use embassy_rp::peripherals::PIO0; | 7 | use embassy_rp::peripherals::PIO0; |
| 7 | use embassy_rp::pio::{Common, Config, Irq, Pio, PioPin, ShiftDirection, StateMachine}; | 8 | use embassy_rp::pio::{Common, Config, InterruptHandler, Irq, Pio, PioPin, ShiftDirection, StateMachine}; |
| 8 | use embassy_rp::relocate::RelocatedProgram; | 9 | use embassy_rp::relocate::RelocatedProgram; |
| 9 | use fixed::traits::ToFixed; | 10 | use fixed::traits::ToFixed; |
| 10 | use fixed_macro::types::U56F8; | 11 | use fixed_macro::types::U56F8; |
| 11 | use {defmt_rtt as _, panic_probe as _}; | 12 | use {defmt_rtt as _, panic_probe as _}; |
| 12 | 13 | ||
| 14 | bind_interrupts!(struct Irqs { | ||
| 15 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 16 | }); | ||
| 17 | |||
| 13 | fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { | 18 | fn setup_pio_task_sm0<'a>(pio: &mut Common<'a, PIO0>, sm: &mut StateMachine<'a, PIO0, 0>, pin: impl PioPin) { |
| 14 | // Setup sm0 | 19 | // Setup sm0 |
| 15 | 20 | ||
| @@ -110,7 +115,7 @@ async fn main(spawner: Spawner) { | |||
| 110 | mut sm1, | 115 | mut sm1, |
| 111 | mut sm2, | 116 | mut sm2, |
| 112 | .. | 117 | .. |
| 113 | } = Pio::new(pio); | 118 | } = Pio::new(pio, Irqs); |
| 114 | 119 | ||
| 115 | setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); | 120 | setup_pio_task_sm0(&mut common, &mut sm0, p.PIN_0); |
| 116 | setup_pio_task_sm1(&mut common, &mut sm1); | 121 | setup_pio_task_sm1(&mut common, &mut sm1); |
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 05c0ebb16..80c963556 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs | |||
| @@ -4,13 +4,18 @@ | |||
| 4 | use defmt::info; | 4 | use defmt::info; |
| 5 | use embassy_executor::Spawner; | 5 | use embassy_executor::Spawner; |
| 6 | use embassy_futures::join::join; | 6 | use embassy_futures::join::join; |
| 7 | use embassy_rp::pio::{Config, Pio, ShiftConfig, ShiftDirection}; | 7 | use embassy_rp::peripherals::PIO0; |
| 8 | use embassy_rp::pio::{Config, InterruptHandler, Pio, ShiftConfig, ShiftDirection}; | ||
| 8 | use embassy_rp::relocate::RelocatedProgram; | 9 | use embassy_rp::relocate::RelocatedProgram; |
| 9 | use embassy_rp::Peripheral; | 10 | use embassy_rp::{bind_interrupts, Peripheral}; |
| 10 | use fixed::traits::ToFixed; | 11 | use fixed::traits::ToFixed; |
| 11 | use fixed_macro::types::U56F8; | 12 | use fixed_macro::types::U56F8; |
| 12 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| 13 | 14 | ||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 17 | }); | ||
| 18 | |||
| 14 | fn swap_nibbles(v: u32) -> u32 { | 19 | fn swap_nibbles(v: u32) -> u32 { |
| 15 | let v = (v & 0x0f0f_0f0f) << 4 | (v & 0xf0f0_f0f0) >> 4; | 20 | let v = (v & 0x0f0f_0f0f) << 4 | (v & 0xf0f0_f0f0) >> 4; |
| 16 | let v = (v & 0x00ff_00ff) << 8 | (v & 0xff00_ff00) >> 8; | 21 | let v = (v & 0x00ff_00ff) << 8 | (v & 0xff00_ff00) >> 8; |
| @@ -25,7 +30,7 @@ async fn main(_spawner: Spawner) { | |||
| 25 | mut common, | 30 | mut common, |
| 26 | sm0: mut sm, | 31 | sm0: mut sm, |
| 27 | .. | 32 | .. |
| 28 | } = Pio::new(pio); | 33 | } = Pio::new(pio, Irqs); |
| 29 | 34 | ||
| 30 | let prg = pio_proc::pio_asm!( | 35 | let prg = pio_proc::pio_asm!( |
| 31 | ".origin 0", | 36 | ".origin 0", |
diff --git a/examples/rp/src/bin/pio_hd44780.rs b/examples/rp/src/bin/pio_hd44780.rs index bfc6c9908..0a4514a66 100644 --- a/examples/rp/src/bin/pio_hd44780.rs +++ b/examples/rp/src/bin/pio_hd44780.rs | |||
| @@ -7,13 +7,19 @@ use core::fmt::Write; | |||
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_rp::dma::{AnyChannel, Channel}; | 8 | use embassy_rp::dma::{AnyChannel, Channel}; |
| 9 | use embassy_rp::peripherals::PIO0; | 9 | use embassy_rp::peripherals::PIO0; |
| 10 | use embassy_rp::pio::{Config, Direction, FifoJoin, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; | 10 | use embassy_rp::pio::{ |
| 11 | Config, Direction, FifoJoin, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, | ||
| 12 | }; | ||
| 11 | use embassy_rp::pwm::{self, Pwm}; | 13 | use embassy_rp::pwm::{self, Pwm}; |
| 12 | use embassy_rp::relocate::RelocatedProgram; | 14 | use embassy_rp::relocate::RelocatedProgram; |
| 13 | use embassy_rp::{into_ref, Peripheral, PeripheralRef}; | 15 | use embassy_rp::{bind_interrupts, into_ref, Peripheral, PeripheralRef}; |
| 14 | use embassy_time::{Duration, Instant, Timer}; | 16 | use embassy_time::{Duration, Instant, Timer}; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 17 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 18 | ||
| 19 | bind_interrupts!(pub struct Irqs { | ||
| 20 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 21 | }); | ||
| 22 | |||
| 17 | #[embassy_executor::main] | 23 | #[embassy_executor::main] |
| 18 | async fn main(_spawner: Spawner) { | 24 | async fn main(_spawner: Spawner) { |
| 19 | // this test assumes a 2x16 HD44780 display attached as follow: | 25 | // this test assumes a 2x16 HD44780 display attached as follow: |
| @@ -37,7 +43,7 @@ async fn main(_spawner: Spawner) { | |||
| 37 | }); | 43 | }); |
| 38 | 44 | ||
| 39 | let mut hd = HD44780::new( | 45 | let mut hd = HD44780::new( |
| 40 | p.PIO0, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6, | 46 | p.PIO0, Irqs, p.DMA_CH3, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, p.PIN_4, p.PIN_5, p.PIN_6, |
| 41 | ) | 47 | ) |
| 42 | .await; | 48 | .await; |
| 43 | 49 | ||
| @@ -72,6 +78,7 @@ pub struct HD44780<'l> { | |||
| 72 | impl<'l> HD44780<'l> { | 78 | impl<'l> HD44780<'l> { |
| 73 | pub async fn new( | 79 | pub async fn new( |
| 74 | pio: impl Peripheral<P = PIO0> + 'l, | 80 | pio: impl Peripheral<P = PIO0> + 'l, |
| 81 | irq: Irqs, | ||
| 75 | dma: impl Peripheral<P = impl Channel> + 'l, | 82 | dma: impl Peripheral<P = impl Channel> + 'l, |
| 76 | rs: impl PioPin, | 83 | rs: impl PioPin, |
| 77 | rw: impl PioPin, | 84 | rw: impl PioPin, |
| @@ -88,7 +95,7 @@ impl<'l> HD44780<'l> { | |||
| 88 | mut irq0, | 95 | mut irq0, |
| 89 | mut sm0, | 96 | mut sm0, |
| 90 | .. | 97 | .. |
| 91 | } = Pio::new(pio); | 98 | } = Pio::new(pio, irq); |
| 92 | 99 | ||
| 93 | // takes command words (<wait:24> <command:4> <0:4>) | 100 | // takes command words (<wait:24> <command:4> <0:4>) |
| 94 | let prg = pio_proc::pio_asm!( | 101 | let prg = pio_proc::pio_asm!( |
diff --git a/examples/rp/src/bin/pio_ws2812.rs b/examples/rp/src/bin/pio_ws2812.rs index 26422421f..4a111e7aa 100644 --- a/examples/rp/src/bin/pio_ws2812.rs +++ b/examples/rp/src/bin/pio_ws2812.rs | |||
| @@ -5,15 +5,22 @@ | |||
| 5 | use defmt::*; | 5 | use defmt::*; |
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_rp::dma::{AnyChannel, Channel}; | 7 | use embassy_rp::dma::{AnyChannel, Channel}; |
| 8 | use embassy_rp::pio::{Common, Config, FifoJoin, Instance, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine}; | 8 | use embassy_rp::peripherals::PIO0; |
| 9 | use embassy_rp::pio::{ | ||
| 10 | Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftConfig, ShiftDirection, StateMachine, | ||
| 11 | }; | ||
| 9 | use embassy_rp::relocate::RelocatedProgram; | 12 | use embassy_rp::relocate::RelocatedProgram; |
| 10 | use embassy_rp::{clocks, into_ref, Peripheral, PeripheralRef}; | 13 | use embassy_rp::{bind_interrupts, clocks, into_ref, Peripheral, PeripheralRef}; |
| 11 | use embassy_time::{Duration, Timer}; | 14 | use embassy_time::{Duration, Timer}; |
| 12 | use fixed::types::U24F8; | 15 | use fixed::types::U24F8; |
| 13 | use fixed_macro::fixed; | 16 | use fixed_macro::fixed; |
| 14 | use smart_leds::RGB8; | 17 | use smart_leds::RGB8; |
| 15 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| 16 | 19 | ||
| 20 | bind_interrupts!(struct Irqs { | ||
| 21 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 22 | }); | ||
| 23 | |||
| 17 | pub struct Ws2812<'d, P: Instance, const S: usize, const N: usize> { | 24 | pub struct Ws2812<'d, P: Instance, const S: usize, const N: usize> { |
| 18 | dma: PeripheralRef<'d, AnyChannel>, | 25 | dma: PeripheralRef<'d, AnyChannel>, |
| 19 | sm: StateMachine<'d, P, S>, | 26 | sm: StateMachine<'d, P, S>, |
| @@ -123,7 +130,7 @@ async fn main(_spawner: Spawner) { | |||
| 123 | info!("Start"); | 130 | info!("Start"); |
| 124 | let p = embassy_rp::init(Default::default()); | 131 | let p = embassy_rp::init(Default::default()); |
| 125 | 132 | ||
| 126 | let Pio { mut common, sm0, .. } = Pio::new(p.PIO0); | 133 | let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs); |
| 127 | 134 | ||
| 128 | // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit | 135 | // This is the number of leds in the string. Helpfully, the sparkfun thing plus and adafruit |
| 129 | // feather boards for the 2040 both have one built in. | 136 | // feather boards for the 2040 both have one built in. |
diff --git a/examples/rp/src/bin/wifi_ap_tcp_server.rs b/examples/rp/src/bin/wifi_ap_tcp_server.rs index 310e84d92..3e41f83be 100644 --- a/examples/rp/src/bin/wifi_ap_tcp_server.rs +++ b/examples/rp/src/bin/wifi_ap_tcp_server.rs | |||
| @@ -11,14 +11,19 @@ use defmt::*; | |||
| 11 | use embassy_executor::Spawner; | 11 | use embassy_executor::Spawner; |
| 12 | use embassy_net::tcp::TcpSocket; | 12 | use embassy_net::tcp::TcpSocket; |
| 13 | use embassy_net::{Config, Stack, StackResources}; | 13 | use embassy_net::{Config, Stack, StackResources}; |
| 14 | use embassy_rp::bind_interrupts; | ||
| 14 | use embassy_rp::gpio::{Level, Output}; | 15 | use embassy_rp::gpio::{Level, Output}; |
| 15 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; | 16 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; |
| 16 | use embassy_rp::pio::Pio; | 17 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 17 | use embassy_time::Duration; | 18 | use embassy_time::Duration; |
| 18 | use embedded_io::asynch::Write; | 19 | use embedded_io::asynch::Write; |
| 19 | use static_cell::make_static; | 20 | use static_cell::make_static; |
| 20 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 21 | 22 | ||
| 23 | bind_interrupts!(struct Irqs { | ||
| 24 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 25 | }); | ||
| 26 | |||
| 22 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| 23 | async fn wifi_task( | 28 | async fn wifi_task( |
| 24 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, | 29 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, |
| @@ -49,7 +54,7 @@ async fn main(spawner: Spawner) { | |||
| 49 | 54 | ||
| 50 | let pwr = Output::new(p.PIN_23, Level::Low); | 55 | let pwr = Output::new(p.PIN_23, Level::Low); |
| 51 | let cs = Output::new(p.PIN_25, Level::High); | 56 | let cs = Output::new(p.PIN_25, Level::High); |
| 52 | let mut pio = Pio::new(p.PIO0); | 57 | let mut pio = Pio::new(p.PIO0, Irqs); |
| 53 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | 58 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); |
| 54 | 59 | ||
| 55 | let state = make_static!(cyw43::State::new()); | 60 | let state = make_static!(cyw43::State::new()); |
diff --git a/examples/rp/src/bin/wifi_blinky.rs b/examples/rp/src/bin/wifi_blinky.rs index bbcb1b5ec..6eb207af6 100644 --- a/examples/rp/src/bin/wifi_blinky.rs +++ b/examples/rp/src/bin/wifi_blinky.rs | |||
| @@ -5,13 +5,18 @@ | |||
| 5 | use cyw43_pio::PioSpi; | 5 | use cyw43_pio::PioSpi; |
| 6 | use defmt::*; | 6 | use defmt::*; |
| 7 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_rp::bind_interrupts; | ||
| 8 | use embassy_rp::gpio::{Level, Output}; | 9 | use embassy_rp::gpio::{Level, Output}; |
| 9 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; | 10 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; |
| 10 | use embassy_rp::pio::Pio; | 11 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 11 | use embassy_time::{Duration, Timer}; | 12 | use embassy_time::{Duration, Timer}; |
| 12 | use static_cell::make_static; | 13 | use static_cell::make_static; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 14 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 15 | ||
| 16 | bind_interrupts!(struct Irqs { | ||
| 17 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 18 | }); | ||
| 19 | |||
| 15 | #[embassy_executor::task] | 20 | #[embassy_executor::task] |
| 16 | async fn wifi_task( | 21 | async fn wifi_task( |
| 17 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, | 22 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, |
| @@ -34,7 +39,7 @@ async fn main(spawner: Spawner) { | |||
| 34 | 39 | ||
| 35 | let pwr = Output::new(p.PIN_23, Level::Low); | 40 | let pwr = Output::new(p.PIN_23, Level::Low); |
| 36 | let cs = Output::new(p.PIN_25, Level::High); | 41 | let cs = Output::new(p.PIN_25, Level::High); |
| 37 | let mut pio = Pio::new(p.PIO0); | 42 | let mut pio = Pio::new(p.PIO0, Irqs); |
| 38 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | 43 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); |
| 39 | 44 | ||
| 40 | let state = make_static!(cyw43::State::new()); | 45 | let state = make_static!(cyw43::State::new()); |
diff --git a/examples/rp/src/bin/wifi_scan.rs b/examples/rp/src/bin/wifi_scan.rs index 391e12282..aef18aa24 100644 --- a/examples/rp/src/bin/wifi_scan.rs +++ b/examples/rp/src/bin/wifi_scan.rs | |||
| @@ -10,12 +10,17 @@ use cyw43_pio::PioSpi; | |||
| 10 | use defmt::*; | 10 | use defmt::*; |
| 11 | use embassy_executor::Spawner; | 11 | use embassy_executor::Spawner; |
| 12 | use embassy_net::Stack; | 12 | use embassy_net::Stack; |
| 13 | use embassy_rp::bind_interrupts; | ||
| 13 | use embassy_rp::gpio::{Level, Output}; | 14 | use embassy_rp::gpio::{Level, Output}; |
| 14 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; | 15 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; |
| 15 | use embassy_rp::pio::Pio; | 16 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 16 | use static_cell::make_static; | 17 | use static_cell::make_static; |
| 17 | use {defmt_rtt as _, panic_probe as _}; | 18 | use {defmt_rtt as _, panic_probe as _}; |
| 18 | 19 | ||
| 20 | bind_interrupts!(struct Irqs { | ||
| 21 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 22 | }); | ||
| 23 | |||
| 19 | #[embassy_executor::task] | 24 | #[embassy_executor::task] |
| 20 | async fn wifi_task( | 25 | async fn wifi_task( |
| 21 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, | 26 | runner: cyw43::Runner<'static, Output<'static, PIN_23>, PioSpi<'static, PIN_25, PIO0, 0, DMA_CH0>>, |
| @@ -46,7 +51,7 @@ async fn main(spawner: Spawner) { | |||
| 46 | 51 | ||
| 47 | let pwr = Output::new(p.PIN_23, Level::Low); | 52 | let pwr = Output::new(p.PIN_23, Level::Low); |
| 48 | let cs = Output::new(p.PIN_25, Level::High); | 53 | let cs = Output::new(p.PIN_25, Level::High); |
| 49 | let mut pio = Pio::new(p.PIO0); | 54 | let mut pio = Pio::new(p.PIO0, Irqs); |
| 50 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | 55 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); |
| 51 | 56 | ||
| 52 | let state = make_static!(cyw43::State::new()); | 57 | let state = make_static!(cyw43::State::new()); |
diff --git a/examples/rp/src/bin/wifi_tcp_server.rs b/examples/rp/src/bin/wifi_tcp_server.rs index 197535f45..4fce74a66 100644 --- a/examples/rp/src/bin/wifi_tcp_server.rs +++ b/examples/rp/src/bin/wifi_tcp_server.rs | |||
| @@ -11,14 +11,19 @@ use defmt::*; | |||
| 11 | use embassy_executor::Spawner; | 11 | use embassy_executor::Spawner; |
| 12 | use embassy_net::tcp::TcpSocket; | 12 | use embassy_net::tcp::TcpSocket; |
| 13 | use embassy_net::{Config, Stack, StackResources}; | 13 | use embassy_net::{Config, Stack, StackResources}; |
| 14 | use embassy_rp::bind_interrupts; | ||
| 14 | use embassy_rp::gpio::{Level, Output}; | 15 | use embassy_rp::gpio::{Level, Output}; |
| 15 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; | 16 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; |
| 16 | use embassy_rp::pio::Pio; | 17 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 17 | use embassy_time::Duration; | 18 | use embassy_time::Duration; |
| 18 | use embedded_io::asynch::Write; | 19 | use embedded_io::asynch::Write; |
| 19 | use static_cell::make_static; | 20 | use static_cell::make_static; |
| 20 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 21 | 22 | ||
| 23 | bind_interrupts!(struct Irqs { | ||
| 24 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 25 | }); | ||
| 26 | |||
| 22 | const WIFI_NETWORK: &str = "EmbassyTest"; | 27 | const WIFI_NETWORK: &str = "EmbassyTest"; |
| 23 | const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; | 28 | const WIFI_PASSWORD: &str = "V8YxhKt5CdIAJFud"; |
| 24 | 29 | ||
| @@ -52,7 +57,7 @@ async fn main(spawner: Spawner) { | |||
| 52 | 57 | ||
| 53 | let pwr = Output::new(p.PIN_23, Level::Low); | 58 | let pwr = Output::new(p.PIN_23, Level::Low); |
| 54 | let cs = Output::new(p.PIN_25, Level::High); | 59 | let cs = Output::new(p.PIN_25, Level::High); |
| 55 | let mut pio = Pio::new(p.PIO0); | 60 | let mut pio = Pio::new(p.PIO0, Irqs); |
| 56 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | 61 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); |
| 57 | 62 | ||
| 58 | let state = make_static!(cyw43::State::new()); | 63 | let state = make_static!(cyw43::State::new()); |
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml index 368d4acf9..f2c902787 100644 --- a/tests/rp/Cargo.toml +++ b/tests/rp/Cargo.toml | |||
| @@ -29,6 +29,8 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa | |||
| 29 | embedded-io = { version = "0.4.0", features = ["async"] } | 29 | embedded-io = { version = "0.4.0", features = ["async"] } |
| 30 | embedded-storage = { version = "0.3" } | 30 | embedded-storage = { version = "0.3" } |
| 31 | static_cell = { version = "1.1", features = ["nightly"]} | 31 | static_cell = { version = "1.1", features = ["nightly"]} |
| 32 | pio = "0.2" | ||
| 33 | pio-proc = "0.2" | ||
| 32 | 34 | ||
| 33 | [profile.dev] | 35 | [profile.dev] |
| 34 | debug = 2 | 36 | debug = 2 |
diff --git a/tests/rp/src/bin/cyw43-perf.rs b/tests/rp/src/bin/cyw43-perf.rs index 1ecaab266..bc127e2e5 100644 --- a/tests/rp/src/bin/cyw43-perf.rs +++ b/tests/rp/src/bin/cyw43-perf.rs | |||
| @@ -12,12 +12,16 @@ use embassy_net::tcp::TcpSocket; | |||
| 12 | use embassy_net::{Config, Ipv4Address, Stack, StackResources}; | 12 | use embassy_net::{Config, Ipv4Address, Stack, StackResources}; |
| 13 | use embassy_rp::gpio::{Level, Output}; | 13 | use embassy_rp::gpio::{Level, Output}; |
| 14 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; | 14 | use embassy_rp::peripherals::{DMA_CH0, PIN_23, PIN_25, PIO0}; |
| 15 | use embassy_rp::pio::Pio; | 15 | use embassy_rp::pio::{InterruptHandler, Pio}; |
| 16 | use embassy_rp::rom_data; | 16 | use embassy_rp::{bind_interrupts, rom_data}; |
| 17 | use embassy_time::{with_timeout, Duration, Timer}; | 17 | use embassy_time::{with_timeout, Duration, Timer}; |
| 18 | use static_cell::make_static; | 18 | use static_cell::make_static; |
| 19 | use {defmt_rtt as _, panic_probe as _}; | 19 | use {defmt_rtt as _, panic_probe as _}; |
| 20 | 20 | ||
| 21 | bind_interrupts!(struct Irqs { | ||
| 22 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 23 | }); | ||
| 24 | |||
| 21 | teleprobe_meta::timeout!(120); | 25 | teleprobe_meta::timeout!(120); |
| 22 | 26 | ||
| 23 | #[embassy_executor::task] | 27 | #[embassy_executor::task] |
| @@ -51,7 +55,7 @@ async fn main(spawner: Spawner) { | |||
| 51 | 55 | ||
| 52 | let pwr = Output::new(p.PIN_23, Level::Low); | 56 | let pwr = Output::new(p.PIN_23, Level::Low); |
| 53 | let cs = Output::new(p.PIN_25, Level::High); | 57 | let cs = Output::new(p.PIN_25, Level::High); |
| 54 | let mut pio = Pio::new(p.PIO0); | 58 | let mut pio = Pio::new(p.PIO0, Irqs); |
| 55 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); | 59 | let spi = PioSpi::new(&mut pio.common, pio.sm0, pio.irq0, cs, p.PIN_24, p.PIN_29, p.DMA_CH0); |
| 56 | 60 | ||
| 57 | let state = make_static!(cyw43::State::new()); | 61 | let state = make_static!(cyw43::State::new()); |
diff --git a/tests/rp/src/bin/pio_irq.rs b/tests/rp/src/bin/pio_irq.rs new file mode 100644 index 000000000..45004424a --- /dev/null +++ b/tests/rp/src/bin/pio_irq.rs | |||
| @@ -0,0 +1,55 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | #[path = "../common.rs"] | ||
| 5 | mod common; | ||
| 6 | |||
| 7 | use defmt::info; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_rp::bind_interrupts; | ||
| 10 | use embassy_rp::peripherals::PIO0; | ||
| 11 | use embassy_rp::pio::{Config, InterruptHandler, Pio}; | ||
| 12 | use embassy_rp::relocate::RelocatedProgram; | ||
| 13 | use {defmt_rtt as _, panic_probe as _}; | ||
| 14 | |||
| 15 | bind_interrupts!(struct Irqs { | ||
| 16 | PIO0_IRQ_0 => InterruptHandler<PIO0>; | ||
| 17 | }); | ||
| 18 | |||
| 19 | #[embassy_executor::main] | ||
| 20 | async fn main(_spawner: Spawner) { | ||
| 21 | let p = embassy_rp::init(Default::default()); | ||
| 22 | let pio = p.PIO0; | ||
| 23 | let Pio { | ||
| 24 | mut common, | ||
| 25 | sm0: mut sm, | ||
| 26 | irq_flags, | ||
| 27 | .. | ||
| 28 | } = Pio::new(pio, Irqs); | ||
| 29 | |||
| 30 | let prg = pio_proc::pio_asm!( | ||
| 31 | "irq set 0", | ||
| 32 | "irq wait 0", | ||
| 33 | "irq set 1", | ||
| 34 | // pause execution here | ||
| 35 | "irq wait 1", | ||
| 36 | ); | ||
| 37 | |||
| 38 | let relocated = RelocatedProgram::new(&prg.program); | ||
| 39 | let mut cfg = Config::default(); | ||
| 40 | cfg.use_program(&common.load_program(&relocated), &[]); | ||
| 41 | sm.set_config(&cfg); | ||
| 42 | sm.set_enable(true); | ||
| 43 | |||
| 44 | // not using the wait futures on purpose because they clear the irq bits, | ||
| 45 | // and we want to see in which order they are set. | ||
| 46 | while !irq_flags.check(0) {} | ||
| 47 | cortex_m::asm::nop(); | ||
| 48 | assert!(!irq_flags.check(1)); | ||
| 49 | irq_flags.clear(0); | ||
| 50 | cortex_m::asm::nop(); | ||
| 51 | assert!(irq_flags.check(1)); | ||
| 52 | |||
| 53 | info!("Test OK"); | ||
| 54 | cortex_m::asm::bkpt(); | ||
| 55 | } | ||
