aboutsummaryrefslogtreecommitdiff
path: root/cyw43/src/runner.rs
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2024-08-05 20:58:04 +0200
committerDario Nieuwenhuis <[email protected]>2024-08-05 21:07:42 +0200
commit4f7ac1946a43379306aa432961fb97bba1139a6e (patch)
tree2589e67baa770acf244dfdea355e16585d683d16 /cyw43/src/runner.rs
parentafc8e684dd16c3bc947b365ca293f0f37d95b342 (diff)
cyw43: add Bluetooth support.
Co-Authored-By: Brandon Ros <[email protected]>
Diffstat (limited to 'cyw43/src/runner.rs')
-rw-r--r--cyw43/src/runner.rs120
1 files changed, 96 insertions, 24 deletions
diff --git a/cyw43/src/runner.rs b/cyw43/src/runner.rs
index e90316302..6522d40fa 100644
--- a/cyw43/src/runner.rs
+++ b/cyw43/src/runner.rs
@@ -1,4 +1,4 @@
1use embassy_futures::select::{select3, Either3}; 1use embassy_futures::select::{select4, Either4};
2use embassy_net_driver_channel as ch; 2use embassy_net_driver_channel as ch;
3use embassy_time::{block_for, Duration, Timer}; 3use embassy_time::{block_for, Duration, Timer};
4use embedded_hal_1::digital::OutputPin; 4use embedded_hal_1::digital::OutputPin;
@@ -11,7 +11,8 @@ use crate::fmt::Bytes;
11use crate::ioctl::{IoctlState, IoctlType, PendingIoctl}; 11use crate::ioctl::{IoctlState, IoctlType, PendingIoctl};
12use crate::nvram::NVRAM; 12use crate::nvram::NVRAM;
13use crate::structs::*; 13use crate::structs::*;
14use crate::{events, slice8_mut, Core, CHIP, MTU}; 14use crate::util::slice8_mut;
15use crate::{events, Core, CHIP, MTU};
15 16
16#[cfg(feature = "firmware-logs")] 17#[cfg(feature = "firmware-logs")]
17struct LogState { 18struct LogState {
@@ -36,7 +37,7 @@ impl Default for LogState {
36/// Driver communicating with the WiFi chip. 37/// Driver communicating with the WiFi chip.
37pub struct Runner<'a, PWR, SPI> { 38pub struct Runner<'a, PWR, SPI> {
38 ch: ch::Runner<'a, MTU>, 39 ch: ch::Runner<'a, MTU>,
39 bus: Bus<PWR, SPI>, 40 pub(crate) bus: Bus<PWR, SPI>,
40 41
41 ioctl_state: &'a IoctlState, 42 ioctl_state: &'a IoctlState,
42 ioctl_id: u16, 43 ioctl_id: u16,
@@ -47,6 +48,9 @@ pub struct Runner<'a, PWR, SPI> {
47 48
48 #[cfg(feature = "firmware-logs")] 49 #[cfg(feature = "firmware-logs")]
49 log: LogState, 50 log: LogState,
51
52 #[cfg(feature = "bluetooth")]
53 pub(crate) bt: Option<crate::bluetooth::BtRunner<'a>>,
50} 54}
51 55
52impl<'a, PWR, SPI> Runner<'a, PWR, SPI> 56impl<'a, PWR, SPI> Runner<'a, PWR, SPI>
@@ -59,6 +63,7 @@ where
59 bus: Bus<PWR, SPI>, 63 bus: Bus<PWR, SPI>,
60 ioctl_state: &'a IoctlState, 64 ioctl_state: &'a IoctlState,
61 events: &'a Events, 65 events: &'a Events,
66 #[cfg(feature = "bluetooth")] bt: Option<crate::bluetooth::BtRunner<'a>>,
62 ) -> Self { 67 ) -> Self {
63 Self { 68 Self {
64 ch, 69 ch,
@@ -70,33 +75,52 @@ where
70 events, 75 events,
71 #[cfg(feature = "firmware-logs")] 76 #[cfg(feature = "firmware-logs")]
72 log: LogState::default(), 77 log: LogState::default(),
78 #[cfg(feature = "bluetooth")]
79 bt,
73 } 80 }
74 } 81 }
75 82
76 pub(crate) async fn init(&mut self, firmware: &[u8]) { 83 pub(crate) async fn init(&mut self, wifi_fw: &[u8], bt_fw: Option<&[u8]>) {
77 self.bus.init().await; 84 self.bus.init(bt_fw.is_some()).await;
78 85
79 // Init ALP (Active Low Power) clock 86 // Init ALP (Active Low Power) clock
87 debug!("init alp");
80 self.bus 88 self.bus
81 .write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, BACKPLANE_ALP_AVAIL_REQ) 89 .write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, BACKPLANE_ALP_AVAIL_REQ)
82 .await; 90 .await;
91
92 debug!("set f2 watermark");
93 self.bus
94 .write8(FUNC_BACKPLANE, REG_BACKPLANE_FUNCTION2_WATERMARK, 0x10)
95 .await;
96 let watermark = self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_FUNCTION2_WATERMARK).await;
97 debug!("watermark = {:02x}", watermark);
98 assert!(watermark == 0x10);
99
83 debug!("waiting for clock..."); 100 debug!("waiting for clock...");
84 while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & BACKPLANE_ALP_AVAIL == 0 {} 101 while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & BACKPLANE_ALP_AVAIL == 0 {}
85 debug!("clock ok"); 102 debug!("clock ok");
86 103
104 // clear request for ALP
105 debug!("clear request for ALP");
106 self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0).await;
107
87 let chip_id = self.bus.bp_read16(0x1800_0000).await; 108 let chip_id = self.bus.bp_read16(0x1800_0000).await;
88 debug!("chip ID: {}", chip_id); 109 debug!("chip ID: {}", chip_id);
89 110
90 // Upload firmware. 111 // Upload firmware.
91 self.core_disable(Core::WLAN).await; 112 self.core_disable(Core::WLAN).await;
113 self.core_disable(Core::SOCSRAM).await; // TODO: is this needed if we reset right after?
92 self.core_reset(Core::SOCSRAM).await; 114 self.core_reset(Core::SOCSRAM).await;
115
116 // this is 4343x specific stuff: Disable remap for SRAM_3
93 self.bus.bp_write32(CHIP.socsram_base_address + 0x10, 3).await; 117 self.bus.bp_write32(CHIP.socsram_base_address + 0x10, 3).await;
94 self.bus.bp_write32(CHIP.socsram_base_address + 0x44, 0).await; 118 self.bus.bp_write32(CHIP.socsram_base_address + 0x44, 0).await;
95 119
96 let ram_addr = CHIP.atcm_ram_base_address; 120 let ram_addr = CHIP.atcm_ram_base_address;
97 121
98 debug!("loading fw"); 122 debug!("loading fw");
99 self.bus.bp_write(ram_addr, firmware).await; 123 self.bus.bp_write(ram_addr, wifi_fw).await;
100 124
101 debug!("loading nvram"); 125 debug!("loading nvram");
102 // Round up to 4 bytes. 126 // Round up to 4 bytes.
@@ -116,10 +140,23 @@ where
116 self.core_reset(Core::WLAN).await; 140 self.core_reset(Core::WLAN).await;
117 assert!(self.core_is_up(Core::WLAN).await); 141 assert!(self.core_is_up(Core::WLAN).await);
118 142
143 // wait until HT clock is available; takes about 29ms
144 debug!("wait for HT clock");
119 while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {} 145 while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {}
120 146
121 // "Set up the interrupt mask and enable interrupts" 147 // "Set up the interrupt mask and enable interrupts"
122 // self.bus.bp_write32(CHIP.sdiod_core_base_address + 0x24, 0xF0).await; 148 debug!("setup interrupt mask");
149 self.bus
150 .bp_write32(CHIP.sdiod_core_base_address + SDIO_INT_HOST_MASK, I_HMB_SW_MASK)
151 .await;
152
153 // Set up the interrupt mask and enable interrupts
154 if bt_fw.is_some() {
155 debug!("bluetooth setup interrupt mask");
156 self.bus
157 .bp_write32(CHIP.sdiod_core_base_address + SDIO_INT_HOST_MASK, I_HMB_FC_CHANGE)
158 .await;
159 }
123 160
124 self.bus 161 self.bus
125 .write16(FUNC_BUS, REG_BUS_INTERRUPT_ENABLE, IRQ_F2_PACKET_AVAILABLE) 162 .write16(FUNC_BUS, REG_BUS_INTERRUPT_ENABLE, IRQ_F2_PACKET_AVAILABLE)
@@ -128,11 +165,11 @@ where
128 // "Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped." 165 // "Lower F2 Watermark to avoid DMA Hang in F2 when SD Clock is stopped."
129 // Sounds scary... 166 // Sounds scary...
130 self.bus 167 self.bus
131 .write8(FUNC_BACKPLANE, REG_BACKPLANE_FUNCTION2_WATERMARK, 32) 168 .write8(FUNC_BACKPLANE, REG_BACKPLANE_FUNCTION2_WATERMARK, SPI_F2_WATERMARK)
132 .await; 169 .await;
133 170
134 // wait for wifi startup 171 // wait for F2 to be ready
135 debug!("waiting for wifi init..."); 172 debug!("waiting for F2 to be ready...");
136 while self.bus.read32(FUNC_BUS, REG_BUS_STATUS).await & STATUS_F2_RX_READY == 0 {} 173 while self.bus.read32(FUNC_BUS, REG_BUS_STATUS).await & STATUS_F2_RX_READY == 0 {}
137 174
138 // Some random configs related to sleep. 175 // Some random configs related to sleep.
@@ -153,19 +190,27 @@ where
153 */ 190 */
154 191
155 // clear pulls 192 // clear pulls
193 debug!("clear pad pulls");
156 self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP, 0).await; 194 self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP, 0).await;
157 let _ = self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP).await; 195 let _ = self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_PULL_UP).await;
158 196
159 // start HT clock 197 // start HT clock
160 //self.bus.write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x10).await; 198 self.bus
161 //debug!("waiting for HT clock..."); 199 .write8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR, 0x10)
162 //while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {} 200 .await; // SBSDIO_HT_AVAIL_REQ
163 //debug!("clock ok"); 201 debug!("waiting for HT clock...");
202 while self.bus.read8(FUNC_BACKPLANE, REG_BACKPLANE_CHIP_CLOCK_CSR).await & 0x80 == 0 {}
203 debug!("clock ok");
164 204
165 #[cfg(feature = "firmware-logs")] 205 #[cfg(feature = "firmware-logs")]
166 self.log_init().await; 206 self.log_init().await;
167 207
168 debug!("wifi init done"); 208 #[cfg(feature = "bluetooth")]
209 if let Some(bt_fw) = bt_fw {
210 self.bt.as_mut().unwrap().init_bluetooth(&mut self.bus, bt_fw).await;
211 }
212
213 debug!("cyw43 runner init done");
169 } 214 }
170 215
171 #[cfg(feature = "firmware-logs")] 216 #[cfg(feature = "firmware-logs")]
@@ -222,7 +267,7 @@ where
222 } 267 }
223 } 268 }
224 269
225 /// Run the 270 /// Run the CYW43 event handling loop.
226 pub async fn run(mut self) -> ! { 271 pub async fn run(mut self) -> ! {
227 let mut buf = [0; 512]; 272 let mut buf = [0; 512];
228 loop { 273 loop {
@@ -231,11 +276,27 @@ where
231 276
232 if self.has_credit() { 277 if self.has_credit() {
233 let ioctl = self.ioctl_state.wait_pending(); 278 let ioctl = self.ioctl_state.wait_pending();
234 let tx = self.ch.tx_buf(); 279 let wifi_tx = self.ch.tx_buf();
280 #[cfg(feature = "bluetooth")]
281 let bt_tx = async {
282 match &mut self.bt {
283 Some(bt) => bt.tx_chan.receive().await,
284 None => core::future::pending().await,
285 }
286 };
287 #[cfg(not(feature = "bluetooth"))]
288 let bt_tx = core::future::pending::<()>();
289
290 // interrupts aren't working yet for bluetooth. Do busy-polling instead.
291 // Note for this to work `ev` has to go last in the `select()`. It prefers
292 // first futures if they're ready, so other select branches don't get starved.`
293 #[cfg(feature = "bluetooth")]
294 let ev = core::future::ready(());
295 #[cfg(not(feature = "bluetooth"))]
235 let ev = self.bus.wait_for_event(); 296 let ev = self.bus.wait_for_event();
236 297
237 match select3(ioctl, tx, ev).await { 298 match select4(ioctl, wifi_tx, bt_tx, ev).await {
238 Either3::First(PendingIoctl { 299 Either4::First(PendingIoctl {
239 buf: iobuf, 300 buf: iobuf,
240 kind, 301 kind,
241 cmd, 302 cmd,
@@ -244,7 +305,7 @@ where
244 self.send_ioctl(kind, cmd, iface, unsafe { &*iobuf }, &mut buf).await; 305 self.send_ioctl(kind, cmd, iface, unsafe { &*iobuf }, &mut buf).await;
245 self.check_status(&mut buf).await; 306 self.check_status(&mut buf).await;
246 } 307 }
247 Either3::Second(packet) => { 308 Either4::Second(packet) => {
248 trace!("tx pkt {:02x}", Bytes(&packet[..packet.len().min(48)])); 309 trace!("tx pkt {:02x}", Bytes(&packet[..packet.len().min(48)]));
249 310
250 let buf8 = slice8_mut(&mut buf); 311 let buf8 = slice8_mut(&mut buf);
@@ -298,7 +359,11 @@ where
298 self.ch.tx_done(); 359 self.ch.tx_done();
299 self.check_status(&mut buf).await; 360 self.check_status(&mut buf).await;
300 } 361 }
301 Either3::Third(()) => { 362 Either4::Third(_) => {
363 #[cfg(feature = "bluetooth")]
364 self.bt.as_mut().unwrap().hci_write(&mut self.bus).await;
365 }
366 Either4::Fourth(()) => {
302 self.handle_irq(&mut buf).await; 367 self.handle_irq(&mut buf).await;
303 } 368 }
304 } 369 }
@@ -314,17 +379,24 @@ where
314 async fn handle_irq(&mut self, buf: &mut [u32; 512]) { 379 async fn handle_irq(&mut self, buf: &mut [u32; 512]) {
315 // Receive stuff 380 // Receive stuff
316 let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await; 381 let irq = self.bus.read16(FUNC_BUS, REG_BUS_INTERRUPT).await;
317 trace!("irq{}", FormatInterrupt(irq)); 382 if irq != 0 {
383 trace!("irq{}", FormatInterrupt(irq));
384 }
318 385
319 if irq & IRQ_F2_PACKET_AVAILABLE != 0 { 386 if irq & IRQ_F2_PACKET_AVAILABLE != 0 {
320 self.check_status(buf).await; 387 self.check_status(buf).await;
321 } 388 }
322 389
323 if irq & IRQ_DATA_UNAVAILABLE != 0 { 390 if irq & IRQ_DATA_UNAVAILABLE != 0 {
324 // TODO what should we do here? 391 // this seems to be ignorable with no ill effects.
325 warn!("IRQ DATA_UNAVAILABLE, clearing..."); 392 trace!("IRQ DATA_UNAVAILABLE, clearing...");
326 self.bus.write16(FUNC_BUS, REG_BUS_INTERRUPT, 1).await; 393 self.bus.write16(FUNC_BUS, REG_BUS_INTERRUPT, 1).await;
327 } 394 }
395
396 #[cfg(feature = "bluetooth")]
397 if let Some(bt) = &mut self.bt {
398 bt.handle_irq(&mut self.bus).await;
399 }
328 } 400 }
329 401
330 /// Handle F2 events while status register is set 402 /// Handle F2 events while status register is set