diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index 00072749..118f6908 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -25,6 +25,8 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> { type TxToken<'a> = TxToken where Self: 'a; fn receive(&mut self, cx: &mut Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { + self.runner.rx_waker.register(cx.waker()); + // WAKER.register(cx.waker()); // if self.rx.available().is_some() && self.tx.available().is_some() { // Some((RxToken { rx: &mut self.rx }, TxToken { tx: &mut self.tx })) @@ -36,6 +38,8 @@ impl<'d> embassy_net_driver::Driver for Driver<'d> { } fn transmit(&mut self, cx: &mut Context) -> Option> { + self.runner.tx_waker.register(cx.waker()); + // WAKER.register(cx.waker()); // / if self.tx.available().is_some() { // / Some(TxToken { tx: &mut self.tx }) @@ -84,7 +88,7 @@ impl embassy_net_driver::RxToken for RxToken { // NOTE(unwrap): we checked the queue wasn't full when creating the token. // let pkt = unwrap!(self.rx.available()); - let pkt = &[]; + let pkt = &mut []; let r = f(&mut pkt[0..]); // self.rx.pop_packet(); r @@ -102,7 +106,7 @@ impl embassy_net_driver::TxToken for TxToken { { // NOTE(unwrap): we checked the queue wasn't full when creating the token. // let pkt = unwrap!(self.tx.available()); - let pkt = &[]; + let pkt = &mut []; let r = f(&mut pkt[..len]); // self.tx.transmit(len); r diff --git a/embassy-stm32-wpan/src/mac/mod.rs b/embassy-stm32-wpan/src/mac/mod.rs index e024aeae..2f9d1c81 100644 --- a/embassy-stm32-wpan/src/mac/mod.rs +++ b/embassy-stm32-wpan/src/mac/mod.rs @@ -15,16 +15,11 @@ use core::slice; pub use crate::mac::control::{Control, Error as ControlError}; use crate::mac::driver::Driver; pub use crate::mac::runner::Runner; -use crate::sub::mac::Mac; const MTU: usize = 127; -pub async fn new<'a>(mac: Mac) -> (Runner, Control<'a>, Driver<'a>) { - let runner = Runner::new(mac); - let control = Control::new(&runner); - let driver = Driver::new(&runner); - - (runner, control, driver) +pub async fn new<'a>(runner: &'a Runner) -> (Control<'a>, Driver<'a>) { + (Control::new(runner), Driver::new(runner)) } fn slice8_mut(x: &mut [u32]) -> &mut [u8] { diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index e97c9c8e..d545d6c9 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -1,27 +1,86 @@ use embassy_futures::select::{select3, Either3}; +use embassy_sync::waitqueue::AtomicWaker; +use crate::mac::event::{Event, MacEvent}; use crate::mac::MTU; use crate::sub::mac::Mac; +pub(crate) struct TxRing { + // stores n packets of up to mtu size + ring: [[u8; MTU]; 5], + pending: bool, + // start: u8, + // end: u8, +} + +impl TxRing { + pub(crate) fn new() -> Self { + Self { + ring: [[0; MTU]; 5], + pending: false, + } + } + + // wait for a free packet to become available + pub fn is_packet_free(&self) -> bool { + !self.pending + } + + // get the next available free packet + pub fn get_free_packet<'a>(&'a mut self) -> &'a mut [u8] { + self.pending = true; + + &mut self.ring[0] + } + + pub fn get_packet_to_transmit<'a>(&'a mut self) -> Option<&'a [u8]> { + if self.pending { + self.pending = false; + + Some(&self.ring[0]) + } else { + None + } + } +} + pub struct Runner { - mac: Mac, - // TODO: tx_ring - // TODO: rx_buf + mac_subsystem: Mac, + pub(crate) rx_ring: Option, + pub(crate) tx_ring: TxRing, + pub(crate) rx_waker: AtomicWaker, + pub(crate) tx_waker: AtomicWaker, } impl Runner { - pub(crate) fn new(mac: Mac) -> Self { - Self { mac } + pub fn new(mac: Mac) -> Self { + Self { + mac_subsystem: mac, + rx_ring: None, + tx_ring: TxRing::new(), + rx_waker: AtomicWaker::new(), + tx_waker: AtomicWaker::new(), + } } pub(crate) async fn init(&mut self, firmware: &[u8]) { debug!("wifi init done"); } - pub async fn run(mut self) -> ! { - let mut buf = [0; 512]; + pub async fn run(&self) -> ! { loop { - // TODO + let event = self.mac_subsystem.read().await; + if let Ok(evt) = event.mac_event() { + match evt { + MacEvent::McpsDataInd(data_ind) => { + // TODO: store mac_event in rx_ring + self.rx_waker.wake(); + } + _ => {} + } + } + + // TODO: select tx event } } } diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs new file mode 100644 index 00000000..b1cf051b --- /dev/null +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -0,0 +1,180 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::bind_interrupts; +use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32_wpan::mac::commands::{AssociateResponse, ResetRequest, SetRequest, StartRequest}; +use embassy_stm32_wpan::mac::typedefs::{MacChannel, MacStatus, PanId, PibId, SecurityLevel}; +use embassy_stm32_wpan::mac::{self, Runner}; +use embassy_stm32_wpan::sub::mm; +use embassy_stm32_wpan::TlMbox; +use static_cell::make_static; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs{ + IPCC_C1_RX => ReceiveInterruptHandler; + IPCC_C1_TX => TransmitInterruptHandler; +}); + +#[embassy_executor::task] +async fn run_mm_queue(memory_manager: mm::MemoryManager) { + memory_manager.run_queue().await; +} + +#[embassy_executor::task] +async fn run_mac(runner: &'static Runner) { + runner.run().await; +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + /* + How to make this work: + + - Obtain a NUCLEO-STM32WB55 from your preferred supplier. + - Download and Install STM32CubeProgrammer. + - Download stm32wb5x_FUS_fw.bin, stm32wb5x_BLE_Stack_full_fw.bin, and Release_Notes.html from + gh:STMicroelectronics/STM32CubeWB@2234d97/Projects/STM32WB_Copro_Wireless_Binaries/STM32WB5x + - Open STM32CubeProgrammer + - On the right-hand pane, click "firmware upgrade" to upgrade the st-link firmware. + - Once complete, click connect to connect to the device. + - On the left hand pane, click the RSS signal icon to open "Firmware Upgrade Services". + - In the Release_Notes.html, find the memory address that corresponds to your device for the stm32wb5x_FUS_fw.bin file + - Select that file, the memory address, "verify download", and then "Firmware Upgrade". + - Once complete, in the Release_Notes.html, find the memory address that corresponds to your device for the + stm32wb5x_BLE_Stack_full_fw.bin file. It should not be the same memory address. + - Select that file, the memory address, "verify download", and then "Firmware Upgrade". + - Select "Start Wireless Stack". + - Disconnect from the device. + - In the examples folder for stm32wb, modify the memory.x file to match your target device. + - Run this example. + + Note: extended stack versions are not supported at this time. Do not attempt to install a stack with "extended" in the name. + */ + + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + let config = Config::default(); + let mbox = TlMbox::init(p.IPCC, Irqs, config); + + spawner.spawn(run_mm_queue(mbox.mm_subsystem)).unwrap(); + + let sys_event = mbox.sys_subsystem.read().await; + info!("sys event: {}", sys_event.payload()); + + core::mem::drop(sys_event); + + let result = mbox.sys_subsystem.shci_c2_mac_802_15_4_init().await; + info!("initialized mac: {}", result); + + info!("resetting"); + mbox.mac_subsystem + .send_command(&ResetRequest { + set_default_pib: true, + ..Default::default() + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("setting extended address"); + let extended_address: u64 = 0xACDE480000000001; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &extended_address as *const _ as *const u8, + pib_attribute: PibId::ExtendedAddress, + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("setting short address"); + let short_address: u16 = 0x1122; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &short_address as *const _ as *const u8, + pib_attribute: PibId::ShortAddress, + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("setting association permit"); + let association_permit: bool = true; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &association_permit as *const _ as *const u8, + pib_attribute: PibId::AssociationPermit, + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("setting TX power"); + let transmit_power: i8 = 2; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &transmit_power as *const _ as *const u8, + pib_attribute: PibId::TransmitPower, + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("starting FFD device"); + mbox.mac_subsystem + .send_command(&StartRequest { + pan_id: PanId([0x1A, 0xAA]), + channel_number: MacChannel::Channel16, + beacon_order: 0x0F, + superframe_order: 0x0F, + pan_coordinator: true, + battery_life_extension: false, + ..Default::default() + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + info!("setting RX on when idle"); + let rx_on_while_idle: bool = true; + mbox.mac_subsystem + .send_command(&SetRequest { + pib_attribute_ptr: &rx_on_while_idle as *const _ as *const u8, + pib_attribute: PibId::RxOnWhenIdle, + }) + .await + .unwrap(); + { + let evt = mbox.mac_subsystem.read().await; + defmt::info!("{:#x}", evt.mac_event()); + } + + let runner = make_static!(Runner::new(mbox.mac_subsystem)); + + spawner.spawn(run_mac(runner)).unwrap(); + + let (driver, control) = mac::new(runner).await; +}