Make tracing optional and use dedicated task
This commit is contained in:
		
							parent
							
								
									5e27a3e64f
								
							
						
					
					
						commit
						b4221d75b8
					
				| @ -19,12 +19,15 @@ use core::task::{Poll, Waker}; | |||||||
| 
 | 
 | ||||||
| use embassy_net_driver_channel as ch; | use embassy_net_driver_channel as ch; | ||||||
| use embassy_sync::waitqueue::{AtomicWaker, WakerRegistration}; | use embassy_sync::waitqueue::{AtomicWaker, WakerRegistration}; | ||||||
|  | use embassy_sync::blocking_mutex::raw::NoopRawMutex; | ||||||
| use heapless::Vec; | use heapless::Vec; | ||||||
| use nrf9160_pac as pac; | use nrf9160_pac as pac; | ||||||
| use pac::NVIC; | use pac::NVIC; | ||||||
|  | use embassy_sync::pipe; | ||||||
| 
 | 
 | ||||||
| const RX_SIZE: usize = 8 * 1024; | const RX_SIZE: usize = 8 * 1024; | ||||||
| const TRACE_SIZE: usize = 16 * 1024; | const TRACE_SIZE: usize = 16 * 1024; | ||||||
|  | const TRACE_BUF: usize = 1024; | ||||||
| const MTU: usize = 1500; | const MTU: usize = 1500; | ||||||
| 
 | 
 | ||||||
| /// Network driver.
 | /// Network driver.
 | ||||||
| @ -91,11 +94,30 @@ impl<'a> Allocator<'a> { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Create a new nRF91 embassy-net driver.
 | /// Create a new nRF91 embassy-net driver.
 | ||||||
| pub async fn new<'a, TW: embedded_io::Write>( | pub async fn new<'a>( | ||||||
|     state: &'a mut State, |     state: &'a mut State, | ||||||
|     shmem: &'a mut [MaybeUninit<u8>], |     shmem: &'a mut [MaybeUninit<u8>], | ||||||
|     trace_writer: TW, | ) -> (NetDriver<'a>, Control<'a>, Runner<'a>) { | ||||||
| ) -> (NetDriver<'a>, Control<'a>, Runner<'a, TW>) { |     let (n, c, r, _) = new_internal(state, shmem, None).await; | ||||||
|  |     (n, c, r) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Create a new nRF91 embassy-net driver with trace.
 | ||||||
|  | pub async fn new_with_trace<'a>( | ||||||
|  |     state: &'a mut State, | ||||||
|  |     shmem: &'a mut [MaybeUninit<u8>], | ||||||
|  |     trace_buffer: &'a mut TraceBuffer, | ||||||
|  | ) -> (NetDriver<'a>, Control<'a>, Runner<'a>, TraceReader<'a>) { | ||||||
|  |     let (n, c, r, t) = new_internal(state, shmem, Some(trace_buffer)).await; | ||||||
|  |     (n, c, r, t.unwrap()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Create a new nRF91 embassy-net driver.
 | ||||||
|  | async fn new_internal<'a>( | ||||||
|  |     state: &'a mut State, | ||||||
|  |     shmem: &'a mut [MaybeUninit<u8>], | ||||||
|  |     trace_buffer: Option<&'a mut TraceBuffer>, | ||||||
|  | ) -> (NetDriver<'a>, Control<'a>, Runner<'a>, Option<TraceReader<'a>>) { | ||||||
|     let shmem_len = shmem.len(); |     let shmem_len = shmem.len(); | ||||||
|     let shmem_ptr = shmem.as_mut_ptr() as *mut u8; |     let shmem_ptr = shmem.as_mut_ptr() as *mut u8; | ||||||
| 
 | 
 | ||||||
| @ -205,21 +227,49 @@ pub async fn new<'a, TW: embedded_io::Write>( | |||||||
|     let state_ch = ch_runner.state_runner(); |     let state_ch = ch_runner.state_runner(); | ||||||
|     state_ch.set_link_state(ch::driver::LinkState::Up); |     state_ch.set_link_state(ch::driver::LinkState::Up); | ||||||
| 
 | 
 | ||||||
|  |     let (trace_reader, trace_writer) = if let Some(trace) = trace_buffer { | ||||||
|  |         let (r, w) = trace.trace.split(); | ||||||
|  |         (Some(r), Some(w)) | ||||||
|  |     } else { | ||||||
|  |         (None, None) | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|     let runner = Runner { |     let runner = Runner { | ||||||
|         ch: ch_runner, |         ch: ch_runner, | ||||||
|         state: state_inner, |         state: state_inner, | ||||||
|         trace_writer, |         trace_writer, | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     (device, control, runner) |     (device, control, runner, trace_reader) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Shared state for the drivver.
 | /// State holding modem traces.
 | ||||||
|  | pub struct TraceBuffer { | ||||||
|  |     trace: pipe::Pipe<NoopRawMutex, TRACE_BUF>, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Represents writer half of the trace buffer.
 | ||||||
|  | pub type TraceWriter<'a> = pipe::Writer<'a, NoopRawMutex, TRACE_BUF>; | ||||||
|  | 
 | ||||||
|  | /// Represents the reader half of the trace buffer.
 | ||||||
|  | pub type TraceReader<'a> = pipe::Reader<'a, NoopRawMutex, TRACE_BUF>; | ||||||
|  | 
 | ||||||
|  | impl TraceBuffer { | ||||||
|  |     /// Create a new TraceBuffer.
 | ||||||
|  |     pub const fn new() -> Self { | ||||||
|  |         Self { | ||||||
|  |             trace: pipe::Pipe::new(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /// Shared state for the driver.
 | ||||||
| pub struct State { | pub struct State { | ||||||
|     ch: ch::State<MTU, 4, 4>, |     ch: ch::State<MTU, 4, 4>, | ||||||
|     inner: MaybeUninit<RefCell<StateInner>>, |     inner: MaybeUninit<RefCell<StateInner>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| impl State { | impl State { | ||||||
|     /// Create a new State.
 |     /// Create a new State.
 | ||||||
|     pub const fn new() -> Self { |     pub const fn new() -> Self { | ||||||
| @ -272,7 +322,7 @@ struct StateInner { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl StateInner { | impl StateInner { | ||||||
|     fn poll(&mut self, trace_writer: &mut impl embedded_io::Write, ch: &mut ch::Runner<MTU>) { |     fn poll(&mut self, trace_writer: &mut Option<TraceWriter<'_>>, ch: &mut ch::Runner<MTU>) { | ||||||
|         trace!("poll!"); |         trace!("poll!"); | ||||||
|         let ipc = unsafe { &*pac::IPC_NS::ptr() }; |         let ipc = unsafe { &*pac::IPC_NS::ptr() }; | ||||||
| 
 | 
 | ||||||
| @ -399,15 +449,17 @@ impl StateInner { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn handle_trace(writer: &mut impl embedded_io::Write, id: u8, data: &[u8]) { |     fn handle_trace(writer: &mut Option<TraceWriter<'_>>, id: u8, data: &[u8]) { | ||||||
|         trace!("trace: {} {}", id, data.len()); |         if let Some(writer) = writer { | ||||||
|         let mut header = [0u8; 5]; |             trace!("trace: {} {}", id, data.len()); | ||||||
|         header[0] = 0xEF; |             let mut header = [0u8; 5]; | ||||||
|         header[1] = 0xBE; |             header[0] = 0xEF; | ||||||
|         header[2..4].copy_from_slice(&(data.len() as u16).to_le_bytes()); |             header[1] = 0xBE; | ||||||
|         header[4] = id; |             header[2..4].copy_from_slice(&(data.len() as u16).to_le_bytes()); | ||||||
|         writer.write_all(&header).unwrap(); |             header[4] = id; | ||||||
|         writer.write_all(data).unwrap(); |             writer.try_write(&header).ok(); | ||||||
|  |             writer.try_write(data).ok(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fn process(&mut self, list: *mut List, is_control: bool, ch: &mut ch::Runner<MTU>) -> bool { |     fn process(&mut self, list: *mut List, is_control: bool, ch: &mut ch::Runner<MTU>) -> bool { | ||||||
| @ -794,7 +846,7 @@ impl<'a> Control<'a> { | |||||||
|     /// Open the raw socket used for sending/receiving IP packets.
 |     /// Open the raw socket used for sending/receiving IP packets.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// This must be done after `AT+CFUN=1` (?)
 |     /// This must be done after `AT+CFUN=1` (?)
 | ||||||
|     pub async fn open_raw_socket(&self) { |     async fn open_raw_socket(&self) { | ||||||
|         let mut msg: Message = unsafe { mem::zeroed() }; |         let mut msg: Message = unsafe { mem::zeroed() }; | ||||||
|         msg.channel = 2; // data
 |         msg.channel = 2; // data
 | ||||||
|         msg.id = 0x7001_0004; // open socket
 |         msg.id = 0x7001_0004; // open socket
 | ||||||
| @ -822,13 +874,13 @@ impl<'a> Control<'a> { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /// Background runner for the driver.
 | /// Background runner for the driver.
 | ||||||
| pub struct Runner<'a, TW: embedded_io::Write> { | pub struct Runner<'a> { | ||||||
|     ch: ch::Runner<'a, MTU>, |     ch: ch::Runner<'a, MTU>, | ||||||
|     state: &'a RefCell<StateInner>, |     state: &'a RefCell<StateInner>, | ||||||
|     trace_writer: TW, |     trace_writer: Option<TraceWriter<'a>>, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl<'a, TW: embedded_io::Write> Runner<'a, TW> { | impl<'a> Runner<'a> { | ||||||
|     /// Run the driver operation in the background.
 |     /// Run the driver operation in the background.
 | ||||||
|     ///
 |     ///
 | ||||||
|     /// You must run this in a background task, concurrently with all network operations.
 |     /// You must run this in a background task, concurrently with all network operations.
 | ||||||
|  | |||||||
| @ -4,20 +4,20 @@ | |||||||
| use core::mem::MaybeUninit; | use core::mem::MaybeUninit; | ||||||
| use core::net::IpAddr; | use core::net::IpAddr; | ||||||
| use core::ptr::addr_of_mut; | use core::ptr::addr_of_mut; | ||||||
| use core::str::FromStr; |  | ||||||
| use core::slice; | use core::slice; | ||||||
|  | use core::str::FromStr; | ||||||
| 
 | 
 | ||||||
| use defmt::{info, warn, unwrap}; | use defmt::{info, unwrap, warn}; | ||||||
| use heapless::Vec; |  | ||||||
| use embassy_executor::Spawner; | use embassy_executor::Spawner; | ||||||
| use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; | use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources}; | ||||||
| use embassy_net_nrf91::{Runner, State, context}; | use embassy_net_nrf91::{context, Runner, State, TraceBuffer, TraceReader}; | ||||||
| use embassy_nrf::buffered_uarte::{self, BufferedUarteTx}; | use embassy_nrf::buffered_uarte::{self, BufferedUarteTx}; | ||||||
| use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive, Pin}; | use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive, Pin}; | ||||||
| use embassy_nrf::uarte::Baudrate; | use embassy_nrf::uarte::Baudrate; | ||||||
| use embassy_nrf::{bind_interrupts, interrupt, peripherals, uarte}; | use embassy_nrf::{bind_interrupts, interrupt, peripherals, uarte}; | ||||||
| use embassy_time::{Duration, Timer}; | use embassy_time::{Duration, Timer}; | ||||||
| use embedded_io_async::Write; | use embedded_io_async::Write; | ||||||
|  | use heapless::Vec; | ||||||
| use static_cell::StaticCell; | use static_cell::StaticCell; | ||||||
| use {defmt_rtt as _, panic_probe as _}; | use {defmt_rtt as _, panic_probe as _}; | ||||||
| 
 | 
 | ||||||
| @ -30,28 +30,17 @@ bind_interrupts!(struct Irqs { | |||||||
|     UARTE0_SPIM0_SPIS0_TWIM0_TWIS0 => buffered_uarte::InterruptHandler<peripherals::SERIAL0>; |     UARTE0_SPIM0_SPIS0_TWIM0_TWIS0 => buffered_uarte::InterruptHandler<peripherals::SERIAL0>; | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| // embassy-net-nrf91 only supports blocking trace write for now.
 | #[embassy_executor::task] | ||||||
| // We don't want to block packet processing with slow uart writes, so
 | async fn trace_task(mut uart: BufferedUarteTx<'static, peripherals::SERIAL0>, reader: TraceReader<'static>) -> ! { | ||||||
| // we make an adapter that writes whatever fits in the buffer and drops
 |     let mut rx = [0u8; 1024]; | ||||||
| // data if it's full.
 |     loop { | ||||||
| struct TraceWriter(BufferedUarteTx<'static, peripherals::SERIAL0>); |         let n = reader.read(&mut rx[..]).await; | ||||||
| 
 |         unwrap!(uart.write_all(&rx[..n]).await); | ||||||
| impl embedded_io::ErrorType for TraceWriter { |  | ||||||
|     type Error = core::convert::Infallible; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| impl embedded_io::Write for TraceWriter { |  | ||||||
|     fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |  | ||||||
|         let _ = self.0.try_write(buf); |  | ||||||
|         Ok(buf.len()) |  | ||||||
|     } |  | ||||||
|     fn flush(&mut self) -> Result<(), Self::Error> { |  | ||||||
|         Ok(()) |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[embassy_executor::task] | #[embassy_executor::task] | ||||||
| async fn modem_task(runner: Runner<'static, TraceWriter>) -> ! { | async fn modem_task(runner: Runner<'static>) -> ! { | ||||||
|     runner.run().await |     runner.run().await | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -93,8 +82,8 @@ async fn main(spawner: Spawner) { | |||||||
| 
 | 
 | ||||||
|     static mut TRACE_BUF: [u8; 4096] = [0u8; 4096]; |     static mut TRACE_BUF: [u8; 4096] = [0u8; 4096]; | ||||||
|     let mut config = uarte::Config::default(); |     let mut config = uarte::Config::default(); | ||||||
|     config.baudrate = Baudrate::BAUD115200; |     config.baudrate = Baudrate::BAUD1M; | ||||||
|     let trace_writer = TraceWriter(BufferedUarteTx::new( |     let uart = BufferedUarteTx::new( | ||||||
|         //let trace_uart = BufferedUarteTx::new(
 |         //let trace_uart = BufferedUarteTx::new(
 | ||||||
|         unsafe { peripherals::SERIAL0::steal() }, |         unsafe { peripherals::SERIAL0::steal() }, | ||||||
|         Irqs, |         Irqs, | ||||||
| @ -102,11 +91,14 @@ async fn main(spawner: Spawner) { | |||||||
|         //unsafe { peripherals::P0_14::steal() },
 |         //unsafe { peripherals::P0_14::steal() },
 | ||||||
|         config, |         config, | ||||||
|         unsafe { &mut *addr_of_mut!(TRACE_BUF) }, |         unsafe { &mut *addr_of_mut!(TRACE_BUF) }, | ||||||
|     )); |     ); | ||||||
| 
 | 
 | ||||||
|     static STATE: StaticCell<State> = StaticCell::new(); |     static STATE: StaticCell<State> = StaticCell::new(); | ||||||
|     let (device, control, runner) = embassy_net_nrf91::new(STATE.init(State::new()), ipc_mem, trace_writer).await; |     static TRACE: StaticCell<TraceBuffer> = StaticCell::new(); | ||||||
|  |     let (device, control, runner, tracer) = | ||||||
|  |         embassy_net_nrf91::new_with_trace(STATE.init(State::new()), ipc_mem, TRACE.init(TraceBuffer::new())).await; | ||||||
|     unwrap!(spawner.spawn(modem_task(runner))); |     unwrap!(spawner.spawn(modem_task(runner))); | ||||||
|  |     unwrap!(spawner.spawn(trace_task(uart, tracer))); | ||||||
| 
 | 
 | ||||||
|     let config = embassy_net::Config::default(); |     let config = embassy_net::Config::default(); | ||||||
| 
 | 
 | ||||||
| @ -127,11 +119,15 @@ async fn main(spawner: Spawner) { | |||||||
| 
 | 
 | ||||||
|     let control = context::Control::new(control, 0).await; |     let control = context::Control::new(control, 0).await; | ||||||
| 
 | 
 | ||||||
|     unwrap!(control.configure(context::Config { |     unwrap!( | ||||||
|         apn: "iot.nat.es", |         control | ||||||
|         auth_prot: context::AuthProt::Pap, |             .configure(context::Config { | ||||||
|         auth: Some(("orange", "orange")), |                 apn: "iot.nat.es", | ||||||
|     }).await); |                 auth_prot: context::AuthProt::Pap, | ||||||
|  |                 auth: Some(("orange", "orange")), | ||||||
|  |             }) | ||||||
|  |             .await | ||||||
|  |     ); | ||||||
| 
 | 
 | ||||||
|     info!("waiting for attach..."); |     info!("waiting for attach..."); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user