diff options
| author | xoviat <[email protected]> | 2023-07-16 09:32:54 -0500 |
|---|---|---|
| committer | xoviat <[email protected]> | 2023-07-16 09:32:54 -0500 |
| commit | 582006c75cdd7e9d819bcacc0f6724c05f161bee (patch) | |
| tree | e6ee5c4151be02eb87bb26f25b410e8a1d8dd286 | |
| parent | cd592cb0550146158ea6f9d90ba8afe9e1b06a92 (diff) | |
wpan/mac: further cleanup
| -rw-r--r-- | embassy-stm32-wpan/src/mac/event.rs | 119 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/ioctl.rs | 124 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/mod.rs | 14 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/runner.rs | 161 |
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 @@ | |||
| 1 | use core::cell::RefCell; | ||
| 2 | |||
| 3 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 4 | use embassy_sync::pubsub::{PubSubChannel, Subscriber}; | ||
| 5 | |||
| 1 | use super::helpers::to_u16; | 6 | use super::helpers::to_u16; |
| 2 | use super::indications::{ | 7 | use 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))] |
| 29 | pub enum MacEvent { | 35 | pub 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. | ||
| 103 | pub type EventQueue = PubSubChannel<NoopRawMutex, Message, 2, 1, 1>; | ||
| 104 | pub type EventSubscriber<'a> = Subscriber<'a, NoopRawMutex, Message, 2, 1, 1>; | ||
| 105 | |||
| 106 | pub struct Events { | ||
| 107 | pub queue: EventQueue, | ||
| 108 | pub mask: SharedEventMask, | ||
| 109 | } | ||
| 110 | |||
| 111 | impl 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))] | ||
| 122 | pub struct Status { | ||
| 123 | pub event_type: MacEvent, | ||
| 124 | pub status: u32, | ||
| 125 | } | ||
| 126 | |||
| 127 | #[derive(Clone, Copy)] | ||
| 128 | pub enum Payload { | ||
| 129 | None, | ||
| 130 | // BssInfo(BssInfo), | ||
| 131 | } | ||
| 132 | |||
| 133 | #[derive(Clone)] | ||
| 134 | |||
| 135 | pub struct Message { | ||
| 136 | pub header: Status, | ||
| 137 | pub payload: Payload, | ||
| 138 | } | ||
| 139 | |||
| 140 | impl Message { | ||
| 141 | pub fn new(status: Status, payload: Payload) -> Self { | ||
| 142 | Self { | ||
| 143 | header: status, | ||
| 144 | payload, | ||
| 145 | } | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | #[derive(Default)] | ||
| 150 | struct EventMask { | ||
| 151 | mask: [u32; Self::WORD_COUNT], | ||
| 152 | } | ||
| 153 | |||
| 154 | impl 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 | |||
| 184 | pub struct SharedEventMask { | ||
| 185 | mask: RefCell<EventMask>, | ||
| 186 | } | ||
| 187 | |||
| 188 | impl 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 @@ | |||
| 1 | use core::cell::{Cell, RefCell}; | ||
| 2 | use core::future::poll_fn; | ||
| 3 | use core::task::{Poll, Waker}; | ||
| 4 | |||
| 5 | use embassy_sync::waitqueue::WakerRegistration; | ||
| 6 | |||
| 7 | #[derive(Clone, Copy)] | ||
| 8 | pub enum IoctlType { | ||
| 9 | Get = 0, | ||
| 10 | Set = 2, | ||
| 11 | } | ||
| 12 | |||
| 13 | #[derive(Clone, Copy)] | ||
| 14 | pub 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)] | ||
| 22 | enum IoctlStateInner { | ||
| 23 | Pending(PendingIoctl), | ||
| 24 | Sent { buf: *mut [u8] }, | ||
| 25 | Done { resp_len: usize }, | ||
| 26 | } | ||
| 27 | |||
| 28 | struct Wakers { | ||
| 29 | control: WakerRegistration, | ||
| 30 | runner: WakerRegistration, | ||
| 31 | } | ||
| 32 | |||
| 33 | impl Default for Wakers { | ||
| 34 | fn default() -> Self { | ||
| 35 | Self { | ||
| 36 | control: WakerRegistration::new(), | ||
| 37 | runner: WakerRegistration::new(), | ||
| 38 | } | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | pub struct IoctlState { | ||
| 43 | state: Cell<IoctlStateInner>, | ||
| 44 | wakers: RefCell<Wakers>, | ||
| 45 | } | ||
| 46 | |||
| 47 | impl 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; | |||
| 4 | pub mod event; | 4 | pub mod event; |
| 5 | mod helpers; | 5 | mod helpers; |
| 6 | pub mod indications; | 6 | pub mod indications; |
| 7 | mod ioctl; | ||
| 7 | mod macros; | 8 | mod macros; |
| 8 | mod opcodes; | 9 | mod opcodes; |
| 9 | pub mod responses; | 10 | pub mod responses; |
| @@ -14,11 +15,10 @@ use core::slice; | |||
| 14 | 15 | ||
| 15 | use embassy_net_driver_channel as ch; | 16 | use embassy_net_driver_channel as ch; |
| 16 | 17 | ||
| 17 | use crate::bus::Bus; | ||
| 18 | pub use crate::bus::SpiBusCyw43; | ||
| 19 | pub use crate::mac::control::{Control, Error as ControlError}; | 18 | pub use crate::mac::control::{Control, Error as ControlError}; |
| 20 | pub use crate::runner::Runner; | 19 | use crate::mac::event::Events; |
| 21 | pub use crate::structs::BssInfo; | 20 | use crate::mac::ioctl::IoctlState; |
| 21 | pub use crate::mac::runner::Runner; | ||
| 22 | use crate::sub::mac::Mac; | 22 | use crate::sub::mac::Mac; |
| 23 | 23 | ||
| 24 | const MTU: usize = 1514; | 24 | const MTU: usize = 1514; |
| @@ -76,15 +76,15 @@ impl PowerManagementMode { | |||
| 76 | 76 | ||
| 77 | pub type NetDriver<'a> = ch::Device<'a, MTU>; | 77 | pub type NetDriver<'a> = ch::Device<'a, MTU>; |
| 78 | 78 | ||
| 79 | pub async fn new<'a, PWR, SPI>( | 79 | pub 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}; | |||
| 2 | use embassy_net_driver_channel as ch; | 2 | use embassy_net_driver_channel as ch; |
| 3 | use embassy_sync::pubsub::PubSubBehavior; | 3 | use embassy_sync::pubsub::PubSubBehavior; |
| 4 | 4 | ||
| 5 | use crate::mac::event::Events; | ||
| 6 | use crate::mac::ioctl::{IoctlState, PendingIoctl}; | ||
| 7 | use crate::mac::MTU; | ||
| 5 | use crate::sub::mac::Mac; | 8 | use crate::sub::mac::Mac; |
| 6 | 9 | ||
| 7 | #[cfg(feature = "firmware-logs")] | 10 | pub struct Runner<'a> { |
| 8 | struct LogState { | ||
| 9 | addr: u32, | ||
| 10 | last_idx: usize, | ||
| 11 | buf: [u8; 256], | ||
| 12 | buf_count: usize, | ||
| 13 | } | ||
| 14 | |||
| 15 | #[cfg(feature = "firmware-logs")] | ||
| 16 | impl 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 | |||
| 27 | pub 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 | ||
| 42 | impl<'a, PWR, SPI> Runner<'a, PWR, SPI> | 22 | impl<'a> Runner<'a> { |
| 43 | where | 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 | } |
