diff options
| author | kbleeke <[email protected]> | 2023-02-19 16:31:33 +0100 |
|---|---|---|
| committer | kbleeke <[email protected]> | 2023-03-19 16:57:54 +0100 |
| commit | d57fe0de867cfc6510f0192fab488355d9ae8586 (patch) | |
| tree | 08a59192f1dbba10000759cb2d473178beefda00 /src/bus.rs | |
| parent | e33b99e9ec9902d6f93582530fd9cfe38953ce69 (diff) | |
Custom Bus Trait to support PIO
Diffstat (limited to 'src/bus.rs')
| -rw-r--r-- | src/bus.rs | 100 |
1 files changed, 71 insertions, 29 deletions
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 | ||
| 3 | use embassy_time::{Duration, Timer}; | 3 | use embassy_time::{Duration, Timer}; |
| 4 | use embedded_hal_1::digital::OutputPin; | 4 | use embedded_hal_1::digital::OutputPin; |
| 5 | use embedded_hal_1::spi::ErrorType; | ||
| 5 | use embedded_hal_async::spi::{transaction, SpiBusRead, SpiBusWrite, SpiDevice}; | 6 | use embedded_hal_async::spi::{transaction, SpiBusRead, SpiBusWrite, SpiDevice}; |
| 6 | 7 | ||
| 7 | use crate::consts::*; | 8 | use crate::consts::*; |
| 8 | 9 | ||
| 10 | /// Custom Spi Trait that _only_ supports the bus operation of the cyw43 | ||
| 11 | pub 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 | |||
| 9 | pub(crate) struct Bus<PWR, SPI> { | 22 | pub(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> | |||
| 16 | where | 29 | where |
| 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 |
