use irqs to wait for events

This commit is contained in:
kbleeke 2023-03-02 19:02:32 +01:00
parent a2272dda08
commit b58cc2aa23
6 changed files with 87 additions and 53 deletions

View file

@ -227,4 +227,10 @@ impl cyw43::SpiBusCyw43 for MySpi {
self.read(read).await;
self.cs.set_high();
}
async fn wait_for_event(&mut self) {}
fn clear_event(&mut self) {}
}

View file

@ -41,6 +41,9 @@ where
"in pins, 1 side 1"
"jmp y-- lp2 side 0"
"wait 1 pin 0 side 0"
"irq 0 side 0"
".wrap"
);
@ -106,6 +109,7 @@ where
}
pub async fn write(&mut self, write: &[u32]) {
self.sm.set_enable(false);
let write_bits = write.len() * 32 - 1;
let read_bits = 31;
@ -124,11 +128,10 @@ where
let mut status = 0;
self.sm.dma_pull(dma, slice::from_mut(&mut status)).await;
defmt::trace!("{:#08x}", status);
self.sm.set_enable(false);
}
pub async fn cmd_read(&mut self, cmd: u32, read: &mut [u32]) {
self.sm.set_enable(false);
let write_bits = 31;
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_pull(dma, read).await;
self.sm.set_enable(false);
}
}
@ -166,4 +167,12 @@ where
self.cmd_read(write, read).await;
self.cs.set_high();
}
async fn wait_for_event(&mut self) {
self.sm.wait_irq(0).await;
}
fn clear_event(&mut self) {
self.sm.clear_irq(0);
}
}

View file

@ -19,6 +19,9 @@ pub trait SpiBusCyw43 {
/// 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.
async fn cmd_read(&mut self, write: u32, read: &mut [u32]);
async fn wait_for_event(&mut self);
fn clear_event(&mut self);
}
pub(crate) struct Bus<PWR, SPI> {
@ -63,7 +66,8 @@ where
trace!("{:#010b}", (val & 0xff));
// 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;
trace!("{:#b}", val);
@ -297,6 +301,14 @@ where
self.spi.cmd_write(&buf).await;
}
pub async fn wait_for_event(&mut self) {
self.spi.wait_for_event().await;
}
pub fn clear_event(&mut self) {
self.spi.clear_event();
}
}
fn swap16(x: u32) -> u32 {

View file

@ -14,6 +14,8 @@ pub(crate) const REG_BUS_TEST_RW: u32 = 0x18;
pub(crate) const REG_BUS_RESP_DELAY: u32 = 0x1c;
pub(crate) const WORD_LENGTH_32: u32 = 0x1;
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
pub(crate) const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001;

View file

@ -75,7 +75,6 @@ impl IoctlState {
pub async fn wait_pending(&self) -> PendingIoctl {
let pending = poll_fn(|cx| {
if let IoctlStateInner::Pending(pending) = self.state.get() {
warn!("found pending ioctl");
Poll::Ready(pending)
} else {
self.register_runner(cx.waker());
@ -89,7 +88,6 @@ impl IoctlState {
}
pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize {
warn!("doing ioctl");
self.state
.set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface }));
self.wake_runner();
@ -98,7 +96,6 @@ impl IoctlState {
pub fn ioctl_done(&self, response: &[u8]) {
if let IoctlStateInner::Sent { buf } = self.state.get() {
warn!("ioctl complete");
// TODO fix this
(unsafe { &mut *buf }[..response.len()]).copy_from_slice(response);

View file

@ -122,7 +122,11 @@ where
while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {}
// "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."
// Sounds scary...
@ -227,22 +231,22 @@ where
#[cfg(feature = "firmware-logs")]
self.log_read().await;
let ev = || async {
// TODO use IRQs
yield_now().await;
};
if self.has_credit() {
let ioctl = self.ioctl_state.wait_pending();
let tx = self.ch.tx_buf();
let ev = self.bus.wait_for_event();
match select3(ioctl, tx, ev()).await {
Either3::First(PendingIoctl { buf, kind, cmd, iface }) => {
warn!("ioctl");
self.send_ioctl(kind, cmd, iface, unsafe { &*buf }).await;
match select3(ioctl, tx, ev).await {
Either3::First(PendingIoctl {
buf: iobuf,
kind,
cmd,
iface,
}) => {
self.send_ioctl(kind, cmd, iface, unsafe { &*iobuf }).await;
self.check_status(&mut buf).await;
}
Either3::Second(packet) => {
warn!("packet");
trace!("tx pkt {:02x}", Bytes(&packet[..packet.len().min(48)]));
let mut buf = [0; 512];
@ -284,50 +288,54 @@ where
self.bus.wlan_write(&buf[..(total_len / 4)]).await;
self.ch.tx_done();
self.check_status(&mut buf).await;
}
Either3::Third(()) => {
// Receive stuff
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]);
}
}
self.handle_irq(&mut buf).await;
}
}
} else {
warn!("TX stalled");
ev().await;
// Receive stuff
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]);
}
}
self.bus.wait_for_event().await;
self.handle_irq(&mut buf).await;
}
}
}
/// Wait for IRQ on F2 packet available
async fn handle_irq(&mut self, buf: &mut [u32; 512]) {
self.bus.clear_event();
// Receive stuff
let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await;
trace!("irq{}", FormatInterrupt(irq));
if irq & IRQ_F2_PACKET_AVAILABLE != 0 {
self.check_status(buf).await;
}
}
/// Handle F2 events while status register is set
async fn check_status(&mut self, buf: &mut [u32; 512]) {
loop {
let mut status = 0xFFFF_FFFF;
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;
}
yield_now().await;
}
}
fn rx(&mut self, packet: &[u8]) {
if packet.len() < SdpcmHeader::SIZE {
warn!("packet too short, len={}", packet.len());