diff options
| author | xoviat <[email protected]> | 2025-11-17 08:23:34 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2025-11-17 08:23:34 -0600 |
| commit | 80ceb42eb1c842fcb214a5fbfbb1c39265c6b29b (patch) | |
| tree | 8a77d8998a5f8681c93eed4297d9bee6fb83ec3c | |
| parent | 9cd6c92151e4ee68bca95bfc17658e50ad2c1aca (diff) | |
wpan_ get net example actually working
| -rw-r--r-- | embassy-stm32-wpan/src/mac/control.rs | 36 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/driver.rs | 12 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/mac/runner.rs | 24 | ||||
| -rw-r--r-- | embassy-stm32-wpan/src/sub/mm.rs | 2 | ||||
| -rw-r--r-- | 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> { | |||
| 38 | } | 38 | } |
| 39 | } | 39 | } |
| 40 | 40 | ||
| 41 | pub async fn init_link(&mut self, short_address: [u8; 2], extended_address: [u8; 8], pan_id: [u8; 2]) { | 41 | pub async fn init_link(&mut self, pan_id: [u8; 2]) { |
| 42 | debug!("resetting"); | 42 | debug!("resetting"); |
| 43 | 43 | ||
| 44 | debug!( | 44 | debug!( |
| @@ -52,12 +52,19 @@ impl<'a> Control<'a> { | |||
| 52 | .await | 52 | .await |
| 53 | ); | 53 | ); |
| 54 | 54 | ||
| 55 | let (short_address, mac_address) = critical_section::with(|cs| { | ||
| 56 | let mut network_state = self.network_state.borrow(cs).borrow_mut(); | ||
| 57 | |||
| 58 | network_state.pan_id = pan_id; | ||
| 59 | |||
| 60 | (network_state.short_addr, network_state.mac_addr) | ||
| 61 | }); | ||
| 62 | |||
| 55 | debug!("setting extended address"); | 63 | debug!("setting extended address"); |
| 56 | let extended_address: u64 = u64::from_be_bytes(extended_address); | ||
| 57 | debug!( | 64 | debug!( |
| 58 | "{:#x}", | 65 | "{:#x}", |
| 59 | self.send_command_and_get_response(&SetRequest { | 66 | self.send_command_and_get_response(&SetRequest { |
| 60 | pib_attribute_ptr: &extended_address as *const _ as *const u8, | 67 | pib_attribute_ptr: &u64::from_be_bytes(mac_address) as *const _ as *const u8, |
| 61 | pib_attribute: PibId::ExtendedAddress, | 68 | pib_attribute: PibId::ExtendedAddress, |
| 62 | }) | 69 | }) |
| 63 | .await | 70 | .await |
| @@ -66,11 +73,10 @@ impl<'a> Control<'a> { | |||
| 66 | ); | 73 | ); |
| 67 | 74 | ||
| 68 | debug!("setting short address"); | 75 | debug!("setting short address"); |
| 69 | let short_address: u16 = u16::from_be_bytes(short_address); | ||
| 70 | debug!( | 76 | debug!( |
| 71 | "{:#x}", | 77 | "{:#x}", |
| 72 | self.send_command_and_get_response(&SetRequest { | 78 | self.send_command_and_get_response(&SetRequest { |
| 73 | pib_attribute_ptr: &short_address as *const _ as *const u8, | 79 | pib_attribute_ptr: &u16::from_be_bytes(short_address) as *const _ as *const u8, |
| 74 | pib_attribute: PibId::ShortAddress, | 80 | pib_attribute: PibId::ShortAddress, |
| 75 | }) | 81 | }) |
| 76 | .await | 82 | .await |
| @@ -78,10 +84,6 @@ impl<'a> Control<'a> { | |||
| 78 | .await | 84 | .await |
| 79 | ); | 85 | ); |
| 80 | 86 | ||
| 81 | critical_section::with(|cs| { | ||
| 82 | self.network_state.borrow(cs).borrow_mut().mac_addr = extended_address.to_be_bytes(); | ||
| 83 | }); | ||
| 84 | |||
| 85 | debug!("setting association permit"); | 87 | debug!("setting association permit"); |
| 86 | let association_permit: bool = true; | 88 | let association_permit: bool = true; |
| 87 | debug!( | 89 | debug!( |
| @@ -186,20 +188,8 @@ impl<'a> Future for EventToken<'a> { | |||
| 186 | type Output = MacEvent<'a>; | 188 | type Output = MacEvent<'a>; |
| 187 | 189 | ||
| 188 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { | 190 | fn poll(self: core::pin::Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> { |
| 189 | self.rx_event_channel.lock(|s| { | 191 | self.rx_event_channel |
| 190 | let signal = s.borrow_mut(); | 192 | .lock(|s| s.borrow_mut().as_mut().unwrap().wait().poll_unpin(cx)) |
| 191 | let signal = match &*signal { | ||
| 192 | Some(s) => s, | ||
| 193 | _ => unreachable!(), | ||
| 194 | }; | ||
| 195 | |||
| 196 | let result = match signal.wait().poll_unpin(cx) { | ||
| 197 | Poll::Ready(mac_event) => Poll::Ready(mac_event), | ||
| 198 | Poll::Pending => Poll::Pending, | ||
| 199 | }; | ||
| 200 | |||
| 201 | result | ||
| 202 | }) | ||
| 203 | } | 193 | } |
| 204 | } | 194 | } |
| 205 | 195 | ||
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}; | |||
| 17 | 17 | ||
| 18 | pub struct NetworkState { | 18 | pub struct NetworkState { |
| 19 | pub mac_addr: [u8; 8], | 19 | pub mac_addr: [u8; 8], |
| 20 | pub short_addr: [u8; 2], | ||
| 21 | pub pan_id: [u8; 2], | ||
| 20 | pub link_state: LinkState, | 22 | pub link_state: LinkState, |
| 21 | pub link_waker: AtomicWaker, | 23 | pub link_waker: AtomicWaker, |
| 22 | } | 24 | } |
| @@ -25,6 +27,8 @@ impl NetworkState { | |||
| 25 | pub const fn new() -> Self { | 27 | pub const fn new() -> Self { |
| 26 | Self { | 28 | Self { |
| 27 | mac_addr: [0u8; 8], | 29 | mac_addr: [0u8; 8], |
| 30 | short_addr: [0u8; 2], | ||
| 31 | pan_id: [0u8; 2], | ||
| 28 | link_state: LinkState::Down, | 32 | link_state: LinkState::Down, |
| 29 | link_waker: AtomicWaker::new(), | 33 | link_waker: AtomicWaker::new(), |
| 30 | } | 34 | } |
| @@ -68,7 +72,11 @@ pub struct Driver<'d> { | |||
| 68 | } | 72 | } |
| 69 | 73 | ||
| 70 | impl<'d> Driver<'d> { | 74 | impl<'d> Driver<'d> { |
| 71 | pub fn new(driver_state: &'d mut DriverState<'d>) -> (Self, Runner<'d>, Control<'d>) { | 75 | pub fn new( |
| 76 | driver_state: &'d mut DriverState<'d>, | ||
| 77 | short_address: [u8; 2], | ||
| 78 | mac_address: [u8; 8], | ||
| 79 | ) -> (Self, Runner<'d>, Control<'d>) { | ||
| 72 | ( | 80 | ( |
| 73 | Self { | 81 | Self { |
| 74 | tx_data_channel: &driver_state.tx_data_channel, | 82 | tx_data_channel: &driver_state.tx_data_channel, |
| @@ -85,6 +93,8 @@ impl<'d> Driver<'d> { | |||
| 85 | &driver_state.mac_tx, | 93 | &driver_state.mac_tx, |
| 86 | &mut driver_state.tx_buf_queue, | 94 | &mut driver_state.tx_buf_queue, |
| 87 | &driver_state.network_state, | 95 | &driver_state.network_state, |
| 96 | short_address, | ||
| 97 | mac_address, | ||
| 88 | ), | 98 | ), |
| 89 | Control::new( | 99 | Control::new( |
| 90 | &driver_state.rx_event_channel, | 100 | &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> { | |||
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | impl<'a> Runner<'a> { | 36 | impl<'a> Runner<'a> { |
| 37 | pub fn new( | 37 | pub(crate) fn new( |
| 38 | rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>, | 38 | rx_event_channel: &'a ZeroCopyPubSub<CriticalSectionRawMutex, MacEvent<'a>>, |
| 39 | rx_data_channel: &'a Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>, | 39 | rx_data_channel: &'a Channel<CriticalSectionRawMutex, MacEvent<'a>, 1>, |
| 40 | mac_rx: &'a mut MacRx, | 40 | mac_rx: &'a mut MacRx, |
| @@ -43,11 +43,20 @@ impl<'a> Runner<'a> { | |||
| 43 | mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx>, | 43 | mac_tx: &'a Mutex<CriticalSectionRawMutex, MacTx>, |
| 44 | tx_buf_queue: &'a mut [[u8; MTU]; BUF_SIZE], | 44 | tx_buf_queue: &'a mut [[u8; MTU]; BUF_SIZE], |
| 45 | network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>, | 45 | network_state: &'a blocking_mutex::Mutex<CriticalSectionRawMutex, RefCell<NetworkState>>, |
| 46 | short_address: [u8; 2], | ||
| 47 | mac_address: [u8; 8], | ||
| 46 | ) -> Self { | 48 | ) -> Self { |
| 47 | for buf in tx_buf_queue { | 49 | for buf in tx_buf_queue { |
| 48 | tx_buf_channel.try_send(buf).unwrap(); | 50 | tx_buf_channel.try_send(buf).unwrap(); |
| 49 | } | 51 | } |
| 50 | 52 | ||
| 53 | critical_section::with(|cs| { | ||
| 54 | let mut network_state = network_state.borrow(cs).borrow_mut(); | ||
| 55 | |||
| 56 | network_state.mac_addr = mac_address; | ||
| 57 | network_state.short_addr = short_address; | ||
| 58 | }); | ||
| 59 | |||
| 51 | Self { | 60 | Self { |
| 52 | rx_event_channel, | 61 | rx_event_channel, |
| 53 | rx_data_channel, | 62 | rx_data_channel, |
| @@ -70,12 +79,7 @@ impl<'a> Runner<'a> { | |||
| 70 | } | 79 | } |
| 71 | _ => { | 80 | _ => { |
| 72 | self.rx_event_channel.lock(|s| { | 81 | self.rx_event_channel.lock(|s| { |
| 73 | match &*s.borrow() { | 82 | s.borrow().as_ref().map(|signal| signal.signal(mac_event)); |
| 74 | Some(signal) => { | ||
| 75 | signal.signal(mac_event); | ||
| 76 | } | ||
| 77 | None => {} | ||
| 78 | }; | ||
| 79 | }); | 83 | }); |
| 80 | } | 84 | } |
| 81 | } | 85 | } |
| @@ -89,7 +93,9 @@ impl<'a> Runner<'a> { | |||
| 89 | let (buf, len) = self.tx_data_channel.receive().await; | 93 | let (buf, len) = self.tx_data_channel.receive().await; |
| 90 | let mac_tx = self.mac_tx.lock().await; | 94 | let mac_tx = self.mac_tx.lock().await; |
| 91 | 95 | ||
| 92 | // TODO: skip this if the link state is down | 96 | let pan_id = critical_section::with(|cs| self.network_state.borrow(cs).borrow().pan_id); |
| 97 | |||
| 98 | // TODO: get the destination address from the packet instead of using the broadcast address | ||
| 93 | 99 | ||
| 94 | // The mutex should be dropped on the next loop iteration | 100 | // The mutex should be dropped on the next loop iteration |
| 95 | mac_tx | 101 | mac_tx |
| @@ -97,7 +103,7 @@ impl<'a> Runner<'a> { | |||
| 97 | DataRequest { | 103 | DataRequest { |
| 98 | src_addr_mode: AddressMode::Short, | 104 | src_addr_mode: AddressMode::Short, |
| 99 | dst_addr_mode: AddressMode::Short, | 105 | dst_addr_mode: AddressMode::Short, |
| 100 | dst_pan_id: PanId([0x1A, 0xAA]), | 106 | dst_pan_id: PanId(pan_id), |
| 101 | dst_address: MacAddress::BROADCAST, | 107 | dst_address: MacAddress::BROADCAST, |
| 102 | msdu_handle: msdu_handle, | 108 | msdu_handle: msdu_handle, |
| 103 | ack_tx: 0x00, | 109 | 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 { | |||
| 46 | Self { _private: () } | 46 | Self { _private: () } |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | pub async fn run_queue(&self) { | 49 | pub async fn run_queue(&self) -> ! { |
| 50 | loop { | 50 | loop { |
| 51 | poll_fn(|cx| unsafe { | 51 | poll_fn(|cx| unsafe { |
| 52 | MM_WAKER.register(cx.waker()); | 52 | 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 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use core::net::Ipv6Addr; | ||
| 5 | |||
| 4 | use defmt::*; | 6 | use defmt::*; |
| 5 | use embassy_executor::Spawner; | 7 | use embassy_executor::Spawner; |
| 8 | use embassy_net::udp::{PacketMetadata, UdpSocket}; | ||
| 9 | use embassy_net::{Ipv6Cidr, StackResources, StaticConfigV6}; | ||
| 6 | use embassy_stm32::bind_interrupts; | 10 | use embassy_stm32::bind_interrupts; |
| 7 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; | 11 | use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; |
| 12 | use embassy_stm32::peripherals::RNG; | ||
| 8 | use embassy_stm32::rcc::WPAN_DEFAULT; | 13 | use embassy_stm32::rcc::WPAN_DEFAULT; |
| 14 | use embassy_stm32::rng::InterruptHandler as RngInterruptHandler; | ||
| 9 | use embassy_stm32_wpan::TlMbox; | 15 | use embassy_stm32_wpan::TlMbox; |
| 10 | use embassy_stm32_wpan::mac::{Driver, DriverState, Runner}; | 16 | use embassy_stm32_wpan::mac::{Driver, DriverState, Runner}; |
| 11 | use embassy_stm32_wpan::sub::mm; | 17 | use embassy_stm32_wpan::sub::mm; |
| 18 | use embassy_time::{Duration, Timer}; | ||
| 19 | use heapless::Vec; | ||
| 12 | use static_cell::StaticCell; | 20 | use static_cell::StaticCell; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 21 | use {defmt_rtt as _, panic_probe as _}; |
| 14 | 22 | ||
| 15 | bind_interrupts!(struct Irqs{ | 23 | bind_interrupts!(struct Irqs{ |
| 16 | IPCC_C1_RX => ReceiveInterruptHandler; | 24 | IPCC_C1_RX => ReceiveInterruptHandler; |
| 17 | IPCC_C1_TX => TransmitInterruptHandler; | 25 | IPCC_C1_TX => TransmitInterruptHandler; |
| 26 | RNG => RngInterruptHandler<RNG>; | ||
| 18 | }); | 27 | }); |
| 19 | 28 | ||
| 20 | #[embassy_executor::task] | 29 | #[embassy_executor::task] |
| 21 | async fn run_mm_queue(memory_manager: mm::MemoryManager) { | 30 | async fn run_mm_queue(memory_manager: mm::MemoryManager) -> ! { |
| 22 | memory_manager.run_queue().await; | 31 | memory_manager.run_queue().await |
| 32 | } | ||
| 33 | |||
| 34 | #[embassy_executor::task] | ||
| 35 | async fn run_mac(runner: &'static Runner<'static>) -> ! { | ||
| 36 | runner.run().await | ||
| 23 | } | 37 | } |
| 24 | 38 | ||
| 25 | #[embassy_executor::task] | 39 | #[embassy_executor::task] |
| 26 | async fn run_mac(runner: &'static Runner<'static>) { | 40 | async fn run_net(mut runner: embassy_net::Runner<'static, Driver<'static>>) -> ! { |
| 27 | runner.run().await; | 41 | runner.run().await |
| 28 | } | 42 | } |
| 29 | 43 | ||
| 30 | #[embassy_executor::main] | 44 | #[embassy_executor::main] |
| @@ -72,21 +86,67 @@ async fn main(spawner: Spawner) { | |||
| 72 | 86 | ||
| 73 | static DRIVER_STATE: StaticCell<DriverState> = StaticCell::new(); | 87 | static DRIVER_STATE: StaticCell<DriverState> = StaticCell::new(); |
| 74 | static RUNNER: StaticCell<Runner> = StaticCell::new(); | 88 | static RUNNER: StaticCell<Runner> = StaticCell::new(); |
| 89 | static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new(); | ||
| 75 | 90 | ||
| 76 | let driver_state = DRIVER_STATE.init(DriverState::new(mbox.mac_subsystem)); | 91 | let driver_state = DRIVER_STATE.init(DriverState::new(mbox.mac_subsystem)); |
| 77 | let (driver, runner, mut control) = Driver::new(driver_state); | ||
| 78 | 92 | ||
| 79 | spawner.spawn(run_mac(RUNNER.init(runner)).unwrap()); | 93 | let (driver, mac_runner, mut control) = Driver::new( |
| 94 | driver_state, | ||
| 95 | 0x1122u16.to_be_bytes().try_into().unwrap(), | ||
| 96 | 0xACDE480000000001u64.to_be_bytes().try_into().unwrap(), | ||
| 97 | ); | ||
| 80 | 98 | ||
| 81 | control | 99 | // TODO: rng does not work for some reason |
| 82 | .init_link( | 100 | // Generate random seed. |
| 83 | 0x1122u16.to_be_bytes().try_into().unwrap(), | 101 | // let mut rng = Rng::new(p.RNG, Irqs); |
| 84 | 0xACDE480000000001u64.to_be_bytes().try_into().unwrap(), | 102 | let seed = [0; 8]; |
| 85 | [0x1A, 0xAA], | 103 | // let _ = rng.async_fill_bytes(&mut seed).await; |
| 86 | ) | 104 | let seed = u64::from_le_bytes(seed); |
| 87 | .await; | ||
| 88 | 105 | ||
| 89 | cortex_m::asm::bkpt(); | 106 | info!("seed generated"); |
| 107 | |||
| 108 | // Init network stack | ||
| 109 | let ipv6_addr = Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff); | ||
| 110 | |||
| 111 | let config = embassy_net::Config::ipv6_static(StaticConfigV6 { | ||
| 112 | address: Ipv6Cidr::new(ipv6_addr, 104), | ||
| 113 | gateway: None, | ||
| 114 | dns_servers: Vec::new(), | ||
| 115 | }); | ||
| 116 | |||
| 117 | let (stack, eth_runner) = embassy_net::new(driver, config, RESOURCES.init(StackResources::new()), seed); | ||
| 118 | |||
| 119 | // wpan runner | ||
| 120 | spawner.spawn(run_mac(RUNNER.init(mac_runner)).unwrap()); | ||
| 121 | |||
| 122 | // Launch network task | ||
| 123 | spawner.spawn(unwrap!(run_net(eth_runner))); | ||
| 124 | |||
| 125 | info!("Network task initialized"); | ||
| 90 | 126 | ||
| 91 | let _ = driver; | 127 | control.init_link([0x1A, 0xAA]).await; |
| 128 | |||
| 129 | // Ensure DHCP configuration is up before trying connect | ||
| 130 | stack.wait_config_up().await; | ||
| 131 | |||
| 132 | info!("Network up"); | ||
| 133 | |||
| 134 | // Then we can use it! | ||
| 135 | let mut rx_meta = [PacketMetadata::EMPTY]; | ||
| 136 | let mut rx_buffer = [0; 4096]; | ||
| 137 | let mut tx_meta = [PacketMetadata::EMPTY]; | ||
| 138 | let mut tx_buffer = [0; 4096]; | ||
| 139 | |||
| 140 | let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer); | ||
| 141 | |||
| 142 | let remote_endpoint = (Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2fb), 8000); | ||
| 143 | |||
| 144 | let send_buf = [0u8; 20]; | ||
| 145 | |||
| 146 | socket.bind((ipv6_addr, 8000)).unwrap(); | ||
| 147 | socket.send_to(&send_buf, remote_endpoint).await.unwrap(); | ||
| 148 | |||
| 149 | Timer::after(Duration::from_secs(2)).await; | ||
| 150 | |||
| 151 | cortex_m::asm::bkpt(); | ||
| 92 | } | 152 | } |
