From 39c166ef9b754c5caa44ef4dd4a4e216078dbcea Mon Sep 17 00:00:00 2001 From: Ulf Lilleengen Date: Tue, 19 Dec 2023 16:08:06 +0100 Subject: [PATCH] docs: document public apis for cyw43 driver --- cyw43-pio/README.md | 17 +++++++++++++++++ cyw43-pio/src/lib.rs | 6 ++++++ cyw43/README.md | 4 ++++ cyw43/src/control.rs | 16 +++++++++++++++- cyw43/src/lib.rs | 10 ++++++++++ cyw43/src/runner.rs | 2 ++ cyw43/src/structs.rs | 14 +++++++++++++- 7 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 cyw43-pio/README.md diff --git a/cyw43-pio/README.md b/cyw43-pio/README.md new file mode 100644 index 000000000..2b22db360 --- /dev/null +++ b/cyw43-pio/README.md @@ -0,0 +1,17 @@ +# cyw43-pio + +RP2040 PIO driver for the nonstandard half-duplex SPI used in the Pico W. The PIO driver offloads SPI communication with the WiFi chip and improves throughput. + +## Minimum supported Rust version (MSRV) + +Embassy is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release. + +## License + +This work is licensed under either of + +- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or + ) +- MIT license ([LICENSE-MIT](LICENSE-MIT) or ) + +at your option. diff --git a/cyw43-pio/src/lib.rs b/cyw43-pio/src/lib.rs index 8304740b3..5efab10e4 100644 --- a/cyw43-pio/src/lib.rs +++ b/cyw43-pio/src/lib.rs @@ -1,5 +1,7 @@ #![no_std] #![allow(async_fn_in_trait)] +#![doc = include_str!("../README.md")] +#![warn(missing_docs)] use core::slice; @@ -11,6 +13,7 @@ use embassy_rp::{Peripheral, PeripheralRef}; use fixed::FixedU32; use pio_proc::pio_asm; +/// SPI comms driven by PIO. pub struct PioSpi<'d, CS: Pin, PIO: Instance, const SM: usize, DMA> { cs: Output<'d, CS>, sm: StateMachine<'d, PIO, SM>, @@ -25,6 +28,7 @@ where CS: Pin, PIO: Instance, { + /// Create a new instance of PioSpi. pub fn new( common: &mut Common<'d, PIO>, mut sm: StateMachine<'d, PIO, SM>, @@ -143,6 +147,7 @@ where } } + /// Write data to peripheral and return status. pub async fn write(&mut self, write: &[u32]) -> u32 { self.sm.set_enable(false); let write_bits = write.len() * 32 - 1; @@ -170,6 +175,7 @@ where status } + /// Send command and read response into buffer. pub async fn cmd_read(&mut self, cmd: u32, read: &mut [u32]) -> u32 { self.sm.set_enable(false); let write_bits = 31; diff --git a/cyw43/README.md b/cyw43/README.md index 5b8f3cf40..2c24c7d36 100644 --- a/cyw43/README.md +++ b/cyw43/README.md @@ -45,6 +45,10 @@ nc 192.168.0.250 1234 ``` Send it some data, you should see it echoed back and printed in the firmware's logs. +## Minimum supported Rust version (MSRV) + +Embassy is guaranteed to compile on the latest stable Rust version at the time of release. It might compile with older versions but that may change in any new patch release. + ## License This work is licensed under either of diff --git a/cyw43/src/control.rs b/cyw43/src/control.rs index 826edfe1a..311fcb08c 100644 --- a/cyw43/src/control.rs +++ b/cyw43/src/control.rs @@ -12,17 +12,23 @@ use crate::ioctl::{IoctlState, IoctlType}; use crate::structs::*; use crate::{countries, events, PowerManagementMode}; +/// Control errors. #[derive(Debug)] pub struct Error { + /// Status code. pub status: u32, } +/// Multicast errors. #[derive(Debug)] pub enum AddMulticastAddressError { + /// Not a multicast address. NotMulticast, + /// No free address slots. NoFreeSlots, } +/// Control driver. pub struct Control<'a> { state_ch: ch::StateRunner<'a>, events: &'a Events, @@ -38,6 +44,7 @@ impl<'a> Control<'a> { } } + /// Initialize WiFi controller. pub async fn init(&mut self, clm: &[u8]) { const CHUNK_SIZE: usize = 1024; @@ -154,6 +161,7 @@ impl<'a> Control<'a> { self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await; } + /// Set power management mode. pub async fn set_power_management(&mut self, mode: PowerManagementMode) { // power save mode let mode_num = mode.mode(); @@ -166,6 +174,7 @@ impl<'a> Control<'a> { self.ioctl_set_u32(86, 0, mode_num).await; } + /// Join an unprotected network with the provided ssid. pub async fn join_open(&mut self, ssid: &str) -> Result<(), Error> { self.set_iovar_u32("ampdu_ba_wsize", 8).await; @@ -183,6 +192,7 @@ impl<'a> Control<'a> { self.wait_for_join(i).await } + /// Join an protected network with the provided ssid and passphrase. pub async fn join_wpa2(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> { self.set_iovar_u32("ampdu_ba_wsize", 8).await; @@ -250,16 +260,19 @@ impl<'a> Control<'a> { } } + /// Set GPIO pin on WiFi chip. pub async fn gpio_set(&mut self, gpio_n: u8, gpio_en: bool) { assert!(gpio_n < 3); self.set_iovar_u32x2("gpioout", 1 << gpio_n, if gpio_en { 1 << gpio_n } else { 0 }) .await } + /// Start open access point. pub async fn start_ap_open(&mut self, ssid: &str, channel: u8) { self.start_ap(ssid, "", Security::OPEN, channel).await; } + /// Start WPA2 protected access point. pub async fn start_ap_wpa2(&mut self, ssid: &str, passphrase: &str, channel: u8) { self.start_ap(ssid, passphrase, Security::WPA2_AES_PSK, channel).await; } @@ -494,13 +507,14 @@ impl<'a> Control<'a> { } } +/// WiFi network scanner. pub struct Scanner<'a> { subscriber: EventSubscriber<'a>, events: &'a Events, } impl Scanner<'_> { - /// wait for the next found network + /// Wait for the next found network. pub async fn next(&mut self) -> Option { let event = self.subscriber.next_message_pure().await; if event.header.status != EStatus::PARTIAL { diff --git a/cyw43/src/lib.rs b/cyw43/src/lib.rs index 300465e36..19b0cb194 100644 --- a/cyw43/src/lib.rs +++ b/cyw43/src/lib.rs @@ -2,6 +2,8 @@ #![no_main] #![allow(async_fn_in_trait)] #![deny(unused_must_use)] +#![doc = include_str!("../README.md")] +#![warn(missing_docs)] // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; @@ -102,6 +104,7 @@ const CHIP: Chip = Chip { chanspec_ctl_sb_mask: 0x0700, }; +/// Driver state. pub struct State { ioctl_state: IoctlState, ch: ch::State, @@ -109,6 +112,7 @@ pub struct State { } impl State { + /// Create new driver state holder. pub fn new() -> Self { Self { ioctl_state: IoctlState::new(), @@ -118,6 +122,7 @@ impl State { } } +/// Power management modes. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum PowerManagementMode { /// Custom, officially unsupported mode. Use at your own risk. @@ -203,8 +208,13 @@ impl PowerManagementMode { } } +/// Embassy-net driver. pub type NetDriver<'a> = ch::Device<'a, MTU>; +/// Create a new instance of the CYW43 driver. +/// +/// Returns a handle to the network device, control handle and a runner for driving the low level +/// stack. pub async fn new<'a, PWR, SPI>( state: &'a mut State, pwr: PWR, diff --git a/cyw43/src/runner.rs b/cyw43/src/runner.rs index 83aee6b40..b2a9e3e80 100644 --- a/cyw43/src/runner.rs +++ b/cyw43/src/runner.rs @@ -34,6 +34,7 @@ impl Default for LogState { } } +/// Driver communicating with the WiFi chip. pub struct Runner<'a, PWR, SPI> { ch: ch::Runner<'a, MTU>, bus: Bus, @@ -222,6 +223,7 @@ where } } + /// Run the pub async fn run(mut self) -> ! { let mut buf = [0; 512]; loop { diff --git a/cyw43/src/structs.rs b/cyw43/src/structs.rs index 5ba633c74..5ea62d95b 100644 --- a/cyw43/src/structs.rs +++ b/cyw43/src/structs.rs @@ -4,13 +4,16 @@ use crate::fmt::Bytes; macro_rules! impl_bytes { ($t:ident) => { impl $t { + /// Bytes consumed by this type. pub const SIZE: usize = core::mem::size_of::(); + /// Convert to byte array. #[allow(unused)] pub fn to_bytes(&self) -> [u8; Self::SIZE] { unsafe { core::mem::transmute(*self) } } + /// Create from byte array. #[allow(unused)] pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> &Self { let alignment = core::mem::align_of::(); @@ -23,6 +26,7 @@ macro_rules! impl_bytes { unsafe { core::mem::transmute(bytes) } } + /// Create from mutable byte array. #[allow(unused)] pub fn from_bytes_mut(bytes: &mut [u8; Self::SIZE]) -> &mut Self { let alignment = core::mem::align_of::(); @@ -204,6 +208,7 @@ pub struct EthernetHeader { } impl EthernetHeader { + /// Swap endianness. pub fn byteswap(&mut self) { self.ether_type = self.ether_type.to_be(); } @@ -472,19 +477,26 @@ impl ScanResults { #[repr(C, packed(2))] #[non_exhaustive] pub struct BssInfo { + /// Version. pub version: u32, + /// Length. pub length: u32, + /// BSSID. pub bssid: [u8; 6], + /// Beacon period. pub beacon_period: u16, + /// Capability. pub capability: u16, + /// SSID length. pub ssid_len: u8, + /// SSID. pub ssid: [u8; 32], // there will be more stuff here } impl_bytes!(BssInfo); impl BssInfo { - pub fn parse(packet: &mut [u8]) -> Option<&mut Self> { + pub(crate) fn parse(packet: &mut [u8]) -> Option<&mut Self> { if packet.len() < BssInfo::SIZE { return None; }