From 224d6b03125dd9c799611883914dd99c5431e749 Mon Sep 17 00:00:00 2001 From: Remmirad Date: Sat, 6 Sep 2025 11:32:23 +0200 Subject: nrf: 802.15.4 embassy-net-driver --- examples/nrf52840/Cargo.toml | 4 +- examples/nrf52840/src/bin/sixlowpan.rs | 120 +++++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 examples/nrf52840/src/bin/sixlowpan.rs (limited to 'examples') diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml index a9339bcd3..452e83b7e 100644 --- a/examples/nrf52840/Cargo.toml +++ b/examples/nrf52840/Cargo.toml @@ -10,8 +10,8 @@ embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt", "defmt"] } embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] } -embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } +embassy-nrf = { version = "0.7.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time", "net-driver"] } +embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet","udp", "medium-ieee802154", "proto-ipv6"] } embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } embedded-io = { version = "0.6.0", features = ["defmt-03"] } embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } diff --git a/examples/nrf52840/src/bin/sixlowpan.rs b/examples/nrf52840/src/bin/sixlowpan.rs new file mode 100644 index 000000000..00a597366 --- /dev/null +++ b/examples/nrf52840/src/bin/sixlowpan.rs @@ -0,0 +1,120 @@ +#![no_std] +#![no_main] + +use core::net::Ipv6Addr; + +use defmt::{info, unwrap, warn}; +use embassy_executor::Spawner; +use embassy_net::udp::{PacketMetadata, UdpMetadata, UdpSocket}; +use embassy_net::{IpAddress, IpEndpoint, IpListenEndpoint, Ipv6Cidr, StackResources, StaticConfigV6}; +use embassy_nrf::config::{Config, HfclkSource}; +use embassy_nrf::rng::Rng; +use embassy_nrf::{bind_interrupts, embassy_net_802154_driver as net, peripherals, radio}; +use embassy_time::Delay; +use embedded_hal_async::delay::DelayNs; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + RADIO => radio::InterruptHandler; + RNG => embassy_nrf::rng::InterruptHandler; +}); + +#[embassy_executor::task] +async fn ieee802154_task(runner: net::Runner<'static, peripherals::RADIO>) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(mut runner: embassy_net::Runner<'static, net::Device<'static>>) -> ! { + runner.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let mut config = Config::default(); + // Necessary to run the radio nrf52840 v1.11 5.4.1 + config.hfclk_source = HfclkSource::ExternalXtal; + let p = embassy_nrf::init(config); + + let mac_addr: [u8; 8] = [2, 3, 4, 5, 6, 7, 8, 9]; + static NRF802154_STATE: StaticCell> = StaticCell::new(); + let (device, runner) = net::new(mac_addr, p.RADIO, Irqs, NRF802154_STATE.init(net::State::new())) + .await + .unwrap(); + + spawner.spawn(unwrap!(ieee802154_task(runner))); + + // Swap these when flashing a second board + let peer = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xd701, 0xda3f, 0x3955, 0x82a4); + let local = Ipv6Addr::new(0xfe80, 0, 0, 0, 0xd701, 0xda3f, 0x3955, 0x82a5); + + let config = embassy_net::Config::ipv6_static(StaticConfigV6 { + address: Ipv6Cidr::new(local, 64), + gateway: None, + dns_servers: Default::default(), + }); + + // Generate random seed + let mut rng = Rng::new(p.RNG, Irqs); + let mut seed = [0; 8]; + rng.blocking_fill_bytes(&mut seed); + let seed = u64::from_le_bytes(seed); + + // Init network stack + static RESOURCES: StaticCell> = StaticCell::new(); + let (stack, runner) = embassy_net::new(device, config, RESOURCES.init(StackResources::new()), seed); + + spawner.spawn(unwrap!(net_task(runner))); + + let mut rx_buffer = [0; 2096]; + let mut tx_buffer = [0; 2096]; + let mut tx_m_buffer = [PacketMetadata::EMPTY; 5]; + let mut rx_m_buffer = [PacketMetadata::EMPTY; 5]; + + let mut delay = Delay; + loop { + let mut socket = UdpSocket::new( + stack, + &mut tx_m_buffer, + &mut rx_buffer, + &mut rx_m_buffer, + &mut tx_buffer, + ); + socket + .bind(IpListenEndpoint { + addr: Some(IpAddress::Ipv6(local)), + port: 1234, + }) + .unwrap(); + let rep = UdpMetadata { + endpoint: IpEndpoint { + addr: IpAddress::Ipv6(peer), + port: 1234, + }, + local_address: Some(IpAddress::Ipv6(local)), + meta: Default::default(), + }; + + info!("Listening on {:?} UDP:1234...", local); + + let mut recv_buf = [0; 12]; + loop { + delay.delay_ms(2000).await; + if socket.may_recv() { + let n = match socket.recv_from(&mut recv_buf).await { + Ok((0, _)) => panic!(), + Ok((n, _)) => n, + Err(e) => { + warn!("read error: {:?}", e); + break; + } + }; + info!("Received {:02x}", &recv_buf[..n]); + } + + info!("Sending"); + socket.send_to(b"Hello World", rep).await.unwrap(); + } + } +} -- cgit