rework event handling to allow sending data

This commit is contained in:
kbleeke 2023-04-02 20:19:47 +02:00
parent 6a1a3e6877
commit 2d7ba44621
7 changed files with 192 additions and 42 deletions

View File

@ -1,11 +1,10 @@
use core::slice;
use embassy_futures::yield_now; use embassy_futures::yield_now;
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use embedded_hal_1::digital::OutputPin; use embedded_hal_1::digital::OutputPin;
use futures::FutureExt; use futures::FutureExt;
use crate::consts::*; use crate::consts::*;
use crate::slice8_mut;
/// Custom Spi Trait that _only_ supports the bus operation of the cyw43 /// Custom Spi Trait that _only_ supports the bus operation of the cyw43
/// Implementors are expected to hold the CS pin low during an operation. /// Implementors are expected to hold the CS pin low during an operation.
@ -327,8 +326,3 @@ fn swap16(x: u32) -> u32 {
fn cmd_word(write: bool, incr: bool, func: u32, addr: u32, len: u32) -> u32 { 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) (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) }
}

View File

@ -109,6 +109,50 @@ pub(crate) const READ: bool = false;
pub(crate) const INC_ADDR: bool = true; pub(crate) const INC_ADDR: bool = true;
pub(crate) const FIXED_ADDR: bool = false; pub(crate) const FIXED_ADDR: bool = false;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
#[repr(u8)]
pub enum EStatus {
/// operation was successful
SUCCESS = 0,
/// operation failed
FAIL = 1,
/// operation timed out
TIMEOUT = 2,
/// failed due to no matching network found
NO_NETWORKS = 3,
/// operation was aborted
ABORT = 4,
/// protocol failure: packet not ack'd
NO_ACK = 5,
/// AUTH or ASSOC packet was unsolicited
UNSOLICITED = 6,
/// attempt to assoc to an auto auth configuration
ATTEMPT = 7,
/// scan results are incomplete
PARTIAL = 8,
/// scan aborted by another scan
NEWSCAN = 9,
/// scan aborted due to assoc in progress
NEWASSOC = 10,
/// 802.11h quiet period started
_11HQUIET = 11,
/// user disabled scanning (WLC_SET_SCANSUPPRESS)
SUPPRESS = 12,
/// no allowable channels to scan
NOCHANS = 13,
/// scan aborted due to CCX fast roam
CCXFASTRM = 14,
/// abort channel select
CS_ABORT = 15,
}
impl PartialEq<EStatus> for u32 {
fn eq(&self, other: &EStatus) -> bool {
*self == *other as Self
}
}
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) struct FormatStatus(pub u32); pub(crate) struct FormatStatus(pub u32);

View File

@ -6,7 +6,7 @@ use embassy_time::{Duration, Timer};
pub use crate::bus::SpiBusCyw43; pub use crate::bus::SpiBusCyw43;
use crate::consts::*; use crate::consts::*;
use crate::events::{Event, EventQueue}; use crate::events::{Event, Events};
use crate::fmt::Bytes; use crate::fmt::Bytes;
use crate::ioctl::{IoctlState, IoctlType}; use crate::ioctl::{IoctlState, IoctlType};
use crate::structs::*; use crate::structs::*;
@ -14,15 +14,15 @@ use crate::{countries, PowerManagementMode};
pub struct Control<'a> { pub struct Control<'a> {
state_ch: ch::StateRunner<'a>, state_ch: ch::StateRunner<'a>,
event_sub: &'a EventQueue, events: &'a Events,
ioctl_state: &'a IoctlState, ioctl_state: &'a IoctlState,
} }
impl<'a> Control<'a> { impl<'a> Control<'a> {
pub(crate) fn new(state_ch: ch::StateRunner<'a>, event_sub: &'a EventQueue, ioctl_state: &'a IoctlState) -> Self { pub(crate) fn new(state_ch: ch::StateRunner<'a>, event_sub: &'a Events, ioctl_state: &'a IoctlState) -> Self {
Self { Self {
state_ch, state_ch,
event_sub, events: event_sub,
ioctl_state, ioctl_state,
} }
} }
@ -195,24 +195,25 @@ impl<'a> Control<'a> {
} }
async fn wait_for_join(&mut self, i: SsidInfo) { async fn wait_for_join(&mut self, i: SsidInfo) {
let mut subscriber = self.event_sub.subscriber().unwrap(); self.events.mask.enable(&[Event::JOIN, Event::AUTH]);
let mut subscriber = self.events.queue.subscriber().unwrap();
self.ioctl(IoctlType::Set, IOCTL_CMD_SET_SSID, 0, &mut i.to_bytes()) self.ioctl(IoctlType::Set, IOCTL_CMD_SET_SSID, 0, &mut i.to_bytes())
.await; .await;
// set_ssid // set_ssid
loop { loop {
let msg = subscriber.next_message_pure().await; let msg = subscriber.next_message_pure().await;
if msg.event_type == Event::AUTH && msg.status != 0 { if msg.header.event_type == Event::AUTH && msg.header.status != 0 {
// retry // retry
warn!("JOIN failed with status={}", msg.status); warn!("JOIN failed with status={}", msg.header.status);
self.ioctl(IoctlType::Set, IOCTL_CMD_SET_SSID, 0, &mut i.to_bytes()) self.ioctl(IoctlType::Set, IOCTL_CMD_SET_SSID, 0, &mut i.to_bytes())
.await; .await;
} else if msg.event_type == Event::JOIN && msg.status == 0 { } else if msg.header.event_type == Event::JOIN && msg.header.status == 0 {
// successful join // successful join
break; break;
} }
} }
self.events.mask.disable_all();
self.state_ch.set_link_state(LinkState::Up); self.state_ch.set_link_state(LinkState::Up);
info!("JOINED"); info!("JOINED");
} }

View File

@ -1,7 +1,7 @@
#![allow(unused)] #![allow(unused)]
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
use core::num; use core::cell::RefCell;
use embassy_sync::blocking_mutex::raw::NoopRawMutex; use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::pubsub::{PubSubChannel, Publisher, Subscriber}; use embassy_sync::pubsub::{PubSubChannel, Publisher, Subscriber};
@ -284,13 +284,114 @@ pub enum Event {
LAST = 190, LAST = 190,
} }
pub type EventQueue = PubSubChannel<NoopRawMutex, EventStatus, 2, 1, 1>; // TODO this PubSub can probably be replaced with shared memory to make it a bit more efficient.
pub type EventPublisher<'a> = Publisher<'a, NoopRawMutex, EventStatus, 2, 1, 1>; pub type EventQueue = PubSubChannel<NoopRawMutex, Message, 2, 1, 1>;
pub type EventSubscriber<'a> = Subscriber<'a, NoopRawMutex, EventStatus, 2, 1, 1>; pub type EventPublisher<'a> = Publisher<'a, NoopRawMutex, Message, 2, 1, 1>;
pub type EventSubscriber<'a> = Subscriber<'a, NoopRawMutex, Message, 2, 1, 1>;
pub struct Events {
pub queue: EventQueue,
pub mask: SharedEventMask,
}
impl Events {
pub fn new() -> Self {
Self {
queue: EventQueue::new(),
mask: SharedEventMask::default(),
}
}
}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct EventStatus { pub struct Status {
pub event_type: Event, pub event_type: Event,
pub status: u32, pub status: u32,
} }
#[derive(Clone, Copy)]
pub enum Payload {
None,
}
#[derive(Clone, Copy)]
pub struct Message {
pub header: Status,
pub payload: Payload,
}
impl Message {
pub fn new(status: Status, payload: Payload) -> Self {
Self {
header: status,
payload,
}
}
}
const EVENT_BITS: usize = ((Event::LAST as usize + 31) & !31) / 32;
#[derive(Default)]
struct EventMask {
mask: [u32; EVENT_BITS],
}
impl EventMask {
fn enable(&mut self, event: Event) {
let n = event as u32;
let word = n >> 5;
let bit = n & 0b11111;
self.mask[word as usize] |= (1 << bit);
}
fn disable(&mut self, event: Event) {
let n = event as u32;
let word = n >> 5;
let bit = n & 0b11111;
self.mask[word as usize] &= !(1 << bit);
}
fn is_enabled(&self, event: Event) -> bool {
let n = event as u32;
let word = n >> 5;
let bit = n & 0b11111;
self.mask[word as usize] & (1 << bit) > 0
}
}
#[derive(Default)]
pub struct SharedEventMask {
mask: RefCell<EventMask>,
}
impl SharedEventMask {
pub fn enable(&self, events: &[Event]) {
let mut mask = self.mask.borrow_mut();
for event in events {
mask.enable(*event);
}
}
pub fn disable(&self, events: &[Event]) {
let mut mask = self.mask.borrow_mut();
for event in events {
mask.disable(*event);
}
}
pub fn disable_all(&self) {
let mut mask = self.mask.borrow_mut();
mask.mask = Default::default();
}
pub fn is_enabled(&self, event: Event) -> bool {
let mask = self.mask.borrow();
mask.is_enabled(event)
}
}

View File

@ -4,6 +4,8 @@ use core::task::{Poll, Waker};
use embassy_sync::waitqueue::WakerRegistration; use embassy_sync::waitqueue::WakerRegistration;
use crate::fmt::Bytes;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum IoctlType { pub enum IoctlType {
Get = 0, Get = 0,
@ -100,6 +102,8 @@ impl IoctlState {
pub fn ioctl_done(&self, response: &[u8]) { pub fn ioctl_done(&self, response: &[u8]) {
if let IoctlStateInner::Sent { buf } = self.state.get() { if let IoctlStateInner::Sent { buf } = self.state.get() {
info!("IOCTL Response: {:02x}", Bytes(response));
// TODO fix this // TODO fix this
(unsafe { &mut *buf }[..response.len()]).copy_from_slice(response); (unsafe { &mut *buf }[..response.len()]).copy_from_slice(response);
@ -107,6 +111,8 @@ impl IoctlState {
resp_len: response.len(), resp_len: response.len(),
}); });
self.wake_control(); self.wake_control();
} else {
warn!("IOCTL Response but no pending Ioctl");
} }
} }
} }

View File

@ -18,9 +18,11 @@ mod control;
mod nvram; mod nvram;
mod runner; mod runner;
use core::slice;
use embassy_net_driver_channel as ch; use embassy_net_driver_channel as ch;
use embedded_hal_1::digital::OutputPin; use embedded_hal_1::digital::OutputPin;
use events::EventQueue; use events::Events;
use ioctl::IoctlState; use ioctl::IoctlState;
use crate::bus::Bus; use crate::bus::Bus;
@ -103,7 +105,7 @@ const CHIP: Chip = Chip {
pub struct State { pub struct State {
ioctl_state: IoctlState, ioctl_state: IoctlState,
ch: ch::State<MTU, 4, 4>, ch: ch::State<MTU, 4, 4>,
events: EventQueue, events: Events,
} }
impl State { impl State {
@ -111,7 +113,7 @@ impl State {
Self { Self {
ioctl_state: IoctlState::new(), ioctl_state: IoctlState::new(),
ch: ch::State::new(), ch: ch::State::new(),
events: EventQueue::new(), events: Events::new(),
} }
} }
} }
@ -225,3 +227,8 @@ where
runner, runner,
) )
} }
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) }
}

View File

@ -1,5 +1,3 @@
use core::slice;
use embassy_futures::select::{select3, Either3}; use embassy_futures::select::{select3, Either3};
use embassy_net_driver_channel as ch; use embassy_net_driver_channel as ch;
use embassy_sync::pubsub::PubSubBehavior; use embassy_sync::pubsub::PubSubBehavior;
@ -9,12 +7,12 @@ use embedded_hal_1::digital::OutputPin;
use crate::bus::Bus; use crate::bus::Bus;
pub use crate::bus::SpiBusCyw43; pub use crate::bus::SpiBusCyw43;
use crate::consts::*; use crate::consts::*;
use crate::events::{EventQueue, EventStatus}; use crate::events::{Events, Status};
use crate::fmt::Bytes; use crate::fmt::Bytes;
use crate::ioctl::{IoctlState, IoctlType, PendingIoctl}; use crate::ioctl::{IoctlState, IoctlType, PendingIoctl};
use crate::nvram::NVRAM; use crate::nvram::NVRAM;
use crate::structs::*; use crate::structs::*;
use crate::{events, Core, CHIP, MTU}; use crate::{events, slice8_mut, Core, CHIP, MTU};
#[cfg(feature = "firmware-logs")] #[cfg(feature = "firmware-logs")]
struct LogState { struct LogState {
@ -45,7 +43,7 @@ pub struct Runner<'a, PWR, SPI> {
sdpcm_seq: u8, sdpcm_seq: u8,
sdpcm_seq_max: u8, sdpcm_seq_max: u8,
events: &'a EventQueue, events: &'a Events,
#[cfg(feature = "firmware-logs")] #[cfg(feature = "firmware-logs")]
log: LogState, log: LogState,
@ -60,7 +58,7 @@ where
ch: ch::Runner<'a, MTU>, ch: ch::Runner<'a, MTU>,
bus: Bus<PWR, SPI>, bus: Bus<PWR, SPI>,
ioctl_state: &'a IoctlState, ioctl_state: &'a IoctlState,
events: &'a EventQueue, events: &'a Events,
) -> Self { ) -> Self {
Self { Self {
ch, ch,
@ -353,8 +351,6 @@ where
panic!("IOCTL error {}", cdc_header.status as i32); panic!("IOCTL error {}", cdc_header.status as i32);
} }
info!("IOCTL Response: {:02x}", Bytes(response));
self.ioctl_state.ioctl_done(response); self.ioctl_state.ioctl_done(response);
} }
} }
@ -406,11 +402,17 @@ where
Bytes(evt_data) Bytes(evt_data)
); );
if evt_type == events::Event::AUTH || evt_type == events::Event::JOIN { if self.events.mask.is_enabled(evt_type) {
self.events.publish_immediate(EventStatus { let status = event_packet.msg.status;
status: event_packet.msg.status, let event_payload = events::Payload::None;
self.events.queue.publish_immediate(events::Message::new(
Status {
event_type: evt_type, event_type: evt_type,
}); status,
},
event_payload,
));
} }
} }
CHANNEL_TYPE_DATA => { CHANNEL_TYPE_DATA => {
@ -548,8 +550,3 @@ where
true true
} }
} }
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) }
}