diff --git a/src/bus.rs b/src/bus.rs new file mode 100644 index 00000000..f220cffc --- /dev/null +++ b/src/bus.rs @@ -0,0 +1,321 @@ +use core::slice; + +use embassy_time::{Duration, Timer}; +use embedded_hal_1::digital::OutputPin; +use embedded_hal_async::spi::{transaction, SpiBusRead, SpiBusWrite, SpiDevice}; + +use crate::consts::*; + +pub(crate) struct Bus { + backplane_window: u32, + pwr: PWR, + spi: SPI, +} + +impl Bus +where + PWR: OutputPin, + SPI: SpiDevice, + SPI::Bus: SpiBusRead + SpiBusWrite, +{ + pub(crate) fn new(pwr: PWR, spi: SPI) -> Self { + Self { + backplane_window: 0xAAAA_AAAA, + pwr, + spi, + } + } + + pub async fn init(&mut self) { + // Reset + self.pwr.set_low().unwrap(); + Timer::after(Duration::from_millis(20)).await; + self.pwr.set_high().unwrap(); + Timer::after(Duration::from_millis(250)).await; + + while self.read32_swapped(REG_BUS_TEST_RO).await != FEEDBEAD {} + + self.write32_swapped(REG_BUS_TEST_RW, TEST_PATTERN).await; + let val = self.read32_swapped(REG_BUS_TEST_RW).await; + assert_eq!(val, TEST_PATTERN); + + // 32-bit word length, little endian (which is the default endianess). + self.write32_swapped(REG_BUS_CTRL, WORD_LENGTH_32 | HIGH_SPEED).await; + + let val = self.read32(FUNC_BUS, REG_BUS_TEST_RO).await; + assert_eq!(val, FEEDBEAD); + let val = self.read32(FUNC_BUS, REG_BUS_TEST_RW).await; + assert_eq!(val, TEST_PATTERN); + } + + pub async fn wlan_read(&mut self, buf: &mut [u32]) { + let cmd = cmd_word(READ, INC_ADDR, FUNC_WLAN, 0, buf.len() as u32 * 4); + transaction!(&mut self.spi, |bus| async { + bus.write(&[cmd]).await?; + bus.read(buf).await?; + Ok(()) + }) + .await + .unwrap(); + } + + pub async fn wlan_write(&mut self, buf: &[u32]) { + let cmd = cmd_word(WRITE, INC_ADDR, FUNC_WLAN, 0, buf.len() as u32 * 4); + transaction!(&mut self.spi, |bus| async { + bus.write(&[cmd]).await?; + bus.write(buf).await?; + Ok(()) + }) + .await + .unwrap(); + } + + #[allow(unused)] + pub async fn bp_read(&mut self, mut addr: u32, mut data: &mut [u8]) { + // It seems the HW force-aligns the addr + // to 2 if data.len() >= 2 + // to 4 if data.len() >= 4 + // To simplify, enforce 4-align for now. + assert!(addr % 4 == 0); + + let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; + + while !data.is_empty() { + // Ensure transfer doesn't cross a window boundary. + let window_offs = addr & BACKPLANE_ADDRESS_MASK; + let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize; + + let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining); + + self.backplane_set_window(addr).await; + + let cmd = cmd_word(READ, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); + + transaction!(&mut self.spi, |bus| async { + bus.write(&[cmd]).await?; + + // 4-byte response delay. + let mut junk = [0; 1]; + bus.read(&mut junk).await?; + + // Read data + bus.read(&mut buf[..(len + 3) / 4]).await?; + Ok(()) + }) + .await + .unwrap(); + + data[..len].copy_from_slice(&slice8_mut(&mut buf)[..len]); + + // Advance ptr. + addr += len as u32; + data = &mut data[len..]; + } + } + + pub async fn bp_write(&mut self, mut addr: u32, mut data: &[u8]) { + // It seems the HW force-aligns the addr + // to 2 if data.len() >= 2 + // to 4 if data.len() >= 4 + // To simplify, enforce 4-align for now. + assert!(addr % 4 == 0); + + let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; + + while !data.is_empty() { + // Ensure transfer doesn't cross a window boundary. + let window_offs = addr & BACKPLANE_ADDRESS_MASK; + let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize; + + let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining); + slice8_mut(&mut buf)[..len].copy_from_slice(&data[..len]); + + self.backplane_set_window(addr).await; + + let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); + + transaction!(&mut self.spi, |bus| async { + bus.write(&[cmd]).await?; + bus.write(&buf[..(len + 3) / 4]).await?; + Ok(()) + }) + .await + .unwrap(); + + // Advance ptr. + addr += len as u32; + data = &data[len..]; + } + } + + pub async fn bp_read8(&mut self, addr: u32) -> u8 { + self.backplane_readn(addr, 1).await as u8 + } + + pub async fn bp_write8(&mut self, addr: u32, val: u8) { + self.backplane_writen(addr, val as u32, 1).await + } + + pub async fn bp_read16(&mut self, addr: u32) -> u16 { + self.backplane_readn(addr, 2).await as u16 + } + + #[allow(unused)] + pub async fn bp_write16(&mut self, addr: u32, val: u16) { + self.backplane_writen(addr, val as u32, 2).await + } + + #[allow(unused)] + pub async fn bp_read32(&mut self, addr: u32) -> u32 { + self.backplane_readn(addr, 4).await + } + + pub async fn bp_write32(&mut self, addr: u32, val: u32) { + self.backplane_writen(addr, val, 4).await + } + + async fn backplane_readn(&mut self, addr: u32, len: u32) -> u32 { + self.backplane_set_window(addr).await; + + let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; + if len == 4 { + bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG + } + self.readn(FUNC_BACKPLANE, bus_addr, len).await + } + + async fn backplane_writen(&mut self, addr: u32, val: u32, len: u32) { + self.backplane_set_window(addr).await; + + let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; + if len == 4 { + bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG + } + self.writen(FUNC_BACKPLANE, bus_addr, val, len).await + } + + async fn backplane_set_window(&mut self, addr: u32) { + let new_window = addr & !BACKPLANE_ADDRESS_MASK; + + if (new_window >> 24) as u8 != (self.backplane_window >> 24) as u8 { + self.write8( + FUNC_BACKPLANE, + REG_BACKPLANE_BACKPLANE_ADDRESS_HIGH, + (new_window >> 24) as u8, + ) + .await; + } + if (new_window >> 16) as u8 != (self.backplane_window >> 16) as u8 { + self.write8( + FUNC_BACKPLANE, + REG_BACKPLANE_BACKPLANE_ADDRESS_MID, + (new_window >> 16) as u8, + ) + .await; + } + if (new_window >> 8) as u8 != (self.backplane_window >> 8) as u8 { + self.write8( + FUNC_BACKPLANE, + REG_BACKPLANE_BACKPLANE_ADDRESS_LOW, + (new_window >> 8) as u8, + ) + .await; + } + self.backplane_window = new_window; + } + + pub async fn read8(&mut self, func: u32, addr: u32) -> u8 { + self.readn(func, addr, 1).await as u8 + } + + pub async fn write8(&mut self, func: u32, addr: u32, val: u8) { + self.writen(func, addr, val as u32, 1).await + } + + pub async fn read16(&mut self, func: u32, addr: u32) -> u16 { + self.readn(func, addr, 2).await as u16 + } + + #[allow(unused)] + pub async fn write16(&mut self, func: u32, addr: u32, val: u16) { + self.writen(func, addr, val as u32, 2).await + } + + pub async fn read32(&mut self, func: u32, addr: u32) -> u32 { + self.readn(func, addr, 4).await + } + + #[allow(unused)] + pub async fn write32(&mut self, func: u32, addr: u32, val: u32) { + self.writen(func, addr, val, 4).await + } + + async fn readn(&mut self, func: u32, addr: u32, len: u32) -> u32 { + let cmd = cmd_word(READ, INC_ADDR, func, addr, len); + let mut buf = [0; 1]; + + transaction!(&mut self.spi, |bus| async { + bus.write(&[cmd]).await?; + if func == FUNC_BACKPLANE { + // 4-byte response delay. + bus.read(&mut buf).await?; + } + bus.read(&mut buf).await?; + Ok(()) + }) + .await + .unwrap(); + + buf[0] + } + + async fn writen(&mut self, func: u32, addr: u32, val: u32, len: u32) { + let cmd = cmd_word(WRITE, INC_ADDR, func, addr, len); + + transaction!(&mut self.spi, |bus| async { + bus.write(&[cmd, val]).await?; + Ok(()) + }) + .await + .unwrap(); + } + + async fn read32_swapped(&mut self, addr: u32) -> u32 { + let cmd = cmd_word(READ, INC_ADDR, FUNC_BUS, addr, 4); + let mut buf = [0; 1]; + + transaction!(&mut self.spi, |bus| async { + bus.write(&[swap16(cmd)]).await?; + bus.read(&mut buf).await?; + Ok(()) + }) + .await + .unwrap(); + + swap16(buf[0]) + } + + async fn write32_swapped(&mut self, addr: u32, val: u32) { + let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BUS, addr, 4); + + transaction!(&mut self.spi, |bus| async { + bus.write(&[swap16(cmd), swap16(val)]).await?; + Ok(()) + }) + .await + .unwrap(); + } +} + +fn swap16(x: u32) -> u32 { + x.rotate_left(16) +} + +fn cmd_word(write: bool, incr: bool, func: u32, addr: u32, len: u32) -> u32 { + (write as u32) << 31 | (incr as u32) << 30 | (func & 0b11) << 28 | (addr & 0x1FFFF) << 11 | (len & 0x7FF) +} + +fn slice8_mut(x: &mut [u32]) -> &mut [u8] { + let len = x.len() * 4; + unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } +} diff --git a/src/consts.rs b/src/consts.rs new file mode 100644 index 00000000..bee70660 --- /dev/null +++ b/src/consts.rs @@ -0,0 +1,105 @@ +#![allow(unused)] +pub(crate) const FUNC_BUS: u32 = 0; +pub(crate) const FUNC_BACKPLANE: u32 = 1; +pub(crate) const FUNC_WLAN: u32 = 2; +pub(crate) const FUNC_BT: u32 = 3; + +pub(crate) const REG_BUS_CTRL: u32 = 0x0; +pub(crate) const REG_BUS_INTERRUPT: u32 = 0x04; // 16 bits - Interrupt status +pub(crate) const REG_BUS_INTERRUPT_ENABLE: u32 = 0x06; // 16 bits - Interrupt mask +pub(crate) const REG_BUS_STATUS: u32 = 0x8; +pub(crate) const REG_BUS_TEST_RO: u32 = 0x14; +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; + +// SPI_STATUS_REGISTER bits +pub(crate) const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001; +pub(crate) const STATUS_UNDERFLOW: u32 = 0x00000002; +pub(crate) const STATUS_OVERFLOW: u32 = 0x00000004; +pub(crate) const STATUS_F2_INTR: u32 = 0x00000008; +pub(crate) const STATUS_F3_INTR: u32 = 0x00000010; +pub(crate) const STATUS_F2_RX_READY: u32 = 0x00000020; +pub(crate) const STATUS_F3_RX_READY: u32 = 0x00000040; +pub(crate) const STATUS_HOST_CMD_DATA_ERR: u32 = 0x00000080; +pub(crate) const STATUS_F2_PKT_AVAILABLE: u32 = 0x00000100; +pub(crate) const STATUS_F2_PKT_LEN_MASK: u32 = 0x000FFE00; +pub(crate) const STATUS_F2_PKT_LEN_SHIFT: u32 = 9; +pub(crate) const STATUS_F3_PKT_AVAILABLE: u32 = 0x00100000; +pub(crate) const STATUS_F3_PKT_LEN_MASK: u32 = 0xFFE00000; +pub(crate) const STATUS_F3_PKT_LEN_SHIFT: u32 = 21; + +pub(crate) const REG_BACKPLANE_GPIO_SELECT: u32 = 0x10005; +pub(crate) const REG_BACKPLANE_GPIO_OUTPUT: u32 = 0x10006; +pub(crate) const REG_BACKPLANE_GPIO_ENABLE: u32 = 0x10007; +pub(crate) const REG_BACKPLANE_FUNCTION2_WATERMARK: u32 = 0x10008; +pub(crate) const REG_BACKPLANE_DEVICE_CONTROL: u32 = 0x10009; +pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_LOW: u32 = 0x1000A; +pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_MID: u32 = 0x1000B; +pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_HIGH: u32 = 0x1000C; +pub(crate) const REG_BACKPLANE_FRAME_CONTROL: u32 = 0x1000D; +pub(crate) const REG_BACKPLANE_CHIP_CLOCK_CSR: u32 = 0x1000E; +pub(crate) const REG_BACKPLANE_PULL_UP: u32 = 0x1000F; +pub(crate) const REG_BACKPLANE_READ_FRAME_BC_LOW: u32 = 0x1001B; +pub(crate) const REG_BACKPLANE_READ_FRAME_BC_HIGH: u32 = 0x1001C; +pub(crate) const REG_BACKPLANE_WAKEUP_CTRL: u32 = 0x1001E; +pub(crate) const REG_BACKPLANE_SLEEP_CSR: u32 = 0x1001F; + +pub(crate) const BACKPLANE_WINDOW_SIZE: usize = 0x8000; +pub(crate) const BACKPLANE_ADDRESS_MASK: u32 = 0x7FFF; +pub(crate) const BACKPLANE_ADDRESS_32BIT_FLAG: u32 = 0x08000; +pub(crate) const BACKPLANE_MAX_TRANSFER_SIZE: usize = 64; +// Active Low Power (ALP) clock constants +pub(crate) const BACKPLANE_ALP_AVAIL_REQ: u8 = 0x08; +pub(crate) const BACKPLANE_ALP_AVAIL: u8 = 0x40; + +// Broadcom AMBA (Advanced Microcontroller Bus Architecture) Interconnect +// (AI) pub (crate) constants +pub(crate) const AI_IOCTRL_OFFSET: u32 = 0x408; +pub(crate) const AI_IOCTRL_BIT_FGC: u8 = 0x0002; +pub(crate) const AI_IOCTRL_BIT_CLOCK_EN: u8 = 0x0001; +pub(crate) const AI_IOCTRL_BIT_CPUHALT: u8 = 0x0020; + +pub(crate) const AI_RESETCTRL_OFFSET: u32 = 0x800; +pub(crate) const AI_RESETCTRL_BIT_RESET: u8 = 1; + +pub(crate) const AI_RESETSTATUS_OFFSET: u32 = 0x804; + +pub(crate) const TEST_PATTERN: u32 = 0x12345678; +pub(crate) const FEEDBEAD: u32 = 0xFEEDBEAD; + +// SPI_INTERRUPT_REGISTER and SPI_INTERRUPT_ENABLE_REGISTER Bits +pub(crate) const IRQ_DATA_UNAVAILABLE: u16 = 0x0001; // Requested data not available; Clear by writing a "1" +pub(crate) const IRQ_F2_F3_FIFO_RD_UNDERFLOW: u16 = 0x0002; +pub(crate) const IRQ_F2_F3_FIFO_WR_OVERFLOW: u16 = 0x0004; +pub(crate) const IRQ_COMMAND_ERROR: u16 = 0x0008; // Cleared by writing 1 +pub(crate) const IRQ_DATA_ERROR: u16 = 0x0010; // Cleared by writing 1 +pub(crate) const IRQ_F2_PACKET_AVAILABLE: u16 = 0x0020; +pub(crate) const IRQ_F3_PACKET_AVAILABLE: u16 = 0x0040; +pub(crate) const IRQ_F1_OVERFLOW: u16 = 0x0080; // Due to last write. Bkplane has pending write requests +pub(crate) const IRQ_MISC_INTR0: u16 = 0x0100; +pub(crate) const IRQ_MISC_INTR1: u16 = 0x0200; +pub(crate) const IRQ_MISC_INTR2: u16 = 0x0400; +pub(crate) const IRQ_MISC_INTR3: u16 = 0x0800; +pub(crate) const IRQ_MISC_INTR4: u16 = 0x1000; +pub(crate) const IRQ_F1_INTR: u16 = 0x2000; +pub(crate) const IRQ_F2_INTR: u16 = 0x4000; +pub(crate) const IRQ_F3_INTR: u16 = 0x8000; + +pub(crate) const IOCTL_CMD_UP: u32 = 2; +pub(crate) const IOCTL_CMD_SET_SSID: u32 = 26; +pub(crate) const IOCTL_CMD_ANTDIV: u32 = 64; +pub(crate) const IOCTL_CMD_SET_VAR: u32 = 263; +pub(crate) const IOCTL_CMD_GET_VAR: u32 = 262; +pub(crate) const IOCTL_CMD_SET_PASSPHRASE: u32 = 268; + +pub(crate) const CHANNEL_TYPE_CONTROL: u8 = 0; +pub(crate) const CHANNEL_TYPE_EVENT: u8 = 1; +pub(crate) const CHANNEL_TYPE_DATA: u8 = 2; + +// CYW_SPID command structure constants. +pub(crate) const WRITE: bool = true; +pub(crate) const READ: bool = false; +pub(crate) const INC_ADDR: bool = true; +pub(crate) const FIXED_ADDR: bool = false; diff --git a/src/lib.rs b/src/lib.rs index 883e669d..fa73b32e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,8 @@ // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; +mod bus; +mod consts; mod countries; mod events; mod structs; @@ -23,132 +25,12 @@ use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::channel::Channel; use embassy_time::{block_for, Duration, Timer}; use embedded_hal_1::digital::OutputPin; -use embedded_hal_async::spi::{transaction, SpiBusRead, SpiBusWrite, SpiDevice}; +use embedded_hal_async::spi::{SpiBusRead, SpiBusWrite, SpiDevice}; -use self::structs::*; +use crate::bus::Bus; +use crate::consts::*; use crate::events::Event; - -fn swap16(x: u32) -> u32 { - x.rotate_left(16) -} - -fn cmd_word(write: bool, incr: bool, func: u32, addr: u32, len: u32) -> u32 { - (write as u32) << 31 | (incr as u32) << 30 | (func & 0b11) << 28 | (addr & 0x1FFFF) << 11 | (len & 0x7FF) -} - -fn slice8_mut(x: &mut [u32]) -> &mut [u8] { - let len = x.len() * 4; - unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } -} - -mod constants { - #![allow(unused)] - pub(crate) const FUNC_BUS: u32 = 0; - pub(crate) const FUNC_BACKPLANE: u32 = 1; - pub(crate) const FUNC_WLAN: u32 = 2; - pub(crate) const FUNC_BT: u32 = 3; - - pub(crate) const REG_BUS_CTRL: u32 = 0x0; - pub(crate) const REG_BUS_INTERRUPT: u32 = 0x04; // 16 bits - Interrupt status - pub(crate) const REG_BUS_INTERRUPT_ENABLE: u32 = 0x06; // 16 bits - Interrupt mask - pub(crate) const REG_BUS_STATUS: u32 = 0x8; - pub(crate) const REG_BUS_TEST_RO: u32 = 0x14; - 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; - - // SPI_STATUS_REGISTER bits - pub(crate) const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001; - pub(crate) const STATUS_UNDERFLOW: u32 = 0x00000002; - pub(crate) const STATUS_OVERFLOW: u32 = 0x00000004; - pub(crate) const STATUS_F2_INTR: u32 = 0x00000008; - pub(crate) const STATUS_F3_INTR: u32 = 0x00000010; - pub(crate) const STATUS_F2_RX_READY: u32 = 0x00000020; - pub(crate) const STATUS_F3_RX_READY: u32 = 0x00000040; - pub(crate) const STATUS_HOST_CMD_DATA_ERR: u32 = 0x00000080; - pub(crate) const STATUS_F2_PKT_AVAILABLE: u32 = 0x00000100; - pub(crate) const STATUS_F2_PKT_LEN_MASK: u32 = 0x000FFE00; - pub(crate) const STATUS_F2_PKT_LEN_SHIFT: u32 = 9; - pub(crate) const STATUS_F3_PKT_AVAILABLE: u32 = 0x00100000; - pub(crate) const STATUS_F3_PKT_LEN_MASK: u32 = 0xFFE00000; - pub(crate) const STATUS_F3_PKT_LEN_SHIFT: u32 = 21; - - pub(crate) const REG_BACKPLANE_GPIO_SELECT: u32 = 0x10005; - pub(crate) const REG_BACKPLANE_GPIO_OUTPUT: u32 = 0x10006; - pub(crate) const REG_BACKPLANE_GPIO_ENABLE: u32 = 0x10007; - pub(crate) const REG_BACKPLANE_FUNCTION2_WATERMARK: u32 = 0x10008; - pub(crate) const REG_BACKPLANE_DEVICE_CONTROL: u32 = 0x10009; - pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_LOW: u32 = 0x1000A; - pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_MID: u32 = 0x1000B; - pub(crate) const REG_BACKPLANE_BACKPLANE_ADDRESS_HIGH: u32 = 0x1000C; - pub(crate) const REG_BACKPLANE_FRAME_CONTROL: u32 = 0x1000D; - pub(crate) const REG_BACKPLANE_CHIP_CLOCK_CSR: u32 = 0x1000E; - pub(crate) const REG_BACKPLANE_PULL_UP: u32 = 0x1000F; - pub(crate) const REG_BACKPLANE_READ_FRAME_BC_LOW: u32 = 0x1001B; - pub(crate) const REG_BACKPLANE_READ_FRAME_BC_HIGH: u32 = 0x1001C; - pub(crate) const REG_BACKPLANE_WAKEUP_CTRL: u32 = 0x1001E; - pub(crate) const REG_BACKPLANE_SLEEP_CSR: u32 = 0x1001F; - - pub(crate) const BACKPLANE_WINDOW_SIZE: usize = 0x8000; - pub(crate) const BACKPLANE_ADDRESS_MASK: u32 = 0x7FFF; - pub(crate) const BACKPLANE_ADDRESS_32BIT_FLAG: u32 = 0x08000; - pub(crate) const BACKPLANE_MAX_TRANSFER_SIZE: usize = 64; - // Active Low Power (ALP) clock constants - pub(crate) const BACKPLANE_ALP_AVAIL_REQ: u8 = 0x08; - pub(crate) const BACKPLANE_ALP_AVAIL: u8 = 0x40; - - // Broadcom AMBA (Advanced Microcontroller Bus Architecture) Interconnect - // (AI) pub (crate) constants - pub(crate) const AI_IOCTRL_OFFSET: u32 = 0x408; - pub(crate) const AI_IOCTRL_BIT_FGC: u8 = 0x0002; - pub(crate) const AI_IOCTRL_BIT_CLOCK_EN: u8 = 0x0001; - pub(crate) const AI_IOCTRL_BIT_CPUHALT: u8 = 0x0020; - - pub(crate) const AI_RESETCTRL_OFFSET: u32 = 0x800; - pub(crate) const AI_RESETCTRL_BIT_RESET: u8 = 1; - - pub(crate) const AI_RESETSTATUS_OFFSET: u32 = 0x804; - - pub(crate) const TEST_PATTERN: u32 = 0x12345678; - pub(crate) const FEEDBEAD: u32 = 0xFEEDBEAD; - - // SPI_INTERRUPT_REGISTER and SPI_INTERRUPT_ENABLE_REGISTER Bits - pub(crate) const IRQ_DATA_UNAVAILABLE: u16 = 0x0001; // Requested data not available; Clear by writing a "1" - pub(crate) const IRQ_F2_F3_FIFO_RD_UNDERFLOW: u16 = 0x0002; - pub(crate) const IRQ_F2_F3_FIFO_WR_OVERFLOW: u16 = 0x0004; - pub(crate) const IRQ_COMMAND_ERROR: u16 = 0x0008; // Cleared by writing 1 - pub(crate) const IRQ_DATA_ERROR: u16 = 0x0010; // Cleared by writing 1 - pub(crate) const IRQ_F2_PACKET_AVAILABLE: u16 = 0x0020; - pub(crate) const IRQ_F3_PACKET_AVAILABLE: u16 = 0x0040; - pub(crate) const IRQ_F1_OVERFLOW: u16 = 0x0080; // Due to last write. Bkplane has pending write requests - pub(crate) const IRQ_MISC_INTR0: u16 = 0x0100; - pub(crate) const IRQ_MISC_INTR1: u16 = 0x0200; - pub(crate) const IRQ_MISC_INTR2: u16 = 0x0400; - pub(crate) const IRQ_MISC_INTR3: u16 = 0x0800; - pub(crate) const IRQ_MISC_INTR4: u16 = 0x1000; - pub(crate) const IRQ_F1_INTR: u16 = 0x2000; - pub(crate) const IRQ_F2_INTR: u16 = 0x4000; - pub(crate) const IRQ_F3_INTR: u16 = 0x8000; - - pub(crate) const IOCTL_CMD_UP: u32 = 2; - pub(crate) const IOCTL_CMD_SET_SSID: u32 = 26; - pub(crate) const IOCTL_CMD_ANTDIV: u32 = 64; - pub(crate) const IOCTL_CMD_SET_VAR: u32 = 263; - pub(crate) const IOCTL_CMD_GET_VAR: u32 = 262; - pub(crate) const IOCTL_CMD_SET_PASSPHRASE: u32 = 268; - - pub(crate) const CHANNEL_TYPE_CONTROL: u8 = 0; - pub(crate) const CHANNEL_TYPE_EVENT: u8 = 1; - pub(crate) const CHANNEL_TYPE_DATA: u8 = 2; - - // CYW_SPID command structure constants. - pub(crate) const WRITE: bool = true; - pub(crate) const READ: bool = false; - pub(crate) const INC_ADDR: bool = true; - pub(crate) const FIXED_ADDR: bool = false; -} -use crate::constants::*; +use crate::structs::*; #[derive(Clone, Copy)] pub enum IoctlType { @@ -565,15 +447,11 @@ impl<'a> embassy_net::Device for NetDevice<'a> { } pub struct Runner<'a, PWR, SPI> { + bus: Bus, + state: &'a State, - - pwr: PWR, - spi: SPI, - ioctl_id: u16, sdpcm_seq: u8, - backplane_window: u32, - sdpcm_seq_max: u8, #[cfg(feature = "firmware-logs")] @@ -600,14 +478,11 @@ where SPI::Bus: SpiBusRead + SpiBusWrite, { let mut runner = Runner { - state, - pwr, - spi, + bus: Bus::new(pwr, spi), + state, ioctl_id: 0, sdpcm_seq: 0, - backplane_window: 0xAAAA_AAAA, - sdpcm_seq_max: 1, #[cfg(feature = "firmware-logs")] @@ -631,62 +506,41 @@ where SPI::Bus: SpiBusRead + SpiBusWrite, { async fn init(&mut self, firmware: &[u8]) { - // Reset - self.pwr.set_low().unwrap(); - Timer::after(Duration::from_millis(20)).await; - self.pwr.set_high().unwrap(); - Timer::after(Duration::from_millis(250)).await; - - info!("waiting for ping..."); - while self.read32_swapped(REG_BUS_TEST_RO).await != FEEDBEAD {} - info!("ping ok"); - - self.write32_swapped(REG_BUS_TEST_RW, TEST_PATTERN).await; - let val = self.read32_swapped(REG_BUS_TEST_RW).await; - assert_eq!(val, TEST_PATTERN); - - // 32-bit word length, little endian (which is the default endianess). - self.write32_swapped(REG_BUS_CTRL, WORD_LENGTH_32 | HIGH_SPEED).await; - - let val = self.read32(FUNC_BUS, REG_BUS_TEST_RO).await; - assert_eq!(val, FEEDBEAD); - let val = self.read32(FUNC_BUS, REG_BUS_TEST_RW).await; - assert_eq!(val, TEST_PATTERN); - - // No response delay in any of the funcs. - // seems to break backplane??? eat the 4-byte delay instead, that's what the vendor drivers do... - //self.write32(FUNC_BUS, REG_BUS_RESP_DELAY, 0).await; + self.bus.init().await; // Init ALP (Active Low Power) clock - self.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, BACKPLANE_ALP_AVAIL_REQ) + self.bus + .write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, BACKPLANE_ALP_AVAIL_REQ) .await; info!("waiting for clock..."); - while self.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & BACKPLANE_ALP_AVAIL == 0 {} + while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & BACKPLANE_ALP_AVAIL == 0 {} info!("clock ok"); - let chip_id = self.bp_read16(0x1800_0000).await; + let chip_id = self.bus.bp_read16(0x1800_0000).await; info!("chip ID: {}", chip_id); // Upload firmware. self.core_disable(Core::WLAN).await; self.core_reset(Core::SOCSRAM).await; - self.bp_write32(CHIP.socsram_base_address + 0x10, 3).await; - self.bp_write32(CHIP.socsram_base_address + 0x44, 0).await; + self.bus.bp_write32(CHIP.socsram_base_address + 0x10, 3).await; + self.bus.bp_write32(CHIP.socsram_base_address + 0x44, 0).await; let ram_addr = CHIP.atcm_ram_base_address; info!("loading fw"); - self.bp_write(ram_addr, firmware).await; + self.bus.bp_write(ram_addr, firmware).await; info!("loading nvram"); // Round up to 4 bytes. let nvram_len = (NVRAM.len() + 3) / 4 * 4; - self.bp_write(ram_addr + CHIP.chip_ram_size - 4 - nvram_len as u32, NVRAM) + self.bus + .bp_write(ram_addr + CHIP.chip_ram_size - 4 - nvram_len as u32, NVRAM) .await; let nvram_len_words = nvram_len as u32 / 4; let nvram_len_magic = (!nvram_len_words << 16) | nvram_len_words; - self.bp_write32(ram_addr + CHIP.chip_ram_size - 4, nvram_len_magic) + self.bus + .bp_write32(ram_addr + CHIP.chip_ram_size - 4, nvram_len_magic) .await; // Start core! @@ -694,18 +548,20 @@ where self.core_reset(Core::WLAN).await; assert!(self.core_is_up(Core::WLAN).await); - while self.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" - self.bp_write32(CHIP.sdiod_core_base_address + 0x24, 0xF0).await; + self.bus.bp_write32(CHIP.sdiod_core_base_address + 0x24, 0xF0).await; // "Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped." // Sounds scary... - self.write8(FUNC_BACKPLANE, REG_BACKPLANE_FUNCTION2_WATERMARK, 32).await; + self.bus + .write8(FUNC_BACKPLANE, REG_BACKPLANE_FUNCTION2_WATERMARK, 32) + .await; // wait for wifi startup info!("waiting for wifi init..."); - while self.read32(FUNC_BUS, REG_BUS_STATUS).await & STATUS_F2_RX_READY == 0 {} + while self.bus.read32(FUNC_BUS, REG_BUS_STATUS).await & STATUS_F2_RX_READY == 0 {} // Some random configs related to sleep. // These aren't needed if we don't want to sleep the bus. @@ -713,25 +569,25 @@ where // being on the same pin as MOSI/MISO? /* - let mut val = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL).await; + let mut val = self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL).await; val |= 0x02; // WAKE_TILL_HT_AVAIL - self.write8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL, val).await; - self.write8(FUNC_BUS, 0xF0, 0x08).await; // SDIOD_CCCR_BRCM_CARDCAP.CMD_NODEC = 1 - self.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x02).await; // SBSDIO_FORCE_HT + self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL, val).await; + self.bus.write8(FUNC_BUS, 0xF0, 0x08).await; // SDIOD_CCCR_BRCM_CARDCAP.CMD_NODEC = 1 + self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x02).await; // SBSDIO_FORCE_HT - let mut val = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_SLEEP_CSR).await; + let mut val = self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_SLEEP_CSR).await; val |= 0x01; // SBSDIO_SLPCSR_KEEP_SDIO_ON - self.write8(FUNC_BACKPLANE, REG_BACKPLANE_SLEEP_CSR, val).await; + self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_SLEEP_CSR, val).await; */ // clear pulls - self.write8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP, 0).await; - let _ = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP).await; + self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP, 0).await; + let _ = self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP).await; // start HT clock - //self.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x10).await; + //self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x10).await; //info!("waiting for HT clock..."); - //while self.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 {} //info!("clock ok"); #[cfg(feature = "firmware-logs")] @@ -744,13 +600,12 @@ where async fn log_init(&mut self) { // Initialize shared memory for logging. - let shared_addr = self - .bp_read32(CHIP.atcm_ram_base_address + CHIP.chip_ram_size - 4 - CHIP.socram_srmem_size) - .await; + let addr = CHIP.atcm_ram_base_address + CHIP.chip_ram_size - 4 - CHIP.socram_srmem_size; + let shared_addr = self.bus.bp_read32(addr).await; info!("shared_addr {:08x}", shared_addr); let mut shared = [0; SharedMemData::SIZE]; - self.bp_read(shared_addr, &mut shared).await; + self.bus.bp_read(shared_addr, &mut shared).await; let shared = SharedMemData::from_bytes(&shared); info!("shared: {:08x}", shared); @@ -761,7 +616,7 @@ where async fn log_read(&mut self) { // Read log struct let mut log = [0; SharedMemLog::SIZE]; - self.bp_read(self.log.addr, &mut log).await; + self.bus.bp_read(self.log.addr, &mut log).await; let log = SharedMemLog::from_bytes(&log); let idx = log.idx as usize; @@ -774,7 +629,7 @@ where // Read entire buf for now. We could read only what we need, but then we // run into annoying alignment issues in `bp_read`. let mut buf = [0; 0x400]; - self.bp_read(log.buf, &mut buf).await; + self.bus.bp_read(log.buf, &mut buf).await; while self.log.last_idx != idx as usize { let b = buf[self.log.last_idx]; @@ -821,29 +676,19 @@ where } // Receive stuff - let irq = self.read16(FUNC_BUS, REG_BUS_INTERRUPT).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.read32(FUNC_BUS, REG_BUS_STATUS).await; + 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; - let cmd = cmd_word(READ, INC_ADDR, FUNC_WLAN, 0, len); - - transaction!(&mut self.spi, |bus| async { - bus.write(&[cmd]).await?; - bus.read(&mut buf[..(len as usize + 3) / 4]).await?; - Ok(()) - }) - .await - .unwrap(); - + self.bus.wlan_read(&mut buf[..(len as usize + 3) / 4]).await; trace!("rx {:02x}", &slice8_mut(&mut buf)[..(len as usize).min(48)]); - self.rx(&slice8_mut(&mut buf)[..len as usize]); } } @@ -893,14 +738,7 @@ where trace!(" {:02x}", &buf8[..total_len.min(48)]); - let cmd = cmd_word(WRITE, INC_ADDR, FUNC_WLAN, 0, total_len as _); - transaction!(&mut self.spi, |bus| async { - bus.write(&[cmd]).await?; - bus.write(&buf[..(total_len / 4)]).await?; - Ok(()) - }) - .await - .unwrap(); + self.bus.wlan_write(&buf[..(total_len / 4)]).await; } fn rx(&mut self, packet: &[u8]) { @@ -1086,52 +924,49 @@ where trace!(" {:02x}", &buf8[..total_len.min(48)]); - let cmd = cmd_word(WRITE, INC_ADDR, FUNC_WLAN, 0, total_len as _); - - transaction!(&mut self.spi, |bus| async { - bus.write(&[cmd]).await?; - bus.write(&buf[..total_len / 4]).await?; - Ok(()) - }) - .await - .unwrap(); + self.bus.wlan_write(&buf[..total_len / 4]).await; } async fn core_disable(&mut self, core: Core) { let base = core.base_addr(); // Dummy read? - let _ = self.bp_read8(base + AI_RESETCTRL_OFFSET).await; + let _ = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; // Check it isn't already reset - let r = self.bp_read8(base + AI_RESETCTRL_OFFSET).await; + let r = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; if r & AI_RESETCTRL_BIT_RESET != 0 { return; } - self.bp_write8(base + AI_IOCTRL_OFFSET, 0).await; - let _ = self.bp_read8(base + AI_IOCTRL_OFFSET).await; + self.bus.bp_write8(base + AI_IOCTRL_OFFSET, 0).await; + let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; block_for(Duration::from_millis(1)); - self.bp_write8(base + AI_RESETCTRL_OFFSET, AI_RESETCTRL_BIT_RESET).await; - let _ = self.bp_read8(base + AI_RESETCTRL_OFFSET).await; + self.bus + .bp_write8(base + AI_RESETCTRL_OFFSET, AI_RESETCTRL_BIT_RESET) + .await; + let _ = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; } async fn core_reset(&mut self, core: Core) { self.core_disable(core).await; let base = core.base_addr(); - self.bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) + self.bus + .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) .await; - let _ = self.bp_read8(base + AI_IOCTRL_OFFSET).await; + let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; - self.bp_write8(base + AI_RESETCTRL_OFFSET, 0).await; + self.bus.bp_write8(base + AI_RESETCTRL_OFFSET, 0).await; Timer::after(Duration::from_millis(1)).await; - self.bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_CLOCK_EN).await; - let _ = self.bp_read8(base + AI_IOCTRL_OFFSET).await; + self.bus + .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_CLOCK_EN) + .await; + let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; Timer::after(Duration::from_millis(1)).await; } @@ -1139,13 +974,13 @@ where async fn core_is_up(&mut self, core: Core) -> bool { let base = core.base_addr(); - let io = self.bp_read8(base + AI_IOCTRL_OFFSET).await; + let io = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await; if io & (AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) != AI_IOCTRL_BIT_CLOCK_EN { debug!("core_is_up: returning false due to bad ioctrl {:02x}", io); return false; } - let r = self.bp_read8(base + AI_RESETCTRL_OFFSET).await; + let r = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await; if r & (AI_RESETCTRL_BIT_RESET) != 0 { debug!("core_is_up: returning false due to bad resetctrl {:02x}", r); return false; @@ -1153,242 +988,11 @@ where true } +} - #[allow(unused)] - async fn bp_read(&mut self, mut addr: u32, mut data: &mut [u8]) { - // It seems the HW force-aligns the addr - // to 2 if data.len() >= 2 - // to 4 if data.len() >= 4 - // To simplify, enforce 4-align for now. - assert!(addr % 4 == 0); - - let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; - - while !data.is_empty() { - // Ensure transfer doesn't cross a window boundary. - let window_offs = addr & BACKPLANE_ADDRESS_MASK; - let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize; - - let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining); - - self.backplane_set_window(addr).await; - - let cmd = cmd_word(READ, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); - - transaction!(&mut self.spi, |bus| async { - bus.write(&[cmd]).await?; - - // 4-byte response delay. - let mut junk = [0; 1]; - bus.read(&mut junk).await?; - - // Read data - bus.read(&mut buf[..(len + 3) / 4]).await?; - Ok(()) - }) - .await - .unwrap(); - - data[..len].copy_from_slice(&slice8_mut(&mut buf)[..len]); - - // Advance ptr. - addr += len as u32; - data = &mut data[len..]; - } - } - - async fn bp_write(&mut self, mut addr: u32, mut data: &[u8]) { - // It seems the HW force-aligns the addr - // to 2 if data.len() >= 2 - // to 4 if data.len() >= 4 - // To simplify, enforce 4-align for now. - assert!(addr % 4 == 0); - - let mut buf = [0u32; BACKPLANE_MAX_TRANSFER_SIZE / 4]; - - while !data.is_empty() { - // Ensure transfer doesn't cross a window boundary. - let window_offs = addr & BACKPLANE_ADDRESS_MASK; - let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize; - - let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining); - slice8_mut(&mut buf)[..len].copy_from_slice(&data[..len]); - - self.backplane_set_window(addr).await; - - let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BACKPLANE, window_offs, len as u32); - - transaction!(&mut self.spi, |bus| async { - bus.write(&[cmd]).await?; - bus.write(&buf[..(len + 3) / 4]).await?; - Ok(()) - }) - .await - .unwrap(); - - // Advance ptr. - addr += len as u32; - data = &data[len..]; - } - } - - async fn bp_read8(&mut self, addr: u32) -> u8 { - self.backplane_readn(addr, 1).await as u8 - } - - async fn bp_write8(&mut self, addr: u32, val: u8) { - self.backplane_writen(addr, val as u32, 1).await - } - - async fn bp_read16(&mut self, addr: u32) -> u16 { - self.backplane_readn(addr, 2).await as u16 - } - - #[allow(unused)] - async fn bp_write16(&mut self, addr: u32, val: u16) { - self.backplane_writen(addr, val as u32, 2).await - } - - #[allow(unused)] - async fn bp_read32(&mut self, addr: u32) -> u32 { - self.backplane_readn(addr, 4).await - } - - async fn bp_write32(&mut self, addr: u32, val: u32) { - self.backplane_writen(addr, val, 4).await - } - - async fn backplane_readn(&mut self, addr: u32, len: u32) -> u32 { - self.backplane_set_window(addr).await; - - let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; - if len == 4 { - bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG - } - self.readn(FUNC_BACKPLANE, bus_addr, len).await - } - - async fn backplane_writen(&mut self, addr: u32, val: u32, len: u32) { - self.backplane_set_window(addr).await; - - let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK; - if len == 4 { - bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG - } - self.writen(FUNC_BACKPLANE, bus_addr, val, len).await - } - - async fn backplane_set_window(&mut self, addr: u32) { - let new_window = addr & !BACKPLANE_ADDRESS_MASK; - - if (new_window >> 24) as u8 != (self.backplane_window >> 24) as u8 { - self.write8( - FUNC_BACKPLANE, - REG_BACKPLANE_BACKPLANE_ADDRESS_HIGH, - (new_window >> 24) as u8, - ) - .await; - } - if (new_window >> 16) as u8 != (self.backplane_window >> 16) as u8 { - self.write8( - FUNC_BACKPLANE, - REG_BACKPLANE_BACKPLANE_ADDRESS_MID, - (new_window >> 16) as u8, - ) - .await; - } - if (new_window >> 8) as u8 != (self.backplane_window >> 8) as u8 { - self.write8( - FUNC_BACKPLANE, - REG_BACKPLANE_BACKPLANE_ADDRESS_LOW, - (new_window >> 8) as u8, - ) - .await; - } - self.backplane_window = new_window; - } - - async fn read8(&mut self, func: u32, addr: u32) -> u8 { - self.readn(func, addr, 1).await as u8 - } - - async fn write8(&mut self, func: u32, addr: u32, val: u8) { - self.writen(func, addr, val as u32, 1).await - } - - async fn read16(&mut self, func: u32, addr: u32) -> u16 { - self.readn(func, addr, 2).await as u16 - } - - #[allow(unused)] - async fn write16(&mut self, func: u32, addr: u32, val: u16) { - self.writen(func, addr, val as u32, 2).await - } - - async fn read32(&mut self, func: u32, addr: u32) -> u32 { - self.readn(func, addr, 4).await - } - - #[allow(unused)] - async fn write32(&mut self, func: u32, addr: u32, val: u32) { - self.writen(func, addr, val, 4).await - } - - async fn readn(&mut self, func: u32, addr: u32, len: u32) -> u32 { - let cmd = cmd_word(READ, INC_ADDR, func, addr, len); - let mut buf = [0; 1]; - - transaction!(&mut self.spi, |bus| async { - bus.write(&[cmd]).await?; - if func == FUNC_BACKPLANE { - // 4-byte response delay. - bus.read(&mut buf).await?; - } - bus.read(&mut buf).await?; - Ok(()) - }) - .await - .unwrap(); - - buf[0] - } - - async fn writen(&mut self, func: u32, addr: u32, val: u32, len: u32) { - let cmd = cmd_word(WRITE, INC_ADDR, func, addr, len); - - transaction!(&mut self.spi, |bus| async { - bus.write(&[cmd, val]).await?; - Ok(()) - }) - .await - .unwrap(); - } - - async fn read32_swapped(&mut self, addr: u32) -> u32 { - let cmd = cmd_word(READ, INC_ADDR, FUNC_BUS, addr, 4); - let mut buf = [0; 1]; - - transaction!(&mut self.spi, |bus| async { - bus.write(&[swap16(cmd)]).await?; - bus.read(&mut buf).await?; - Ok(()) - }) - .await - .unwrap(); - - swap16(buf[0]) - } - - async fn write32_swapped(&mut self, addr: u32, val: u32) { - let cmd = cmd_word(WRITE, INC_ADDR, FUNC_BUS, addr, 4); - - transaction!(&mut self.spi, |bus| async { - bus.write(&[swap16(cmd), swap16(val)]).await?; - Ok(()) - }) - .await - .unwrap(); - } +fn slice8_mut(x: &mut [u32]) -> &mut [u8] { + let len = x.len() * 4; + unsafe { slice::from_raw_parts_mut(x.as_mut_ptr() as _, len) } } macro_rules! nvram {