aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bus.rs14
-rw-r--r--src/consts.rs149
-rw-r--r--src/ioctl.rs3
-rw-r--r--src/runner.rs92
4 files changed, 210 insertions, 48 deletions
diff --git a/src/bus.rs b/src/bus.rs
index 7700a832a..d2a249f97 100644
--- a/src/bus.rs
+++ b/src/bus.rs
@@ -1,5 +1,6 @@
1use core::slice; 1use core::slice;
2 2
3use embassy_futures::yield_now;
3use embassy_time::{Duration, Timer}; 4use embassy_time::{Duration, Timer};
4use embedded_hal_1::digital::OutputPin; 5use embedded_hal_1::digital::OutputPin;
5use futures::FutureExt; 6use futures::FutureExt;
@@ -19,6 +20,12 @@ pub trait SpiBusCyw43 {
19 /// Backplane reads have a response delay that produces one extra unspecified word at the beginning of `read`. 20 /// 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 /// 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 async fn cmd_read(&mut self, write: u32, read: &mut [u32]);
23
24 /// Wait for events from the Device. A typical implementation would wait for the IRQ pin to be high.
25 /// The default implementation always reports ready, resulting in active polling of the device.
26 async fn wait_for_event(&mut self) {
27 yield_now().await;
28 }
22} 29}
23 30
24pub(crate) struct Bus<PWR, SPI> { 31pub(crate) struct Bus<PWR, SPI> {
@@ -63,7 +70,8 @@ where
63 trace!("{:#010b}", (val & 0xff)); 70 trace!("{:#010b}", (val & 0xff));
64 71
65 // 32-bit word length, little endian (which is the default endianess). 72 // 32-bit word length, little endian (which is the default endianess).
66 self.write32_swapped(REG_BUS_CTRL, WORD_LENGTH_32 | HIGH_SPEED).await; 73 self.write32_swapped(REG_BUS_CTRL, WORD_LENGTH_32 | HIGH_SPEED | INTERRUPT_HIGH | WAKE_UP)
74 .await;
67 75
68 let val = self.read8(FUNC_BUS, REG_BUS_CTRL).await; 76 let val = self.read8(FUNC_BUS, REG_BUS_CTRL).await;
69 trace!("{:#b}", val); 77 trace!("{:#b}", val);
@@ -297,6 +305,10 @@ where
297 305
298 self.spi.cmd_write(&buf).await; 306 self.spi.cmd_write(&buf).await;
299 } 307 }
308
309 pub async fn wait_for_event(&mut self) {
310 self.spi.wait_for_event().await;
311 }
300} 312}
301 313
302fn swap16(x: u32) -> u32 { 314fn swap16(x: u32) -> u32 {
diff --git a/src/consts.rs b/src/consts.rs
index bee706600..70d6660e0 100644
--- a/src/consts.rs
+++ b/src/consts.rs
@@ -1,4 +1,5 @@
1#![allow(unused)] 1#![allow(unused)]
2
2pub(crate) const FUNC_BUS: u32 = 0; 3pub(crate) const FUNC_BUS: u32 = 0;
3pub(crate) const FUNC_BACKPLANE: u32 = 1; 4pub(crate) const FUNC_BACKPLANE: u32 = 1;
4pub(crate) const FUNC_WLAN: u32 = 2; 5pub(crate) const FUNC_WLAN: u32 = 2;
@@ -13,6 +14,8 @@ pub(crate) const REG_BUS_TEST_RW: u32 = 0x18;
13pub(crate) const REG_BUS_RESP_DELAY: u32 = 0x1c; 14pub(crate) const REG_BUS_RESP_DELAY: u32 = 0x1c;
14pub(crate) const WORD_LENGTH_32: u32 = 0x1; 15pub(crate) const WORD_LENGTH_32: u32 = 0x1;
15pub(crate) const HIGH_SPEED: u32 = 0x10; 16pub(crate) const HIGH_SPEED: u32 = 0x10;
17pub(crate) const INTERRUPT_HIGH: u32 = 1 << 5;
18pub(crate) const WAKE_UP: u32 = 1 << 7;
16 19
17// SPI_STATUS_REGISTER bits 20// SPI_STATUS_REGISTER bits
18pub(crate) const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001; 21pub(crate) const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001;
@@ -103,3 +106,149 @@ pub(crate) const WRITE: bool = true;
103pub(crate) const READ: bool = false; 106pub(crate) const READ: bool = false;
104pub(crate) const INC_ADDR: bool = true; 107pub(crate) const INC_ADDR: bool = true;
105pub(crate) const FIXED_ADDR: bool = false; 108pub(crate) const FIXED_ADDR: bool = false;
109
110#[allow(dead_code)]
111pub(crate) struct FormatStatus(pub u32);
112
113#[cfg(feature = "defmt")]
114impl defmt::Format for FormatStatus {
115 fn format(&self, fmt: defmt::Formatter) {
116 macro_rules! implm {
117 ($($name:ident),*) => {
118 $(
119 if self.0 & $name > 0 {
120 defmt::write!(fmt, " | {}", &stringify!($name)[7..]);
121 }
122 )*
123 };
124 }
125
126 implm!(
127 STATUS_DATA_NOT_AVAILABLE,
128 STATUS_UNDERFLOW,
129 STATUS_OVERFLOW,
130 STATUS_F2_INTR,
131 STATUS_F3_INTR,
132 STATUS_F2_RX_READY,
133 STATUS_F3_RX_READY,
134 STATUS_HOST_CMD_DATA_ERR,
135 STATUS_F2_PKT_AVAILABLE,
136 STATUS_F3_PKT_AVAILABLE
137 );
138 }
139}
140
141#[cfg(feature = "log")]
142impl core::fmt::Debug for FormatStatus {
143 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
144 macro_rules! implm {
145 ($($name:ident),*) => {
146 $(
147 if self.0 & $name > 0 {
148 core::write!(fmt, " | {}", &stringify!($name)[7..])?;
149 }
150 )*
151 };
152 }
153
154 implm!(
155 STATUS_DATA_NOT_AVAILABLE,
156 STATUS_UNDERFLOW,
157 STATUS_OVERFLOW,
158 STATUS_F2_INTR,
159 STATUS_F3_INTR,
160 STATUS_F2_RX_READY,
161 STATUS_F3_RX_READY,
162 STATUS_HOST_CMD_DATA_ERR,
163 STATUS_F2_PKT_AVAILABLE,
164 STATUS_F3_PKT_AVAILABLE
165 );
166 Ok(())
167 }
168}
169
170#[cfg(feature = "log")]
171impl core::fmt::Display for FormatStatus {
172 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
173 core::fmt::Debug::fmt(self, f)
174 }
175}
176
177#[allow(dead_code)]
178pub(crate) struct FormatInterrupt(pub u16);
179
180#[cfg(feature = "defmt")]
181impl defmt::Format for FormatInterrupt {
182 fn format(&self, fmt: defmt::Formatter) {
183 macro_rules! implm {
184 ($($name:ident),*) => {
185 $(
186 if self.0 & $name > 0 {
187 defmt::write!(fmt, " | {}", &stringify!($name)[4..]);
188 }
189 )*
190 };
191 }
192
193 implm!(
194 IRQ_DATA_UNAVAILABLE,
195 IRQ_F2_F3_FIFO_RD_UNDERFLOW,
196 IRQ_F2_F3_FIFO_WR_OVERFLOW,
197 IRQ_COMMAND_ERROR,
198 IRQ_DATA_ERROR,
199 IRQ_F2_PACKET_AVAILABLE,
200 IRQ_F3_PACKET_AVAILABLE,
201 IRQ_F1_OVERFLOW,
202 IRQ_MISC_INTR0,
203 IRQ_MISC_INTR1,
204 IRQ_MISC_INTR2,
205 IRQ_MISC_INTR3,
206 IRQ_MISC_INTR4,
207 IRQ_F1_INTR,
208 IRQ_F2_INTR,
209 IRQ_F3_INTR
210 );
211 }
212}
213
214#[cfg(feature = "log")]
215impl core::fmt::Debug for FormatInterrupt {
216 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
217 macro_rules! implm {
218 ($($name:ident),*) => {
219 $(
220 if self.0 & $name > 0 {
221 core::write!(fmt, " | {}", &stringify!($name)[7..])?;
222 }
223 )*
224 };
225 }
226
227 implm!(
228 IRQ_DATA_UNAVAILABLE,
229 IRQ_F2_F3_FIFO_RD_UNDERFLOW,
230 IRQ_F2_F3_FIFO_WR_OVERFLOW,
231 IRQ_COMMAND_ERROR,
232 IRQ_DATA_ERROR,
233 IRQ_F2_PACKET_AVAILABLE,
234 IRQ_F3_PACKET_AVAILABLE,
235 IRQ_F1_OVERFLOW,
236 IRQ_MISC_INTR0,
237 IRQ_MISC_INTR1,
238 IRQ_MISC_INTR2,
239 IRQ_MISC_INTR3,
240 IRQ_MISC_INTR4,
241 IRQ_F1_INTR,
242 IRQ_F2_INTR,
243 IRQ_F3_INTR
244 );
245 Ok(())
246 }
247}
248
249#[cfg(feature = "log")]
250impl core::fmt::Display for FormatInterrupt {
251 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
252 core::fmt::Debug::fmt(self, f)
253 }
254}
diff --git a/src/ioctl.rs b/src/ioctl.rs
index f5ab410db..89b20a2d6 100644
--- a/src/ioctl.rs
+++ b/src/ioctl.rs
@@ -75,7 +75,6 @@ impl IoctlState {
75 pub async fn wait_pending(&self) -> PendingIoctl { 75 pub async fn wait_pending(&self) -> PendingIoctl {
76 let pending = poll_fn(|cx| { 76 let pending = poll_fn(|cx| {
77 if let IoctlStateInner::Pending(pending) = self.state.get() { 77 if let IoctlStateInner::Pending(pending) = self.state.get() {
78 warn!("found pending ioctl");
79 Poll::Ready(pending) 78 Poll::Ready(pending)
80 } else { 79 } else {
81 self.register_runner(cx.waker()); 80 self.register_runner(cx.waker());
@@ -93,7 +92,6 @@ impl IoctlState {
93 } 92 }
94 93
95 pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize { 94 pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize {
96 warn!("doing ioctl");
97 self.state 95 self.state
98 .set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface })); 96 .set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface }));
99 self.wake_runner(); 97 self.wake_runner();
@@ -102,7 +100,6 @@ impl IoctlState {
102 100
103 pub fn ioctl_done(&self, response: &[u8]) { 101 pub fn ioctl_done(&self, response: &[u8]) {
104 if let IoctlStateInner::Sent { buf } = self.state.get() { 102 if let IoctlStateInner::Sent { buf } = self.state.get() {
105 warn!("ioctl complete");
106 // TODO fix this 103 // TODO fix this
107 (unsafe { &mut *buf }[..response.len()]).copy_from_slice(response); 104 (unsafe { &mut *buf }[..response.len()]).copy_from_slice(response);
108 105
diff --git a/src/runner.rs b/src/runner.rs
index 4abccf48b..abfac3ae3 100644
--- a/src/runner.rs
+++ b/src/runner.rs
@@ -1,7 +1,6 @@
1use core::slice; 1use core::slice;
2 2
3use embassy_futures::select::{select3, Either3}; 3use embassy_futures::select::{select3, Either3};
4use embassy_futures::yield_now;
5use embassy_net_driver_channel as ch; 4use embassy_net_driver_channel as ch;
6use embassy_sync::pubsub::PubSubBehavior; 5use embassy_sync::pubsub::PubSubBehavior;
7use embassy_time::{block_for, Duration, Timer}; 6use embassy_time::{block_for, Duration, Timer};
@@ -122,7 +121,11 @@ where
122 while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {} 121 while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {}
123 122
124 // "Set up the interrupt mask and enable interrupts" 123 // "Set up the interrupt mask and enable interrupts"
125 self.bus.bp_write32(CHIP.sdiod_core_base_address + 0x24, 0xF0).await; 124 // self.bus.bp_write32(CHIP.sdiod_core_base_address + 0x24, 0xF0).await;
125
126 self.bus
127 .write16(FUNC_BUS, REG_BUS_INTERRUPT_ENABLE, IRQ_F2_PACKET_AVAILABLE)
128 .await;
126 129
127 // "Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped." 130 // "Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped."
128 // Sounds scary... 131 // Sounds scary...
@@ -227,22 +230,22 @@ where
227 #[cfg(feature = "firmware-logs")] 230 #[cfg(feature = "firmware-logs")]
228 self.log_read().await; 231 self.log_read().await;
229 232
230 let ev = || async {
231 // TODO use IRQs
232 yield_now().await;
233 };
234
235 if self.has_credit() { 233 if self.has_credit() {
236 let ioctl = self.ioctl_state.wait_pending(); 234 let ioctl = self.ioctl_state.wait_pending();
237 let tx = self.ch.tx_buf(); 235 let tx = self.ch.tx_buf();
238 236 let ev = self.bus.wait_for_event();
239 match select3(ioctl, tx, ev()).await { 237
240 Either3::First(PendingIoctl { buf, kind, cmd, iface }) => { 238 match select3(ioctl, tx, ev).await {
241 warn!("ioctl"); 239 Either3::First(PendingIoctl {
242 self.send_ioctl(kind, cmd, iface, unsafe { &*buf }).await; 240 buf: iobuf,
241 kind,
242 cmd,
243 iface,
244 }) => {
245 self.send_ioctl(kind, cmd, iface, unsafe { &*iobuf }).await;
246 self.check_status(&mut buf).await;
243 } 247 }
244 Either3::Second(packet) => { 248 Either3::Second(packet) => {
245 warn!("packet");
246 trace!("tx pkt {:02x}", Bytes(&packet[..packet.len().min(48)])); 249 trace!("tx pkt {:02x}", Bytes(&packet[..packet.len().min(48)]));
247 250
248 let mut buf = [0; 512]; 251 let mut buf = [0; 512];
@@ -284,46 +287,47 @@ where
284 287
285 self.bus.wlan_write(&buf[..(total_len / 4)]).await; 288 self.bus.wlan_write(&buf[..(total_len / 4)]).await;
286 self.ch.tx_done(); 289 self.ch.tx_done();
290 self.check_status(&mut buf).await;
287 } 291 }
288 Either3::Third(()) => { 292 Either3::Third(()) => {
289 // Receive stuff 293 self.handle_irq(&mut buf).await;
290 let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await;
291
292 if irq & IRQ_F2_PACKET_AVAILABLE != 0 {
293 let mut status = 0xFFFF_FFFF;
294 while status == 0xFFFF_FFFF {
295 status = self.bus.read32(FUNC_BUS, REG_BUS_STATUS).await;
296 }
297
298 if status & STATUS_F2_PKT_AVAILABLE != 0 {
299 let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT;
300 self.bus.wlan_read(&mut buf, len).await;
301 trace!("rx {:02x}", Bytes(&slice8_mut(&mut buf)[..(len as usize).min(48)]));
302 self.rx(&slice8_mut(&mut buf)[..len as usize]);
303 }
304 }
305 } 294 }
306 } 295 }
307 } else { 296 } else {
308 warn!("TX stalled"); 297 warn!("TX stalled");
309 ev().await; 298 self.bus.wait_for_event().await;
299 self.handle_irq(&mut buf).await;
300 }
301 }
302 }
310 303
311 // Receive stuff 304 /// Wait for IRQ on F2 packet available
312 let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await; 305 async fn handle_irq(&mut self, buf: &mut [u32; 512]) {
306 // Receive stuff
307 let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await;
308 trace!("irq{}", FormatInterrupt(irq));
313 309
314 if irq & IRQ_F2_PACKET_AVAILABLE != 0 { 310 if irq & IRQ_F2_PACKET_AVAILABLE != 0 {
315 let mut status = 0xFFFF_FFFF; 311 self.check_status(buf).await;
316 while status == 0xFFFF_FFFF { 312 }
317 status = self.bus.read32(FUNC_BUS, REG_BUS_STATUS).await; 313 }
318 }
319 314
320 if status & STATUS_F2_PKT_AVAILABLE != 0 { 315 /// Handle F2 events while status register is set
321 let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT; 316 async fn check_status(&mut self, buf: &mut [u32; 512]) {
322 self.bus.wlan_read(&mut buf, len).await; 317 loop {
323 trace!("rx {:02x}", Bytes(&slice8_mut(&mut buf)[..(len as usize).min(48)])); 318 let mut status = 0xFFFF_FFFF;
324 self.rx(&slice8_mut(&mut buf)[..len as usize]); 319 while status == 0xFFFF_FFFF {
325 } 320 status = self.bus.read32(FUNC_BUS, REG_BUS_STATUS).await;
326 } 321 }
322 trace!("check status{}", FormatStatus(status));
323
324 if status & STATUS_F2_PKT_AVAILABLE != 0 {
325 let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT;
326 self.bus.wlan_read(buf, len).await;
327 trace!("rx {:02x}", Bytes(&slice8_mut(buf)[..(len as usize).min(48)]));
328 self.rx(&slice8_mut(buf)[..len as usize]);
329 } else {
330 break;
327 } 331 }
328 } 332 }
329 } 333 }