Merge pull request #47 from kbleeke/pio-irq
Use IRQ instead of polling the status register
This commit is contained in:
commit
273e6f5b83
@ -41,6 +41,9 @@ where
|
|||||||
"in pins, 1 side 1"
|
"in pins, 1 side 1"
|
||||||
"jmp y-- lp2 side 0"
|
"jmp y-- lp2 side 0"
|
||||||
|
|
||||||
|
"wait 1 pin 0 side 0"
|
||||||
|
"irq 0 side 0"
|
||||||
|
|
||||||
".wrap"
|
".wrap"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -106,6 +109,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn write(&mut self, write: &[u32]) {
|
pub async fn write(&mut self, write: &[u32]) {
|
||||||
|
self.sm.set_enable(false);
|
||||||
let write_bits = write.len() * 32 - 1;
|
let write_bits = write.len() * 32 - 1;
|
||||||
let read_bits = 31;
|
let read_bits = 31;
|
||||||
|
|
||||||
@ -124,11 +128,10 @@ where
|
|||||||
let mut status = 0;
|
let mut status = 0;
|
||||||
self.sm.dma_pull(dma, slice::from_mut(&mut status)).await;
|
self.sm.dma_pull(dma, slice::from_mut(&mut status)).await;
|
||||||
defmt::trace!("{:#08x}", status);
|
defmt::trace!("{:#08x}", status);
|
||||||
|
|
||||||
self.sm.set_enable(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn cmd_read(&mut self, cmd: u32, read: &mut [u32]) {
|
pub async fn cmd_read(&mut self, cmd: u32, read: &mut [u32]) {
|
||||||
|
self.sm.set_enable(false);
|
||||||
let write_bits = 31;
|
let write_bits = 31;
|
||||||
let read_bits = read.len() * 32 - 1;
|
let read_bits = read.len() * 32 - 1;
|
||||||
|
|
||||||
@ -144,8 +147,6 @@ where
|
|||||||
|
|
||||||
self.sm.dma_push(dma.reborrow(), slice::from_ref(&cmd)).await;
|
self.sm.dma_push(dma.reborrow(), slice::from_ref(&cmd)).await;
|
||||||
self.sm.dma_pull(dma, read).await;
|
self.sm.dma_pull(dma, read).await;
|
||||||
|
|
||||||
self.sm.set_enable(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,4 +167,9 @@ where
|
|||||||
self.cmd_read(write, read).await;
|
self.cmd_read(write, read).await;
|
||||||
self.cs.set_high();
|
self.cs.set_high();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn wait_for_event(&mut self) {
|
||||||
|
self.sm.wait_irq(0).await;
|
||||||
|
self.sm.clear_irq(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
14
src/bus.rs
14
src/bus.rs
@ -1,5 +1,6 @@
|
|||||||
use core::slice;
|
use core::slice;
|
||||||
|
|
||||||
|
use embassy_futures::yield_now;
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use embedded_hal_1::digital::OutputPin;
|
use embedded_hal_1::digital::OutputPin;
|
||||||
use futures::FutureExt;
|
use futures::FutureExt;
|
||||||
@ -19,6 +20,12 @@ pub trait SpiBusCyw43 {
|
|||||||
/// Backplane reads have a response delay that produces one extra unspecified word at the beginning of `read`.
|
/// Backplane reads have a response delay that produces one extra unspecified word at the beginning of `read`.
|
||||||
/// Callers that want to read `n` word from the backplane, have to provide a slice that is `n+1` words long.
|
/// Callers that want to read `n` word from the backplane, have to provide a slice that is `n+1` words long.
|
||||||
async fn cmd_read(&mut self, write: u32, read: &mut [u32]);
|
async fn cmd_read(&mut self, write: u32, read: &mut [u32]);
|
||||||
|
|
||||||
|
/// Wait for events from the Device. A typical implementation would wait for the IRQ pin to be high.
|
||||||
|
/// The default implementation always reports ready, resulting in active polling of the device.
|
||||||
|
async fn wait_for_event(&mut self) {
|
||||||
|
yield_now().await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Bus<PWR, SPI> {
|
pub(crate) struct Bus<PWR, SPI> {
|
||||||
@ -63,7 +70,8 @@ where
|
|||||||
trace!("{:#010b}", (val & 0xff));
|
trace!("{:#010b}", (val & 0xff));
|
||||||
|
|
||||||
// 32-bit word length, little endian (which is the default endianess).
|
// 32-bit word length, little endian (which is the default endianess).
|
||||||
self.write32_swapped(REG_BUS_CTRL, WORD_LENGTH_32 | HIGH_SPEED).await;
|
self.write32_swapped(REG_BUS_CTRL, WORD_LENGTH_32 | HIGH_SPEED | INTERRUPT_HIGH | WAKE_UP)
|
||||||
|
.await;
|
||||||
|
|
||||||
let val = self.read8(FUNC_BUS, REG_BUS_CTRL).await;
|
let val = self.read8(FUNC_BUS, REG_BUS_CTRL).await;
|
||||||
trace!("{:#b}", val);
|
trace!("{:#b}", val);
|
||||||
@ -297,6 +305,10 @@ where
|
|||||||
|
|
||||||
self.spi.cmd_write(&buf).await;
|
self.spi.cmd_write(&buf).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn wait_for_event(&mut self) {
|
||||||
|
self.spi.wait_for_event().await;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn swap16(x: u32) -> u32 {
|
fn swap16(x: u32) -> u32 {
|
||||||
|
149
src/consts.rs
149
src/consts.rs
@ -1,4 +1,5 @@
|
|||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
|
|
||||||
pub(crate) const FUNC_BUS: u32 = 0;
|
pub(crate) const FUNC_BUS: u32 = 0;
|
||||||
pub(crate) const FUNC_BACKPLANE: u32 = 1;
|
pub(crate) const FUNC_BACKPLANE: u32 = 1;
|
||||||
pub(crate) const FUNC_WLAN: u32 = 2;
|
pub(crate) const FUNC_WLAN: u32 = 2;
|
||||||
@ -13,6 +14,8 @@ pub(crate) const REG_BUS_TEST_RW: u32 = 0x18;
|
|||||||
pub(crate) const REG_BUS_RESP_DELAY: u32 = 0x1c;
|
pub(crate) const REG_BUS_RESP_DELAY: u32 = 0x1c;
|
||||||
pub(crate) const WORD_LENGTH_32: u32 = 0x1;
|
pub(crate) const WORD_LENGTH_32: u32 = 0x1;
|
||||||
pub(crate) const HIGH_SPEED: u32 = 0x10;
|
pub(crate) const HIGH_SPEED: u32 = 0x10;
|
||||||
|
pub(crate) const INTERRUPT_HIGH: u32 = 1 << 5;
|
||||||
|
pub(crate) const WAKE_UP: u32 = 1 << 7;
|
||||||
|
|
||||||
// SPI_STATUS_REGISTER bits
|
// SPI_STATUS_REGISTER bits
|
||||||
pub(crate) const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001;
|
pub(crate) const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001;
|
||||||
@ -103,3 +106,149 @@ pub(crate) const WRITE: bool = true;
|
|||||||
pub(crate) const READ: bool = false;
|
pub(crate) const READ: bool = false;
|
||||||
pub(crate) const INC_ADDR: bool = true;
|
pub(crate) const INC_ADDR: bool = true;
|
||||||
pub(crate) const FIXED_ADDR: bool = false;
|
pub(crate) const FIXED_ADDR: bool = false;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub(crate) struct FormatStatus(pub u32);
|
||||||
|
|
||||||
|
#[cfg(feature = "defmt")]
|
||||||
|
impl defmt::Format for FormatStatus {
|
||||||
|
fn format(&self, fmt: defmt::Formatter) {
|
||||||
|
macro_rules! implm {
|
||||||
|
($($name:ident),*) => {
|
||||||
|
$(
|
||||||
|
if self.0 & $name > 0 {
|
||||||
|
defmt::write!(fmt, " | {}", &stringify!($name)[7..]);
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
implm!(
|
||||||
|
STATUS_DATA_NOT_AVAILABLE,
|
||||||
|
STATUS_UNDERFLOW,
|
||||||
|
STATUS_OVERFLOW,
|
||||||
|
STATUS_F2_INTR,
|
||||||
|
STATUS_F3_INTR,
|
||||||
|
STATUS_F2_RX_READY,
|
||||||
|
STATUS_F3_RX_READY,
|
||||||
|
STATUS_HOST_CMD_DATA_ERR,
|
||||||
|
STATUS_F2_PKT_AVAILABLE,
|
||||||
|
STATUS_F3_PKT_AVAILABLE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "log")]
|
||||||
|
impl core::fmt::Debug for FormatStatus {
|
||||||
|
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
|
macro_rules! implm {
|
||||||
|
($($name:ident),*) => {
|
||||||
|
$(
|
||||||
|
if self.0 & $name > 0 {
|
||||||
|
core::write!(fmt, " | {}", &stringify!($name)[7..])?;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
implm!(
|
||||||
|
STATUS_DATA_NOT_AVAILABLE,
|
||||||
|
STATUS_UNDERFLOW,
|
||||||
|
STATUS_OVERFLOW,
|
||||||
|
STATUS_F2_INTR,
|
||||||
|
STATUS_F3_INTR,
|
||||||
|
STATUS_F2_RX_READY,
|
||||||
|
STATUS_F3_RX_READY,
|
||||||
|
STATUS_HOST_CMD_DATA_ERR,
|
||||||
|
STATUS_F2_PKT_AVAILABLE,
|
||||||
|
STATUS_F3_PKT_AVAILABLE
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "log")]
|
||||||
|
impl core::fmt::Display for FormatStatus {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
core::fmt::Debug::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub(crate) struct FormatInterrupt(pub u16);
|
||||||
|
|
||||||
|
#[cfg(feature = "defmt")]
|
||||||
|
impl defmt::Format for FormatInterrupt {
|
||||||
|
fn format(&self, fmt: defmt::Formatter) {
|
||||||
|
macro_rules! implm {
|
||||||
|
($($name:ident),*) => {
|
||||||
|
$(
|
||||||
|
if self.0 & $name > 0 {
|
||||||
|
defmt::write!(fmt, " | {}", &stringify!($name)[4..]);
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
implm!(
|
||||||
|
IRQ_DATA_UNAVAILABLE,
|
||||||
|
IRQ_F2_F3_FIFO_RD_UNDERFLOW,
|
||||||
|
IRQ_F2_F3_FIFO_WR_OVERFLOW,
|
||||||
|
IRQ_COMMAND_ERROR,
|
||||||
|
IRQ_DATA_ERROR,
|
||||||
|
IRQ_F2_PACKET_AVAILABLE,
|
||||||
|
IRQ_F3_PACKET_AVAILABLE,
|
||||||
|
IRQ_F1_OVERFLOW,
|
||||||
|
IRQ_MISC_INTR0,
|
||||||
|
IRQ_MISC_INTR1,
|
||||||
|
IRQ_MISC_INTR2,
|
||||||
|
IRQ_MISC_INTR3,
|
||||||
|
IRQ_MISC_INTR4,
|
||||||
|
IRQ_F1_INTR,
|
||||||
|
IRQ_F2_INTR,
|
||||||
|
IRQ_F3_INTR
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "log")]
|
||||||
|
impl core::fmt::Debug for FormatInterrupt {
|
||||||
|
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
|
macro_rules! implm {
|
||||||
|
($($name:ident),*) => {
|
||||||
|
$(
|
||||||
|
if self.0 & $name > 0 {
|
||||||
|
core::write!(fmt, " | {}", &stringify!($name)[7..])?;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
implm!(
|
||||||
|
IRQ_DATA_UNAVAILABLE,
|
||||||
|
IRQ_F2_F3_FIFO_RD_UNDERFLOW,
|
||||||
|
IRQ_F2_F3_FIFO_WR_OVERFLOW,
|
||||||
|
IRQ_COMMAND_ERROR,
|
||||||
|
IRQ_DATA_ERROR,
|
||||||
|
IRQ_F2_PACKET_AVAILABLE,
|
||||||
|
IRQ_F3_PACKET_AVAILABLE,
|
||||||
|
IRQ_F1_OVERFLOW,
|
||||||
|
IRQ_MISC_INTR0,
|
||||||
|
IRQ_MISC_INTR1,
|
||||||
|
IRQ_MISC_INTR2,
|
||||||
|
IRQ_MISC_INTR3,
|
||||||
|
IRQ_MISC_INTR4,
|
||||||
|
IRQ_F1_INTR,
|
||||||
|
IRQ_F2_INTR,
|
||||||
|
IRQ_F3_INTR
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "log")]
|
||||||
|
impl core::fmt::Display for FormatInterrupt {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
core::fmt::Debug::fmt(self, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -75,7 +75,6 @@ impl IoctlState {
|
|||||||
pub async fn wait_pending(&self) -> PendingIoctl {
|
pub async fn wait_pending(&self) -> PendingIoctl {
|
||||||
let pending = poll_fn(|cx| {
|
let pending = poll_fn(|cx| {
|
||||||
if let IoctlStateInner::Pending(pending) = self.state.get() {
|
if let IoctlStateInner::Pending(pending) = self.state.get() {
|
||||||
warn!("found pending ioctl");
|
|
||||||
Poll::Ready(pending)
|
Poll::Ready(pending)
|
||||||
} else {
|
} else {
|
||||||
self.register_runner(cx.waker());
|
self.register_runner(cx.waker());
|
||||||
@ -93,7 +92,6 @@ impl IoctlState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize {
|
pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize {
|
||||||
warn!("doing ioctl");
|
|
||||||
self.state
|
self.state
|
||||||
.set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface }));
|
.set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface }));
|
||||||
self.wake_runner();
|
self.wake_runner();
|
||||||
@ -102,7 +100,6 @@ impl IoctlState {
|
|||||||
|
|
||||||
pub fn ioctl_done(&self, response: &[u8]) {
|
pub fn ioctl_done(&self, response: &[u8]) {
|
||||||
if let IoctlStateInner::Sent { buf } = self.state.get() {
|
if let IoctlStateInner::Sent { buf } = self.state.get() {
|
||||||
warn!("ioctl complete");
|
|
||||||
// TODO fix this
|
// TODO fix this
|
||||||
(unsafe { &mut *buf }[..response.len()]).copy_from_slice(response);
|
(unsafe { &mut *buf }[..response.len()]).copy_from_slice(response);
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
use core::slice;
|
use core::slice;
|
||||||
|
|
||||||
use embassy_futures::select::{select3, Either3};
|
use embassy_futures::select::{select3, Either3};
|
||||||
use embassy_futures::yield_now;
|
|
||||||
use embassy_net_driver_channel as ch;
|
use embassy_net_driver_channel as ch;
|
||||||
use embassy_sync::pubsub::PubSubBehavior;
|
use embassy_sync::pubsub::PubSubBehavior;
|
||||||
use embassy_time::{block_for, Duration, Timer};
|
use embassy_time::{block_for, Duration, Timer};
|
||||||
@ -122,7 +121,11 @@ where
|
|||||||
while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {}
|
while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {}
|
||||||
|
|
||||||
// "Set up the interrupt mask and enable interrupts"
|
// "Set up the interrupt mask and enable interrupts"
|
||||||
self.bus.bp_write32(CHIP.sdiod_core_base_address + 0x24, 0xF0).await;
|
// self.bus.bp_write32(CHIP.sdiod_core_base_address + 0x24, 0xF0).await;
|
||||||
|
|
||||||
|
self.bus
|
||||||
|
.write16(FUNC_BUS, REG_BUS_INTERRUPT_ENABLE, IRQ_F2_PACKET_AVAILABLE)
|
||||||
|
.await;
|
||||||
|
|
||||||
// "Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped."
|
// "Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped."
|
||||||
// Sounds scary...
|
// Sounds scary...
|
||||||
@ -227,22 +230,22 @@ where
|
|||||||
#[cfg(feature = "firmware-logs")]
|
#[cfg(feature = "firmware-logs")]
|
||||||
self.log_read().await;
|
self.log_read().await;
|
||||||
|
|
||||||
let ev = || async {
|
|
||||||
// TODO use IRQs
|
|
||||||
yield_now().await;
|
|
||||||
};
|
|
||||||
|
|
||||||
if self.has_credit() {
|
if self.has_credit() {
|
||||||
let ioctl = self.ioctl_state.wait_pending();
|
let ioctl = self.ioctl_state.wait_pending();
|
||||||
let tx = self.ch.tx_buf();
|
let tx = self.ch.tx_buf();
|
||||||
|
let ev = self.bus.wait_for_event();
|
||||||
|
|
||||||
match select3(ioctl, tx, ev()).await {
|
match select3(ioctl, tx, ev).await {
|
||||||
Either3::First(PendingIoctl { buf, kind, cmd, iface }) => {
|
Either3::First(PendingIoctl {
|
||||||
warn!("ioctl");
|
buf: iobuf,
|
||||||
self.send_ioctl(kind, cmd, iface, unsafe { &*buf }).await;
|
kind,
|
||||||
|
cmd,
|
||||||
|
iface,
|
||||||
|
}) => {
|
||||||
|
self.send_ioctl(kind, cmd, iface, unsafe { &*iobuf }).await;
|
||||||
|
self.check_status(&mut buf).await;
|
||||||
}
|
}
|
||||||
Either3::Second(packet) => {
|
Either3::Second(packet) => {
|
||||||
warn!("packet");
|
|
||||||
trace!("tx pkt {:02x}", Bytes(&packet[..packet.len().min(48)]));
|
trace!("tx pkt {:02x}", Bytes(&packet[..packet.len().min(48)]));
|
||||||
|
|
||||||
let mut buf = [0; 512];
|
let mut buf = [0; 512];
|
||||||
@ -284,46 +287,47 @@ where
|
|||||||
|
|
||||||
self.bus.wlan_write(&buf[..(total_len / 4)]).await;
|
self.bus.wlan_write(&buf[..(total_len / 4)]).await;
|
||||||
self.ch.tx_done();
|
self.ch.tx_done();
|
||||||
|
self.check_status(&mut buf).await;
|
||||||
}
|
}
|
||||||
Either3::Third(()) => {
|
Either3::Third(()) => {
|
||||||
// Receive stuff
|
self.handle_irq(&mut buf).await;
|
||||||
let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await;
|
|
||||||
|
|
||||||
if irq & IRQ_F2_PACKET_AVAILABLE != 0 {
|
|
||||||
let mut status = 0xFFFF_FFFF;
|
|
||||||
while status == 0xFFFF_FFFF {
|
|
||||||
status = self.bus.read32(FUNC_BUS, REG_BUS_STATUS).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
if status & STATUS_F2_PKT_AVAILABLE != 0 {
|
|
||||||
let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT;
|
|
||||||
self.bus.wlan_read(&mut buf, len).await;
|
|
||||||
trace!("rx {:02x}", Bytes(&slice8_mut(&mut buf)[..(len as usize).min(48)]));
|
|
||||||
self.rx(&slice8_mut(&mut buf)[..len as usize]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn!("TX stalled");
|
warn!("TX stalled");
|
||||||
ev().await;
|
self.bus.wait_for_event().await;
|
||||||
|
self.handle_irq(&mut buf).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Receive stuff
|
/// Wait for IRQ on F2 packet available
|
||||||
let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await;
|
async fn handle_irq(&mut self, buf: &mut [u32; 512]) {
|
||||||
|
// Receive stuff
|
||||||
|
let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await;
|
||||||
|
trace!("irq{}", FormatInterrupt(irq));
|
||||||
|
|
||||||
if irq & IRQ_F2_PACKET_AVAILABLE != 0 {
|
if irq & IRQ_F2_PACKET_AVAILABLE != 0 {
|
||||||
let mut status = 0xFFFF_FFFF;
|
self.check_status(buf).await;
|
||||||
while status == 0xFFFF_FFFF {
|
}
|
||||||
status = self.bus.read32(FUNC_BUS, REG_BUS_STATUS).await;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if status & STATUS_F2_PKT_AVAILABLE != 0 {
|
/// Handle F2 events while status register is set
|
||||||
let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT;
|
async fn check_status(&mut self, buf: &mut [u32; 512]) {
|
||||||
self.bus.wlan_read(&mut buf, len).await;
|
loop {
|
||||||
trace!("rx {:02x}", Bytes(&slice8_mut(&mut buf)[..(len as usize).min(48)]));
|
let mut status = 0xFFFF_FFFF;
|
||||||
self.rx(&slice8_mut(&mut buf)[..len as usize]);
|
while status == 0xFFFF_FFFF {
|
||||||
}
|
status = self.bus.read32(FUNC_BUS, REG_BUS_STATUS).await;
|
||||||
}
|
}
|
||||||
|
trace!("check status{}", FormatStatus(status));
|
||||||
|
|
||||||
|
if status & STATUS_F2_PKT_AVAILABLE != 0 {
|
||||||
|
let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT;
|
||||||
|
self.bus.wlan_read(buf, len).await;
|
||||||
|
trace!("rx {:02x}", Bytes(&slice8_mut(buf)[..(len as usize).min(48)]));
|
||||||
|
self.rx(&slice8_mut(buf)[..len as usize]);
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user