aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-net-nrf91/src/lib.rs90
-rw-r--r--examples/nrf9160/src/bin/modem_tcp_client.rs58
2 files changed, 98 insertions, 50 deletions
diff --git a/embassy-net-nrf91/src/lib.rs b/embassy-net-nrf91/src/lib.rs
index beed7c65a..673784cb2 100644
--- a/embassy-net-nrf91/src/lib.rs
+++ b/embassy-net-nrf91/src/lib.rs
@@ -19,12 +19,15 @@ use core::task::{Poll, Waker};
19 19
20use embassy_net_driver_channel as ch; 20use embassy_net_driver_channel as ch;
21use embassy_sync::waitqueue::{AtomicWaker, WakerRegistration}; 21use embassy_sync::waitqueue::{AtomicWaker, WakerRegistration};
22use embassy_sync::blocking_mutex::raw::NoopRawMutex;
22use heapless::Vec; 23use heapless::Vec;
23use nrf9160_pac as pac; 24use nrf9160_pac as pac;
24use pac::NVIC; 25use pac::NVIC;
26use embassy_sync::pipe;
25 27
26const RX_SIZE: usize = 8 * 1024; 28const RX_SIZE: usize = 8 * 1024;
27const TRACE_SIZE: usize = 16 * 1024; 29const TRACE_SIZE: usize = 16 * 1024;
30const TRACE_BUF: usize = 1024;
28const MTU: usize = 1500; 31const MTU: usize = 1500;
29 32
30/// Network driver. 33/// Network driver.
@@ -91,11 +94,30 @@ impl<'a> Allocator<'a> {
91} 94}
92 95
93/// Create a new nRF91 embassy-net driver. 96/// Create a new nRF91 embassy-net driver.
94pub async fn new<'a, TW: embedded_io::Write>( 97pub async fn new<'a>(
95 state: &'a mut State, 98 state: &'a mut State,
96 shmem: &'a mut [MaybeUninit<u8>], 99 shmem: &'a mut [MaybeUninit<u8>],
97 trace_writer: TW, 100) -> (NetDriver<'a>, Control<'a>, Runner<'a>) {
98) -> (NetDriver<'a>, Control<'a>, Runner<'a, TW>) { 101 let (n, c, r, _) = new_internal(state, shmem, None).await;
102 (n, c, r)
103}
104
105/// Create a new nRF91 embassy-net driver with trace.
106pub async fn new_with_trace<'a>(
107 state: &'a mut State,
108 shmem: &'a mut [MaybeUninit<u8>],
109 trace_buffer: &'a mut TraceBuffer,
110) -> (NetDriver<'a>, Control<'a>, Runner<'a>, TraceReader<'a>) {
111 let (n, c, r, t) = new_internal(state, shmem, Some(trace_buffer)).await;
112 (n, c, r, t.unwrap())
113}
114
115/// Create a new nRF91 embassy-net driver.
116async fn new_internal<'a>(
117 state: &'a mut State,
118 shmem: &'a mut [MaybeUninit<u8>],
119 trace_buffer: Option<&'a mut TraceBuffer>,
120) -> (NetDriver<'a>, Control<'a>, Runner<'a>, Option<TraceReader<'a>>) {
99 let shmem_len = shmem.len(); 121 let shmem_len = shmem.len();
100 let shmem_ptr = shmem.as_mut_ptr() as *mut u8; 122 let shmem_ptr = shmem.as_mut_ptr() as *mut u8;
101 123
@@ -205,21 +227,49 @@ pub async fn new<'a, TW: embedded_io::Write>(
205 let state_ch = ch_runner.state_runner(); 227 let state_ch = ch_runner.state_runner();
206 state_ch.set_link_state(ch::driver::LinkState::Up); 228 state_ch.set_link_state(ch::driver::LinkState::Up);
207 229
230 let (trace_reader, trace_writer) = if let Some(trace) = trace_buffer {
231 let (r, w) = trace.trace.split();
232 (Some(r), Some(w))
233 } else {
234 (None, None)
235 };
236
208 let runner = Runner { 237 let runner = Runner {
209 ch: ch_runner, 238 ch: ch_runner,
210 state: state_inner, 239 state: state_inner,
211 trace_writer, 240 trace_writer,
212 }; 241 };
213 242
214 (device, control, runner) 243 (device, control, runner, trace_reader)
215} 244}
216 245
217/// Shared state for the drivver. 246/// State holding modem traces.
247pub struct TraceBuffer {
248 trace: pipe::Pipe<NoopRawMutex, TRACE_BUF>,
249}
250
251/// Represents writer half of the trace buffer.
252pub type TraceWriter<'a> = pipe::Writer<'a, NoopRawMutex, TRACE_BUF>;
253
254/// Represents the reader half of the trace buffer.
255pub type TraceReader<'a> = pipe::Reader<'a, NoopRawMutex, TRACE_BUF>;
256
257impl TraceBuffer {
258 /// Create a new TraceBuffer.
259 pub const fn new() -> Self {
260 Self {
261 trace: pipe::Pipe::new(),
262 }
263 }
264}
265
266/// Shared state for the driver.
218pub struct State { 267pub struct State {
219 ch: ch::State<MTU, 4, 4>, 268 ch: ch::State<MTU, 4, 4>,
220 inner: MaybeUninit<RefCell<StateInner>>, 269 inner: MaybeUninit<RefCell<StateInner>>,
221} 270}
222 271
272
223impl State { 273impl State {
224 /// Create a new State. 274 /// Create a new State.
225 pub const fn new() -> Self { 275 pub const fn new() -> Self {
@@ -272,7 +322,7 @@ struct StateInner {
272} 322}
273 323
274impl StateInner { 324impl StateInner {
275 fn poll(&mut self, trace_writer: &mut impl embedded_io::Write, ch: &mut ch::Runner<MTU>) { 325 fn poll(&mut self, trace_writer: &mut Option<TraceWriter<'_>>, ch: &mut ch::Runner<MTU>) {
276 trace!("poll!"); 326 trace!("poll!");
277 let ipc = unsafe { &*pac::IPC_NS::ptr() }; 327 let ipc = unsafe { &*pac::IPC_NS::ptr() };
278 328
@@ -399,15 +449,17 @@ impl StateInner {
399 }); 449 });
400 } 450 }
401 451
402 fn handle_trace(writer: &mut impl embedded_io::Write, id: u8, data: &[u8]) { 452 fn handle_trace(writer: &mut Option<TraceWriter<'_>>, id: u8, data: &[u8]) {
403 trace!("trace: {} {}", id, data.len()); 453 if let Some(writer) = writer {
404 let mut header = [0u8; 5]; 454 trace!("trace: {} {}", id, data.len());
405 header[0] = 0xEF; 455 let mut header = [0u8; 5];
406 header[1] = 0xBE; 456 header[0] = 0xEF;
407 header[2..4].copy_from_slice(&(data.len() as u16).to_le_bytes()); 457 header[1] = 0xBE;
408 header[4] = id; 458 header[2..4].copy_from_slice(&(data.len() as u16).to_le_bytes());
409 writer.write_all(&header).unwrap(); 459 header[4] = id;
410 writer.write_all(data).unwrap(); 460 writer.try_write(&header).ok();
461 writer.try_write(data).ok();
462 }
411 } 463 }
412 464
413 fn process(&mut self, list: *mut List, is_control: bool, ch: &mut ch::Runner<MTU>) -> bool { 465 fn process(&mut self, list: *mut List, is_control: bool, ch: &mut ch::Runner<MTU>) -> bool {
@@ -794,7 +846,7 @@ impl<'a> Control<'a> {
794 /// Open the raw socket used for sending/receiving IP packets. 846 /// Open the raw socket used for sending/receiving IP packets.
795 /// 847 ///
796 /// This must be done after `AT+CFUN=1` (?) 848 /// This must be done after `AT+CFUN=1` (?)
797 pub async fn open_raw_socket(&self) { 849 async fn open_raw_socket(&self) {
798 let mut msg: Message = unsafe { mem::zeroed() }; 850 let mut msg: Message = unsafe { mem::zeroed() };
799 msg.channel = 2; // data 851 msg.channel = 2; // data
800 msg.id = 0x7001_0004; // open socket 852 msg.id = 0x7001_0004; // open socket
@@ -822,13 +874,13 @@ impl<'a> Control<'a> {
822} 874}
823 875
824/// Background runner for the driver. 876/// Background runner for the driver.
825pub struct Runner<'a, TW: embedded_io::Write> { 877pub struct Runner<'a> {
826 ch: ch::Runner<'a, MTU>, 878 ch: ch::Runner<'a, MTU>,
827 state: &'a RefCell<StateInner>, 879 state: &'a RefCell<StateInner>,
828 trace_writer: TW, 880 trace_writer: Option<TraceWriter<'a>>,
829} 881}
830 882
831impl<'a, TW: embedded_io::Write> Runner<'a, TW> { 883impl<'a> Runner<'a> {
832 /// Run the driver operation in the background. 884 /// Run the driver operation in the background.
833 /// 885 ///
834 /// You must run this in a background task, concurrently with all network operations. 886 /// You must run this in a background task, concurrently with all network operations.
diff --git a/examples/nrf9160/src/bin/modem_tcp_client.rs b/examples/nrf9160/src/bin/modem_tcp_client.rs
index 55ab2a707..c65e6e153 100644
--- a/examples/nrf9160/src/bin/modem_tcp_client.rs
+++ b/examples/nrf9160/src/bin/modem_tcp_client.rs
@@ -4,20 +4,20 @@
4use core::mem::MaybeUninit; 4use core::mem::MaybeUninit;
5use core::net::IpAddr; 5use core::net::IpAddr;
6use core::ptr::addr_of_mut; 6use core::ptr::addr_of_mut;
7use core::str::FromStr;
8use core::slice; 7use core::slice;
8use core::str::FromStr;
9 9
10use defmt::{info, warn, unwrap}; 10use defmt::{info, unwrap, warn};
11use heapless::Vec;
12use embassy_executor::Spawner; 11use embassy_executor::Spawner;
13use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; 12use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources};
14use embassy_net_nrf91::{Runner, State, context}; 13use embassy_net_nrf91::{context, Runner, State, TraceBuffer, TraceReader};
15use embassy_nrf::buffered_uarte::{self, BufferedUarteTx}; 14use embassy_nrf::buffered_uarte::{self, BufferedUarteTx};
16use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive, Pin}; 15use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive, Pin};
17use embassy_nrf::uarte::Baudrate; 16use embassy_nrf::uarte::Baudrate;
18use embassy_nrf::{bind_interrupts, interrupt, peripherals, uarte}; 17use embassy_nrf::{bind_interrupts, interrupt, peripherals, uarte};
19use embassy_time::{Duration, Timer}; 18use embassy_time::{Duration, Timer};
20use embedded_io_async::Write; 19use embedded_io_async::Write;
20use heapless::Vec;
21use static_cell::StaticCell; 21use static_cell::StaticCell;
22use {defmt_rtt as _, panic_probe as _}; 22use {defmt_rtt as _, panic_probe as _};
23 23
@@ -30,28 +30,17 @@ bind_interrupts!(struct Irqs {
30 UARTE0_SPIM0_SPIS0_TWIM0_TWIS0 => buffered_uarte::InterruptHandler<peripherals::SERIAL0>; 30 UARTE0_SPIM0_SPIS0_TWIM0_TWIS0 => buffered_uarte::InterruptHandler<peripherals::SERIAL0>;
31}); 31});
32 32
33// embassy-net-nrf91 only supports blocking trace write for now. 33#[embassy_executor::task]
34// We don't want to block packet processing with slow uart writes, so 34async fn trace_task(mut uart: BufferedUarteTx<'static, peripherals::SERIAL0>, reader: TraceReader<'static>) -> ! {
35// we make an adapter that writes whatever fits in the buffer and drops 35 let mut rx = [0u8; 1024];
36// data if it's full. 36 loop {
37struct TraceWriter(BufferedUarteTx<'static, peripherals::SERIAL0>); 37 let n = reader.read(&mut rx[..]).await;
38 38 unwrap!(uart.write_all(&rx[..n]).await);
39impl embedded_io::ErrorType for TraceWriter {
40 type Error = core::convert::Infallible;
41}
42
43impl embedded_io::Write for TraceWriter {
44 fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
45 let _ = self.0.try_write(buf);
46 Ok(buf.len())
47 }
48 fn flush(&mut self) -> Result<(), Self::Error> {
49 Ok(())
50 } 39 }
51} 40}
52 41
53#[embassy_executor::task] 42#[embassy_executor::task]
54async fn modem_task(runner: Runner<'static, TraceWriter>) -> ! { 43async fn modem_task(runner: Runner<'static>) -> ! {
55 runner.run().await 44 runner.run().await
56} 45}
57 46
@@ -93,8 +82,8 @@ async fn main(spawner: Spawner) {
93 82
94 static mut TRACE_BUF: [u8; 4096] = [0u8; 4096]; 83 static mut TRACE_BUF: [u8; 4096] = [0u8; 4096];
95 let mut config = uarte::Config::default(); 84 let mut config = uarte::Config::default();
96 config.baudrate = Baudrate::BAUD115200; 85 config.baudrate = Baudrate::BAUD1M;
97 let trace_writer = TraceWriter(BufferedUarteTx::new( 86 let uart = BufferedUarteTx::new(
98 //let trace_uart = BufferedUarteTx::new( 87 //let trace_uart = BufferedUarteTx::new(
99 unsafe { peripherals::SERIAL0::steal() }, 88 unsafe { peripherals::SERIAL0::steal() },
100 Irqs, 89 Irqs,
@@ -102,11 +91,14 @@ async fn main(spawner: Spawner) {
102 //unsafe { peripherals::P0_14::steal() }, 91 //unsafe { peripherals::P0_14::steal() },
103 config, 92 config,
104 unsafe { &mut *addr_of_mut!(TRACE_BUF) }, 93 unsafe { &mut *addr_of_mut!(TRACE_BUF) },
105 )); 94 );
106 95
107 static STATE: StaticCell<State> = StaticCell::new(); 96 static STATE: StaticCell<State> = StaticCell::new();
108 let (device, control, runner) = embassy_net_nrf91::new(STATE.init(State::new()), ipc_mem, trace_writer).await; 97 static TRACE: StaticCell<TraceBuffer> = StaticCell::new();
98 let (device, control, runner, tracer) =
99 embassy_net_nrf91::new_with_trace(STATE.init(State::new()), ipc_mem, TRACE.init(TraceBuffer::new())).await;
109 unwrap!(spawner.spawn(modem_task(runner))); 100 unwrap!(spawner.spawn(modem_task(runner)));
101 unwrap!(spawner.spawn(trace_task(uart, tracer)));
110 102
111 let config = embassy_net::Config::default(); 103 let config = embassy_net::Config::default();
112 104
@@ -127,11 +119,15 @@ async fn main(spawner: Spawner) {
127 119
128 let control = context::Control::new(control, 0).await; 120 let control = context::Control::new(control, 0).await;
129 121
130 unwrap!(control.configure(context::Config { 122 unwrap!(
131 apn: "iot.nat.es", 123 control
132 auth_prot: context::AuthProt::Pap, 124 .configure(context::Config {
133 auth: Some(("orange", "orange")), 125 apn: "iot.nat.es",
134 }).await); 126 auth_prot: context::AuthProt::Pap,
127 auth: Some(("orange", "orange")),
128 })
129 .await
130 );
135 131
136 info!("waiting for attach..."); 132 info!("waiting for attach...");
137 133