aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-17 08:23:34 -0600
committerxoviat <[email protected]>2025-11-17 08:23:34 -0600
commit80ceb42eb1c842fcb214a5fbfbb1c39265c6b29b (patch)
tree8a77d8998a5f8681c93eed4297d9bee6fb83ec3c
parent9cd6c92151e4ee68bca95bfc17658e50ad2c1aca (diff)
wpan_ get net example actually working
-rw-r--r--embassy-stm32-wpan/src/mac/control.rs36
-rw-r--r--embassy-stm32-wpan/src/mac/driver.rs12
-rw-r--r--embassy-stm32-wpan/src/mac/runner.rs24
-rw-r--r--embassy-stm32-wpan/src/sub/mm.rs2
-rw-r--r--examples/stm32wb/src/bin/mac_ffd_net.rs90
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
18pub struct NetworkState { 18pub 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
70impl<'d> Driver<'d> { 74impl<'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
36impl<'a> Runner<'a> { 36impl<'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
4use core::net::Ipv6Addr;
5
4use defmt::*; 6use defmt::*;
5use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_net::udp::{PacketMetadata, UdpSocket};
9use embassy_net::{Ipv6Cidr, StackResources, StaticConfigV6};
6use embassy_stm32::bind_interrupts; 10use embassy_stm32::bind_interrupts;
7use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler}; 11use embassy_stm32::ipcc::{Config, ReceiveInterruptHandler, TransmitInterruptHandler};
12use embassy_stm32::peripherals::RNG;
8use embassy_stm32::rcc::WPAN_DEFAULT; 13use embassy_stm32::rcc::WPAN_DEFAULT;
14use embassy_stm32::rng::InterruptHandler as RngInterruptHandler;
9use embassy_stm32_wpan::TlMbox; 15use embassy_stm32_wpan::TlMbox;
10use embassy_stm32_wpan::mac::{Driver, DriverState, Runner}; 16use embassy_stm32_wpan::mac::{Driver, DriverState, Runner};
11use embassy_stm32_wpan::sub::mm; 17use embassy_stm32_wpan::sub::mm;
18use embassy_time::{Duration, Timer};
19use heapless::Vec;
12use static_cell::StaticCell; 20use static_cell::StaticCell;
13use {defmt_rtt as _, panic_probe as _}; 21use {defmt_rtt as _, panic_probe as _};
14 22
15bind_interrupts!(struct Irqs{ 23bind_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]
21async fn run_mm_queue(memory_manager: mm::MemoryManager) { 30async 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]
35async fn run_mac(runner: &'static Runner<'static>) -> ! {
36 runner.run().await
23} 37}
24 38
25#[embassy_executor::task] 39#[embassy_executor::task]
26async fn run_mac(runner: &'static Runner<'static>) { 40async 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}