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_time::{Duration, Timer};
use embedded_hal_1::digital::OutputPin;
use futures::FutureExt;
use crate::consts::*;
use crate::slice8_mut;
/// Custom Spi Trait that _only_ supports the bus operation of the cyw43
/// 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 {
(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 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)]
pub(crate) struct FormatStatus(pub u32);

View file

@ -6,7 +6,7 @@ use embassy_time::{Duration, Timer};
pub use crate::bus::SpiBusCyw43;
use crate::consts::*;
use crate::events::{Event, EventQueue};
use crate::events::{Event, Events};
use crate::fmt::Bytes;
use crate::ioctl::{IoctlState, IoctlType};
use crate::structs::*;
@ -14,15 +14,15 @@ use crate::{countries, PowerManagementMode};
pub struct Control<'a> {
state_ch: ch::StateRunner<'a>,
event_sub: &'a EventQueue,
events: &'a Events,
ioctl_state: &'a IoctlState,
}
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 {
state_ch,
event_sub,
events: event_sub,
ioctl_state,
}
}
@ -195,24 +195,25 @@ impl<'a> Control<'a> {
}
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())
.await;
// set_ssid
loop {
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
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())
.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
break;
}
}
self.events.mask.disable_all();
self.state_ch.set_link_state(LinkState::Up);
info!("JOINED");
}

View file

@ -1,7 +1,7 @@
#![allow(unused)]
#![allow(non_camel_case_types)]
use core::num;
use core::cell::RefCell;
use embassy_sync::blocking_mutex::raw::NoopRawMutex;
use embassy_sync::pubsub::{PubSubChannel, Publisher, Subscriber};
@ -284,13 +284,114 @@ pub enum Event {
LAST = 190,
}
pub type EventQueue = PubSubChannel<NoopRawMutex, EventStatus, 2, 1, 1>;
pub type EventPublisher<'a> = Publisher<'a, NoopRawMutex, EventStatus, 2, 1, 1>;
pub type EventSubscriber<'a> = Subscriber<'a, NoopRawMutex, EventStatus, 2, 1, 1>;
// TODO this PubSub can probably be replaced with shared memory to make it a bit more efficient.
pub type EventQueue = PubSubChannel<NoopRawMutex, Message, 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)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct EventStatus {
pub struct Status {
pub event_type: Event,
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 crate::fmt::Bytes;
#[derive(Clone, Copy)]
pub enum IoctlType {
Get = 0,
@ -100,6 +102,8 @@ impl IoctlState {
pub fn ioctl_done(&self, response: &[u8]) {
if let IoctlStateInner::Sent { buf } = self.state.get() {
info!("IOCTL Response: {:02x}", Bytes(response));
// TODO fix this
(unsafe { &mut *buf }[..response.len()]).copy_from_slice(response);
@ -107,6 +111,8 @@ impl IoctlState {
resp_len: response.len(),
});
self.wake_control();
} else {
warn!("IOCTL Response but no pending Ioctl");
}
}
}

View file

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