diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-03-27 16:08:22 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-03-27 16:08:22 +0000 |
| commit | 273e6f5b835afe9883a37814a76caba2084d6dc2 (patch) | |
| tree | 3c13c61ab4bb28e6b14bba1157df01ad335fe9ea /src | |
| parent | 07fe37b5ee5d5643eca4bc8db13d8bed5399cefa (diff) | |
| parent | 8926397f4592f22a5ed54f772a979578ca36628f (diff) | |
Merge pull request #47 from kbleeke/pio-irq
Use IRQ instead of polling the status register
Diffstat (limited to 'src')
| -rw-r--r-- | src/bus.rs | 14 | ||||
| -rw-r--r-- | src/consts.rs | 149 | ||||
| -rw-r--r-- | src/ioctl.rs | 3 | ||||
| -rw-r--r-- | src/runner.rs | 92 |
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 @@ | |||
| 1 | use core::slice; | 1 | use core::slice; |
| 2 | 2 | ||
| 3 | use embassy_futures::yield_now; | ||
| 3 | use embassy_time::{Duration, Timer}; | 4 | use embassy_time::{Duration, Timer}; |
| 4 | use embedded_hal_1::digital::OutputPin; | 5 | use embedded_hal_1::digital::OutputPin; |
| 5 | use futures::FutureExt; | 6 | use 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 | ||
| 24 | pub(crate) struct Bus<PWR, SPI> { | 31 | pub(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 | ||
| 302 | fn swap16(x: u32) -> u32 { | 314 | fn 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 | |||
| 2 | pub(crate) const FUNC_BUS: u32 = 0; | 3 | pub(crate) const FUNC_BUS: u32 = 0; |
| 3 | pub(crate) const FUNC_BACKPLANE: u32 = 1; | 4 | pub(crate) const FUNC_BACKPLANE: u32 = 1; |
| 4 | pub(crate) const FUNC_WLAN: u32 = 2; | 5 | pub(crate) const FUNC_WLAN: u32 = 2; |
| @@ -13,6 +14,8 @@ pub(crate) const REG_BUS_TEST_RW: u32 = 0x18; | |||
| 13 | pub(crate) const REG_BUS_RESP_DELAY: u32 = 0x1c; | 14 | pub(crate) const REG_BUS_RESP_DELAY: u32 = 0x1c; |
| 14 | pub(crate) const WORD_LENGTH_32: u32 = 0x1; | 15 | pub(crate) const WORD_LENGTH_32: u32 = 0x1; |
| 15 | pub(crate) const HIGH_SPEED: u32 = 0x10; | 16 | pub(crate) const HIGH_SPEED: u32 = 0x10; |
| 17 | pub(crate) const INTERRUPT_HIGH: u32 = 1 << 5; | ||
| 18 | pub(crate) const WAKE_UP: u32 = 1 << 7; | ||
| 16 | 19 | ||
| 17 | // SPI_STATUS_REGISTER bits | 20 | // SPI_STATUS_REGISTER bits |
| 18 | pub(crate) const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001; | 21 | pub(crate) const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001; |
| @@ -103,3 +106,149 @@ pub(crate) const WRITE: bool = true; | |||
| 103 | pub(crate) const READ: bool = false; | 106 | pub(crate) const READ: bool = false; |
| 104 | pub(crate) const INC_ADDR: bool = true; | 107 | pub(crate) const INC_ADDR: bool = true; |
| 105 | pub(crate) const FIXED_ADDR: bool = false; | 108 | pub(crate) const FIXED_ADDR: bool = false; |
| 109 | |||
| 110 | #[allow(dead_code)] | ||
| 111 | pub(crate) struct FormatStatus(pub u32); | ||
| 112 | |||
| 113 | #[cfg(feature = "defmt")] | ||
| 114 | impl 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")] | ||
| 142 | impl 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")] | ||
| 171 | impl 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)] | ||
| 178 | pub(crate) struct FormatInterrupt(pub u16); | ||
| 179 | |||
| 180 | #[cfg(feature = "defmt")] | ||
| 181 | impl 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")] | ||
| 215 | impl 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")] | ||
| 250 | impl 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 @@ | |||
| 1 | use core::slice; | 1 | use core::slice; |
| 2 | 2 | ||
| 3 | use embassy_futures::select::{select3, Either3}; | 3 | use embassy_futures::select::{select3, Either3}; |
| 4 | use embassy_futures::yield_now; | ||
| 5 | use embassy_net_driver_channel as ch; | 4 | use embassy_net_driver_channel as ch; |
| 6 | use embassy_sync::pubsub::PubSubBehavior; | 5 | use embassy_sync::pubsub::PubSubBehavior; |
| 7 | use embassy_time::{block_for, Duration, Timer}; | 6 | use 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 | } |
