aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUlf Lilleengen <[email protected]>2023-12-19 15:12:45 +0000
committerGitHub <[email protected]>2023-12-19 15:12:45 +0000
commitc995732b0e08b3157aa8886da2e5ce4a36af6e93 (patch)
treecece1955c41b80d92bd8056cc265a91cf3d0cf79
parent5e76c8b41a05c89652a6c53061107482adc4125f (diff)
parent39c166ef9b754c5caa44ef4dd4a4e216078dbcea (diff)
Merge pull request #2320 from embassy-rs/cyw43-docs
docs: document public apis for cyw43 driver
-rw-r--r--cyw43-pio/README.md17
-rw-r--r--cyw43-pio/src/lib.rs6
-rw-r--r--cyw43/README.md4
-rw-r--r--cyw43/src/control.rs16
-rw-r--r--cyw43/src/lib.rs10
-rw-r--r--cyw43/src/runner.rs2
-rw-r--r--cyw43/src/structs.rs14
7 files changed, 67 insertions, 2 deletions
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 @@
1# cyw43-pio
2
3RP2040 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.
4
5## Minimum supported Rust version (MSRV)
6
7Embassy 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.
8
9## License
10
11This work is licensed under either of
12
13- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
14 <http://www.apache.org/licenses/LICENSE-2.0>)
15- MIT license ([LICENSE-MIT](LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
16
17at 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 @@
1#![no_std] 1#![no_std]
2#![allow(async_fn_in_trait)] 2#![allow(async_fn_in_trait)]
3#![doc = include_str!("../README.md")]
4#![warn(missing_docs)]
3 5
4use core::slice; 6use core::slice;
5 7
@@ -11,6 +13,7 @@ use embassy_rp::{Peripheral, PeripheralRef};
11use fixed::FixedU32; 13use fixed::FixedU32;
12use pio_proc::pio_asm; 14use pio_proc::pio_asm;
13 15
16/// SPI comms driven by PIO.
14pub struct PioSpi<'d, CS: Pin, PIO: Instance, const SM: usize, DMA> { 17pub struct PioSpi<'d, CS: Pin, PIO: Instance, const SM: usize, DMA> {
15 cs: Output<'d, CS>, 18 cs: Output<'d, CS>,
16 sm: StateMachine<'d, PIO, SM>, 19 sm: StateMachine<'d, PIO, SM>,
@@ -25,6 +28,7 @@ where
25 CS: Pin, 28 CS: Pin,
26 PIO: Instance, 29 PIO: Instance,
27{ 30{
31 /// Create a new instance of PioSpi.
28 pub fn new<DIO, CLK>( 32 pub fn new<DIO, CLK>(
29 common: &mut Common<'d, PIO>, 33 common: &mut Common<'d, PIO>,
30 mut sm: StateMachine<'d, PIO, SM>, 34 mut sm: StateMachine<'d, PIO, SM>,
@@ -143,6 +147,7 @@ where
143 } 147 }
144 } 148 }
145 149
150 /// Write data to peripheral and return status.
146 pub async fn write(&mut self, write: &[u32]) -> u32 { 151 pub async fn write(&mut self, write: &[u32]) -> u32 {
147 self.sm.set_enable(false); 152 self.sm.set_enable(false);
148 let write_bits = write.len() * 32 - 1; 153 let write_bits = write.len() * 32 - 1;
@@ -170,6 +175,7 @@ where
170 status 175 status
171 } 176 }
172 177
178 /// Send command and read response into buffer.
173 pub async fn cmd_read(&mut self, cmd: u32, read: &mut [u32]) -> u32 { 179 pub async fn cmd_read(&mut self, cmd: u32, read: &mut [u32]) -> u32 {
174 self.sm.set_enable(false); 180 self.sm.set_enable(false);
175 let write_bits = 31; 181 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
45``` 45```
46Send it some data, you should see it echoed back and printed in the firmware's logs. 46Send it some data, you should see it echoed back and printed in the firmware's logs.
47 47
48## Minimum supported Rust version (MSRV)
49
50Embassy 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.
51
48## License 52## License
49 53
50This work is licensed under either of 54This 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};
12use crate::structs::*; 12use crate::structs::*;
13use crate::{countries, events, PowerManagementMode}; 13use crate::{countries, events, PowerManagementMode};
14 14
15/// Control errors.
15#[derive(Debug)] 16#[derive(Debug)]
16pub struct Error { 17pub struct Error {
18 /// Status code.
17 pub status: u32, 19 pub status: u32,
18} 20}
19 21
22/// Multicast errors.
20#[derive(Debug)] 23#[derive(Debug)]
21pub enum AddMulticastAddressError { 24pub enum AddMulticastAddressError {
25 /// Not a multicast address.
22 NotMulticast, 26 NotMulticast,
27 /// No free address slots.
23 NoFreeSlots, 28 NoFreeSlots,
24} 29}
25 30
31/// Control driver.
26pub struct Control<'a> { 32pub struct Control<'a> {
27 state_ch: ch::StateRunner<'a>, 33 state_ch: ch::StateRunner<'a>,
28 events: &'a Events, 34 events: &'a Events,
@@ -38,6 +44,7 @@ impl<'a> Control<'a> {
38 } 44 }
39 } 45 }
40 46
47 /// Initialize WiFi controller.
41 pub async fn init(&mut self, clm: &[u8]) { 48 pub async fn init(&mut self, clm: &[u8]) {
42 const CHUNK_SIZE: usize = 1024; 49 const CHUNK_SIZE: usize = 1024;
43 50
@@ -154,6 +161,7 @@ impl<'a> Control<'a> {
154 self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await; 161 self.ioctl(IoctlType::Set, IOCTL_CMD_DOWN, 0, &mut []).await;
155 } 162 }
156 163
164 /// Set power management mode.
157 pub async fn set_power_management(&mut self, mode: PowerManagementMode) { 165 pub async fn set_power_management(&mut self, mode: PowerManagementMode) {
158 // power save mode 166 // power save mode
159 let mode_num = mode.mode(); 167 let mode_num = mode.mode();
@@ -166,6 +174,7 @@ impl<'a> Control<'a> {
166 self.ioctl_set_u32(86, 0, mode_num).await; 174 self.ioctl_set_u32(86, 0, mode_num).await;
167 } 175 }
168 176
177 /// Join an unprotected network with the provided ssid.
169 pub async fn join_open(&mut self, ssid: &str) -> Result<(), Error> { 178 pub async fn join_open(&mut self, ssid: &str) -> Result<(), Error> {
170 self.set_iovar_u32("ampdu_ba_wsize", 8).await; 179 self.set_iovar_u32("ampdu_ba_wsize", 8).await;
171 180
@@ -183,6 +192,7 @@ impl<'a> Control<'a> {
183 self.wait_for_join(i).await 192 self.wait_for_join(i).await
184 } 193 }
185 194
195 /// Join an protected network with the provided ssid and passphrase.
186 pub async fn join_wpa2(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> { 196 pub async fn join_wpa2(&mut self, ssid: &str, passphrase: &str) -> Result<(), Error> {
187 self.set_iovar_u32("ampdu_ba_wsize", 8).await; 197 self.set_iovar_u32("ampdu_ba_wsize", 8).await;
188 198
@@ -250,16 +260,19 @@ impl<'a> Control<'a> {
250 } 260 }
251 } 261 }
252 262
263 /// Set GPIO pin on WiFi chip.
253 pub async fn gpio_set(&mut self, gpio_n: u8, gpio_en: bool) { 264 pub async fn gpio_set(&mut self, gpio_n: u8, gpio_en: bool) {
254 assert!(gpio_n < 3); 265 assert!(gpio_n < 3);
255 self.set_iovar_u32x2("gpioout", 1 << gpio_n, if gpio_en { 1 << gpio_n } else { 0 }) 266 self.set_iovar_u32x2("gpioout", 1 << gpio_n, if gpio_en { 1 << gpio_n } else { 0 })
256 .await 267 .await
257 } 268 }
258 269
270 /// Start open access point.
259 pub async fn start_ap_open(&mut self, ssid: &str, channel: u8) { 271 pub async fn start_ap_open(&mut self, ssid: &str, channel: u8) {
260 self.start_ap(ssid, "", Security::OPEN, channel).await; 272 self.start_ap(ssid, "", Security::OPEN, channel).await;
261 } 273 }
262 274
275 /// Start WPA2 protected access point.
263 pub async fn start_ap_wpa2(&mut self, ssid: &str, passphrase: &str, channel: u8) { 276 pub async fn start_ap_wpa2(&mut self, ssid: &str, passphrase: &str, channel: u8) {
264 self.start_ap(ssid, passphrase, Security::WPA2_AES_PSK, channel).await; 277 self.start_ap(ssid, passphrase, Security::WPA2_AES_PSK, channel).await;
265 } 278 }
@@ -494,13 +507,14 @@ impl<'a> Control<'a> {
494 } 507 }
495} 508}
496 509
510/// WiFi network scanner.
497pub struct Scanner<'a> { 511pub struct Scanner<'a> {
498 subscriber: EventSubscriber<'a>, 512 subscriber: EventSubscriber<'a>,
499 events: &'a Events, 513 events: &'a Events,
500} 514}
501 515
502impl Scanner<'_> { 516impl Scanner<'_> {
503 /// wait for the next found network 517 /// Wait for the next found network.
504 pub async fn next(&mut self) -> Option<BssInfo> { 518 pub async fn next(&mut self) -> Option<BssInfo> {
505 let event = self.subscriber.next_message_pure().await; 519 let event = self.subscriber.next_message_pure().await;
506 if event.header.status != EStatus::PARTIAL { 520 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 @@
2#![no_main] 2#![no_main]
3#![allow(async_fn_in_trait)] 3#![allow(async_fn_in_trait)]
4#![deny(unused_must_use)] 4#![deny(unused_must_use)]
5#![doc = include_str!("../README.md")]
6#![warn(missing_docs)]
5 7
6// This mod MUST go first, so that the others see its macros. 8// This mod MUST go first, so that the others see its macros.
7pub(crate) mod fmt; 9pub(crate) mod fmt;
@@ -102,6 +104,7 @@ const CHIP: Chip = Chip {
102 chanspec_ctl_sb_mask: 0x0700, 104 chanspec_ctl_sb_mask: 0x0700,
103}; 105};
104 106
107/// Driver state.
105pub struct State { 108pub struct State {
106 ioctl_state: IoctlState, 109 ioctl_state: IoctlState,
107 ch: ch::State<MTU, 4, 4>, 110 ch: ch::State<MTU, 4, 4>,
@@ -109,6 +112,7 @@ pub struct State {
109} 112}
110 113
111impl State { 114impl State {
115 /// Create new driver state holder.
112 pub fn new() -> Self { 116 pub fn new() -> Self {
113 Self { 117 Self {
114 ioctl_state: IoctlState::new(), 118 ioctl_state: IoctlState::new(),
@@ -118,6 +122,7 @@ impl State {
118 } 122 }
119} 123}
120 124
125/// Power management modes.
121#[derive(Debug, Clone, Copy, PartialEq, Eq)] 126#[derive(Debug, Clone, Copy, PartialEq, Eq)]
122pub enum PowerManagementMode { 127pub enum PowerManagementMode {
123 /// Custom, officially unsupported mode. Use at your own risk. 128 /// Custom, officially unsupported mode. Use at your own risk.
@@ -203,8 +208,13 @@ impl PowerManagementMode {
203 } 208 }
204} 209}
205 210
211/// Embassy-net driver.
206pub type NetDriver<'a> = ch::Device<'a, MTU>; 212pub type NetDriver<'a> = ch::Device<'a, MTU>;
207 213
214/// Create a new instance of the CYW43 driver.
215///
216/// Returns a handle to the network device, control handle and a runner for driving the low level
217/// stack.
208pub async fn new<'a, PWR, SPI>( 218pub async fn new<'a, PWR, SPI>(
209 state: &'a mut State, 219 state: &'a mut State,
210 pwr: PWR, 220 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 {
34 } 34 }
35} 35}
36 36
37/// Driver communicating with the WiFi chip.
37pub struct Runner<'a, PWR, SPI> { 38pub struct Runner<'a, PWR, SPI> {
38 ch: ch::Runner<'a, MTU>, 39 ch: ch::Runner<'a, MTU>,
39 bus: Bus<PWR, SPI>, 40 bus: Bus<PWR, SPI>,
@@ -222,6 +223,7 @@ where
222 } 223 }
223 } 224 }
224 225
226 /// Run the
225 pub async fn run(mut self) -> ! { 227 pub async fn run(mut self) -> ! {
226 let mut buf = [0; 512]; 228 let mut buf = [0; 512];
227 loop { 229 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;
4macro_rules! impl_bytes { 4macro_rules! impl_bytes {
5 ($t:ident) => { 5 ($t:ident) => {
6 impl $t { 6 impl $t {
7 /// Bytes consumed by this type.
7 pub const SIZE: usize = core::mem::size_of::<Self>(); 8 pub const SIZE: usize = core::mem::size_of::<Self>();
8 9
10 /// Convert to byte array.
9 #[allow(unused)] 11 #[allow(unused)]
10 pub fn to_bytes(&self) -> [u8; Self::SIZE] { 12 pub fn to_bytes(&self) -> [u8; Self::SIZE] {
11 unsafe { core::mem::transmute(*self) } 13 unsafe { core::mem::transmute(*self) }
12 } 14 }
13 15
16 /// Create from byte array.
14 #[allow(unused)] 17 #[allow(unused)]
15 pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> &Self { 18 pub fn from_bytes(bytes: &[u8; Self::SIZE]) -> &Self {
16 let alignment = core::mem::align_of::<Self>(); 19 let alignment = core::mem::align_of::<Self>();
@@ -23,6 +26,7 @@ macro_rules! impl_bytes {
23 unsafe { core::mem::transmute(bytes) } 26 unsafe { core::mem::transmute(bytes) }
24 } 27 }
25 28
29 /// Create from mutable byte array.
26 #[allow(unused)] 30 #[allow(unused)]
27 pub fn from_bytes_mut(bytes: &mut [u8; Self::SIZE]) -> &mut Self { 31 pub fn from_bytes_mut(bytes: &mut [u8; Self::SIZE]) -> &mut Self {
28 let alignment = core::mem::align_of::<Self>(); 32 let alignment = core::mem::align_of::<Self>();
@@ -204,6 +208,7 @@ pub struct EthernetHeader {
204} 208}
205 209
206impl EthernetHeader { 210impl EthernetHeader {
211 /// Swap endianness.
207 pub fn byteswap(&mut self) { 212 pub fn byteswap(&mut self) {
208 self.ether_type = self.ether_type.to_be(); 213 self.ether_type = self.ether_type.to_be();
209 } 214 }
@@ -472,19 +477,26 @@ impl ScanResults {
472#[repr(C, packed(2))] 477#[repr(C, packed(2))]
473#[non_exhaustive] 478#[non_exhaustive]
474pub struct BssInfo { 479pub struct BssInfo {
480 /// Version.
475 pub version: u32, 481 pub version: u32,
482 /// Length.
476 pub length: u32, 483 pub length: u32,
484 /// BSSID.
477 pub bssid: [u8; 6], 485 pub bssid: [u8; 6],
486 /// Beacon period.
478 pub beacon_period: u16, 487 pub beacon_period: u16,
488 /// Capability.
479 pub capability: u16, 489 pub capability: u16,
490 /// SSID length.
480 pub ssid_len: u8, 491 pub ssid_len: u8,
492 /// SSID.
481 pub ssid: [u8; 32], 493 pub ssid: [u8; 32],
482 // there will be more stuff here 494 // there will be more stuff here
483} 495}
484impl_bytes!(BssInfo); 496impl_bytes!(BssInfo);
485 497
486impl BssInfo { 498impl BssInfo {
487 pub fn parse(packet: &mut [u8]) -> Option<&mut Self> { 499 pub(crate) fn parse(packet: &mut [u8]) -> Option<&mut Self> {
488 if packet.len() < BssInfo::SIZE { 500 if packet.len() < BssInfo::SIZE {
489 return None; 501 return None;
490 } 502 }