diff options
| author | Ulf Lilleengen <[email protected]> | 2024-09-04 14:09:17 +0200 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2024-09-04 14:09:17 +0200 |
| commit | b4221d75b87664485977d37df28f7319143411fc (patch) | |
| tree | 7002cc6264f300c4d321e9bbece46098157d8194 | |
| parent | 5e27a3e64f46340e50bc6f61e6ef5a89e9f077ab (diff) | |
Make tracing optional and use dedicated task
| -rw-r--r-- | embassy-net-nrf91/src/lib.rs | 90 | ||||
| -rw-r--r-- | examples/nrf9160/src/bin/modem_tcp_client.rs | 58 |
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 | ||
| 20 | use embassy_net_driver_channel as ch; | 20 | use embassy_net_driver_channel as ch; |
| 21 | use embassy_sync::waitqueue::{AtomicWaker, WakerRegistration}; | 21 | use embassy_sync::waitqueue::{AtomicWaker, WakerRegistration}; |
| 22 | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||
| 22 | use heapless::Vec; | 23 | use heapless::Vec; |
| 23 | use nrf9160_pac as pac; | 24 | use nrf9160_pac as pac; |
| 24 | use pac::NVIC; | 25 | use pac::NVIC; |
| 26 | use embassy_sync::pipe; | ||
| 25 | 27 | ||
| 26 | const RX_SIZE: usize = 8 * 1024; | 28 | const RX_SIZE: usize = 8 * 1024; |
| 27 | const TRACE_SIZE: usize = 16 * 1024; | 29 | const TRACE_SIZE: usize = 16 * 1024; |
| 30 | const TRACE_BUF: usize = 1024; | ||
| 28 | const MTU: usize = 1500; | 31 | const 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. |
| 94 | pub async fn new<'a, TW: embedded_io::Write>( | 97 | pub 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. | ||
| 106 | pub 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. | ||
| 116 | async 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. |
| 247 | pub struct TraceBuffer { | ||
| 248 | trace: pipe::Pipe<NoopRawMutex, TRACE_BUF>, | ||
| 249 | } | ||
| 250 | |||
| 251 | /// Represents writer half of the trace buffer. | ||
| 252 | pub type TraceWriter<'a> = pipe::Writer<'a, NoopRawMutex, TRACE_BUF>; | ||
| 253 | |||
| 254 | /// Represents the reader half of the trace buffer. | ||
| 255 | pub type TraceReader<'a> = pipe::Reader<'a, NoopRawMutex, TRACE_BUF>; | ||
| 256 | |||
| 257 | impl 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. | ||
| 218 | pub struct State { | 267 | pub 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 | |||
| 223 | impl State { | 273 | impl 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 | ||
| 274 | impl StateInner { | 324 | impl 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. |
| 825 | pub struct Runner<'a, TW: embedded_io::Write> { | 877 | pub 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 | ||
| 831 | impl<'a, TW: embedded_io::Write> Runner<'a, TW> { | 883 | impl<'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 @@ | |||
| 4 | use core::mem::MaybeUninit; | 4 | use core::mem::MaybeUninit; |
| 5 | use core::net::IpAddr; | 5 | use core::net::IpAddr; |
| 6 | use core::ptr::addr_of_mut; | 6 | use core::ptr::addr_of_mut; |
| 7 | use core::str::FromStr; | ||
| 8 | use core::slice; | 7 | use core::slice; |
| 8 | use core::str::FromStr; | ||
| 9 | 9 | ||
| 10 | use defmt::{info, warn, unwrap}; | 10 | use defmt::{info, unwrap, warn}; |
| 11 | use heapless::Vec; | ||
| 12 | use embassy_executor::Spawner; | 11 | use embassy_executor::Spawner; |
| 13 | use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; | 12 | use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; |
| 14 | use embassy_net_nrf91::{Runner, State, context}; | 13 | use embassy_net_nrf91::{context, Runner, State, TraceBuffer, TraceReader}; |
| 15 | use embassy_nrf::buffered_uarte::{self, BufferedUarteTx}; | 14 | use embassy_nrf::buffered_uarte::{self, BufferedUarteTx}; |
| 16 | use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive, Pin}; | 15 | use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive, Pin}; |
| 17 | use embassy_nrf::uarte::Baudrate; | 16 | use embassy_nrf::uarte::Baudrate; |
| 18 | use embassy_nrf::{bind_interrupts, interrupt, peripherals, uarte}; | 17 | use embassy_nrf::{bind_interrupts, interrupt, peripherals, uarte}; |
| 19 | use embassy_time::{Duration, Timer}; | 18 | use embassy_time::{Duration, Timer}; |
| 20 | use embedded_io_async::Write; | 19 | use embedded_io_async::Write; |
| 20 | use heapless::Vec; | ||
| 21 | use static_cell::StaticCell; | 21 | use static_cell::StaticCell; |
| 22 | use {defmt_rtt as _, panic_probe as _}; | 22 | use {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 | 34 | async 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 { |
| 37 | struct TraceWriter(BufferedUarteTx<'static, peripherals::SERIAL0>); | 37 | let n = reader.read(&mut rx[..]).await; |
| 38 | 38 | unwrap!(uart.write_all(&rx[..n]).await); | |
| 39 | impl embedded_io::ErrorType for TraceWriter { | ||
| 40 | type Error = core::convert::Infallible; | ||
| 41 | } | ||
| 42 | |||
| 43 | impl 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] |
| 54 | async fn modem_task(runner: Runner<'static, TraceWriter>) -> ! { | 43 | async 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 | ||
