diff options
| -rw-r--r-- | embassy-rp/src/pio.rs | 104 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_async.rs | 28 | ||||
| -rw-r--r-- | examples/rp/src/bin/pio_dma.rs | 6 | ||||
| -rw-r--r-- | examples/rp/src/bin/ws2812-pio.rs | 4 |
4 files changed, 63 insertions, 79 deletions
diff --git a/embassy-rp/src/pio.rs b/embassy-rp/src/pio.rs index 8492ca31d..7faec10b5 100644 --- a/embassy-rp/src/pio.rs +++ b/embassy-rp/src/pio.rs | |||
| @@ -772,19 +772,6 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin { | |||
| 772 | } | 772 | } |
| 773 | } | 773 | } |
| 774 | 774 | ||
| 775 | fn write_instr<I>(&mut self, start: usize, instrs: I) | ||
| 776 | where | ||
| 777 | I: Iterator<Item = u16>, | ||
| 778 | { | ||
| 779 | write_instr( | ||
| 780 | Self::Pio::PIO, | ||
| 781 | Self::Pio::PIO_NO, | ||
| 782 | start, | ||
| 783 | instrs, | ||
| 784 | MEM_USED_BY_STATEMACHINE | Self::Sm::SM_NO as u32, | ||
| 785 | ); | ||
| 786 | } | ||
| 787 | |||
| 788 | fn wait_push<'a>(&'a mut self, value: u32) -> FifoOutFuture<'a, Self::Pio, Self> { | 775 | fn wait_push<'a>(&'a mut self, value: u32) -> FifoOutFuture<'a, Self::Pio, Self> { |
| 789 | FifoOutFuture::new(self, value) | 776 | FifoOutFuture::new(self, value) |
| 790 | } | 777 | } |
| @@ -880,71 +867,59 @@ pub trait PioStateMachine: sealed::PioStateMachine + Sized + Unpin { | |||
| 880 | } | 867 | } |
| 881 | } | 868 | } |
| 882 | 869 | ||
| 883 | /* | 870 | pub struct PioCommonInstance<PIO: PioInstance> { |
| 884 | This is a bit array containing 4 bits for every word in the PIO instruction memory. | 871 | instructions_used: u32, |
| 885 | */ | 872 | pio: PhantomData<PIO>, |
| 886 | // Bit 3-2 | ||
| 887 | //const MEM_USE_MASK: u32 = 0b1100; | ||
| 888 | const MEM_NOT_USED: u32 = 0b0000; | ||
| 889 | const MEM_USED_BY_STATEMACHINE: u32 = 0b0100; | ||
| 890 | const MEM_USED_BY_COMMON: u32 = 0b1000; | ||
| 891 | |||
| 892 | // Bit 1-0 is the number of the state machine | ||
| 893 | //const MEM_STATE_MASK: u32 = 0b0011; | ||
| 894 | |||
| 895 | // Should use mutex if running on multiple cores | ||
| 896 | static mut INSTR_MEM_STATUS: &'static mut [[u32; 4]; 2] = &mut [[0; 4]; 2]; | ||
| 897 | |||
| 898 | fn instr_mem_get_status(pio_no: u8, addr: u8) -> u32 { | ||
| 899 | ((unsafe { INSTR_MEM_STATUS[pio_no as usize][(addr >> 3) as usize] }) >> ((addr & 0x07) * 4)) & 0xf | ||
| 900 | } | ||
| 901 | |||
| 902 | fn instr_mem_set_status(pio_no: u8, addr: u8, status: u32) { | ||
| 903 | let w = unsafe { &mut INSTR_MEM_STATUS[pio_no as usize][(addr >> 3) as usize] }; | ||
| 904 | let shift = (addr & 0x07) * 4; | ||
| 905 | *w = (*w & !(0xf << shift)) | (status << shift); | ||
| 906 | } | ||
| 907 | |||
| 908 | fn instr_mem_is_free(pio_no: u8, addr: u8) -> bool { | ||
| 909 | instr_mem_get_status(pio_no, addr) == MEM_NOT_USED | ||
| 910 | } | 873 | } |
| 911 | 874 | ||
| 912 | pub struct PioCommonInstance<PIO: PioInstance> { | 875 | pub struct PioInstanceMemory<PIO: PioInstance> { |
| 876 | used_mask: u32, | ||
| 913 | pio: PhantomData<PIO>, | 877 | pio: PhantomData<PIO>, |
| 914 | } | 878 | } |
| 915 | 879 | ||
| 916 | impl<PIO: PioInstance> sealed::PioCommon for PioCommonInstance<PIO> { | 880 | impl<PIO: PioInstance> sealed::PioCommon for PioCommonInstance<PIO> { |
| 917 | type Pio = PIO; | 881 | type Pio = PIO; |
| 918 | } | 882 | } |
| 919 | impl<PIO: PioInstance> PioCommon for PioCommonInstance<PIO> {} | 883 | impl<PIO: PioInstance> PioCommon for PioCommonInstance<PIO> { |
| 920 | 884 | fn write_instr<I>(&mut self, start: usize, instrs: I) -> PioInstanceMemory<Self::Pio> | |
| 921 | fn write_instr<I>(pio: &pac::pio::Pio, pio_no: u8, start: usize, instrs: I, mem_user: u32) | 885 | where |
| 922 | where | 886 | I: Iterator<Item = u16>, |
| 923 | I: Iterator<Item = u16>, | 887 | { |
| 924 | { | 888 | let mut used_mask = 0; |
| 925 | for (i, instr) in instrs.enumerate() { | 889 | for (i, instr) in instrs.enumerate() { |
| 926 | let addr = (i + start) as u8; | 890 | let addr = (i + start) as u8; |
| 927 | assert!( | 891 | let mask = 1 << (addr as usize); |
| 928 | instr_mem_is_free(pio_no, addr), | 892 | assert!( |
| 929 | "Trying to write already used PIO instruction memory at {}", | 893 | self.instructions_used & mask == 0, |
| 930 | addr | 894 | "Trying to write already used PIO instruction memory at {}", |
| 931 | ); | 895 | addr |
| 932 | unsafe { | 896 | ); |
| 933 | pio.instr_mem(addr as usize).write(|w| { | 897 | unsafe { |
| 934 | w.set_instr_mem(instr); | 898 | PIO::PIO.instr_mem(addr as usize).write(|w| { |
| 935 | }); | 899 | w.set_instr_mem(instr); |
| 936 | instr_mem_set_status(pio_no, addr, mem_user); | 900 | }); |
| 901 | } | ||
| 902 | used_mask |= mask; | ||
| 937 | } | 903 | } |
| 904 | self.instructions_used |= used_mask; | ||
| 905 | PioInstanceMemory { | ||
| 906 | used_mask, | ||
| 907 | pio: PhantomData, | ||
| 908 | } | ||
| 909 | } | ||
| 910 | |||
| 911 | fn free_instr(&mut self, instrs: PioInstanceMemory<Self::Pio>) { | ||
| 912 | self.instructions_used &= !instrs.used_mask; | ||
| 938 | } | 913 | } |
| 939 | } | 914 | } |
| 940 | 915 | ||
| 941 | pub trait PioCommon: sealed::PioCommon + Sized { | 916 | pub trait PioCommon: sealed::PioCommon + Sized { |
| 942 | fn write_instr<I>(&mut self, start: usize, instrs: I) | 917 | fn write_instr<I>(&mut self, start: usize, instrs: I) -> PioInstanceMemory<Self::Pio> |
| 943 | where | 918 | where |
| 944 | I: Iterator<Item = u16>, | 919 | I: Iterator<Item = u16>; |
| 945 | { | 920 | |
| 946 | write_instr(Self::Pio::PIO, Self::Pio::PIO_NO, start, instrs, MEM_USED_BY_COMMON); | 921 | // TODO make instruction memory that is currently in use unfreeable |
| 947 | } | 922 | fn free_instr(&mut self, instrs: PioInstanceMemory<Self::Pio>); |
| 948 | 923 | ||
| 949 | fn is_irq_set(&self, irq_no: u8) -> bool { | 924 | fn is_irq_set(&self, irq_no: u8) -> bool { |
| 950 | assert!(irq_no < 8); | 925 | assert!(irq_no < 8); |
| @@ -1027,6 +1002,7 @@ pub trait PioPeripheral: sealed::PioPeripheral + Sized { | |||
| 1027 | ) { | 1002 | ) { |
| 1028 | ( | 1003 | ( |
| 1029 | PioCommonInstance { | 1004 | PioCommonInstance { |
| 1005 | instructions_used: 0, | ||
| 1030 | pio: PhantomData::default(), | 1006 | pio: PhantomData::default(), |
| 1031 | }, | 1007 | }, |
| 1032 | PioStateMachineInstance { | 1008 | PioStateMachineInstance { |
diff --git a/examples/rp/src/bin/pio_async.rs b/examples/rp/src/bin/pio_async.rs index 3cfeec71f..1b075b8fd 100644 --- a/examples/rp/src/bin/pio_async.rs +++ b/examples/rp/src/bin/pio_async.rs | |||
| @@ -28,7 +28,7 @@ fn setup_pio_task_sm0(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachin | |||
| 28 | let out_pin = pio.make_pio_pin(pin); | 28 | let out_pin = pio.make_pio_pin(pin); |
| 29 | let pio_pins = [&out_pin]; | 29 | let pio_pins = [&out_pin]; |
| 30 | sm.set_out_pins(&pio_pins); | 30 | sm.set_out_pins(&pio_pins); |
| 31 | sm.write_instr(relocated.origin() as usize, relocated.code()); | 31 | pio.write_instr(relocated.origin() as usize, relocated.code()); |
| 32 | pio_instr_util::exec_jmp(sm, relocated.origin()); | 32 | pio_instr_util::exec_jmp(sm, relocated.origin()); |
| 33 | sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); | 33 | sm.set_clkdiv((125e6 / 20.0 / 2e2 * 256.0) as u32); |
| 34 | sm.set_set_range(0, 1); | 34 | sm.set_set_range(0, 1); |
| @@ -51,16 +51,15 @@ async fn pio_task_sm0(mut sm: PioStateMachineInstance<Pio0, Sm0>) { | |||
| 51 | } | 51 | } |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | #[embassy_executor::task] | 54 | fn setup_pio_task_sm1(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm1>) { |
| 55 | async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) { | ||
| 56 | // Setupm sm1 | 55 | // Setupm sm1 |
| 57 | 56 | ||
| 58 | // Read 0b10101 repeatedly until ISR is full | 57 | // Read 0b10101 repeatedly until ISR is full |
| 59 | let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); | 58 | let prg = pio_proc::pio_asm!(".origin 8", "set x, 0x15", ".wrap_target", "in x, 5 [31]", ".wrap",); |
| 60 | 59 | ||
| 61 | let relocated = RelocatedProgram::new(&prg.program); | 60 | let relocated = RelocatedProgram::new(&prg.program); |
| 62 | sm.write_instr(relocated.origin() as usize, relocated.code()); | 61 | pio.write_instr(relocated.origin() as usize, relocated.code()); |
| 63 | pio_instr_util::exec_jmp(&mut sm, relocated.origin()); | 62 | pio_instr_util::exec_jmp(sm, relocated.origin()); |
| 64 | sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); | 63 | sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); |
| 65 | sm.set_set_range(0, 0); | 64 | sm.set_set_range(0, 0); |
| 66 | let pio::Wrap { source, target } = relocated.wrap(); | 65 | let pio::Wrap { source, target } = relocated.wrap(); |
| @@ -68,6 +67,10 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) { | |||
| 68 | 67 | ||
| 69 | sm.set_autopush(true); | 68 | sm.set_autopush(true); |
| 70 | sm.set_in_shift_dir(ShiftDirection::Right); | 69 | sm.set_in_shift_dir(ShiftDirection::Right); |
| 70 | } | ||
| 71 | |||
| 72 | #[embassy_executor::task] | ||
| 73 | async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) { | ||
| 71 | sm.set_enable(true); | 74 | sm.set_enable(true); |
| 72 | loop { | 75 | loop { |
| 73 | let rx = sm.wait_pull().await; | 76 | let rx = sm.wait_pull().await; |
| @@ -75,8 +78,7 @@ async fn pio_task_sm1(mut sm: PioStateMachineInstance<Pio0, Sm1>) { | |||
| 75 | } | 78 | } |
| 76 | } | 79 | } |
| 77 | 80 | ||
| 78 | #[embassy_executor::task] | 81 | fn setup_pio_task_sm2(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm2>) { |
| 79 | async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) { | ||
| 80 | // Setup sm2 | 82 | // Setup sm2 |
| 81 | 83 | ||
| 82 | // Repeatedly trigger IRQ 3 | 84 | // Repeatedly trigger IRQ 3 |
| @@ -90,13 +92,17 @@ async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) { | |||
| 90 | ".wrap", | 92 | ".wrap", |
| 91 | ); | 93 | ); |
| 92 | let relocated = RelocatedProgram::new(&prg.program); | 94 | let relocated = RelocatedProgram::new(&prg.program); |
| 93 | sm.write_instr(relocated.origin() as usize, relocated.code()); | 95 | pio.write_instr(relocated.origin() as usize, relocated.code()); |
| 94 | 96 | ||
| 95 | let pio::Wrap { source, target } = relocated.wrap(); | 97 | let pio::Wrap { source, target } = relocated.wrap(); |
| 96 | sm.set_wrap(source, target); | 98 | sm.set_wrap(source, target); |
| 97 | 99 | ||
| 98 | pio_instr_util::exec_jmp(&mut sm, relocated.origin()); | 100 | pio_instr_util::exec_jmp(sm, relocated.origin()); |
| 99 | sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); | 101 | sm.set_clkdiv((125e6 / 2e3 * 256.0) as u32); |
| 102 | } | ||
| 103 | |||
| 104 | #[embassy_executor::task] | ||
| 105 | async fn pio_task_sm2(mut sm: PioStateMachineInstance<Pio0, Sm2>) { | ||
| 100 | sm.set_enable(true); | 106 | sm.set_enable(true); |
| 101 | loop { | 107 | loop { |
| 102 | sm.wait_irq(3).await; | 108 | sm.wait_irq(3).await; |
| @@ -109,9 +115,11 @@ async fn main(spawner: Spawner) { | |||
| 109 | let p = embassy_rp::init(Default::default()); | 115 | let p = embassy_rp::init(Default::default()); |
| 110 | let pio = p.PIO0; | 116 | let pio = p.PIO0; |
| 111 | 117 | ||
| 112 | let (mut pio0, mut sm0, sm1, sm2, ..) = pio.split(); | 118 | let (mut pio0, mut sm0, mut sm1, mut sm2, ..) = pio.split(); |
| 113 | 119 | ||
| 114 | setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade()); | 120 | setup_pio_task_sm0(&mut pio0, &mut sm0, p.PIN_0.degrade()); |
| 121 | setup_pio_task_sm1(&mut pio0, &mut sm1); | ||
| 122 | setup_pio_task_sm2(&mut pio0, &mut sm2); | ||
| 115 | spawner.spawn(pio_task_sm0(sm0)).unwrap(); | 123 | spawner.spawn(pio_task_sm0(sm0)).unwrap(); |
| 116 | spawner.spawn(pio_task_sm1(sm1)).unwrap(); | 124 | spawner.spawn(pio_task_sm1(sm1)).unwrap(); |
| 117 | spawner.spawn(pio_task_sm2(sm2)).unwrap(); | 125 | spawner.spawn(pio_task_sm2(sm2)).unwrap(); |
diff --git a/examples/rp/src/bin/pio_dma.rs b/examples/rp/src/bin/pio_dma.rs index 145e4a656..7d4919f75 100644 --- a/examples/rp/src/bin/pio_dma.rs +++ b/examples/rp/src/bin/pio_dma.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 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::{PioPeripheral, PioStateMachine, ShiftDirection}; | 7 | use embassy_rp::pio::{PioCommon, PioPeripheral, PioStateMachine, ShiftDirection}; |
| 8 | use embassy_rp::relocate::RelocatedProgram; | 8 | use embassy_rp::relocate::RelocatedProgram; |
| 9 | use embassy_rp::{pio_instr_util, Peripheral}; | 9 | use embassy_rp::{pio_instr_util, Peripheral}; |
| 10 | use {defmt_rtt as _, panic_probe as _}; | 10 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -19,7 +19,7 @@ fn swap_nibbles(v: u32) -> u32 { | |||
| 19 | async fn main(_spawner: Spawner) { | 19 | async fn main(_spawner: Spawner) { |
| 20 | let p = embassy_rp::init(Default::default()); | 20 | let p = embassy_rp::init(Default::default()); |
| 21 | let pio = p.PIO0; | 21 | let pio = p.PIO0; |
| 22 | let (_, mut sm, ..) = pio.split(); | 22 | let (mut pio0, mut sm, ..) = pio.split(); |
| 23 | 23 | ||
| 24 | let prg = pio_proc::pio_asm!( | 24 | let prg = pio_proc::pio_asm!( |
| 25 | ".origin 0", | 25 | ".origin 0", |
| @@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) { | |||
| 34 | ); | 34 | ); |
| 35 | 35 | ||
| 36 | let relocated = RelocatedProgram::new(&prg.program); | 36 | let relocated = RelocatedProgram::new(&prg.program); |
| 37 | sm.write_instr(relocated.origin() as usize, relocated.code()); | 37 | pio0.write_instr(relocated.origin() as usize, relocated.code()); |
| 38 | pio_instr_util::exec_jmp(&mut sm, relocated.origin()); | 38 | pio_instr_util::exec_jmp(&mut sm, relocated.origin()); |
| 39 | sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); | 39 | sm.set_clkdiv((125e6 / 10e3 * 256.0) as u32); |
| 40 | let pio::Wrap { source, target } = relocated.wrap(); | 40 | let pio::Wrap { source, target } = relocated.wrap(); |
diff --git a/examples/rp/src/bin/ws2812-pio.rs b/examples/rp/src/bin/ws2812-pio.rs index 211c60c49..041e8ae11 100644 --- a/examples/rp/src/bin/ws2812-pio.rs +++ b/examples/rp/src/bin/ws2812-pio.rs | |||
| @@ -19,7 +19,7 @@ pub struct Ws2812<P: PioInstance, S: SmInstance> { | |||
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | impl<P: PioInstance, S: SmInstance> Ws2812<P, S> { | 21 | impl<P: PioInstance, S: SmInstance> Ws2812<P, S> { |
| 22 | pub fn new(pio: PioCommonInstance<P>, mut sm: PioStateMachineInstance<P, S>, pin: gpio::AnyPin) -> Self { | 22 | pub fn new(mut pio: PioCommonInstance<P>, mut sm: PioStateMachineInstance<P, S>, pin: gpio::AnyPin) -> Self { |
| 23 | // Setup sm0 | 23 | // Setup sm0 |
| 24 | 24 | ||
| 25 | // prepare the PIO program | 25 | // prepare the PIO program |
| @@ -50,7 +50,7 @@ impl<P: PioInstance, S: SmInstance> Ws2812<P, S> { | |||
| 50 | let prg = a.assemble_with_wrap(wrap_source, wrap_target); | 50 | let prg = a.assemble_with_wrap(wrap_source, wrap_target); |
| 51 | 51 | ||
| 52 | let relocated = RelocatedProgram::new(&prg); | 52 | let relocated = RelocatedProgram::new(&prg); |
| 53 | sm.write_instr(relocated.origin() as usize, relocated.code()); | 53 | pio.write_instr(relocated.origin() as usize, relocated.code()); |
| 54 | pio_instr_util::exec_jmp(&mut sm, relocated.origin()); | 54 | pio_instr_util::exec_jmp(&mut sm, relocated.origin()); |
| 55 | 55 | ||
| 56 | // Pin config | 56 | // Pin config |
