aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkbleeke <[email protected]>2023-02-19 16:31:33 +0100
committerkbleeke <[email protected]>2023-03-19 16:57:54 +0100
commitd57fe0de867cfc6510f0192fab488355d9ae8586 (patch)
tree08a59192f1dbba10000759cb2d473178beefda00
parente33b99e9ec9902d6f93582530fd9cfe38953ce69 (diff)
Custom Bus Trait to support PIO
-rw-r--r--examples/rpi-pico-w/build.rs34
-rw-r--r--examples/rpi-pico-w/src/main.rs11
-rw-r--r--src/bus.rs100
-rw-r--r--src/lib.rs8
4 files changed, 104 insertions, 49 deletions
diff --git a/examples/rpi-pico-w/build.rs b/examples/rpi-pico-w/build.rs
index 3f915f931..d4c3ec89d 100644
--- a/examples/rpi-pico-w/build.rs
+++ b/examples/rpi-pico-w/build.rs
@@ -14,23 +14,23 @@ use std::io::Write;
14use std::path::PathBuf; 14use std::path::PathBuf;
15 15
16fn main() { 16fn main() {
17 // Put `memory.x` in our output directory and ensure it's 17 // // Put `memory.x` in our output directory and ensure it's
18 // on the linker search path. 18 // // on the linker search path.
19 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); 19 // let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20 File::create(out.join("memory.x")) 20 // File::create(out.join("memory.x"))
21 .unwrap() 21 // .unwrap()
22 .write_all(include_bytes!("memory.x")) 22 // .write_all(include_bytes!("memory.x"))
23 .unwrap(); 23 // .unwrap();
24 println!("cargo:rustc-link-search={}", out.display()); 24 // println!("cargo:rustc-link-search={}", out.display());
25 25
26 // By default, Cargo will re-run a build script whenever 26 // // By default, Cargo will re-run a build script whenever
27 // any file in the project changes. By specifying `memory.x` 27 // // any file in the project changes. By specifying `memory.x`
28 // here, we ensure the build script is only re-run when 28 // // here, we ensure the build script is only re-run when
29 // `memory.x` is changed. 29 // // `memory.x` is changed.
30 println!("cargo:rerun-if-changed=memory.x"); 30 // println!("cargo:rerun-if-changed=memory.x");
31 31
32 println!("cargo:rustc-link-arg-bins=--nmagic"); 32 // println!("cargo:rustc-link-arg-bins=--nmagic");
33 println!("cargo:rustc-link-arg-bins=-Tlink.x"); 33 // println!("cargo:rustc-link-arg-bins=-Tlink.x");
34 println!("cargo:rustc-link-arg-bins=-Tlink-rp.x"); 34 // println!("cargo:rustc-link-arg-bins=-Tlink-rp.x");
35 println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); 35 // println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
36} 36}
diff --git a/examples/rpi-pico-w/src/main.rs b/examples/rpi-pico-w/src/main.rs
index c706e121d..f768af193 100644
--- a/examples/rpi-pico-w/src/main.rs
+++ b/examples/rpi-pico-w/src/main.rs
@@ -161,6 +161,17 @@ impl ErrorType for MySpi {
161 type Error = Infallible; 161 type Error = Infallible;
162} 162}
163 163
164impl cyw43::SpiBusCyw43<u32> for MySpi {
165 async fn cmd_write<'a>(&'a mut self, write: &'a [u32]) -> Result<(), Self::Error> {
166 self.write(write).await
167 }
168
169 async fn cmd_read<'a>(&'a mut self, write: &'a [u32], read: &'a mut [u32]) -> Result<(), Self::Error> {
170 self.write(write).await?;
171 self.read(read).await
172 }
173}
174
164impl SpiBusFlush for MySpi { 175impl SpiBusFlush for MySpi {
165 async fn flush(&mut self) -> Result<(), Self::Error> { 176 async fn flush(&mut self) -> Result<(), Self::Error> {
166 Ok(()) 177 Ok(())
diff --git a/src/bus.rs b/src/bus.rs
index f64c0abba..1c8bb9893 100644
--- a/src/bus.rs
+++ b/src/bus.rs
@@ -2,10 +2,23 @@ use core::slice;
2 2
3use embassy_time::{Duration, Timer}; 3use embassy_time::{Duration, Timer};
4use embedded_hal_1::digital::OutputPin; 4use embedded_hal_1::digital::OutputPin;
5use embedded_hal_1::spi::ErrorType;
5use embedded_hal_async::spi::{transaction, SpiBusRead, SpiBusWrite, SpiDevice}; 6use embedded_hal_async::spi::{transaction, SpiBusRead, SpiBusWrite, SpiDevice};
6 7
7use crate::consts::*; 8use crate::consts::*;
8 9
10/// Custom Spi Trait that _only_ supports the bus operation of the cyw43
11pub trait SpiBusCyw43<Word: 'static + Copy>: ErrorType {
12 /// Issues a write command on the bus
13 /// Frist 32 bits of `word` are expected to be a cmd word
14 async fn cmd_write<'a>(&'a mut self, write: &'a [Word]) -> Result<(), Self::Error>;
15
16 /// Issues a read command on the bus
17 /// `write` is expected to be a 32 bit cmd word
18 /// `read` will contain the response of the device
19 async fn cmd_read<'a>(&'a mut self, write: &'a [Word], read: &'a mut [Word]) -> Result<(), Self::Error>;
20}
21
9pub(crate) struct Bus<PWR, SPI> { 22pub(crate) struct Bus<PWR, SPI> {
10 backplane_window: u32, 23 backplane_window: u32,
11 pwr: PWR, 24 pwr: PWR,
@@ -16,7 +29,7 @@ impl<PWR, SPI> Bus<PWR, SPI>
16where 29where
17 PWR: OutputPin, 30 PWR: OutputPin,
18 SPI: SpiDevice, 31 SPI: SpiDevice,
19 SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>, 32 SPI::Bus: SpiBusCyw43<u32>,
20{ 33{
21 pub(crate) fn new(pwr: PWR, spi: SPI) -> Self { 34 pub(crate) fn new(pwr: PWR, spi: SPI) -> Self {
22 Self { 35 Self {
@@ -52,8 +65,9 @@ where
52 let cmd = cmd_word(READ, INC_ADDR, FUNC_WLAN, 0, len_in_u8); 65 let cmd = cmd_word(READ, INC_ADDR, FUNC_WLAN, 0, len_in_u8);
53 let len_in_u32 = (len_in_u8 as usize + 3) / 4; 66 let len_in_u32 = (len_in_u8 as usize + 3) / 4;
54 transaction!(&mut self.spi, |bus| async { 67 transaction!(&mut self.spi, |bus| async {
55 bus.write(&[cmd]).await?; 68 // bus.write(&[cmd]).await?;
56 bus.read(&mut buf[..len_in_u32]).await?; 69 // bus.read(&mut buf[..len_in_u32]).await?;
70 bus.cmd_read(slice::from_ref(&cmd), &mut buf[..len_in_u32]).await?;
57 Ok(()) 71 Ok(())
58 }) 72 })
59 .await 73 .await
@@ -62,9 +76,16 @@ where
62 76
63 pub async fn wlan_write(&mut self, buf: &[u32]) { 77 pub async fn wlan_write(&mut self, buf: &[u32]) {
64 let cmd = cmd_word(WRITE, INC_ADDR, FUNC_WLAN, 0, buf.len() as u32 * 4); 78 let cmd = cmd_word(WRITE, INC_ADDR, FUNC_WLAN, 0, buf.len() as u32 * 4);
79 //TODO try to remove copy?
80 let mut cmd_buf = [0_u32; 513];
81 cmd_buf[0] = cmd;
82 cmd_buf[1..][..buf.len()].copy_from_slice(buf);
83
65 transaction!(&mut self.spi, |bus| async { 84 transaction!(&mut self.spi, |bus| async {
66 bus.write(&[cmd]).await?; 85 // bus.write(&[cmd]).await?;
67 bus.write(buf).await?; 86 // bus.write(buf).await?;
87
88 bus.cmd_write(&cmd_buf).await?;
68 Ok(()) 89 Ok(())
69 }) 90 })
70 .await 91 .await
@@ -79,7 +100,7 @@ where
79 // To simplify, enforce 4-align for now. 100 // To simplify, enforce 4-align for now.
80 assert!(addr % 4 == 0); 101 assert!(addr % 4 == 0);
81 102
82 let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; 103 let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4 + 1];
83 104
84 while !data.is_empty() { 105 while !data.is_empty() {
85 // Ensure transfer doesn't cross a window boundary. 106 // Ensure transfer doesn't cross a window boundary.
@@ -93,20 +114,23 @@ where
93 let cmd = cmd_word(READ, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); 114 let cmd = cmd_word(READ, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32);
94 115
95 transaction!(&mut self.spi, |bus| async { 116 transaction!(&mut self.spi, |bus| async {
96 bus.write(&[cmd]).await?; 117 // bus.write(&[cmd]).await?;
118
119 // // 4-byte response delay.
120 // let mut junk = [0; 1];
121 // bus.read(&mut junk).await?;
97 122
98 // 4-byte response delay. 123 // // Read data
99 let mut junk = [0; 1]; 124 // bus.read(&mut buf[..(len + 3) / 4]).await?;
100 bus.read(&mut junk).await?;
101 125
102 // Read data 126 bus.cmd_read(slice::from_ref(&cmd), &mut buf[..(len + 3) / 4 + 1])
103 bus.read(&mut buf[..(len + 3) / 4]).await?; 127 .await?;
104 Ok(()) 128 Ok(())
105 }) 129 })
106 .await 130 .await
107 .unwrap(); 131 .unwrap();
108 132
109 data[..len].copy_from_slice(&slice8_mut(&mut buf)[..len]); 133 data[..len].copy_from_slice(&slice8_mut(&mut buf[1..])[..len]);
110 134
111 // Advance ptr. 135 // Advance ptr.
112 addr += len as u32; 136 addr += len as u32;
@@ -121,7 +145,7 @@ where
121 // To simplify, enforce 4-align for now. 145 // To simplify, enforce 4-align for now.
122 assert!(addr % 4 == 0); 146 assert!(addr % 4 == 0);
123 147
124 let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; 148 let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4 + 1];
125 149
126 while !data.is_empty() { 150 while !data.is_empty() {
127 // Ensure transfer doesn't cross a window boundary. 151 // Ensure transfer doesn't cross a window boundary.
@@ -129,15 +153,19 @@ where
129 let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize; 153 let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize;
130 154
131 let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining); 155 let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining);
132 slice8_mut(&mut buf)[..len].copy_from_slice(&data[..len]); 156 slice8_mut(&mut buf[1..])[..len].copy_from_slice(&data[..len]);
133 157
134 self.backplane_set_window(addr).await; 158 self.backplane_set_window(addr).await;
135 159
136 let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); 160 let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32);
161 buf[0] = cmd;
137 162
138 transaction!(&mut self.spi, |bus| async { 163 transaction!(&mut self.spi, |bus| async {
139 bus.write(&[cmd]).await?; 164 // bus.write(&[cmd]).await?;
140 bus.write(&buf[..(len + 3) / 4]).await?; 165 // bus.write(&buf[..(len + 3) / 4]).await?;
166
167 bus.cmd_write(&buf[..(len + 3) / 4 + 1]).await?;
168
141 Ok(()) 169 Ok(())
142 }) 170 })
143 .await 171 .await
@@ -253,28 +281,36 @@ where
253 281
254 async fn readn(&mut self, func: u32, addr: u32, len: u32) -> u32 { 282 async fn readn(&mut self, func: u32, addr: u32, len: u32) -> u32 {
255 let cmd = cmd_word(READ, INC_ADDR, func, addr, len); 283 let cmd = cmd_word(READ, INC_ADDR, func, addr, len);
256 let mut buf = [0; 1]; 284 let mut buf = [0; 2];
285 let len = if func == FUNC_BACKPLANE { 2 } else { 1 };
257 286
258 transaction!(&mut self.spi, |bus| async { 287 transaction!(&mut self.spi, |bus| async {
259 bus.write(&[cmd]).await?; 288 // bus.write(&[cmd]).await?;
260 if func == FUNC_BACKPLANE { 289 // if func == FUNC_BACKPLANE {
261 // 4-byte response delay. 290 // // 4-byte response delay.
262 bus.read(&mut buf).await?; 291 // bus.read(&mut buf).await?;
263 } 292 // }
264 bus.read(&mut buf).await?; 293 // bus.read(&mut buf).await?;
294
295 bus.cmd_read(slice::from_ref(&cmd), &mut buf[..len]).await?;
265 Ok(()) 296 Ok(())
266 }) 297 })
267 .await 298 .await
268 .unwrap(); 299 .unwrap();
269 300
270 buf[0] 301 if func == FUNC_BACKPLANE {
302 buf[1]
303 } else {
304 buf[0]
305 }
271 } 306 }
272 307
273 async fn writen(&mut self, func: u32, addr: u32, val: u32, len: u32) { 308 async fn writen(&mut self, func: u32, addr: u32, val: u32, len: u32) {
274 let cmd = cmd_word(WRITE, INC_ADDR, func, addr, len); 309 let cmd = cmd_word(WRITE, INC_ADDR, func, addr, len);
275 310
276 transaction!(&mut self.spi, |bus| async { 311 transaction!(&mut self.spi, |bus| async {
277 bus.write(&[cmd, val]).await?; 312 // bus.write(&[cmd, val]).await?;
313 bus.cmd_write(&[cmd, val]).await?;
278 Ok(()) 314 Ok(())
279 }) 315 })
280 .await 316 .await
@@ -283,11 +319,14 @@ where
283 319
284 async fn read32_swapped(&mut self, addr: u32) -> u32 { 320 async fn read32_swapped(&mut self, addr: u32) -> u32 {
285 let cmd = cmd_word(READ, INC_ADDR, FUNC_BUS, addr, 4); 321 let cmd = cmd_word(READ, INC_ADDR, FUNC_BUS, addr, 4);
322 let cmd = swap16(cmd);
286 let mut buf = [0; 1]; 323 let mut buf = [0; 1];
287 324
288 transaction!(&mut self.spi, |bus| async { 325 transaction!(&mut self.spi, |bus| async {
289 bus.write(&[swap16(cmd)]).await?; 326 // bus.write(&[swap16(cmd)]).await?;
290 bus.read(&mut buf).await?; 327 // bus.read(&mut buf).await?;
328
329 bus.cmd_read(slice::from_ref(&cmd), &mut buf).await?;
291 Ok(()) 330 Ok(())
292 }) 331 })
293 .await 332 .await
@@ -298,9 +337,12 @@ where
298 337
299 async fn write32_swapped(&mut self, addr: u32, val: u32) { 338 async fn write32_swapped(&mut self, addr: u32, val: u32) {
300 let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BUS, addr, 4); 339 let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BUS, addr, 4);
340 let buf = [swap16(cmd), swap16(val)];
301 341
302 transaction!(&mut self.spi, |bus| async { 342 transaction!(&mut self.spi, |bus| async {
303 bus.write(&[swap16(cmd), swap16(val)]).await?; 343 // bus.write(&[swap16(cmd), swap16(val)]).await?;
344
345 bus.cmd_write(&buf).await?;
304 Ok(()) 346 Ok(())
305 }) 347 })
306 .await 348 .await
diff --git a/src/lib.rs b/src/lib.rs
index 5733506ac..7bf3992cd 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,6 +1,7 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3#![feature(type_alias_impl_trait, concat_bytes)] 3#![allow(incomplete_features)]
4#![feature(async_fn_in_trait, type_alias_impl_trait, concat_bytes)]
4#![deny(unused_must_use)] 5#![deny(unused_must_use)]
5 6
6// This mod MUST go first, so that the others see its macros. 7// This mod MUST go first, so that the others see its macros.
@@ -24,6 +25,7 @@ use embedded_hal_1::digital::OutputPin;
24use embedded_hal_async::spi::{SpiBusRead, SpiBusWrite, SpiDevice}; 25use embedded_hal_async::spi::{SpiBusRead, SpiBusWrite, SpiDevice};
25 26
26use crate::bus::Bus; 27use crate::bus::Bus;
28pub use crate::bus::SpiBusCyw43;
27use crate::consts::*; 29use crate::consts::*;
28use crate::events::Event; 30use crate::events::Event;
29use crate::structs::*; 31use crate::structs::*;
@@ -512,7 +514,7 @@ pub async fn new<'a, PWR, SPI>(
512where 514where
513 PWR: OutputPin, 515 PWR: OutputPin,
514 SPI: SpiDevice, 516 SPI: SpiDevice,
515 SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>, 517 SPI::Bus: SpiBusCyw43<u32>,
516{ 518{
517 let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]); 519 let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]);
518 let state_ch = ch_runner.state_runner(); 520 let state_ch = ch_runner.state_runner();
@@ -551,7 +553,7 @@ impl<'a, PWR, SPI> Runner<'a, PWR, SPI>
551where 553where
552 PWR: OutputPin, 554 PWR: OutputPin,
553 SPI: SpiDevice, 555 SPI: SpiDevice,
554 SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>, 556 SPI::Bus: SpiBusCyw43<u32>,
555{ 557{
556 async fn init(&mut self, firmware: &[u8]) { 558 async fn init(&mut self, firmware: &[u8]) {
557 self.bus.init().await; 559 self.bus.init().await;