1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
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<peripherals::RADIO>;
RNG => embassy_nrf::rng::InterruptHandler<peripherals::RNG>;
});
#[embassy_executor::task]
async fn ieee802154_task(runner: net::Runner<'static>) -> ! {
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<net::State<20, 20>> = 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<StackResources<3>> = 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();
}
}
}
|