aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32-wpan/src
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-07-16 09:32:54 -0500
committerxoviat <[email protected]>2023-07-16 09:32:54 -0500
commit582006c75cdd7e9d819bcacc0f6724c05f161bee (patch)
treee6ee5c4151be02eb87bb26f25b410e8a1d8dd286 /embassy-stm32-wpan/src
parentcd592cb0550146158ea6f9d90ba8afe9e1b06a92 (diff)
wpan/mac: further cleanup
Diffstat (limited to 'embassy-stm32-wpan/src')
-rw-r--r--embassy-stm32-wpan/src/mac/event.rs119
-rw-r--r--embassy-stm32-wpan/src/mac/ioctl.rs124
-rw-r--r--embassy-stm32-wpan/src/mac/mod.rs14
-rw-r--r--embassy-stm32-wpan/src/mac/runner.rs161
4 files changed, 257 insertions, 161 deletions
diff --git a/embassy-stm32-wpan/src/mac/event.rs b/embassy-stm32-wpan/src/mac/event.rs
index dfce21fea..ea326a336 100644
--- a/embassy-stm32-wpan/src/mac/event.rs
+++ b/embassy-stm32-wpan/src/mac/event.rs
@@ -1,3 +1,8 @@
1use core::cell::RefCell;
2
3use embassy_sync::blocking_mutex::raw::NoopRawMutex;
4use embassy_sync::pubsub::{PubSubChannel, Subscriber};
5
1use super::helpers::to_u16; 6use super::helpers::to_u16;
2use super::indications::{ 7use super::indications::{
3 AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication, 8 AssociateIndication, BeaconNotifyIndication, CommStatusIndication, DataIndication, DisassociateIndication,
@@ -25,6 +30,7 @@ pub trait ParseableMacEvent {
25 Self: Sized; 30 Self: Sized;
26} 31}
27 32
33#[derive(Debug, Clone, PartialEq, Eq)]
28#[cfg_attr(feature = "defmt", derive(defmt::Format))] 34#[cfg_attr(feature = "defmt", derive(defmt::Format))]
29pub enum MacEvent { 35pub enum MacEvent {
30 MlmeAssociateCnf(AssociateConfirm), 36 MlmeAssociateCnf(AssociateConfirm),
@@ -92,3 +98,116 @@ impl TryFrom<&[u8]> for MacEvent {
92 } 98 }
93 } 99 }
94} 100}
101
102// TODO this PubSub can probably be replaced with shared memory to make it a bit more efficient.
103pub type EventQueue = PubSubChannel<NoopRawMutex, Message, 2, 1, 1>;
104pub type EventSubscriber<'a> = Subscriber<'a, NoopRawMutex, Message, 2, 1, 1>;
105
106pub struct Events {
107 pub queue: EventQueue,
108 pub mask: SharedEventMask,
109}
110
111impl Events {
112 pub fn new() -> Self {
113 Self {
114 queue: EventQueue::new(),
115 mask: SharedEventMask::default(),
116 }
117 }
118}
119
120#[derive(Clone)]
121#[cfg_attr(feature = "defmt", derive(defmt::Format))]
122pub struct Status {
123 pub event_type: MacEvent,
124 pub status: u32,
125}
126
127#[derive(Clone, Copy)]
128pub enum Payload {
129 None,
130 // BssInfo(BssInfo),
131}
132
133#[derive(Clone)]
134
135pub struct Message {
136 pub header: Status,
137 pub payload: Payload,
138}
139
140impl Message {
141 pub fn new(status: Status, payload: Payload) -> Self {
142 Self {
143 header: status,
144 payload,
145 }
146 }
147}
148
149#[derive(Default)]
150struct EventMask {
151 mask: [u32; Self::WORD_COUNT],
152}
153
154impl EventMask {
155 const WORD_COUNT: usize = ((Event::LAST as u32 + (u32::BITS - 1)) / u32::BITS) as usize;
156
157 fn enable(&mut self, event: MacEvent) {
158 let n = event as u32;
159 let word = n / u32::BITS;
160 let bit = n % u32::BITS;
161
162 self.mask[word as usize] |= 1 << bit;
163 }
164
165 fn disable(&mut self, event: MacEvent) {
166 let n = event as u32;
167 let word = n / u32::BITS;
168 let bit = n % u32::BITS;
169
170 self.mask[word as usize] &= !(1 << bit);
171 }
172
173 fn is_enabled(&self, event: MacEvent) -> bool {
174 let n = event as u32;
175 let word = n / u32::BITS;
176 let bit = n % u32::BITS;
177
178 self.mask[word as usize] & (1 << bit) > 0
179 }
180}
181
182#[derive(Default)]
183
184pub struct SharedEventMask {
185 mask: RefCell<EventMask>,
186}
187
188impl SharedEventMask {
189 pub fn enable(&self, events: &[MacEvent]) {
190 let mut mask = self.mask.borrow_mut();
191 for event in events {
192 mask.enable(*event);
193 }
194 }
195
196 #[allow(dead_code)]
197 pub fn disable(&self, events: &[MacEvent]) {
198 let mut mask = self.mask.borrow_mut();
199 for event in events {
200 mask.disable(*event);
201 }
202 }
203
204 pub fn disable_all(&self) {
205 let mut mask = self.mask.borrow_mut();
206 mask.mask = Default::default();
207 }
208
209 pub fn is_enabled(&self, event: MacEvent) -> bool {
210 let mask = self.mask.borrow();
211 mask.is_enabled(event)
212 }
213}
diff --git a/embassy-stm32-wpan/src/mac/ioctl.rs b/embassy-stm32-wpan/src/mac/ioctl.rs
new file mode 100644
index 000000000..0fe55cd6c
--- /dev/null
+++ b/embassy-stm32-wpan/src/mac/ioctl.rs
@@ -0,0 +1,124 @@
1use core::cell::{Cell, RefCell};
2use core::future::poll_fn;
3use core::task::{Poll, Waker};
4
5use embassy_sync::waitqueue::WakerRegistration;
6
7#[derive(Clone, Copy)]
8pub enum IoctlType {
9 Get = 0,
10 Set = 2,
11}
12
13#[derive(Clone, Copy)]
14pub struct PendingIoctl {
15 pub buf: *mut [u8],
16 pub kind: IoctlType,
17 pub cmd: u32,
18 pub iface: u32,
19}
20
21#[derive(Clone, Copy)]
22enum IoctlStateInner {
23 Pending(PendingIoctl),
24 Sent { buf: *mut [u8] },
25 Done { resp_len: usize },
26}
27
28struct Wakers {
29 control: WakerRegistration,
30 runner: WakerRegistration,
31}
32
33impl Default for Wakers {
34 fn default() -> Self {
35 Self {
36 control: WakerRegistration::new(),
37 runner: WakerRegistration::new(),
38 }
39 }
40}
41
42pub struct IoctlState {
43 state: Cell<IoctlStateInner>,
44 wakers: RefCell<Wakers>,
45}
46
47impl IoctlState {
48 pub fn new() -> Self {
49 Self {
50 state: Cell::new(IoctlStateInner::Done { resp_len: 0 }),
51 wakers: Default::default(),
52 }
53 }
54
55 fn wake_control(&self) {
56 self.wakers.borrow_mut().control.wake();
57 }
58
59 fn register_control(&self, waker: &Waker) {
60 self.wakers.borrow_mut().control.register(waker);
61 }
62
63 fn wake_runner(&self) {
64 self.wakers.borrow_mut().runner.wake();
65 }
66
67 fn register_runner(&self, waker: &Waker) {
68 self.wakers.borrow_mut().runner.register(waker);
69 }
70
71 pub async fn wait_complete(&self) -> usize {
72 poll_fn(|cx| {
73 if let IoctlStateInner::Done { resp_len } = self.state.get() {
74 Poll::Ready(resp_len)
75 } else {
76 self.register_control(cx.waker());
77 Poll::Pending
78 }
79 })
80 .await
81 }
82
83 pub async fn wait_pending(&self) -> PendingIoctl {
84 let pending = poll_fn(|cx| {
85 if let IoctlStateInner::Pending(pending) = self.state.get() {
86 Poll::Ready(pending)
87 } else {
88 self.register_runner(cx.waker());
89 Poll::Pending
90 }
91 })
92 .await;
93
94 self.state.set(IoctlStateInner::Sent { buf: pending.buf });
95 pending
96 }
97
98 pub fn cancel_ioctl(&self) {
99 self.state.set(IoctlStateInner::Done { resp_len: 0 });
100 }
101
102 pub async fn do_ioctl(&self, kind: IoctlType, cmd: u32, iface: u32, buf: &mut [u8]) -> usize {
103 self.state
104 .set(IoctlStateInner::Pending(PendingIoctl { buf, kind, cmd, iface }));
105 self.wake_runner();
106 self.wait_complete().await
107 }
108
109 pub fn ioctl_done(&self, response: &[u8]) {
110 if let IoctlStateInner::Sent { buf } = self.state.get() {
111 // trace!("IOCTL Response: {:02x}", Bytes(response));
112
113 // TODO fix this
114 (unsafe { &mut *buf }[..response.len()]).copy_from_slice(response);
115
116 self.state.set(IoctlStateInner::Done {
117 resp_len: response.len(),
118 });
119 self.wake_control();
120 } else {
121 warn!("IOCTL Response but no pending Ioctl");
122 }
123 }
124}
diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs
index e27f0ba73..67dc429e2 100644
--- a/embassy-stm32-wpan/src/mac/mod.rs
+++ b/embassy-stm32-wpan/src/mac/mod.rs
@@ -4,6 +4,7 @@ pub mod control;
4pub mod event; 4pub mod event;
5mod helpers; 5mod helpers;
6pub mod indications; 6pub mod indications;
7mod ioctl;
7mod macros; 8mod macros;
8mod opcodes; 9mod opcodes;
9pub mod responses; 10pub mod responses;
@@ -14,11 +15,10 @@ use core::slice;
14 15
15use embassy_net_driver_channel as ch; 16use embassy_net_driver_channel as ch;
16 17
17use crate::bus::Bus;
18pub use crate::bus::SpiBusCyw43;
19pub use crate::mac::control::{Control, Error as ControlError}; 18pub use crate::mac::control::{Control, Error as ControlError};
20pub use crate::runner::Runner; 19use crate::mac::event::Events;
21pub use crate::structs::BssInfo; 20use crate::mac::ioctl::IoctlState;
21pub use crate::mac::runner::Runner;
22use crate::sub::mac::Mac; 22use crate::sub::mac::Mac;
23 23
24const MTU: usize = 1514; 24const MTU: usize = 1514;
@@ -76,15 +76,15 @@ impl PowerManagementMode {
76 76
77pub type NetDriver<'a> = ch::Device<'a, MTU>; 77pub type NetDriver<'a> = ch::Device<'a, MTU>;
78 78
79pub async fn new<'a, PWR, SPI>( 79pub async fn new<'a>(
80 state: &'a mut State, 80 state: &'a mut State,
81 mac_subsystem: Mac, 81 mac_subsystem: Mac,
82 firmware: &[u8], 82 firmware: &[u8],
83) -> (NetDriver<'a>, Control<'a>, Runner<'a, PWR, SPI>) { 83) -> (NetDriver<'a>, Control<'a>, Runner<'a>) {
84 let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]); 84 let (ch_runner, device) = ch::new(&mut state.ch, [0; 6]);
85 let state_ch = ch_runner.state_runner(); 85 let state_ch = ch_runner.state_runner();
86 86
87 let mut runner = Runner::new(ch_runner, Bus::new(pwr, spi), &state.ioctl_state, &state.events); 87 let mut runner = Runner::new(ch_runner, mac_subsystem, &state.ioctl_state, &state.events);
88 88
89 runner.init(firmware).await; 89 runner.init(firmware).await;
90 90
diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs
index 7f0bbd670..fbb7cb747 100644
--- a/embassy-stm32-wpan/src/mac/runner.rs
+++ b/embassy-stm32-wpan/src/mac/runner.rs
@@ -2,29 +2,12 @@ use embassy_futures::select::{select3, Either3};
2use embassy_net_driver_channel as ch; 2use embassy_net_driver_channel as ch;
3use embassy_sync::pubsub::PubSubBehavior; 3use embassy_sync::pubsub::PubSubBehavior;
4 4
5use crate::mac::event::Events;
6use crate::mac::ioctl::{IoctlState, PendingIoctl};
7use crate::mac::MTU;
5use crate::sub::mac::Mac; 8use crate::sub::mac::Mac;
6 9
7#[cfg(feature = "firmware-logs")] 10pub struct Runner<'a> {
8struct LogState {
9 addr: u32,
10 last_idx: usize,
11 buf: [u8; 256],
12 buf_count: usize,
13}
14
15#[cfg(feature = "firmware-logs")]
16impl Default for LogState {
17 fn default() -> Self {
18 Self {
19 addr: Default::default(),
20 last_idx: Default::default(),
21 buf: [0; 256],
22 buf_count: Default::default(),
23 }
24 }
25}
26
27pub struct Runner<'a, PWR, SPI> {
28 ch: ch::Runner<'a, MTU>, 11 ch: ch::Runner<'a, MTU>,
29 mac: Mac, 12 mac: Mac,
30 13
@@ -34,32 +17,18 @@ pub struct Runner<'a, PWR, SPI> {
34 sdpcm_seq_max: u8, 17 sdpcm_seq_max: u8,
35 18
36 events: &'a Events, 19 events: &'a Events,
37
38 #[cfg(feature = "firmware-logs")]
39 log: LogState,
40} 20}
41 21
42impl<'a, PWR, SPI> Runner<'a, PWR, SPI> 22impl<'a> Runner<'a> {
43where 23 pub(crate) fn new(ch: ch::Runner<'a, MTU>, mac: Mac, ioctl_state: &'a IoctlState, events: &'a Events) -> Self {
44 PWR: OutputPin,
45 SPI: SpiBusCyw43,
46{
47 pub(crate) fn new(
48 ch: ch::Runner<'a, MTU>,
49 bus: Bus<PWR, SPI>,
50 ioctl_state: &'a IoctlState,
51 events: &'a Events,
52 ) -> Self {
53 Self { 24 Self {
54 ch, 25 ch,
55 bus, 26 mac,
56 ioctl_state, 27 ioctl_state,
57 ioctl_id: 0, 28 ioctl_id: 0,
58 sdpcm_seq: 0, 29 sdpcm_seq: 0,
59 sdpcm_seq_max: 1, 30 sdpcm_seq_max: 1,
60 events, 31 events,
61 #[cfg(feature = "firmware-logs")]
62 log: LogState::default(),
63 } 32 }
64 } 33 }
65 34
@@ -72,60 +41,6 @@ where
72 debug!("wifi init done"); 41 debug!("wifi init done");
73 } 42 }
74 43
75 #[cfg(feature = "firmware-logs")]
76 async fn log_init(&mut self) {
77 // Initialize shared memory for logging.
78
79 let addr = CHIP.atcm_ram_base_address + CHIP.chip_ram_size - 4 - CHIP.socram_srmem_size;
80 let shared_addr = self.bus.bp_read32(addr).await;
81 debug!("shared_addr {:08x}", shared_addr);
82
83 let mut shared = [0; SharedMemData::SIZE];
84 self.bus.bp_read(shared_addr, &mut shared).await;
85 let shared = SharedMemData::from_bytes(&shared);
86
87 self.log.addr = shared.console_addr + 8;
88 }
89
90 #[cfg(feature = "firmware-logs")]
91 async fn log_read(&mut self) {
92 // Read log struct
93 let mut log = [0; SharedMemLog::SIZE];
94 self.bus.bp_read(self.log.addr, &mut log).await;
95 let log = SharedMemLog::from_bytes(&log);
96
97 let idx = log.idx as usize;
98
99 // If pointer hasn't moved, no need to do anything.
100 if idx == self.log.last_idx {
101 return;
102 }
103
104 // Read entire buf for now. We could read only what we need, but then we
105 // run into annoying alignment issues in `bp_read`.
106 let mut buf = [0; 0x400];
107 self.bus.bp_read(log.buf, &mut buf).await;
108
109 while self.log.last_idx != idx as usize {
110 let b = buf[self.log.last_idx];
111 if b == b'\r' || b == b'\n' {
112 if self.log.buf_count != 0 {
113 let s = unsafe { core::str::from_utf8_unchecked(&self.log.buf[..self.log.buf_count]) };
114 debug!("LOGS: {}", s);
115 self.log.buf_count = 0;
116 }
117 } else if self.log.buf_count < self.log.buf.len() {
118 self.log.buf[self.log.buf_count] = b;
119 self.log.buf_count += 1;
120 }
121
122 self.log.last_idx += 1;
123 if self.log.last_idx == 0x400 {
124 self.log.last_idx = 0;
125 }
126 }
127 }
128
129 pub async fn run(mut self) -> ! { 44 pub async fn run(mut self) -> ! {
130 let mut buf = [0; 512]; 45 let mut buf = [0; 512];
131 loop { 46 loop {
@@ -424,66 +339,4 @@ where
424 339
425 self.bus.wlan_write(&buf[..total_len / 4]).await; 340 self.bus.wlan_write(&buf[..total_len / 4]).await;
426 } 341 }
427
428 async fn core_disable(&mut self, core: Core) {
429 let base = core.base_addr();
430
431 // Dummy read?
432 let _ = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await;
433
434 // Check it isn't already reset
435 let r = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await;
436 if r & AI_RESETCTRL_BIT_RESET != 0 {
437 return;
438 }
439
440 self.bus.bp_write8(base + AI_IOCTRL_OFFSET, 0).await;
441 let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await;
442
443 block_for(Duration::from_millis(1));
444
445 self.bus
446 .bp_write8(base + AI_RESETCTRL_OFFSET, AI_RESETCTRL_BIT_RESET)
447 .await;
448 let _ = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await;
449 }
450
451 async fn core_reset(&mut self, core: Core) {
452 self.core_disable(core).await;
453
454 let base = core.base_addr();
455 self.bus
456 .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN)
457 .await;
458 let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await;
459
460 self.bus.bp_write8(base + AI_RESETCTRL_OFFSET, 0).await;
461
462 Timer::after(Duration::from_millis(1)).await;
463
464 self.bus
465 .bp_write8(base + AI_IOCTRL_OFFSET, AI_IOCTRL_BIT_CLOCK_EN)
466 .await;
467 let _ = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await;
468
469 Timer::after(Duration::from_millis(1)).await;
470 }
471
472 async fn core_is_up(&mut self, core: Core) -> bool {
473 let base = core.base_addr();
474
475 let io = self.bus.bp_read8(base + AI_IOCTRL_OFFSET).await;
476 if io & (AI_IOCTRL_BIT_FGC | AI_IOCTRL_BIT_CLOCK_EN) != AI_IOCTRL_BIT_CLOCK_EN {
477 debug!("core_is_up: returning false due to bad ioctrl {:02x}", io);
478 return false;
479 }
480
481 let r = self.bus.bp_read8(base + AI_RESETCTRL_OFFSET).await;
482 if r & (AI_RESETCTRL_BIT_RESET) != 0 {
483 debug!("core_is_up: returning false due to bad resetctrl {:02x}", r);
484 return false;
485 }
486
487 true
488 }
489} 342}