From 80ceb42eb1c842fcb214a5fbfbb1c39265c6b29b Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 17 Nov 2025 08:23:34 -0600 Subject: wpan_ get net example actually working --- embassy-stm32-wpan/src/mac/control.rs | 36 +++++-------- embassy-stm32-wpan/src/mac/driver.rs | 12 ++++- embassy-stm32-wpan/src/mac/runner.rs | 24 +++++---- embassy-stm32-wpan/src/sub/mm.rs | 2 +- examples/stm32wb/src/bin/mac_ffd_net.rs | 90 +++++++++++++++++++++++++++------ 5 files changed, 115 insertions(+), 49 deletions(-) diff --git a/embassy-stm32-wpan/src/mac/control.rs b/embassy-stm32-wpan/src/mac/control.rs index 8fb971da3..d2a7b65ee 100644 --- a/embassy-stm32-wpan/src/mac/control.rs +++ b/embassy-stm32-wpan/src/mac/control.rs @@ -38,7 +38,7 @@ impl<'a> Control<'a> { } } - pub async fn init_link(&mut self, short_address: [u8; 2], extended_address: [u8; 8], pan_id: [u8; 2]) { + pub async fn init_link(&mut self, pan_id: [u8; 2]) { debug!("resetting"); debug!( @@ -52,12 +52,19 @@ impl<'a> Control<'a> { .await ); + let (short_address, mac_address) = critical_section::with(|cs| { + let mut network_state = self.network_state.borrow(cs).borrow_mut(); + + network_state.pan_id = pan_id; + + (network_state.short_addr, network_state.mac_addr) + }); + debug!("setting extended address"); - let extended_address: u64 = u64::from_be_bytes(extended_address); debug!( "{:#x}", self.send_command_and_get_response(&SetRequest { - pib_attribute_ptr: &extended_address as *const _ as *const u8, + pib_attribute_ptr: &u64::from_be_bytes(mac_address) as *const _ as *const u8, pib_attribute: PibId::ExtendedAddress, }) .await @@ -66,11 +73,10 @@ impl<'a> Control<'a> { ); debug!("setting short address"); - let short_address: u16 = u16::from_be_bytes(short_address); debug!( "{:#x}", self.send_command_and_get_response(&SetRequest { - pib_attribute_ptr: &short_address as *const _ as *const u8, + pib_attribute_ptr: &u16::from_be_bytes(short_address) as *const _ as *const u8, pib_attribute: PibId::ShortAddress, }) .await @@ -78,10 +84,6 @@ impl<'a> Control<'a> { .await ); - critical_section::with(|cs| { - self.network_state.borrow(cs).borrow_mut().mac_addr = extended_address.to_be_bytes(); - }); - debug!("setting association permit"); let association_permit: bool = true; debug!( @@ -186,20 +188,8 @@ impl<'a> Future for EventToken<'a> { type Output = MacEvent<'a>; fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll { - self.rx_event_channel.lock(|s| { - let signal = s.borrow_mut(); - let signal = match &*signal { - Some(s) => s, - _ => unreachable!(), - }; - - let result = match signal.wait().poll_unpin(cx) { - Poll::Ready(mac_event) => Poll::Ready(mac_event), - Poll::Pending => Poll::Pending, - }; - - result - }) + self.rx_event_channel + .lock(|s| s.borrow_mut().as_mut().unwrap().wait().poll_unpin(cx)) } } diff --git a/embassy-stm32-wpan/src/mac/driver.rs b/embassy-stm32-wpan/src/mac/driver.rs index 819299b48..5592723a2 100644 --- a/embassy-stm32-wpan/src/mac/driver.rs +++ b/embassy-stm32-wpan/src/mac/driver.rs @@ -17,6 +17,8 @@ use crate::sub::mac::{Mac, MacRx, MacTx}; pub struct NetworkState { pub mac_addr: [u8; 8], + pub short_addr: [u8; 2], + pub pan_id: [u8; 2], pub link_state: LinkState, pub link_waker: AtomicWaker, } @@ -25,6 +27,8 @@ impl NetworkState { pub const fn new() -> Self { Self { mac_addr: [0u8; 8], + short_addr: [0u8; 2], + pan_id: [0u8; 2], link_state: LinkState::Down, link_waker: AtomicWaker::new(), } @@ -68,7 +72,11 @@ pub struct Driver<'d> { } impl<'d> Driver<'d> { - pub fn new(driver_state: &'d mut DriverState<'d>) -> (Self, Runner<'d>, Control<'d>) { + pub fn new( + driver_state: &'d mut DriverState<'d>, + short_address: [u8; 2], + mac_address: [u8; 8], + ) -> (Self, Runner<'d>, Control<'d>) { ( Self { tx_data_channel: &driver_state.tx_data_channel, @@ -85,6 +93,8 @@ impl<'d> Driver<'d> { &driver_state.mac_tx, &mut driver_state.tx_buf_queue, &driver_state.network_state, + short_address, + mac_address, ), Control::new( &driver_state.rx_event_channel, diff --git a/embassy-stm32-wpan/src/mac/runner.rs b/embassy-stm32-wpan/src/mac/runner.rs index 26fdf23e0..92c74c2ee 100644 --- a/embassy-stm32-wpan/src/mac/runner.rs +++ b/embassy-stm32-wpan/src/mac/runner.rs @@ -34,7 +34,7 @@ pub struct Runner<'a> { } impl<'a> Runner<'a> { - pub fn new( + pub(crate) fn new( rx_event_channel: &'a ZeroCopyPubSub>, rx_data_channel: &'a Channel, 1>, mac_rx: &'a mut MacRx, @@ -43,11 +43,20 @@ impl<'a> Runner<'a> { mac_tx: &'a Mutex, tx_buf_queue: &'a mut [[u8; MTU]; BUF_SIZE], network_state: &'a blocking_mutex::Mutex>, + short_address: [u8; 2], + mac_address: [u8; 8], ) -> Self { for buf in tx_buf_queue { tx_buf_channel.try_send(buf).unwrap(); } + critical_section::with(|cs| { + let mut network_state = network_state.borrow(cs).borrow_mut(); + + network_state.mac_addr = mac_address; + network_state.short_addr = short_address; + }); + Self { rx_event_channel, rx_data_channel, @@ -70,12 +79,7 @@ impl<'a> Runner<'a> { } _ => { self.rx_event_channel.lock(|s| { - match &*s.borrow() { - Some(signal) => { - signal.signal(mac_event); - } - None => {} - }; + s.borrow().as_ref().map(|signal| signal.signal(mac_event)); }); } } @@ -89,7 +93,9 @@ impl<'a> Runner<'a> { let (buf, len) = self.tx_data_channel.receive().await; let mac_tx = self.mac_tx.lock().await; - // TODO: skip this if the link state is down + let pan_id = critical_section::with(|cs| self.network_state.borrow(cs).borrow().pan_id); + + // TODO: get the destination address from the packet instead of using the broadcast address // The mutex should be dropped on the next loop iteration mac_tx @@ -97,7 +103,7 @@ impl<'a> Runner<'a> { DataRequest { src_addr_mode: AddressMode::Short, dst_addr_mode: AddressMode::Short, - dst_pan_id: PanId([0x1A, 0xAA]), + dst_pan_id: PanId(pan_id), dst_address: MacAddress::BROADCAST, msdu_handle: msdu_handle, ack_tx: 0x00, diff --git a/embassy-stm32-wpan/src/sub/mm.rs b/embassy-stm32-wpan/src/sub/mm.rs index 62d0de8bd..a90c6ee55 100644 --- a/embassy-stm32-wpan/src/sub/mm.rs +++ b/embassy-stm32-wpan/src/sub/mm.rs @@ -46,7 +46,7 @@ impl MemoryManager { Self { _private: () } } - pub async fn run_queue(&self) { + pub async fn run_queue(&self) -> ! { loop { poll_fn(|cx| unsafe { MM_WAKER.register(cx.waker()); diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs index 9b705dda9..5d946b35b 100644 --- a/examples/stm32wb/src/bin/mac_ffd_net.rs +++ b/examples/stm32wb/src/bin/mac_ffd_net.rs @@ -1,30 +1,44 @@ #![no_std] #![no_main] +use core::net::Ipv6Addr; + use defmt::*; use embassy_executor::Spawner; +use embassy_net::udp::{PacketMetadata, UdpSocket}; +use embassy_net::{Ipv6Cidr, StackResources, StaticConfigV6}; use embassy_stm32::bind_interrupts; use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; +use embassy_stm32::peripherals::RNG; use embassy_stm32::rcc::WPAN_DEFAULT; +use embassy_stm32::rng::InterruptHandler as RngInterruptHandler; use embassy_stm32_wpan::TlMbox; use embassy_stm32_wpan::mac::{Driver, DriverState, Runner}; use embassy_stm32_wpan::sub::mm; +use embassy_time::{Duration, Timer}; +use heapless::Vec; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs{ IPCC_C1_RX => ReceiveInterruptHandler; IPCC_C1_TX => TransmitInterruptHandler; + RNG => RngInterruptHandler; }); #[embassy_executor::task] -async fn run_mm_queue(memory_manager: mm::MemoryManager) { - memory_manager.run_queue().await; +async fn run_mm_queue(memory_manager: mm::MemoryManager) -> ! { + memory_manager.run_queue().await +} + +#[embassy_executor::task] +async fn run_mac(runner: &'static Runner<'static>) -> ! { + runner.run().await } #[embassy_executor::task] -async fn run_mac(runner: &'static Runner<'static>) { - runner.run().await; +async fn run_net(mut runner: embassy_net::Runner<'static, Driver<'static>>) -> ! { + runner.run().await } #[embassy_executor::main] @@ -72,21 +86,67 @@ async fn main(spawner: Spawner) { static DRIVER_STATE: StaticCell = StaticCell::new(); static RUNNER: StaticCell = StaticCell::new(); + static RESOURCES: StaticCell> = StaticCell::new(); let driver_state = DRIVER_STATE.init(DriverState::new(mbox.mac_subsystem)); - let (driver, runner, mut control) = Driver::new(driver_state); - spawner.spawn(run_mac(RUNNER.init(runner)).unwrap()); + let (driver, mac_runner, mut control) = Driver::new( + driver_state, + 0x1122u16.to_be_bytes().try_into().unwrap(), + 0xACDE480000000001u64.to_be_bytes().try_into().unwrap(), + ); - control - .init_link( - 0x1122u16.to_be_bytes().try_into().unwrap(), - 0xACDE480000000001u64.to_be_bytes().try_into().unwrap(), - [0x1A, 0xAA], - ) - .await; + // TODO: rng does not work for some reason + // Generate random seed. + // let mut rng = Rng::new(p.RNG, Irqs); + let seed = [0; 8]; + // let _ = rng.async_fill_bytes(&mut seed).await; + let seed = u64::from_le_bytes(seed); - cortex_m::asm::bkpt(); + info!("seed generated"); + + // Init network stack + let ipv6_addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); + + let config = embassy_net::Config::ipv6_static(StaticConfigV6 { + address: Ipv6Cidr::new(ipv6_addr, 104), + gateway: None, + dns_servers: Vec::new(), + }); + + let (stack, eth_runner) = embassy_net::new(driver, config, RESOURCES.init(StackResources::new()), seed); + + // wpan runner + spawner.spawn(run_mac(RUNNER.init(mac_runner)).unwrap()); + + // Launch network task + spawner.spawn(unwrap!(run_net(eth_runner))); + + info!("Network task initialized"); - let _ = driver; + control.init_link([0x1A, 0xAA]).await; + + // Ensure DHCP configuration is up before trying connect + stack.wait_config_up().await; + + info!("Network up"); + + // Then we can use it! + let mut rx_meta = [PacketMetadata::EMPTY]; + let mut rx_buffer = [0; 4096]; + let mut tx_meta = [PacketMetadata::EMPTY]; + let mut tx_buffer = [0; 4096]; + + let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); + + let remote_endpoint = (Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2fb), 8000); + + let send_buf = [0u8; 20]; + + socket.bind((ipv6_addr, 8000)).unwrap(); + socket.send_to(&send_buf, remote_endpoint).await.unwrap(); + + Timer::after(Duration::from_secs(2)).await; + + cortex_m::asm::bkpt(); } -- cgit