aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-03-21 19:56:57 +0100
committerGitHub <[email protected]>2023-03-21 19:56:57 +0100
commit33cbc22236634753340392adadd943acb31bd5e2 (patch)
tree87b4e1ab2b4ec5e46790d4533bd31270cff74e55 /src
parent0e946dfb203dcf1ca3f165ffb06f3f58d4eaa119 (diff)
parent359b1c7fdb246c125e0b835eb58283a8a9a6a946 (diff)
Merge pull request #39 from kbleeke/pio
Use PIO for SPI communication in Pico W example
Diffstat (limited to 'src')
-rw-r--r--src/bus.rs141
-rw-r--r--src/lib.rs11
2 files changed, 71 insertions, 81 deletions
diff --git a/src/bus.rs b/src/bus.rs
index f64c0abba..f77b890df 100644
--- a/src/bus.rs
+++ b/src/bus.rs
@@ -2,10 +2,25 @@ 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_async::spi::{transaction, SpiBusRead, SpiBusWrite, SpiDevice}; 5use futures::FutureExt;
6 6
7use crate::consts::*; 7use crate::consts::*;
8 8
9/// Custom Spi Trait that _only_ supports the bus operation of the cyw43
10/// Implementors are expected to hold the CS pin low during an operation.
11pub trait SpiBusCyw43 {
12 /// Issues a write command on the bus
13 /// First 32 bits of `word` are expected to be a cmd word
14 async fn cmd_write(&mut self, write: &[u32]);
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 /// Backplane reads have a response delay that produces one extra unspecified word at the beginning of `read`.
20 /// Callers that want to read `n` word from the backplane, have to provide a slice that is `n+1` words long.
21 async fn cmd_read(&mut self, write: u32, read: &mut [u32]);
22}
23
9pub(crate) struct Bus<PWR, SPI> { 24pub(crate) struct Bus<PWR, SPI> {
10 backplane_window: u32, 25 backplane_window: u32,
11 pwr: PWR, 26 pwr: PWR,
@@ -15,8 +30,7 @@ pub(crate) struct Bus<PWR, SPI> {
15impl<PWR, SPI> Bus<PWR, SPI> 30impl<PWR, SPI> Bus<PWR, SPI>
16where 31where
17 PWR: OutputPin, 32 PWR: OutputPin,
18 SPI: SpiDevice, 33 SPI: SpiBusCyw43,
19 SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>,
20{ 34{
21 pub(crate) fn new(pwr: PWR, spi: SPI) -> Self { 35 pub(crate) fn new(pwr: PWR, spi: SPI) -> Self {
22 Self { 36 Self {
@@ -33,42 +47,50 @@ where
33 self.pwr.set_high().unwrap(); 47 self.pwr.set_high().unwrap();
34 Timer::after(Duration::from_millis(250)).await; 48 Timer::after(Duration::from_millis(250)).await;
35 49
36 while self.read32_swapped(REG_BUS_TEST_RO).await != FEEDBEAD {} 50 while self
51 .read32_swapped(REG_BUS_TEST_RO)
52 .inspect(|v| defmt::trace!("{:#x}", v))
53 .await
54 != FEEDBEAD
55 {}
37 56
38 self.write32_swapped(REG_BUS_TEST_RW, TEST_PATTERN).await; 57 self.write32_swapped(REG_BUS_TEST_RW, TEST_PATTERN).await;
39 let val = self.read32_swapped(REG_BUS_TEST_RW).await; 58 let val = self.read32_swapped(REG_BUS_TEST_RW).await;
59 defmt::trace!("{:#x}", val);
40 assert_eq!(val, TEST_PATTERN); 60 assert_eq!(val, TEST_PATTERN);
41 61
62 let val = self.read32_swapped(REG_BUS_CTRL).await;
63 defmt::trace!("{:#010b}", (val & 0xff));
64
42 // 32-bit word length, little endian (which is the default endianess). 65 // 32-bit word length, little endian (which is the default endianess).
43 self.write32_swapped(REG_BUS_CTRL, WORD_LENGTH_32 | HIGH_SPEED).await; 66 self.write32_swapped(REG_BUS_CTRL, WORD_LENGTH_32 | HIGH_SPEED).await;
44 67
68 let val = self.read8(FUNC_BUS, REG_BUS_CTRL).await;
69 defmt::trace!("{:#b}", val);
70
45 let val = self.read32(FUNC_BUS, REG_BUS_TEST_RO).await; 71 let val = self.read32(FUNC_BUS, REG_BUS_TEST_RO).await;
72 defmt::trace!("{:#x}", val);
46 assert_eq!(val, FEEDBEAD); 73 assert_eq!(val, FEEDBEAD);
47 let val = self.read32(FUNC_BUS, REG_BUS_TEST_RW).await; 74 let val = self.read32(FUNC_BUS, REG_BUS_TEST_RW).await;
75 defmt::trace!("{:#x}", val);
48 assert_eq!(val, TEST_PATTERN); 76 assert_eq!(val, TEST_PATTERN);
49 } 77 }
50 78
51 pub async fn wlan_read(&mut self, buf: &mut [u32], len_in_u8: u32) { 79 pub async fn wlan_read(&mut self, buf: &mut [u32], len_in_u8: u32) {
52 let cmd = cmd_word(READ, INC_ADDR, FUNC_WLAN, 0, len_in_u8); 80 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; 81 let len_in_u32 = (len_in_u8 as usize + 3) / 4;
54 transaction!(&mut self.spi, |bus| async { 82
55 bus.write(&[cmd]).await?; 83 self.spi.cmd_read(cmd, &mut buf[..len_in_u32]).await;
56 bus.read(&mut buf[..len_in_u32]).await?;
57 Ok(())
58 })
59 .await
60 .unwrap();
61 } 84 }
62 85
63 pub async fn wlan_write(&mut self, buf: &[u32]) { 86 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); 87 let cmd = cmd_word(WRITE, INC_ADDR, FUNC_WLAN, 0, buf.len() as u32 * 4);
65 transaction!(&mut self.spi, |bus| async { 88 //TODO try to remove copy?
66 bus.write(&[cmd]).await?; 89 let mut cmd_buf = [0_u32; 513];
67 bus.write(buf).await?; 90 cmd_buf[0] = cmd;
68 Ok(()) 91 cmd_buf[1..][..buf.len()].copy_from_slice(buf);
69 }) 92
70 .await 93 self.spi.cmd_write(&cmd_buf).await;
71 .unwrap();
72 } 94 }
73 95
74 #[allow(unused)] 96 #[allow(unused)]
@@ -79,7 +101,8 @@ where
79 // To simplify, enforce 4-align for now. 101 // To simplify, enforce 4-align for now.
80 assert!(addr % 4 == 0); 102 assert!(addr % 4 == 0);
81 103
82 let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; 104 // Backplane read buffer has one extra word for the response delay.
105 let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4 + 1];
83 106
84 while !data.is_empty() { 107 while !data.is_empty() {
85 // Ensure transfer doesn't cross a window boundary. 108 // Ensure transfer doesn't cross a window boundary.
@@ -92,21 +115,11 @@ where
92 115
93 let cmd = cmd_word(READ, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); 116 let cmd = cmd_word(READ, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32);
94 117
95 transaction!(&mut self.spi, |bus| async { 118 // round `buf` to word boundary, add one extra word for the response delay
96 bus.write(&[cmd]).await?; 119 self.spi.cmd_read(cmd, &mut buf[..(len + 3) / 4 + 1]).await;
97 120
98 // 4-byte response delay. 121 // when writing out the data, we skip the response-delay byte
99 let mut junk = [0; 1]; 122 data[..len].copy_from_slice(&slice8_mut(&mut buf[1..])[..len]);
100 bus.read(&mut junk).await?;
101
102 // Read data
103 bus.read(&mut buf[..(len + 3) / 4]).await?;
104 Ok(())
105 })
106 .await
107 .unwrap();
108
109 data[..len].copy_from_slice(&slice8_mut(&mut buf)[..len]);
110 123
111 // Advance ptr. 124 // Advance ptr.
112 addr += len as u32; 125 addr += len as u32;
@@ -121,7 +134,7 @@ where
121 // To simplify, enforce 4-align for now. 134 // To simplify, enforce 4-align for now.
122 assert!(addr % 4 == 0); 135 assert!(addr % 4 == 0);
123 136
124 let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; 137 let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4 + 1];
125 138
126 while !data.is_empty() { 139 while !data.is_empty() {
127 // Ensure transfer doesn't cross a window boundary. 140 // Ensure transfer doesn't cross a window boundary.
@@ -129,19 +142,14 @@ where
129 let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize; 142 let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize;
130 143
131 let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining); 144 let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining);
132 slice8_mut(&mut buf)[..len].copy_from_slice(&data[..len]); 145 slice8_mut(&mut buf[1..])[..len].copy_from_slice(&data[..len]);
133 146
134 self.backplane_set_window(addr).await; 147 self.backplane_set_window(addr).await;
135 148
136 let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); 149 let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32);
150 buf[0] = cmd;
137 151
138 transaction!(&mut self.spi, |bus| async { 152 self.spi.cmd_write(&buf[..(len + 3) / 4 + 1]).await;
139 bus.write(&[cmd]).await?;
140 bus.write(&buf[..(len + 3) / 4]).await?;
141 Ok(())
142 })
143 .await
144 .unwrap();
145 153
146 // Advance ptr. 154 // Advance ptr.
147 addr += len as u32; 155 addr += len as u32;
@@ -253,58 +261,41 @@ where
253 261
254 async fn readn(&mut self, func: u32, addr: u32, len: u32) -> u32 { 262 async fn readn(&mut self, func: u32, addr: u32, len: u32) -> u32 {
255 let cmd = cmd_word(READ, INC_ADDR, func, addr, len); 263 let cmd = cmd_word(READ, INC_ADDR, func, addr, len);
256 let mut buf = [0; 1]; 264 let mut buf = [0; 2];
265 // if we are reading from the backplane, we need an extra word for the response delay
266 let len = if func == FUNC_BACKPLANE { 2 } else { 1 };
267
268 self.spi.cmd_read(cmd, &mut buf[..len]).await;
257 269
258 transaction!(&mut self.spi, |bus| async { 270 // if we read from the backplane, the result is in the second word, after the response delay
259 bus.write(&[cmd]).await?; 271 if func == FUNC_BACKPLANE {
260 if func == FUNC_BACKPLANE { 272 buf[1]
261 // 4-byte response delay. 273 } else {
262 bus.read(&mut buf).await?; 274 buf[0]
263 } 275 }
264 bus.read(&mut buf).await?;
265 Ok(())
266 })
267 .await
268 .unwrap();
269
270 buf[0]
271 } 276 }
272 277
273 async fn writen(&mut self, func: u32, addr: u32, val: u32, len: u32) { 278 async fn writen(&mut self, func: u32, addr: u32, val: u32, len: u32) {
274 let cmd = cmd_word(WRITE, INC_ADDR, func, addr, len); 279 let cmd = cmd_word(WRITE, INC_ADDR, func, addr, len);
275 280
276 transaction!(&mut self.spi, |bus| async { 281 self.spi.cmd_write(&[cmd, val]).await;
277 bus.write(&[cmd, val]).await?;
278 Ok(())
279 })
280 .await
281 .unwrap();
282 } 282 }
283 283
284 async fn read32_swapped(&mut self, addr: u32) -> u32 { 284 async fn read32_swapped(&mut self, addr: u32) -> u32 {
285 let cmd = cmd_word(READ, INC_ADDR, FUNC_BUS, addr, 4); 285 let cmd = cmd_word(READ, INC_ADDR, FUNC_BUS, addr, 4);
286 let cmd = swap16(cmd);
286 let mut buf = [0; 1]; 287 let mut buf = [0; 1];
287 288
288 transaction!(&mut self.spi, |bus| async { 289 self.spi.cmd_read(cmd, &mut buf).await;
289 bus.write(&[swap16(cmd)]).await?;
290 bus.read(&mut buf).await?;
291 Ok(())
292 })
293 .await
294 .unwrap();
295 290
296 swap16(buf[0]) 291 swap16(buf[0])
297 } 292 }
298 293
299 async fn write32_swapped(&mut self, addr: u32, val: u32) { 294 async fn write32_swapped(&mut self, addr: u32, val: u32) {
300 let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BUS, addr, 4); 295 let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BUS, addr, 4);
296 let buf = [swap16(cmd), swap16(val)];
301 297
302 transaction!(&mut self.spi, |bus| async { 298 self.spi.cmd_write(&buf).await;
303 bus.write(&[swap16(cmd), swap16(val)]).await?;
304 Ok(())
305 })
306 .await
307 .unwrap();
308 } 299 }
309} 300}
310 301
diff --git a/src/lib.rs b/src/lib.rs
index c58ac8e7d..1b7d603d7 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.
@@ -22,10 +23,10 @@ use embassy_net_driver_channel as ch;
22use embassy_sync::pubsub::PubSubBehavior; 23use embassy_sync::pubsub::PubSubBehavior;
23use embassy_time::{block_for, Duration, Timer}; 24use embassy_time::{block_for, Duration, Timer};
24use embedded_hal_1::digital::OutputPin; 25use embedded_hal_1::digital::OutputPin;
25use embedded_hal_async::spi::{SpiBusRead, SpiBusWrite, SpiDevice};
26use events::EventQueue; 26use events::EventQueue;
27 27
28use crate::bus::Bus; 28use crate::bus::Bus;
29pub use crate::bus::SpiBusCyw43;
29use crate::consts::*; 30use crate::consts::*;
30use crate::events::{Event, EventStatus}; 31use crate::events::{Event, EventStatus};
31use crate::structs::*; 32use crate::structs::*;
@@ -533,8 +534,7 @@ pub async fn new<'a, PWR, SPI>(
533) -> (NetDriver<'a>, Control<'a>, Runner<'a, PWR, SPI>) 534) -> (NetDriver<'a>, Control<'a>, Runner<'a, PWR, SPI>)
534where 535where
535 PWR: OutputPin, 536 PWR: OutputPin,
536 SPI: SpiDevice, 537 SPI: SpiBusCyw43,
537 SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>,
538{ 538{
539 let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]); 539 let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]);
540 let state_ch = ch_runner.state_runner(); 540 let state_ch = ch_runner.state_runner();
@@ -575,8 +575,7 @@ where
575impl<'a, PWR, SPI> Runner<'a, PWR, SPI> 575impl<'a, PWR, SPI> Runner<'a, PWR, SPI>
576where 576where
577 PWR: OutputPin, 577 PWR: OutputPin,
578 SPI: SpiDevice, 578 SPI: SpiBusCyw43,
579 SPI::Bus: SpiBusRead<u32> + SpiBusWrite<u32>,
580{ 579{
581 async fn init(&mut self, firmware: &[u8]) { 580 async fn init(&mut self, firmware: &[u8]) {
582 self.bus.init().await; 581 self.bus.init().await;