aboutsummaryrefslogtreecommitdiff
path: root/cyw43-pio
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-05-13 02:20:46 +0200
committerDario Nieuwenhuis <[email protected]>2023-05-13 02:58:42 +0200
commit8800caa216f2c90b7d998280a54dddf14e97e318 (patch)
tree4b1f35c354846541dfe578592f1d9b564083230f /cyw43-pio
parent6b5d9642d583bc034ee35b88c903545e7f423b4e (diff)
Update Embassy, to new PIO API.
Diffstat (limited to 'cyw43-pio')
-rw-r--r--cyw43-pio/Cargo.toml1
-rw-r--r--cyw43-pio/src/lib.rs151
2 files changed, 82 insertions, 70 deletions
diff --git a/cyw43-pio/Cargo.toml b/cyw43-pio/Cargo.toml
index 8272903c3..dd50e02ba 100644
--- a/cyw43-pio/Cargo.toml
+++ b/cyw43-pio/Cargo.toml
@@ -8,4 +8,5 @@ cyw43 = { path = "../" }
8embassy-rp = { version = "0.1.0", features = ["unstable-traits", "nightly", "unstable-pac", "time-driver"] } 8embassy-rp = { version = "0.1.0", features = ["unstable-traits", "nightly", "unstable-pac", "time-driver"] }
9pio-proc = "0.2" 9pio-proc = "0.2"
10pio = "0.2.1" 10pio = "0.2.1"
11fixed = "1.23.1"
11defmt = { version = "0.3", optional = true } \ No newline at end of file 12defmt = { version = "0.3", optional = true } \ No newline at end of file
diff --git a/cyw43-pio/src/lib.rs b/cyw43-pio/src/lib.rs
index c468435f1..2c17b151a 100644
--- a/cyw43-pio/src/lib.rs
+++ b/cyw43-pio/src/lib.rs
@@ -6,30 +6,39 @@ use core::slice;
6 6
7use cyw43::SpiBusCyw43; 7use cyw43::SpiBusCyw43;
8use embassy_rp::dma::Channel; 8use embassy_rp::dma::Channel;
9use embassy_rp::gpio::{Drive, Output, Pin, Pull, SlewRate}; 9use embassy_rp::gpio::{Drive, Level, Output, Pin, Pull, SlewRate};
10use embassy_rp::pio::{PioStateMachine, ShiftDirection}; 10use embassy_rp::pio::{Common, Config, Direction, Instance, Irq, PioPin, ShiftDirection, StateMachine};
11use embassy_rp::relocate::RelocatedProgram; 11use embassy_rp::relocate::RelocatedProgram;
12use embassy_rp::{pio_instr_util, Peripheral}; 12use embassy_rp::{pio_instr_util, Peripheral, PeripheralRef};
13use pio::Wrap; 13use fixed::FixedU32;
14use pio_proc::pio_asm; 14use pio_proc::pio_asm;
15 15
16pub struct PioSpi<CS: Pin, SM, DMA> { 16pub struct PioSpi<'d, CS: Pin, PIO: Instance, const SM: usize, DMA> {
17 cs: Output<'static, CS>, 17 cs: Output<'d, CS>,
18 sm: SM, 18 sm: StateMachine<'d, PIO, SM>,
19 dma: DMA, 19 irq: Irq<'d, PIO, 0>,
20 dma: PeripheralRef<'d, DMA>,
20 wrap_target: u8, 21 wrap_target: u8,
21} 22}
22 23
23impl<CS, SM, DMA> PioSpi<CS, SM, DMA> 24impl<'d, CS, PIO, const SM: usize, DMA> PioSpi<'d, CS, PIO, SM, DMA>
24where 25where
25 SM: PioStateMachine,
26 DMA: Channel, 26 DMA: Channel,
27 CS: Pin, 27 CS: Pin,
28 PIO: Instance,
28{ 29{
29 pub fn new<DIO, CLK>(mut sm: SM, cs: Output<'static, CS>, dio: DIO, clk: CLK, dma: DMA) -> Self 30 pub fn new<DIO, CLK>(
31 common: &mut Common<'d, PIO>,
32 mut sm: StateMachine<'d, PIO, SM>,
33 irq: Irq<'d, PIO, 0>,
34 cs: Output<'d, CS>,
35 dio: DIO,
36 clk: CLK,
37 dma: impl Peripheral<P = DMA> + 'd,
38 ) -> Self
30 where 39 where
31 DIO: Pin, 40 DIO: PioPin,
32 CLK: Pin, 41 CLK: PioPin,
33 { 42 {
34 let program = pio_asm!( 43 let program = pio_asm!(
35 ".side_set 1" 44 ".side_set 1"
@@ -42,8 +51,8 @@ where
42 // switch directions 51 // switch directions
43 "set pindirs, 0 side 0" 52 "set pindirs, 0 side 0"
44 // these nops seem to be necessary for fast clkdiv 53 // these nops seem to be necessary for fast clkdiv
45 "nop side 1" 54 //"nop side 1"
46 "nop side 0" 55 //"nop side 0"
47 "nop side 1" 56 "nop side 1"
48 // read in y-1 bits 57 // read in y-1 bits
49 "lp2:" 58 "lp2:"
@@ -59,68 +68,62 @@ where
59 68
60 let relocated = RelocatedProgram::new(&program.program); 69 let relocated = RelocatedProgram::new(&program.program);
61 70
62 let mut pin_io = sm.make_pio_pin(dio); 71 let mut pin_io: embassy_rp::pio::Pin<PIO> = common.make_pio_pin(dio);
63 pin_io.set_pull(Pull::Down); 72 pin_io.set_pull(Pull::None);
64 pin_io.set_schmitt(true); 73 pin_io.set_schmitt(true);
65 pin_io.set_input_sync_bypass(true); 74 pin_io.set_input_sync_bypass(true);
75 //pin_io.set_drive_strength(Drive::_12mA);
76 //pin_io.set_slew_rate(SlewRate::Fast);
66 77
67 let mut pin_clk = sm.make_pio_pin(clk); 78 let mut pin_clk = common.make_pio_pin(clk);
68 pin_clk.set_drive_strength(Drive::_12mA); 79 pin_clk.set_drive_strength(Drive::_12mA);
69 pin_clk.set_slew_rate(SlewRate::Fast); 80 pin_clk.set_slew_rate(SlewRate::Fast);
70 81
71 sm.write_instr(relocated.origin() as usize, relocated.code()); 82 let mut cfg = Config::default();
83 cfg.use_program(&common.load_program(&relocated), &[&pin_clk]);
84 cfg.set_out_pins(&[&pin_io]);
85 cfg.set_in_pins(&[&pin_io]);
86 cfg.set_set_pins(&[&pin_io]);
87 cfg.shift_out.direction = ShiftDirection::Left;
88 cfg.shift_out.auto_fill = true;
89 //cfg.shift_out.threshold = 32;
90 cfg.shift_in.direction = ShiftDirection::Left;
91 cfg.shift_in.auto_fill = true;
92 //cfg.shift_in.threshold = 32;
72 93
73 // theoretical maximum according to data sheet, 100Mhz Pio => 50Mhz SPI Freq 94 // theoretical maximum according to data sheet, 100Mhz Pio => 50Mhz SPI Freq
74 sm.set_clkdiv(0x0140); 95 // seems to cause random corruption, probably due to jitter due to the fractional divider.
96 // cfg.clock_divider = FixedU32::from_bits(0x0140);
75 97
76 // same speed as pico-sdk, 62.5Mhz 98 // same speed as pico-sdk, 62.5Mhz
77 // sm.set_clkdiv(0x0200); 99 cfg.clock_divider = FixedU32::from_bits(0x0200);
78 100
79 // 32 Mhz 101 // 32 Mhz
80 // sm.set_clkdiv(0x03E8); 102 // cfg.clock_divider = FixedU32::from_bits(0x03E8);
81 103
82 // 16 Mhz 104 // 16 Mhz
83 // sm.set_clkdiv(0x07d0); 105 // cfg.clock_divider = FixedU32::from_bits(0x07d0);
84 106
85 // 8Mhz 107 // 8Mhz
86 // sm.set_clkdiv(0x0a_00); 108 // cfg.clock_divider = FixedU32::from_bits(0x0a_00);
87 109
88 // 1Mhz 110 // 1Mhz
89 // sm.set_clkdiv(0x7d_00); 111 // cfg.clock_divider = FixedU32::from_bits(0x7d_00);
90 112
91 // slowest possible 113 // slowest possible
92 // sm.set_clkdiv(0xffff_00); 114 // cfg.clock_divider = FixedU32::from_bits(0xffff_00);
93
94 sm.set_autopull(true);
95 // sm.set_pull_threshold(32);
96 sm.set_autopush(true);
97 // sm.set_push_threshold(32);
98
99 sm.set_out_pins(&[&pin_io]);
100 sm.set_in_base_pin(&pin_io);
101
102 sm.set_set_pins(&[&pin_clk]);
103 pio_instr_util::set_pindir(&mut sm, 0b1);
104 sm.set_set_pins(&[&pin_io]);
105 pio_instr_util::set_pindir(&mut sm, 0b1);
106
107 sm.set_sideset_base_pin(&pin_clk);
108 sm.set_sideset_count(1);
109 115
110 sm.set_out_shift_dir(ShiftDirection::Left); 116 sm.set_config(&cfg);
111 sm.set_in_shift_dir(ShiftDirection::Left);
112 117
113 let Wrap { source, target } = relocated.wrap(); 118 sm.set_pin_dirs(Direction::Out, &[&pin_clk, &pin_io]);
114 sm.set_wrap(source, target); 119 sm.set_pins(Level::Low, &[&pin_clk, &pin_io]);
115
116 // pull low for startup
117 pio_instr_util::set_pin(&mut sm, 0);
118 120
119 Self { 121 Self {
120 cs, 122 cs,
121 sm, 123 sm,
122 dma, 124 irq,
123 wrap_target: target, 125 dma: dma.into_ref(),
126 wrap_target: relocated.wrap().target,
124 } 127 }
125 } 128 }
126 129
@@ -132,18 +135,22 @@ where
132 #[cfg(feature = "defmt")] 135 #[cfg(feature = "defmt")]
133 defmt::trace!("write={} read={}", write_bits, read_bits); 136 defmt::trace!("write={} read={}", write_bits, read_bits);
134 137
135 let mut dma = Peripheral::into_ref(&mut self.dma); 138 unsafe {
136 pio_instr_util::set_x(&mut self.sm, write_bits as u32); 139 pio_instr_util::set_x(&mut self.sm, write_bits as u32);
137 pio_instr_util::set_y(&mut self.sm, read_bits as u32); 140 pio_instr_util::set_y(&mut self.sm, read_bits as u32);
138 pio_instr_util::set_pindir(&mut self.sm, 0b1); 141 pio_instr_util::set_pindir(&mut self.sm, 0b1);
139 pio_instr_util::exec_jmp(&mut self.sm, self.wrap_target); 142 pio_instr_util::exec_jmp(&mut self.sm, self.wrap_target);
143 }
140 144
141 self.sm.set_enable(true); 145 self.sm.set_enable(true);
142 146
143 self.sm.dma_push(dma.reborrow(), write).await; 147 self.sm.tx().dma_push(self.dma.reborrow(), write).await;
144 148
145 let mut status = 0; 149 let mut status = 0;
146 self.sm.dma_pull(dma.reborrow(), slice::from_mut(&mut status)).await; 150 self.sm
151 .rx()
152 .dma_pull(self.dma.reborrow(), slice::from_mut(&mut status))
153 .await;
147 status 154 status
148 } 155 }
149 156
@@ -155,27 +162,32 @@ where
155 #[cfg(feature = "defmt")] 162 #[cfg(feature = "defmt")]
156 defmt::trace!("write={} read={}", write_bits, read_bits); 163 defmt::trace!("write={} read={}", write_bits, read_bits);
157 164
158 let mut dma = Peripheral::into_ref(&mut self.dma); 165 unsafe {
159 pio_instr_util::set_y(&mut self.sm, read_bits as u32); 166 pio_instr_util::set_y(&mut self.sm, read_bits as u32);
160 pio_instr_util::set_x(&mut self.sm, write_bits as u32); 167 pio_instr_util::set_x(&mut self.sm, write_bits as u32);
161 pio_instr_util::set_pindir(&mut self.sm, 0b1); 168 pio_instr_util::set_pindir(&mut self.sm, 0b1);
162 pio_instr_util::exec_jmp(&mut self.sm, self.wrap_target); 169 pio_instr_util::exec_jmp(&mut self.sm, self.wrap_target);
170 }
171
163 // self.cs.set_low(); 172 // self.cs.set_low();
164 self.sm.set_enable(true); 173 self.sm.set_enable(true);
165 174
166 self.sm.dma_push(dma.reborrow(), slice::from_ref(&cmd)).await; 175 self.sm.tx().dma_push(self.dma.reborrow(), slice::from_ref(&cmd)).await;
167 self.sm.dma_pull(dma.reborrow(), read).await; 176 self.sm.rx().dma_pull(self.dma.reborrow(), read).await;
168 177
169 let mut status = 0; 178 let mut status = 0;
170 self.sm.dma_pull(dma.reborrow(), slice::from_mut(&mut status)).await; 179 self.sm
180 .rx()
181 .dma_pull(self.dma.reborrow(), slice::from_mut(&mut status))
182 .await;
171 status 183 status
172 } 184 }
173} 185}
174 186
175impl<CS, SM, DMA> SpiBusCyw43 for PioSpi<CS, SM, DMA> 187impl<'d, CS, PIO, const SM: usize, DMA> SpiBusCyw43 for PioSpi<'d, CS, PIO, SM, DMA>
176where 188where
177 CS: Pin, 189 CS: Pin,
178 SM: PioStateMachine, 190 PIO: Instance,
179 DMA: Channel, 191 DMA: Channel,
180{ 192{
181 async fn cmd_write(&mut self, write: &[u32]) -> u32 { 193 async fn cmd_write(&mut self, write: &[u32]) -> u32 {
@@ -193,7 +205,6 @@ where
193 } 205 }
194 206
195 async fn wait_for_event(&mut self) { 207 async fn wait_for_event(&mut self) {
196 self.sm.wait_irq(0).await; 208 self.irq.wait().await;
197 self.sm.clear_irq(0);
198 } 209 }
199} 210}