aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-rp/src/pio.rs104
-rw-r--r--examples/rp/src/bin/pio_async.rs28
-rw-r--r--examples/rp/src/bin/pio_dma.rs6
-rw-r--r--examples/rp/src/bin/ws2812-pio.rs4
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/* 870pub struct PioCommonInstance<PIO: PioInstance> {
884This 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;
888const MEM_NOT_USED: u32 = 0b0000;
889const MEM_USED_BY_STATEMACHINE: u32 = 0b0100;
890const 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
896static mut INSTR_MEM_STATUS: &'static mut [[u32; 4]; 2] = &mut [[0; 4]; 2];
897
898fn 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
902fn 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
908fn 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
912pub struct PioCommonInstance<PIO: PioInstance> { 875pub struct PioInstanceMemory<PIO: PioInstance> {
876 used_mask: u32,
913 pio: PhantomData<PIO>, 877 pio: PhantomData<PIO>,
914} 878}
915 879
916impl<PIO: PioInstance> sealed::PioCommon for PioCommonInstance<PIO> { 880impl<PIO: PioInstance> sealed::PioCommon for PioCommonInstance<PIO> {
917 type Pio = PIO; 881 type Pio = PIO;
918} 882}
919impl<PIO: PioInstance> PioCommon for PioCommonInstance<PIO> {} 883impl<PIO: PioInstance> PioCommon for PioCommonInstance<PIO> {
920 884 fn write_instr<I>(&mut self, start: usize, instrs: I) -> PioInstanceMemory<Self::Pio>
921fn write_instr<I>(pio: &pac::pio::Pio, pio_no: u8, start: usize, instrs: I, mem_user: u32) 885 where
922where 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
941pub trait PioCommon: sealed::PioCommon + Sized { 916pub 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] 54fn setup_pio_task_sm1(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm1>) {
55async 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]
73async 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] 81fn setup_pio_task_sm2(pio: &mut PioCommonInstance<Pio0>, sm: &mut PioStateMachineInstance<Pio0, Sm2>) {
79async 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]
105async 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 @@
4use defmt::info; 4use defmt::info;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_futures::join::join; 6use embassy_futures::join::join;
7use embassy_rp::pio::{PioPeripheral, PioStateMachine, ShiftDirection}; 7use embassy_rp::pio::{PioCommon, PioPeripheral, PioStateMachine, ShiftDirection};
8use embassy_rp::relocate::RelocatedProgram; 8use embassy_rp::relocate::RelocatedProgram;
9use embassy_rp::{pio_instr_util, Peripheral}; 9use embassy_rp::{pio_instr_util, Peripheral};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
@@ -19,7 +19,7 @@ fn swap_nibbles(v: u32) -> u32 {
19async fn main(_spawner: Spawner) { 19async 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
21impl<P: PioInstance, S: SmInstance> Ws2812<P, S> { 21impl<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