aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2022-07-10 19:45:26 +0200
committerDario Nieuwenhuis <[email protected]>2022-07-10 19:45:26 +0200
commite560415fde967483573d42f628e52501768584e0 (patch)
tree864f2141d7351b0f1940ee2015d1c7d5c3d37ad1 /src
:rainbow:
Diffstat (limited to 'src')
-rw-r--r--src/fmt.rs228
-rw-r--r--src/lib.rs879
2 files changed, 1107 insertions, 0 deletions
diff --git a/src/fmt.rs b/src/fmt.rs
new file mode 100644
index 000000000..f8bb0a035
--- /dev/null
+++ b/src/fmt.rs
@@ -0,0 +1,228 @@
1#![macro_use]
2#![allow(unused_macros)]
3
4#[cfg(all(feature = "defmt", feature = "log"))]
5compile_error!("You may not enable both `defmt` and `log` features.");
6
7macro_rules! assert {
8 ($($x:tt)*) => {
9 {
10 #[cfg(not(feature = "defmt"))]
11 ::core::assert!($($x)*);
12 #[cfg(feature = "defmt")]
13 ::defmt::assert!($($x)*);
14 }
15 };
16}
17
18macro_rules! assert_eq {
19 ($($x:tt)*) => {
20 {
21 #[cfg(not(feature = "defmt"))]
22 ::core::assert_eq!($($x)*);
23 #[cfg(feature = "defmt")]
24 ::defmt::assert_eq!($($x)*);
25 }
26 };
27}
28
29macro_rules! assert_ne {
30 ($($x:tt)*) => {
31 {
32 #[cfg(not(feature = "defmt"))]
33 ::core::assert_ne!($($x)*);
34 #[cfg(feature = "defmt")]
35 ::defmt::assert_ne!($($x)*);
36 }
37 };
38}
39
40macro_rules! debug_assert {
41 ($($x:tt)*) => {
42 {
43 #[cfg(not(feature = "defmt"))]
44 ::core::debug_assert!($($x)*);
45 #[cfg(feature = "defmt")]
46 ::defmt::debug_assert!($($x)*);
47 }
48 };
49}
50
51macro_rules! debug_assert_eq {
52 ($($x:tt)*) => {
53 {
54 #[cfg(not(feature = "defmt"))]
55 ::core::debug_assert_eq!($($x)*);
56 #[cfg(feature = "defmt")]
57 ::defmt::debug_assert_eq!($($x)*);
58 }
59 };
60}
61
62macro_rules! debug_assert_ne {
63 ($($x:tt)*) => {
64 {
65 #[cfg(not(feature = "defmt"))]
66 ::core::debug_assert_ne!($($x)*);
67 #[cfg(feature = "defmt")]
68 ::defmt::debug_assert_ne!($($x)*);
69 }
70 };
71}
72
73macro_rules! todo {
74 ($($x:tt)*) => {
75 {
76 #[cfg(not(feature = "defmt"))]
77 ::core::todo!($($x)*);
78 #[cfg(feature = "defmt")]
79 ::defmt::todo!($($x)*);
80 }
81 };
82}
83
84macro_rules! unreachable {
85 ($($x:tt)*) => {
86 {
87 #[cfg(not(feature = "defmt"))]
88 ::core::unreachable!($($x)*);
89 #[cfg(feature = "defmt")]
90 ::defmt::unreachable!($($x)*);
91 }
92 };
93}
94
95macro_rules! panic {
96 ($($x:tt)*) => {
97 {
98 #[cfg(not(feature = "defmt"))]
99 ::core::panic!($($x)*);
100 #[cfg(feature = "defmt")]
101 ::defmt::panic!($($x)*);
102 }
103 };
104}
105
106macro_rules! trace {
107 ($s:literal $(, $x:expr)* $(,)?) => {
108 {
109 #[cfg(feature = "log")]
110 ::log::trace!($s $(, $x)*);
111 #[cfg(feature = "defmt")]
112 ::defmt::trace!($s $(, $x)*);
113 #[cfg(not(any(feature = "log", feature="defmt")))]
114 let _ = ($( & $x ),*);
115 }
116 };
117}
118
119macro_rules! debug {
120 ($s:literal $(, $x:expr)* $(,)?) => {
121 {
122 #[cfg(feature = "log")]
123 ::log::debug!($s $(, $x)*);
124 #[cfg(feature = "defmt")]
125 ::defmt::debug!($s $(, $x)*);
126 #[cfg(not(any(feature = "log", feature="defmt")))]
127 let _ = ($( & $x ),*);
128 }
129 };
130}
131
132macro_rules! info {
133 ($s:literal $(, $x:expr)* $(,)?) => {
134 {
135 #[cfg(feature = "log")]
136 ::log::info!($s $(, $x)*);
137 #[cfg(feature = "defmt")]
138 ::defmt::info!($s $(, $x)*);
139 #[cfg(not(any(feature = "log", feature="defmt")))]
140 let _ = ($( & $x ),*);
141 }
142 };
143}
144
145macro_rules! warn {
146 ($s:literal $(, $x:expr)* $(,)?) => {
147 {
148 #[cfg(feature = "log")]
149 ::log::warn!($s $(, $x)*);
150 #[cfg(feature = "defmt")]
151 ::defmt::warn!($s $(, $x)*);
152 #[cfg(not(any(feature = "log", feature="defmt")))]
153 let _ = ($( & $x ),*);
154 }
155 };
156}
157
158macro_rules! error {
159 ($s:literal $(, $x:expr)* $(,)?) => {
160 {
161 #[cfg(feature = "log")]
162 ::log::error!($s $(, $x)*);
163 #[cfg(feature = "defmt")]
164 ::defmt::error!($s $(, $x)*);
165 #[cfg(not(any(feature = "log", feature="defmt")))]
166 let _ = ($( & $x ),*);
167 }
168 };
169}
170
171#[cfg(feature = "defmt")]
172macro_rules! unwrap {
173 ($($x:tt)*) => {
174 ::defmt::unwrap!($($x)*)
175 };
176}
177
178#[cfg(not(feature = "defmt"))]
179macro_rules! unwrap {
180 ($arg:expr) => {
181 match $crate::fmt::Try::into_result($arg) {
182 ::core::result::Result::Ok(t) => t,
183 ::core::result::Result::Err(e) => {
184 ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e);
185 }
186 }
187 };
188 ($arg:expr, $($msg:expr),+ $(,)? ) => {
189 match $crate::fmt::Try::into_result($arg) {
190 ::core::result::Result::Ok(t) => t,
191 ::core::result::Result::Err(e) => {
192 ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e);
193 }
194 }
195 }
196}
197
198#[cfg(feature = "defmt-timestamp-uptime")]
199defmt::timestamp! {"{=u64:us}", crate::time::Instant::now().as_micros() }
200
201#[derive(Debug, Copy, Clone, Eq, PartialEq)]
202pub struct NoneError;
203
204pub trait Try {
205 type Ok;
206 type Error;
207 fn into_result(self) -> Result<Self::Ok, Self::Error>;
208}
209
210impl<T> Try for Option<T> {
211 type Ok = T;
212 type Error = NoneError;
213
214 #[inline]
215 fn into_result(self) -> Result<T, NoneError> {
216 self.ok_or(NoneError)
217 }
218}
219
220impl<T, E> Try for Result<T, E> {
221 type Ok = T;
222 type Error = E;
223
224 #[inline]
225 fn into_result(self) -> Self {
226 self
227 }
228}
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 000000000..5caf19267
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,879 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait, concat_bytes)]
4
5// This mod MUST go first, so that the others see its macros.
6pub(crate) mod fmt;
7
8use core::slice;
9
10use embassy::time::{block_for, Duration, Timer};
11use embassy::util::yield_now;
12use embassy_rp::gpio::{Flex, Output, Pin};
13
14fn swap16(x: u32) -> u32 {
15 (x & 0xFF00FF00) >> 8 | (x & 0x00FF00FF) << 8
16}
17
18fn cmd_word(write: bool, incr: bool, func: u32, addr: u32, len: u32) -> u32 {
19 (write as u32) << 31 | (incr as u32) << 30 | (func & 0b11) << 28 | (addr & 0x1FFFF) << 11 | (len & 0x7FF)
20}
21
22const FUNC_BUS: u32 = 0;
23const FUNC_BACKPLANE: u32 = 1;
24const FUNC_WLAN: u32 = 2;
25const FUNC_BT: u32 = 3;
26
27const REG_BUS_CTRL: u32 = 0x0;
28const REG_BUS_INTERRUPT: u32 = 0x04; // 16 bits - Interrupt status
29const REG_BUS_INTERRUPT_ENABLE: u32 = 0x06; // 16 bits - Interrupt mask
30const REG_BUS_STATUS: u32 = 0x8;
31const REG_BUS_FEEDBEAD: u32 = 0x14;
32const REG_BUS_TEST: u32 = 0x18;
33const REG_BUS_RESP_DELAY: u32 = 0x1c;
34
35// SPI_STATUS_REGISTER bits
36const STATUS_DATA_NOT_AVAILABLE: u32 = 0x00000001;
37const STATUS_UNDERFLOW: u32 = 0x00000002;
38const STATUS_OVERFLOW: u32 = 0x00000004;
39const STATUS_F2_INTR: u32 = 0x00000008;
40const STATUS_F3_INTR: u32 = 0x00000010;
41const STATUS_F2_RX_READY: u32 = 0x00000020;
42const STATUS_F3_RX_READY: u32 = 0x00000040;
43const STATUS_HOST_CMD_DATA_ERR: u32 = 0x00000080;
44const STATUS_F2_PKT_AVAILABLE: u32 = 0x00000100;
45const STATUS_F2_PKT_LEN_MASK: u32 = 0x000FFE00;
46const STATUS_F2_PKT_LEN_SHIFT: u32 = 9;
47const STATUS_F3_PKT_AVAILABLE: u32 = 0x00100000;
48const STATUS_F3_PKT_LEN_MASK: u32 = 0xFFE00000;
49const STATUS_F3_PKT_LEN_SHIFT: u32 = 21;
50
51const REG_BACKPLANE_GPIO_SELECT: u32 = 0x10005;
52const REG_BACKPLANE_GPIO_OUTPUT: u32 = 0x10006;
53const REG_BACKPLANE_GPIO_ENABLE: u32 = 0x10007;
54const REG_BACKPLANE_FUNCTION2_WATERMARK: u32 = 0x10008;
55const REG_BACKPLANE_DEVICE_CONTROL: u32 = 0x10009;
56const REG_BACKPLANE_BACKPLANE_ADDRESS_LOW: u32 = 0x1000A;
57const REG_BACKPLANE_BACKPLANE_ADDRESS_MID: u32 = 0x1000B;
58const REG_BACKPLANE_BACKPLANE_ADDRESS_HIGH: u32 = 0x1000C;
59const REG_BACKPLANE_FRAME_CONTROL: u32 = 0x1000D;
60const REG_BACKPLANE_CHIP_CLOCK_CSR: u32 = 0x1000E;
61const REG_BACKPLANE_PULL_UP: u32 = 0x1000F;
62const REG_BACKPLANE_READ_FRAME_BC_LOW: u32 = 0x1001B;
63const REG_BACKPLANE_READ_FRAME_BC_HIGH: u32 = 0x1001C;
64const REG_BACKPLANE_WAKEUP_CTRL: u32 = 0x1001E;
65const REG_BACKPLANE_SLEEP_CSR: u32 = 0x1001F;
66
67const BACKPLANE_WINDOW_SIZE: usize = 0x8000;
68const BACKPLANE_ADDRESS_MASK: u32 = 0x7FFF;
69const BACKPLANE_ADDRESS_32BIT_FLAG: u32 = 0x08000;
70const BACKPLANE_MAX_TRANSFER_SIZE: usize = 64;
71
72const AI_IOCTRL_OFFSET: u32 = 0x408;
73const AI_IOCTRL_BIT_FGC: u8 = 0x0002;
74const AI_IOCTRL_BIT_CLOCK_EN: u8 = 0x0001;
75const AI_IOCTRL_BIT_CPUHALT: u8 = 0x0020;
76
77const AI_RESETCTRL_OFFSET: u32 = 0x800;
78const AI_RESETCTRL_BIT_RESET: u8 = 1;
79
80const AI_RESETSTATUS_OFFSET: u32 = 0x804;
81
82const TEST_PATTERN: u32 = 0x12345678;
83const FEEDBEAD: u32 = 0xFEEDBEAD;
84
85// SPI_INTERRUPT_REGISTER and SPI_INTERRUPT_ENABLE_REGISTER Bits
86const IRQ_DATA_UNAVAILABLE: u16 = 0x0001; // Requested data not available; Clear by writing a "1"
87const IRQ_F2_F3_FIFO_RD_UNDERFLOW: u16 = 0x0002;
88const IRQ_F2_F3_FIFO_WR_OVERFLOW: u16 = 0x0004;
89const IRQ_COMMAND_ERROR: u16 = 0x0008; // Cleared by writing 1
90const IRQ_DATA_ERROR: u16 = 0x0010; // Cleared by writing 1
91const IRQ_F2_PACKET_AVAILABLE: u16 = 0x0020;
92const IRQ_F3_PACKET_AVAILABLE: u16 = 0x0040;
93const IRQ_F1_OVERFLOW: u16 = 0x0080; // Due to last write. Bkplane has pending write requests
94const IRQ_MISC_INTR0: u16 = 0x0100;
95const IRQ_MISC_INTR1: u16 = 0x0200;
96const IRQ_MISC_INTR2: u16 = 0x0400;
97const IRQ_MISC_INTR3: u16 = 0x0800;
98const IRQ_MISC_INTR4: u16 = 0x1000;
99const IRQ_F1_INTR: u16 = 0x2000;
100const IRQ_F2_INTR: u16 = 0x4000;
101const IRQ_F3_INTR: u16 = 0x8000;
102
103#[derive(Clone, Copy, PartialEq, Eq)]
104enum Core {
105 WLAN = 0,
106 SOCSRAM = 1,
107 SDIOD = 2,
108}
109
110impl Core {
111 fn base_addr(&self) -> u32 {
112 match self {
113 Self::WLAN => CHIP.arm_core_base_address,
114 Self::SOCSRAM => CHIP.socsram_wrapper_base_address,
115 Self::SDIOD => CHIP.sdiod_core_base_address,
116 }
117 }
118}
119
120struct Chip {
121 arm_core_base_address: u32,
122 socsram_base_address: u32,
123 socsram_wrapper_base_address: u32,
124 sdiod_core_base_address: u32,
125 pmu_base_address: u32,
126 chip_ram_size: u32,
127 atcm_ram_base_address: u32,
128 socram_srmem_size: u32,
129 chanspec_band_mask: u32,
130 chanspec_band_2g: u32,
131 chanspec_band_5g: u32,
132 chanspec_band_shift: u32,
133 chanspec_bw_10: u32,
134 chanspec_bw_20: u32,
135 chanspec_bw_40: u32,
136 chanspec_bw_mask: u32,
137 chanspec_bw_shift: u32,
138 chanspec_ctl_sb_lower: u32,
139 chanspec_ctl_sb_upper: u32,
140 chanspec_ctl_sb_none: u32,
141 chanspec_ctl_sb_mask: u32,
142}
143
144const WRAPPER_REGISTER_OFFSET: u32 = 0x100000;
145
146// Data for CYW43439
147const CHIP: Chip = Chip {
148 arm_core_base_address: 0x18003000 + WRAPPER_REGISTER_OFFSET,
149 socsram_base_address: 0x18004000,
150 socsram_wrapper_base_address: 0x18004000 + WRAPPER_REGISTER_OFFSET,
151 sdiod_core_base_address: 0x18002000,
152 pmu_base_address: 0x18000000,
153 chip_ram_size: 512 * 1024,
154 atcm_ram_base_address: 0,
155 socram_srmem_size: 64 * 1024,
156 chanspec_band_mask: 0xc000,
157 chanspec_band_2g: 0x0000,
158 chanspec_band_5g: 0xc000,
159 chanspec_band_shift: 14,
160 chanspec_bw_10: 0x0800,
161 chanspec_bw_20: 0x1000,
162 chanspec_bw_40: 0x1800,
163 chanspec_bw_mask: 0x3800,
164 chanspec_bw_shift: 11,
165 chanspec_ctl_sb_lower: 0x0000,
166 chanspec_ctl_sb_upper: 0x0100,
167 chanspec_ctl_sb_none: 0x0000,
168 chanspec_ctl_sb_mask: 0x0700,
169};
170
171#[derive(Clone, Copy)]
172#[repr(C)]
173struct SdpcmHeader {
174 len: u16,
175 len_inv: u16,
176 /// Rx/Tx sequence number
177 sequence: u8,
178 /// 4 MSB Channel number, 4 LSB arbitrary flag
179 channel_and_flags: u8,
180 /// Length of next data frame, reserved for Tx
181 next_length: u8,
182 /// Data offset
183 header_length: u8,
184 /// Flow control bits, reserved for Tx
185 wireless_flow_control: u8,
186 /// Maximum Sequence number allowed by firmware for Tx
187 bus_data_credit: u8,
188 /// Reserved
189 reserved: [u8; 2],
190}
191
192#[derive(Clone, Copy)]
193#[repr(C)]
194struct CdcHeader {
195 cmd: u32,
196 out_len: u16,
197 in_len: u16,
198 flags: u16,
199 id: u16,
200 status: u32,
201}
202
203#[derive(Clone, Copy)]
204#[repr(C)]
205struct BdcHeader {
206 flags: u8,
207 /// 802.1d Priority (low 3 bits)
208 priority: u8,
209 flags2: u8,
210 /// Offset from end of BDC header to packet data, in 4-uint8_t words. Leaves room for optional headers.
211 data_offset: u8,
212}
213
214macro_rules! impl_bytes {
215 ($t:ident) => {
216 impl $t {
217 const SIZE: usize = core::mem::size_of::<Self>();
218
219 pub fn to_bytes(&self) -> [u8; Self::SIZE] {
220 unsafe { core::mem::transmute(*self) }
221 }
222
223 pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> Self {
224 unsafe { core::mem::transmute(*bytes) }
225 }
226 }
227 };
228}
229impl_bytes!(SdpcmHeader);
230impl_bytes!(CdcHeader);
231impl_bytes!(BdcHeader);
232
233pub struct Driver<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> {
234 pwr: Output<'a, PWR>,
235
236 /// SPI chip-select.
237 cs: Output<'a, CS>,
238
239 /// SPI clock
240 clk: Output<'a, CLK>,
241
242 /// 4 signals, all in one!!
243 /// - SPI MISO
244 /// - SPI MOSI
245 /// - IRQ
246 /// - strap to set to gSPI mode on boot.
247 dio: Flex<'a, DIO>,
248
249 backplane_window: u32,
250}
251
252impl<'a, PWR: Pin, CS: Pin, CLK: Pin, DIO: Pin> Driver<'a, PWR, CS, CLK, DIO> {
253 pub fn new(pwr: Output<'a, PWR>, cs: Output<'a, CS>, clk: Output<'a, CLK>, dio: Flex<'a, DIO>) -> Self {
254 Self {
255 pwr,
256 cs,
257 clk,
258 dio,
259 backplane_window: 0xAAAA_AAAA,
260 }
261 }
262
263 pub async fn init(&mut self) {
264 // Set strap to select gSPI mode.
265 self.dio.set_as_output();
266 self.dio.set_low();
267
268 // Reset
269 self.pwr.set_low();
270 Timer::after(Duration::from_millis(20)).await;
271 self.pwr.set_high();
272 Timer::after(Duration::from_millis(250)).await;
273
274 info!("waiting for ping...");
275 while self.read32_swapped(REG_BUS_FEEDBEAD) != FEEDBEAD {}
276 info!("ping ok");
277
278 self.write32_swapped(0x18, TEST_PATTERN);
279 let val = self.read32_swapped(REG_BUS_TEST);
280 assert_eq!(val, TEST_PATTERN);
281
282 // 32bit, big endian.
283 self.write32_swapped(REG_BUS_CTRL, 0x00010033);
284
285 let val = self.read32(FUNC_BUS, REG_BUS_FEEDBEAD);
286 assert_eq!(val, FEEDBEAD);
287 let val = self.read32(FUNC_BUS, REG_BUS_TEST);
288 assert_eq!(val, TEST_PATTERN);
289
290 // No response delay in any of the funcs.
291 // seems to break backplane??? eat the 4-byte delay instead, that's what the vendor drivers do...
292 //self.write32(FUNC_BUS, REG_BUS_RESP_DELAY, 0);
293
294 // Init ALP (no idea what that stands for) clock
295 self.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x08);
296 info!("waiting for clock...");
297 while self.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR) & 0x40 == 0 {}
298 info!("clock ok");
299
300 let chip_id = self.bp_read16(0x1800_0000);
301 info!("chip ID: {}", chip_id);
302
303 // Upload firmware.
304 self.core_disable(Core::WLAN);
305 self.core_reset(Core::SOCSRAM);
306 self.bp_write32(CHIP.socsram_base_address + 0x10, 3);
307 self.bp_write32(CHIP.socsram_base_address + 0x44, 0);
308
309 // I'm flashing the firmwares independently at hardcoded addresses, instead of baking them
310 // into the program with `include_bytes!` or similar, so that flashing the program stays fast.
311 //
312 // Flash them like this, also don't forget to update the lengths below if you change them!.
313 //
314 // probe-rs-cli download 43439A0.bin --format bin --chip RP2040 --base-address 0x10100000
315 // probe-rs-cli download 43439A0.clm_blob --format bin --chip RP2040 --base-address 0x10140000
316 let fw = unsafe { slice::from_raw_parts(0x10100000 as *const u8, 224190) };
317 let clm = unsafe { slice::from_raw_parts(0x10140000 as *const u8, 4752) };
318
319 let ram_addr = CHIP.atcm_ram_base_address;
320
321 info!("loading fw");
322 self.bp_write(ram_addr, fw);
323
324 info!("verifying fw");
325 let mut buf = [0; 1024];
326 for (i, chunk) in fw.chunks(1024).enumerate() {
327 let buf = &mut buf[..chunk.len()];
328 self.bp_read(ram_addr + i as u32 * 1024, buf);
329 assert_eq!(chunk, buf);
330 }
331
332 info!("loading nvram");
333 // Round up to 4 bytes.
334 let nvram_len = (NVRAM.len() + 3) / 4 * 4;
335 self.bp_write(ram_addr + CHIP.chip_ram_size - 4 - nvram_len as u32, NVRAM);
336
337 let nvram_len_words = nvram_len as u32 / 4;
338 let nvram_len_magic = (!nvram_len_words << 16) | nvram_len_words;
339 self.bp_write32(ram_addr + CHIP.chip_ram_size - 4, nvram_len_magic);
340
341 // Start core!
342 info!("starting up core...");
343 self.core_reset(Core::WLAN);
344 assert!(self.core_is_up(Core::WLAN));
345
346 while self.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR) & 0x80 == 0 {}
347
348 // "Set up the interrupt mask and enable interrupts"
349 self.bp_write32(CHIP.sdiod_core_base_address + 0x24, 0xF0);
350
351 // "Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped."
352 // Sounds scary...
353 self.write8(FUNC_BACKPLANE, REG_BACKPLANE_FUNCTION2_WATERMARK, 32);
354
355 // wait for wifi startup
356 info!("waiting for wifi init...");
357 while self.read32(FUNC_BUS, REG_BUS_STATUS) & STATUS_F2_RX_READY == 0 {}
358
359 // Some random configs related to sleep.
360 // I think they're not needed if we don't want sleep...???
361 /*
362 let mut val = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL);
363 val |= 0x02; // WAKE_TILL_HT_AVAIL
364 self.write8(FUNC_BACKPLANE, REG_BACKPLANE_WAKEUP_CTRL, val);
365 self.write8(FUNC_BUS, 0xF0, 0x08); // SDIOD_CCCR_BRCM_CARDCAP.CMD_NODEC = 1
366 self.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x02); // SBSDIO_FORCE_HT
367
368 let mut val = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_SLEEP_CSR);
369 val |= 0x01; // SBSDIO_SLPCSR_KEEP_SDIO_ON
370 self.write8(FUNC_BACKPLANE, REG_BACKPLANE_SLEEP_CSR, val);
371
372 // clear pulls
373 self.write8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP, 0);
374 let _ = self.read8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP);
375 */
376
377 let mut buf = [0; 8 + 12 + 1024];
378 buf[0..8].copy_from_slice(b"clmload\x00");
379 buf[8..20].copy_from_slice(b"\x02\x10\x02\x00\x00\x04\x00\x00\x00\x00\x00\x00");
380 buf[20..].copy_from_slice(&clm[..1024]);
381 self.send_ioctl(2, 263, 0, &buf);
382
383 info!("init done ");
384
385 let mut old_irq = 0;
386 let mut buf = [0; 2048];
387 loop {
388 let irq = self.read16(FUNC_BUS, REG_BUS_INTERRUPT);
389 if irq != old_irq {
390 info!("irq: {:04x}", irq);
391 }
392 old_irq = irq;
393
394 if irq & IRQ_F2_PACKET_AVAILABLE != 0 {
395 let mut status = 0xFFFF_FFFF;
396 while status == 0xFFFF_FFFF {
397 status = self.read32(FUNC_BUS, REG_BUS_STATUS);
398 }
399
400 if status & STATUS_F2_PKT_AVAILABLE != 0 {
401 let len = (status & STATUS_F2_PKT_LEN_MASK) >> STATUS_F2_PKT_LEN_SHIFT;
402 info!("got len {}", len);
403
404 let cmd = cmd_word(false, true, FUNC_WLAN, 0, len);
405
406 self.cs.set_low();
407 self.spi_write(&cmd.to_le_bytes());
408 self.spi_read(&mut buf[..len as usize]);
409 // pad to 32bit
410 let mut junk = [0; 4];
411 if len % 4 != 0 {
412 self.spi_read(&mut junk[..(4 - len as usize % 4)]);
413 }
414 self.cs.set_high();
415
416 info!("rxd packet {:02x}", &buf[..len as usize]);
417
418 self.rx(&buf[..len as usize]);
419 }
420 }
421
422 yield_now().await;
423 }
424 }
425
426 fn rx(&mut self, packet: &[u8]) {
427 if packet.len() < SdpcmHeader::SIZE {
428 warn!("packet too short, len={}", packet.len());
429 return;
430 }
431
432 let sdpcm_header = SdpcmHeader::from_bytes(packet[..SdpcmHeader::SIZE].try_into().unwrap());
433
434 if sdpcm_header.len != !sdpcm_header.len_inv {
435 warn!("len inv mismatch");
436 return;
437 }
438 if sdpcm_header.len as usize != packet.len() {
439 // TODO: is this guaranteed??
440 warn!("len from header doesn't match len from spi");
441 return;
442 }
443
444 let channel = sdpcm_header.channel_and_flags & 0x0f;
445
446 match channel {
447 0 => {
448 if packet.len() < SdpcmHeader::SIZE + CdcHeader::SIZE {
449 warn!("control packet too short, len={}", packet.len());
450 return;
451 }
452
453 let cdc_header =
454 CdcHeader::from_bytes(packet[SdpcmHeader::SIZE..][..CdcHeader::SIZE].try_into().unwrap());
455
456 // TODO check cdc_header.id matches
457 // TODO check status
458 }
459 _ => {}
460 }
461 }
462
463 fn send_ioctl(&mut self, kind: u32, cmd: u32, iface: u32, data: &[u8]) {
464 let mut buf = [0; 2048];
465
466 let total_len = SdpcmHeader::SIZE + CdcHeader::SIZE + data.len();
467
468 let sdpcm_header = SdpcmHeader {
469 len: total_len as u16,
470 len_inv: !total_len as u16,
471 sequence: 0x02, // todo
472 channel_and_flags: 0, // control channle
473 next_length: 0,
474 header_length: SdpcmHeader::SIZE as _,
475 wireless_flow_control: 0,
476 bus_data_credit: 0,
477 reserved: [0, 0],
478 };
479
480 let cdc_header = CdcHeader {
481 cmd: cmd,
482 out_len: data.len() as _,
483 in_len: 0,
484 flags: kind as u16 | (iface as u16) << 12,
485 id: 1, // todo
486 status: 0,
487 };
488
489 buf[0..SdpcmHeader::SIZE].copy_from_slice(&sdpcm_header.to_bytes());
490 buf[SdpcmHeader::SIZE..][..CdcHeader::SIZE].copy_from_slice(&cdc_header.to_bytes());
491 buf[SdpcmHeader::SIZE + CdcHeader::SIZE..][..data.len()].copy_from_slice(data);
492
493 info!("txing {:02x}", &buf[..total_len]);
494
495 let cmd = cmd_word(true, true, FUNC_WLAN, 0, total_len as _);
496 self.cs.set_low();
497 self.spi_write(&cmd.to_le_bytes());
498 self.spi_write(&buf[..total_len]);
499 self.cs.set_high();
500 }
501
502 fn core_disable(&mut self, core: Core) {
503 let base = core.base_addr();
504
505 // Dummy read?
506 let _ = self.bp_read8(base + AI_RESETCTRL_OFFSET);
507
508 // Check it isn't already reset
509 let r = self.bp_read8(base + AI_RESETCTRL_OFFSET);
510 if r & AI_RESETCTRL_BIT_RESET != 0 {
511 return;
512 }
513
514 self.bp_write8(base + AI_IOCTRL_OFFSET, 0);
515 let _ = self.bp_read8(base + AI_IOCTRL_OFFSET);
516
517 block_for(Duration::from_millis(1));
518
519 self.bp_write8(base + AI_RESETCTRL_OFFSET, AI_RESETCTRL_BIT_RESET);
520 let _ = self.bp_read8(base + AI_RESETCTRL_OFFSET);
521 }
522
523 fn core_reset(&mut self, core: Core) {
524 self.core_disable(core);
525
526 let base = core.base_addr();
527 self.bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN);
528 let _ = self.bp_read8(base + AI_IOCTRL_OFFSET);
529
530 self.bp_write8(base + AI_RESETCTRL_OFFSET, 0);
531
532 block_for(Duration::from_millis(1));
533
534 self.bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_CLOCK_EN);
535 let _ = self.bp_read8(base + AI_IOCTRL_OFFSET);
536
537 block_for(Duration::from_millis(1));
538 }
539
540 fn core_is_up(&mut self, core: Core) -> bool {
541 let base = core.base_addr();
542
543 let io = self.bp_read8(base + AI_IOCTRL_OFFSET);
544 if io & (AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) != AI_IOCTRL_BIT_CLOCK_EN {
545 debug!("core_is_up: returning false due to bad ioctrl {:02x}", io);
546 return false;
547 }
548
549 let r = self.bp_read8(base + AI_RESETCTRL_OFFSET);
550 if r & (AI_RESETCTRL_BIT_RESET) != 0 {
551 debug!("core_is_up: returning false due to bad resetctrl {:02x}", r);
552 return false;
553 }
554
555 true
556 }
557
558 fn bp_read(&mut self, mut addr: u32, mut data: &mut [u8]) {
559 // It seems the HW force-aligns the addr
560 // to 2 if data.len() >= 2
561 // to 4 if data.len() >= 4
562 // To simplify, enforce 4-align for now.
563 assert!(addr % 4 == 0);
564
565 while !data.is_empty() {
566 // Ensure transfer doesn't cross a window boundary.
567 let window_offs = addr & BACKPLANE_ADDRESS_MASK;
568 let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize;
569
570 let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining);
571
572 self.backplane_set_window(addr);
573
574 let cmd = cmd_word(false, true, FUNC_BACKPLANE, window_offs, len as u32);
575 self.cs.set_low();
576 self.spi_write(&cmd.to_le_bytes());
577
578 // 4-byte response delay.
579 let mut junk = [0; 4];
580 self.spi_read(&mut junk);
581
582 // Read data
583 self.spi_read(&mut data[..len]);
584
585 // pad to 32bit
586 if len % 4 != 0 {
587 self.spi_read(&mut junk[..(4 - len % 4)]);
588 }
589 self.cs.set_high();
590
591 // Advance ptr.
592 addr += len as u32;
593 data = &mut data[len..];
594 }
595 }
596
597 fn bp_write(&mut self, mut addr: u32, mut data: &[u8]) {
598 // It seems the HW force-aligns the addr
599 // to 2 if data.len() >= 2
600 // to 4 if data.len() >= 4
601 // To simplify, enforce 4-align for now.
602 assert!(addr % 4 == 0);
603
604 while !data.is_empty() {
605 // Ensure transfer doesn't cross a window boundary.
606 let window_offs = addr & BACKPLANE_ADDRESS_MASK;
607 let window_remaining = BACKPLANE_WINDOW_SIZE - window_offs as usize;
608
609 let len = data.len().min(BACKPLANE_MAX_TRANSFER_SIZE).min(window_remaining);
610
611 self.backplane_set_window(addr);
612
613 let cmd = cmd_word(true, true, FUNC_BACKPLANE, window_offs, len as u32);
614 self.cs.set_low();
615 self.spi_write(&cmd.to_le_bytes());
616 self.spi_write(&data[..len]);
617 // pad to 32bit
618 if len % 4 != 0 {
619 let zeros = [0; 4];
620 self.spi_write(&zeros[..(4 - len % 4)]);
621 }
622 self.cs.set_high();
623
624 // Advance ptr.
625 addr += len as u32;
626 data = &data[len..];
627 }
628 }
629
630 fn bp_read8(&mut self, addr: u32) -> u8 {
631 self.backplane_readn(addr, 1) as u8
632 }
633
634 fn bp_write8(&mut self, addr: u32, val: u8) {
635 self.backplane_writen(addr, val as u32, 1)
636 }
637
638 fn bp_read16(&mut self, addr: u32) -> u16 {
639 self.backplane_readn(addr, 2) as u16
640 }
641
642 fn bp_write16(&mut self, addr: u32, val: u16) {
643 self.backplane_writen(addr, val as u32, 2)
644 }
645
646 fn bp_read32(&mut self, addr: u32) -> u32 {
647 self.backplane_readn(addr, 4)
648 }
649
650 fn bp_write32(&mut self, addr: u32, val: u32) {
651 self.backplane_writen(addr, val, 4)
652 }
653
654 fn backplane_readn(&mut self, addr: u32, len: u32) -> u32 {
655 self.backplane_set_window(addr);
656
657 let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK;
658 if len == 4 {
659 bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG
660 }
661 self.readn(FUNC_BACKPLANE, bus_addr, len)
662 }
663
664 fn backplane_writen(&mut self, addr: u32, val: u32, len: u32) {
665 self.backplane_set_window(addr);
666
667 let mut bus_addr = addr & BACKPLANE_ADDRESS_MASK;
668 if len == 4 {
669 bus_addr |= BACKPLANE_ADDRESS_32BIT_FLAG
670 }
671 self.writen(FUNC_BACKPLANE, bus_addr, val, len)
672 }
673
674 fn backplane_set_window(&mut self, addr: u32) {
675 let new_window = addr & !BACKPLANE_ADDRESS_MASK;
676
677 if (new_window >> 24) as u8 != (self.backplane_window >> 24) as u8 {
678 self.write8(
679 FUNC_BACKPLANE,
680 REG_BACKPLANE_BACKPLANE_ADDRESS_HIGH,
681 (new_window >> 24) as u8,
682 );
683 }
684 if (new_window >> 16) as u8 != (self.backplane_window >> 16) as u8 {
685 self.write8(
686 FUNC_BACKPLANE,
687 REG_BACKPLANE_BACKPLANE_ADDRESS_MID,
688 (new_window >> 16) as u8,
689 );
690 }
691 if (new_window >> 8) as u8 != (self.backplane_window >> 8) as u8 {
692 self.write8(
693 FUNC_BACKPLANE,
694 REG_BACKPLANE_BACKPLANE_ADDRESS_LOW,
695 (new_window >> 8) as u8,
696 );
697 }
698 self.backplane_window = new_window;
699 }
700
701 fn read8(&mut self, func: u32, addr: u32) -> u8 {
702 self.readn(func, addr, 1) as u8
703 }
704
705 fn write8(&mut self, func: u32, addr: u32, val: u8) {
706 self.writen(func, addr, val as u32, 1)
707 }
708
709 fn read16(&mut self, func: u32, addr: u32) -> u16 {
710 self.readn(func, addr, 2) as u16
711 }
712
713 fn write16(&mut self, func: u32, addr: u32, val: u16) {
714 self.writen(func, addr, val as u32, 2)
715 }
716
717 fn read32(&mut self, func: u32, addr: u32) -> u32 {
718 self.readn(func, addr, 4)
719 }
720
721 fn write32(&mut self, func: u32, addr: u32, val: u32) {
722 self.writen(func, addr, val, 4)
723 }
724
725 fn readn(&mut self, func: u32, addr: u32, len: u32) -> u32 {
726 let cmd = cmd_word(false, true, func, addr, len);
727 let mut buf = [0; 4];
728
729 self.cs.set_low();
730 self.spi_write(&cmd.to_le_bytes());
731 if func == FUNC_BACKPLANE {
732 // 4-byte response delay.
733 self.spi_read(&mut buf);
734 }
735 self.spi_read(&mut buf);
736 self.cs.set_high();
737
738 u32::from_le_bytes(buf)
739 }
740
741 fn writen(&mut self, func: u32, addr: u32, val: u32, len: u32) {
742 let cmd = cmd_word(true, true, func, addr, len);
743
744 self.cs.set_low();
745 self.spi_write(&cmd.to_le_bytes());
746 self.spi_write(&val.to_le_bytes());
747 self.cs.set_high();
748 }
749
750 fn read32_swapped(&mut self, addr: u32) -> u32 {
751 let cmd = cmd_word(false, true, FUNC_BUS, addr, 4);
752 let mut buf = [0; 4];
753
754 self.cs.set_low();
755 self.spi_write(&swap16(cmd).to_le_bytes());
756 self.spi_read(&mut buf);
757 self.cs.set_high();
758
759 swap16(u32::from_le_bytes(buf))
760 }
761
762 fn write32_swapped(&mut self, addr: u32, val: u32) {
763 let cmd = cmd_word(true, true, FUNC_BUS, addr, 4);
764
765 self.cs.set_low();
766 self.spi_write(&swap16(cmd).to_le_bytes());
767 self.spi_write(&swap16(val).to_le_bytes());
768 self.cs.set_high();
769 }
770
771 fn spi_read(&mut self, words: &mut [u8]) {
772 self.dio.set_as_input();
773 for word in words {
774 let mut w = 0;
775 for _ in 0..8 {
776 w = w << 1;
777
778 // rising edge, sample data
779 if self.dio.is_high() {
780 w |= 0x01;
781 }
782 self.clk.set_high();
783 delay();
784
785 // falling edge
786 self.clk.set_low();
787 delay();
788 }
789 *word = w
790 }
791 self.clk.set_low();
792 delay();
793 }
794
795 fn spi_write(&mut self, words: &[u8]) {
796 self.dio.set_as_output();
797 for word in words {
798 let mut word = *word;
799 for _ in 0..8 {
800 // falling edge, setup data
801 self.clk.set_low();
802 if word & 0x80 == 0 {
803 self.dio.set_low();
804 } else {
805 self.dio.set_high();
806 }
807 delay();
808
809 // rising edge
810 self.clk.set_high();
811 delay();
812
813 word = word << 1;
814 }
815 }
816 self.clk.set_low();
817 delay();
818 self.dio.set_as_input();
819 }
820}
821
822fn delay() {
823 //cortex_m::asm::delay(5);
824}
825
826macro_rules! nvram {
827 ($($s:literal,)*) => {
828 concat_bytes!($($s, b"\x00",)* b"\x00\x00")
829 };
830}
831
832static NVRAM: &'static [u8] = &*nvram!(
833 b"NVRAMRev=$Rev$",
834 b"manfid=0x2d0",
835 b"prodid=0x0727",
836 b"vendid=0x14e4",
837 b"devid=0x43e2",
838 b"boardtype=0x0887",
839 b"boardrev=0x1100",
840 b"boardnum=22",
841 b"macaddr=00:A0:50:86:aa:b6",
842 b"sromrev=11",
843 b"boardflags=0x00404001",
844 b"boardflags3=0x04000000",
845 b"xtalfreq=26000",
846 b"nocrc=1",
847 b"ag0=255",
848 b"aa2g=1",
849 b"ccode=ALL",
850 b"pa0itssit=0x20",
851 b"extpagain2g=0",
852 b"pa2ga0=-168,7161,-820",
853 b"AvVmid_c0=0x0,0xc8",
854 b"cckpwroffset0=5",
855 b"maxp2ga0=84",
856 b"txpwrbckof=6",
857 b"cckbw202gpo=0",
858 b"legofdmbw202gpo=0x66111111",
859 b"mcsbw202gpo=0x77711111",
860 b"propbw202gpo=0xdd",
861 b"ofdmdigfilttype=18",
862 b"ofdmdigfilttypebe=18",
863 b"papdmode=1",
864 b"papdvalidtest=1",
865 b"pacalidx2g=45",
866 b"papdepsoffset=-30",
867 b"papdendidx=58",
868 b"ltecxmux=0",
869 b"ltecxpadnum=0x0102",
870 b"ltecxfnsel=0x44",
871 b"ltecxgcigpio=0x01",
872 b"il0macaddr=00:90:4c:c5:12:38",
873 b"wl0id=0x431b",
874 b"deadman_to=0xffffffff",
875 b"muxenab=0x1",
876 b"spurconfig=0x3",
877 b"glitch_based_crsmin=1",
878 b"btc_mode=1",
879);