Compare commits

...

33 Commits

Author SHA1 Message Date
d6fda686bc net-esp-hosted: use released noproto version. 2023-12-20 14:13:52 +01:00
76c600365d Merge pull request #2334 from embassy-rs/embassy-net-adin1110-docs
docs: embassy-net-adin1110
2023-12-20 12:44:19 +00:00
18dac099cb Merge pull request #2333 from embassy-rs/embassy-net-wiznet-docs
docs: document public apis of wiznet driver
2023-12-20 12:44:16 +00:00
49005e955d Merge pull request #2330 from embassy-rs/embassy-net-esp-hosted-docs
Embassy net esp hosted docs
2023-12-20 12:44:11 +00:00
70ea805af3 Merge pull request #2332 from embassy-rs/embassy-net-tuntap-docs
docs: document embassy-net-tuntap
2023-12-20 12:44:06 +00:00
93bb34d8d1 fix: expose less 2023-12-20 13:39:45 +01:00
51a67cb69a fix: expose less 2023-12-20 13:34:34 +01:00
c8eb128a56 Merge pull request #2328 from rmja/signal-try-take
feat(embassy-sync): Add try_take() to signal
2023-12-20 12:34:01 +00:00
22ee868f04 Merge pull request #2335 from embassy-rs/remove-embedded-sdmmc
remove embedded-sdmmc
2023-12-20 12:32:04 +00:00
1c3cf347cb remove embedded-sdmmc
Remove support for embedded-sdmmc due to lack of maintainership. Bring
it back once the upstream includes the async functionality.
2023-12-20 13:25:36 +01:00
b8777eaea2 better keep missing docs for into 2023-12-20 13:12:32 +01:00
13c107e815 Put waiting state back if any 2023-12-20 13:09:16 +01:00
b0583b17cb fix: make non-public instead 2023-12-20 13:08:06 +01:00
246c49621c docs: embassy-net-adin1110 2023-12-20 12:52:35 +01:00
c3b827d8cd fix: add readme and fix remaining warnings 2023-12-20 12:24:51 +01:00
4dfae9328e add missing guards 2023-12-20 12:18:02 +01:00
73f8cd7ade fix: add repository to manifest 2023-12-20 12:16:01 +01:00
4a2dd7b944 docs: document public apis of wiznet driver 2023-12-20 12:14:25 +01:00
afb01e3fc5 docs: document embassy-net-tuntap 2023-12-20 12:08:26 +01:00
89cfdcb9f5 fix suddenly ending comment 2023-12-20 12:06:49 +01:00
abea4dde3d docs: document most of esp-hosted driver 2023-12-20 10:15:18 +01:00
52a801fdb7 Merge pull request #2329 from embassy-rs/apidoc-embassy-net-driver-channel
docs: document public apis of embassy-net-driver-channel
2023-12-20 09:08:55 +00:00
fc6e70caa5 docs: document public apis of embassy-net-driver-channel 2023-12-20 09:24:10 +01:00
f9d0daad80 feat(embassy-sync): Add try_take() to signal 2023-12-20 08:37:15 +01:00
97e919ea64 Merge pull request #2326 from embassy-rs/salty-update
Salty update
2023-12-19 21:30:32 +00:00
c7841a37fa boot: update ed25519-dalek in dev-dependencies. 2023-12-19 22:26:50 +01:00
589a16b255 Merge pull request #2327 from dragonnn/main
fix stm32 rtc year from 1970 base 2000 to make leap years work
2023-12-19 20:26:01 +00:00
4567b87482 cargo fmt 2023-12-19 21:21:52 +01:00
12de90e13d fix: update ed25519-dalek to new version 2023-12-19 21:20:30 +01:00
871ed538b1 fix stm32 rtc year from 1970 base 2000 2023-12-19 21:17:42 +01:00
efd5dbe019 fix: build warnings 2023-12-19 20:25:20 +01:00
9d46ee0758 fix: update salty to released version 2023-12-19 20:24:55 +01:00
e5912972ec Merge pull request #2325 from embassy-rs/stm32-docs
stm32: finish docs.
2023-12-19 17:07:53 +00:00
29 changed files with 255 additions and 153 deletions

4
ci.sh
View File

@ -91,12 +91,12 @@ cargo batch \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f417zg,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f417zg,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f423zh,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f423zh,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f427zi,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f427zi,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,embedded-sdmmc,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f429zi,log,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f437zi,log,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f437zi,log,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f439zi,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f439zi,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446ze,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f446ze,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f469zi,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f469zi,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f479zi,defmt,exti,time-driver-any,embedded-sdmmc,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f479zi,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f730i8,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32f730i8,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h753zi,defmt,exti,time-driver-any,time \
--- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h735zg,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h735zg,defmt,exti,time-driver-any,time \

View File

@ -26,25 +26,22 @@ features = ["defmt"]
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }
digest = "0.10" digest = "0.10"
log = { version = "0.4", optional = true } log = { version = "0.4", optional = true }
ed25519-dalek = { version = "1.0.1", default_features = false, features = ["u32_backend"], optional = true } ed25519-dalek = { version = "2", default_features = false, features = ["digest"], optional = true }
embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" } embassy-embedded-hal = { version = "0.1.0", path = "../../embassy-embedded-hal" }
embassy-sync = { version = "0.5.0", path = "../../embassy-sync" } embassy-sync = { version = "0.5.0", path = "../../embassy-sync" }
embedded-storage = "0.3.1" embedded-storage = "0.3.1"
embedded-storage-async = { version = "0.4.1" } embedded-storage-async = { version = "0.4.1" }
salty = { git = "https://github.com/ycrypto/salty.git", rev = "a9f17911a5024698406b75c0fac56ab5ccf6a8c7", optional = true } salty = { version = "0.3", optional = true }
signature = { version = "1.6.4", default-features = false } signature = { version = "2.0", default-features = false }
[dev-dependencies] [dev-dependencies]
log = "0.4" log = "0.4"
env_logger = "0.9" env_logger = "0.9"
rand = "0.7" # ed25519-dalek v1.0.1 depends on this exact version rand = "0.8"
futures = { version = "0.3", features = ["executor"] } futures = { version = "0.3", features = ["executor"] }
sha1 = "0.10.5" sha1 = "0.10.5"
critical-section = { version = "1.1.1", features = ["std"] } critical-section = { version = "1.1.1", features = ["std"] }
ed25519-dalek = { version = "2", default_features = false, features = ["std", "rand_core", "digest"] }
[dev-dependencies.ed25519-dalek]
default_features = false
features = ["rand", "std", "u32_backend"]
[features] [features]
ed25519-dalek = ["dep:ed25519-dalek", "_verify"] ed25519-dalek = ["dep:ed25519-dalek", "_verify"]

View File

@ -1,6 +1,6 @@
use digest::typenum::U64; use digest::typenum::U64;
use digest::{FixedOutput, HashMarker, OutputSizeUser, Update}; use digest::{FixedOutput, HashMarker, OutputSizeUser, Update};
use ed25519_dalek::Digest as _; use ed25519_dalek::Digest;
pub struct Sha512(ed25519_dalek::Sha512); pub struct Sha512(ed25519_dalek::Sha512);
@ -12,7 +12,7 @@ impl Default for Sha512 {
impl Update for Sha512 { impl Update for Sha512 {
fn update(&mut self, data: &[u8]) { fn update(&mut self, data: &[u8]) {
self.0.update(data) Digest::update(&mut self.0, data)
} }
} }

View File

@ -79,8 +79,8 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
#[cfg(feature = "_verify")] #[cfg(feature = "_verify")]
pub async fn verify_and_mark_updated( pub async fn verify_and_mark_updated(
&mut self, &mut self,
_public_key: &[u8], _public_key: &[u8; 32],
_signature: &[u8], _signature: &[u8; 64],
_update_len: u32, _update_len: u32,
) -> Result<(), FirmwareUpdaterError> { ) -> Result<(), FirmwareUpdaterError> {
assert!(_update_len <= self.dfu.capacity() as u32); assert!(_update_len <= self.dfu.capacity() as u32);
@ -89,14 +89,14 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
#[cfg(feature = "ed25519-dalek")] #[cfg(feature = "ed25519-dalek")]
{ {
use ed25519_dalek::{PublicKey, Signature, SignatureError, Verifier}; use ed25519_dalek::{Signature, SignatureError, Verifier, VerifyingKey};
use crate::digest_adapters::ed25519_dalek::Sha512; use crate::digest_adapters::ed25519_dalek::Sha512;
let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into()); let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into());
let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?; let public_key = VerifyingKey::from_bytes(_public_key).map_err(into_signature_error)?;
let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; let signature = Signature::from_bytes(_signature);
let mut chunk_buf = [0; 2]; let mut chunk_buf = [0; 2];
let mut message = [0; 64]; let mut message = [0; 64];
@ -106,7 +106,6 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
} }
#[cfg(feature = "ed25519-salty")] #[cfg(feature = "ed25519-salty")]
{ {
use salty::constants::{PUBLICKEY_SERIALIZED_LENGTH, SIGNATURE_SERIALIZED_LENGTH};
use salty::{PublicKey, Signature}; use salty::{PublicKey, Signature};
use crate::digest_adapters::salty::Sha512; use crate::digest_adapters::salty::Sha512;
@ -115,10 +114,8 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> FirmwareUpdater<'d, DFU, STATE> {
FirmwareUpdaterError::Signature(signature::Error::default()) FirmwareUpdaterError::Signature(signature::Error::default())
} }
let public_key: [u8; PUBLICKEY_SERIALIZED_LENGTH] = _public_key.try_into().map_err(into_signature_error)?; let public_key = PublicKey::try_from(_public_key).map_err(into_signature_error)?;
let public_key = PublicKey::try_from(&public_key).map_err(into_signature_error)?; let signature = Signature::try_from(_signature).map_err(into_signature_error)?;
let signature: [u8; SIGNATURE_SERIALIZED_LENGTH] = _signature.try_into().map_err(into_signature_error)?;
let signature = Signature::try_from(&signature).map_err(into_signature_error)?;
let mut message = [0; 64]; let mut message = [0; 64];
let mut chunk_buf = [0; 2]; let mut chunk_buf = [0; 2];

View File

@ -86,8 +86,8 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
#[cfg(feature = "_verify")] #[cfg(feature = "_verify")]
pub fn verify_and_mark_updated( pub fn verify_and_mark_updated(
&mut self, &mut self,
_public_key: &[u8], _public_key: &[u8; 32],
_signature: &[u8], _signature: &[u8; 64],
_update_len: u32, _update_len: u32,
) -> Result<(), FirmwareUpdaterError> { ) -> Result<(), FirmwareUpdaterError> {
assert!(_update_len <= self.dfu.capacity() as u32); assert!(_update_len <= self.dfu.capacity() as u32);
@ -96,14 +96,14 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
#[cfg(feature = "ed25519-dalek")] #[cfg(feature = "ed25519-dalek")]
{ {
use ed25519_dalek::{PublicKey, Signature, SignatureError, Verifier}; use ed25519_dalek::{Signature, SignatureError, Verifier, VerifyingKey};
use crate::digest_adapters::ed25519_dalek::Sha512; use crate::digest_adapters::ed25519_dalek::Sha512;
let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into()); let into_signature_error = |e: SignatureError| FirmwareUpdaterError::Signature(e.into());
let public_key = PublicKey::from_bytes(_public_key).map_err(into_signature_error)?; let public_key = VerifyingKey::from_bytes(_public_key).map_err(into_signature_error)?;
let signature = Signature::from_bytes(_signature).map_err(into_signature_error)?; let signature = Signature::from_bytes(_signature);
let mut message = [0; 64]; let mut message = [0; 64];
let mut chunk_buf = [0; 2]; let mut chunk_buf = [0; 2];
@ -113,7 +113,6 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
} }
#[cfg(feature = "ed25519-salty")] #[cfg(feature = "ed25519-salty")]
{ {
use salty::constants::{PUBLICKEY_SERIALIZED_LENGTH, SIGNATURE_SERIALIZED_LENGTH};
use salty::{PublicKey, Signature}; use salty::{PublicKey, Signature};
use crate::digest_adapters::salty::Sha512; use crate::digest_adapters::salty::Sha512;
@ -122,10 +121,8 @@ impl<'d, DFU: NorFlash, STATE: NorFlash> BlockingFirmwareUpdater<'d, DFU, STATE>
FirmwareUpdaterError::Signature(signature::Error::default()) FirmwareUpdaterError::Signature(signature::Error::default())
} }
let public_key: [u8; PUBLICKEY_SERIALIZED_LENGTH] = _public_key.try_into().map_err(into_signature_error)?; let public_key = PublicKey::try_from(_public_key).map_err(into_signature_error)?;
let public_key = PublicKey::try_from(&public_key).map_err(into_signature_error)?; let signature = Signature::try_from(_signature).map_err(into_signature_error)?;
let signature: [u8; SIGNATURE_SERIALIZED_LENGTH] = _signature.try_into().map_err(into_signature_error)?;
let signature = Signature::try_from(&signature).map_err(into_signature_error)?;
let mut message = [0; 64]; let mut message = [0; 64];
let mut chunk_buf = [0; 2]; let mut chunk_buf = [0; 2];

View File

@ -275,21 +275,19 @@ mod tests {
// The following key setup is based on: // The following key setup is based on:
// https://docs.rs/ed25519-dalek/latest/ed25519_dalek/#example // https://docs.rs/ed25519-dalek/latest/ed25519_dalek/#example
use ed25519_dalek::Keypair; use ed25519_dalek::{Digest, Sha512, Signature, Signer, SigningKey, VerifyingKey};
use rand::rngs::OsRng; use rand::rngs::OsRng;
let mut csprng = OsRng {}; let mut csprng = OsRng {};
let keypair: Keypair = Keypair::generate(&mut csprng); let keypair = SigningKey::generate(&mut csprng);
use ed25519_dalek::{Digest, Sha512, Signature, Signer};
let firmware: &[u8] = b"This are bytes that would otherwise be firmware bytes for DFU."; let firmware: &[u8] = b"This are bytes that would otherwise be firmware bytes for DFU.";
let mut digest = Sha512::new(); let mut digest = Sha512::new();
digest.update(&firmware); digest.update(&firmware);
let message = digest.finalize(); let message = digest.finalize();
let signature: Signature = keypair.sign(&message); let signature: Signature = keypair.sign(&message);
use ed25519_dalek::PublicKey; let public_key = keypair.verifying_key();
let public_key: PublicKey = keypair.public;
// Setup flash // Setup flash
let flash = BlockingTestFlash::new(BootLoaderConfig { let flash = BlockingTestFlash::new(BootLoaderConfig {

View File

@ -6,8 +6,7 @@ keywords = ["embedded", "ADIN1110", "embassy-net", "embedded-hal-async", "ethern
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"] categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
edition = "2021" edition = "2021"
repository = "https://github.com/embassy-rs/embassy"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
heapless = "0.8" heapless = "0.8"

View File

@ -1,3 +1,4 @@
/// CRC32 lookup table.
pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [ pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [
0x0000_0000, 0x0000_0000,
0x7707_3096, 0x7707_3096,
@ -263,8 +264,9 @@ pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [
pub struct ETH_FCS(pub u32); pub struct ETH_FCS(pub u32);
impl ETH_FCS { impl ETH_FCS {
pub const CRC32_OK: u32 = 0x2144_df1c; const CRC32_OK: u32 = 0x2144_df1c;
/// Create a new frame check sequence from `data`.
#[must_use] #[must_use]
pub fn new(data: &[u8]) -> Self { pub fn new(data: &[u8]) -> Self {
let fcs = data.iter().fold(u32::MAX, |crc, byte| { let fcs = data.iter().fold(u32::MAX, |crc, byte| {
@ -274,6 +276,7 @@ impl ETH_FCS {
Self(fcs) Self(fcs)
} }
/// Update the frame check sequence with `data`.
#[must_use] #[must_use]
pub fn update(self, data: &[u8]) -> Self { pub fn update(self, data: &[u8]) -> Self {
let fcs = data.iter().fold(self.0 ^ u32::MAX, |crc, byte| { let fcs = data.iter().fold(self.0 ^ u32::MAX, |crc, byte| {
@ -283,16 +286,19 @@ impl ETH_FCS {
Self(fcs) Self(fcs)
} }
/// Check if the frame check sequence is correct.
#[must_use] #[must_use]
pub fn crc_ok(&self) -> bool { pub fn crc_ok(&self) -> bool {
self.0 == Self::CRC32_OK self.0 == Self::CRC32_OK
} }
/// Switch byte order.
#[must_use] #[must_use]
pub fn hton_bytes(&self) -> [u8; 4] { pub fn hton_bytes(&self) -> [u8; 4] {
self.0.to_le_bytes() self.0.to_le_bytes()
} }
/// Switch byte order as a u32.
#[must_use] #[must_use]
pub fn hton(&self) -> u32 { pub fn hton(&self) -> u32 {
self.0.to_le() self.0.to_le()

View File

@ -5,6 +5,7 @@
#![allow(clippy::missing_errors_doc)] #![allow(clippy::missing_errors_doc)]
#![allow(clippy::missing_panics_doc)] #![allow(clippy::missing_panics_doc)]
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
#![warn(missing_docs)]
// must go first! // must go first!
mod fmt; mod fmt;
@ -26,8 +27,9 @@ use embedded_hal_async::digital::Wait;
use embedded_hal_async::spi::{Error, Operation, SpiDevice}; use embedded_hal_async::spi::{Error, Operation, SpiDevice};
use heapless::Vec; use heapless::Vec;
pub use mdio::MdioBus; pub use mdio::MdioBus;
pub use phy::{Phy10BaseT1x, RegsC22, RegsC45}; pub use phy::Phy10BaseT1x;
pub use regs::{Config0, Config2, SpiRegisters as sr, Status0, Status1}; use phy::{RegsC22, RegsC45};
use regs::{Config0, Config2, SpiRegisters as sr, Status0, Status1};
use crate::fmt::Bytes; use crate::fmt::Bytes;
use crate::regs::{LedCntrl, LedFunc, LedPol, LedPolarity, SpiHeader}; use crate::regs::{LedCntrl, LedFunc, LedPol, LedPolarity, SpiHeader};
@ -446,6 +448,7 @@ pub struct Runner<'d, SPI, INT, RST> {
} }
impl<'d, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, SPI, INT, RST> { impl<'d, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, SPI, INT, RST> {
/// Run the driver.
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
pub async fn run(mut self) -> ! { pub async fn run(mut self) -> ! {
loop { loop {

View File

@ -39,6 +39,7 @@ enum Reg13Op {
/// ///
/// Clause 45 methodes are bases on <https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf> /// Clause 45 methodes are bases on <https://www.ieee802.org/3/efm/public/nov02/oam/pannell_oam_1_1102.pdf>
pub trait MdioBus { pub trait MdioBus {
/// Error type.
type Error; type Error;
/// Read, Clause 22 /// Read, Clause 22

View File

@ -2,6 +2,7 @@ use core::fmt::{Debug, Display};
use bitfield::{bitfield, bitfield_bitrange, bitfield_fields}; use bitfield::{bitfield, bitfield_bitrange, bitfield_fields};
#[allow(missing_docs)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]

View File

@ -1,5 +1,6 @@
#![no_std] #![no_std]
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
#![warn(missing_docs)]
// must go first! // must go first!
mod fmt; mod fmt;
@ -15,6 +16,9 @@ use embassy_sync::blocking_mutex::Mutex;
use embassy_sync::waitqueue::WakerRegistration; use embassy_sync::waitqueue::WakerRegistration;
use embassy_sync::zerocopy_channel; use embassy_sync::zerocopy_channel;
/// Channel state.
///
/// Holds a buffer of packets with size MTU, for both TX and RX.
pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> { pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
rx: [PacketBuf<MTU>; N_RX], rx: [PacketBuf<MTU>; N_RX],
tx: [PacketBuf<MTU>; N_TX], tx: [PacketBuf<MTU>; N_TX],
@ -24,6 +28,7 @@ pub struct State<const MTU: usize, const N_RX: usize, const N_TX: usize> {
impl<const MTU: usize, const N_RX: usize, const N_TX: usize> State<MTU, N_RX, N_TX> { impl<const MTU: usize, const N_RX: usize, const N_TX: usize> State<MTU, N_RX, N_TX> {
const NEW_PACKET: PacketBuf<MTU> = PacketBuf::new(); const NEW_PACKET: PacketBuf<MTU> = PacketBuf::new();
/// Create a new channel state.
pub const fn new() -> Self { pub const fn new() -> Self {
Self { Self {
rx: [Self::NEW_PACKET; N_RX], rx: [Self::NEW_PACKET; N_RX],
@ -39,33 +44,45 @@ struct StateInner<'d, const MTU: usize> {
shared: Mutex<NoopRawMutex, RefCell<Shared>>, shared: Mutex<NoopRawMutex, RefCell<Shared>>,
} }
/// State of the LinkState
struct Shared { struct Shared {
link_state: LinkState, link_state: LinkState,
waker: WakerRegistration, waker: WakerRegistration,
hardware_address: driver::HardwareAddress, hardware_address: driver::HardwareAddress,
} }
/// Channel runner.
///
/// Holds the shared state and the lower end of channels for inbound and outbound packets.
pub struct Runner<'d, const MTU: usize> { pub struct Runner<'d, const MTU: usize> {
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>, tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>, rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>, shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
} }
/// State runner.
///
/// Holds the shared state of the channel such as link state.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub struct StateRunner<'d> { pub struct StateRunner<'d> {
shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>, shared: &'d Mutex<NoopRawMutex, RefCell<Shared>>,
} }
/// RX runner.
///
/// Holds the lower end of the channel for passing inbound packets up the stack.
pub struct RxRunner<'d, const MTU: usize> { pub struct RxRunner<'d, const MTU: usize> {
rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>, rx_chan: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
} }
/// TX runner.
///
/// Holds the lower end of the channel for passing outbound packets down the stack.
pub struct TxRunner<'d, const MTU: usize> { pub struct TxRunner<'d, const MTU: usize> {
tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>, tx_chan: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
} }
impl<'d, const MTU: usize> Runner<'d, MTU> { impl<'d, const MTU: usize> Runner<'d, MTU> {
/// Split the runner into separate runners for controlling state, rx and tx.
pub fn split(self) -> (StateRunner<'d>, RxRunner<'d, MTU>, TxRunner<'d, MTU>) { pub fn split(self) -> (StateRunner<'d>, RxRunner<'d, MTU>, TxRunner<'d, MTU>) {
( (
StateRunner { shared: self.shared }, StateRunner { shared: self.shared },
@ -74,6 +91,7 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
) )
} }
/// Split the runner into separate runners for controlling state, rx and tx borrowing the underlying state.
pub fn borrow_split(&mut self) -> (StateRunner<'_>, RxRunner<'_, MTU>, TxRunner<'_, MTU>) { pub fn borrow_split(&mut self) -> (StateRunner<'_>, RxRunner<'_, MTU>, TxRunner<'_, MTU>) {
( (
StateRunner { shared: self.shared }, StateRunner { shared: self.shared },
@ -86,10 +104,12 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
) )
} }
/// Create a state runner sharing the state channel.
pub fn state_runner(&self) -> StateRunner<'d> { pub fn state_runner(&self) -> StateRunner<'d> {
StateRunner { shared: self.shared } StateRunner { shared: self.shared }
} }
/// Set the link state.
pub fn set_link_state(&mut self, state: LinkState) { pub fn set_link_state(&mut self, state: LinkState) {
self.shared.lock(|s| { self.shared.lock(|s| {
let s = &mut *s.borrow_mut(); let s = &mut *s.borrow_mut();
@ -98,6 +118,7 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
}); });
} }
/// Set the hardware address.
pub fn set_hardware_address(&mut self, address: driver::HardwareAddress) { pub fn set_hardware_address(&mut self, address: driver::HardwareAddress) {
self.shared.lock(|s| { self.shared.lock(|s| {
let s = &mut *s.borrow_mut(); let s = &mut *s.borrow_mut();
@ -106,16 +127,19 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
}); });
} }
/// Wait until there is space for more inbound packets and return a slice they can be copied into.
pub async fn rx_buf(&mut self) -> &mut [u8] { pub async fn rx_buf(&mut self) -> &mut [u8] {
let p = self.rx_chan.send().await; let p = self.rx_chan.send().await;
&mut p.buf &mut p.buf
} }
/// Check if there is space for more inbound packets right now.
pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> { pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
let p = self.rx_chan.try_send()?; let p = self.rx_chan.try_send()?;
Some(&mut p.buf) Some(&mut p.buf)
} }
/// Polling the inbound channel if there is space for packets.
pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> { pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
match self.rx_chan.poll_send(cx) { match self.rx_chan.poll_send(cx) {
Poll::Ready(p) => Poll::Ready(&mut p.buf), Poll::Ready(p) => Poll::Ready(&mut p.buf),
@ -123,22 +147,26 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
} }
} }
/// Mark packet of len bytes as pushed to the inbound channel.
pub fn rx_done(&mut self, len: usize) { pub fn rx_done(&mut self, len: usize) {
let p = self.rx_chan.try_send().unwrap(); let p = self.rx_chan.try_send().unwrap();
p.len = len; p.len = len;
self.rx_chan.send_done(); self.rx_chan.send_done();
} }
/// Wait until there is space for more outbound packets and return a slice they can be copied into.
pub async fn tx_buf(&mut self) -> &mut [u8] { pub async fn tx_buf(&mut self) -> &mut [u8] {
let p = self.tx_chan.receive().await; let p = self.tx_chan.receive().await;
&mut p.buf[..p.len] &mut p.buf[..p.len]
} }
/// Check if there is space for more outbound packets right now.
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> { pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
let p = self.tx_chan.try_receive()?; let p = self.tx_chan.try_receive()?;
Some(&mut p.buf[..p.len]) Some(&mut p.buf[..p.len])
} }
/// Polling the outbound channel if there is space for packets.
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> { pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
match self.tx_chan.poll_receive(cx) { match self.tx_chan.poll_receive(cx) {
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]), Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
@ -146,12 +174,14 @@ impl<'d, const MTU: usize> Runner<'d, MTU> {
} }
} }
/// Mark outbound packet as copied.
pub fn tx_done(&mut self) { pub fn tx_done(&mut self) {
self.tx_chan.receive_done(); self.tx_chan.receive_done();
} }
} }
impl<'d> StateRunner<'d> { impl<'d> StateRunner<'d> {
/// Set link state.
pub fn set_link_state(&self, state: LinkState) { pub fn set_link_state(&self, state: LinkState) {
self.shared.lock(|s| { self.shared.lock(|s| {
let s = &mut *s.borrow_mut(); let s = &mut *s.borrow_mut();
@ -160,6 +190,7 @@ impl<'d> StateRunner<'d> {
}); });
} }
/// Set the hardware address.
pub fn set_hardware_address(&self, address: driver::HardwareAddress) { pub fn set_hardware_address(&self, address: driver::HardwareAddress) {
self.shared.lock(|s| { self.shared.lock(|s| {
let s = &mut *s.borrow_mut(); let s = &mut *s.borrow_mut();
@ -170,16 +201,19 @@ impl<'d> StateRunner<'d> {
} }
impl<'d, const MTU: usize> RxRunner<'d, MTU> { impl<'d, const MTU: usize> RxRunner<'d, MTU> {
/// Wait until there is space for more inbound packets and return a slice they can be copied into.
pub async fn rx_buf(&mut self) -> &mut [u8] { pub async fn rx_buf(&mut self) -> &mut [u8] {
let p = self.rx_chan.send().await; let p = self.rx_chan.send().await;
&mut p.buf &mut p.buf
} }
/// Check if there is space for more inbound packets right now.
pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> { pub fn try_rx_buf(&mut self) -> Option<&mut [u8]> {
let p = self.rx_chan.try_send()?; let p = self.rx_chan.try_send()?;
Some(&mut p.buf) Some(&mut p.buf)
} }
/// Polling the inbound channel if there is space for packets.
pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> { pub fn poll_rx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
match self.rx_chan.poll_send(cx) { match self.rx_chan.poll_send(cx) {
Poll::Ready(p) => Poll::Ready(&mut p.buf), Poll::Ready(p) => Poll::Ready(&mut p.buf),
@ -187,6 +221,7 @@ impl<'d, const MTU: usize> RxRunner<'d, MTU> {
} }
} }
/// Mark packet of len bytes as pushed to the inbound channel.
pub fn rx_done(&mut self, len: usize) { pub fn rx_done(&mut self, len: usize) {
let p = self.rx_chan.try_send().unwrap(); let p = self.rx_chan.try_send().unwrap();
p.len = len; p.len = len;
@ -195,16 +230,19 @@ impl<'d, const MTU: usize> RxRunner<'d, MTU> {
} }
impl<'d, const MTU: usize> TxRunner<'d, MTU> { impl<'d, const MTU: usize> TxRunner<'d, MTU> {
/// Wait until there is space for more outbound packets and return a slice they can be copied into.
pub async fn tx_buf(&mut self) -> &mut [u8] { pub async fn tx_buf(&mut self) -> &mut [u8] {
let p = self.tx_chan.receive().await; let p = self.tx_chan.receive().await;
&mut p.buf[..p.len] &mut p.buf[..p.len]
} }
/// Check if there is space for more outbound packets right now.
pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> { pub fn try_tx_buf(&mut self) -> Option<&mut [u8]> {
let p = self.tx_chan.try_receive()?; let p = self.tx_chan.try_receive()?;
Some(&mut p.buf[..p.len]) Some(&mut p.buf[..p.len])
} }
/// Polling the outbound channel if there is space for packets.
pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> { pub fn poll_tx_buf(&mut self, cx: &mut Context) -> Poll<&mut [u8]> {
match self.tx_chan.poll_receive(cx) { match self.tx_chan.poll_receive(cx) {
Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]), Poll::Ready(p) => Poll::Ready(&mut p.buf[..p.len]),
@ -212,11 +250,18 @@ impl<'d, const MTU: usize> TxRunner<'d, MTU> {
} }
} }
/// Mark outbound packet as copied.
pub fn tx_done(&mut self) { pub fn tx_done(&mut self) {
self.tx_chan.receive_done(); self.tx_chan.receive_done();
} }
} }
/// Create a channel.
///
/// Returns a pair of handles for interfacing with the peripheral and the networking stack.
///
/// The runner is interfacing with the peripheral at the lower part of the stack.
/// The device is interfacing with the networking stack on the layer above.
pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>( pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
state: &'d mut State<MTU, N_RX, N_TX>, state: &'d mut State<MTU, N_RX, N_TX>,
hardware_address: driver::HardwareAddress, hardware_address: driver::HardwareAddress,
@ -257,17 +302,22 @@ pub fn new<'d, const MTU: usize, const N_RX: usize, const N_TX: usize>(
) )
} }
/// Represents a packet of size MTU.
pub struct PacketBuf<const MTU: usize> { pub struct PacketBuf<const MTU: usize> {
len: usize, len: usize,
buf: [u8; MTU], buf: [u8; MTU],
} }
impl<const MTU: usize> PacketBuf<MTU> { impl<const MTU: usize> PacketBuf<MTU> {
/// Create a new packet buffer.
pub const fn new() -> Self { pub const fn new() -> Self {
Self { len: 0, buf: [0; MTU] } Self { len: 0, buf: [0; MTU] }
} }
} }
/// Channel device.
///
/// Holds the shared state and upper end of channels for inbound and outbound packets.
pub struct Device<'d, const MTU: usize> { pub struct Device<'d, const MTU: usize> {
rx: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>, rx: zerocopy_channel::Receiver<'d, NoopRawMutex, PacketBuf<MTU>>,
tx: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>, tx: zerocopy_channel::Sender<'d, NoopRawMutex, PacketBuf<MTU>>,
@ -314,6 +364,9 @@ impl<'d, const MTU: usize> embassy_net_driver::Driver for Device<'d, MTU> {
} }
} }
/// A rx token.
///
/// Holds inbound receive channel and interfaces with embassy-net-driver.
pub struct RxToken<'a, const MTU: usize> { pub struct RxToken<'a, const MTU: usize> {
rx: zerocopy_channel::Receiver<'a, NoopRawMutex, PacketBuf<MTU>>, rx: zerocopy_channel::Receiver<'a, NoopRawMutex, PacketBuf<MTU>>,
} }
@ -331,6 +384,9 @@ impl<'a, const MTU: usize> embassy_net_driver::RxToken for RxToken<'a, MTU> {
} }
} }
/// A tx token.
///
/// Holds outbound transmit channel and interfaces with embassy-net-driver.
pub struct TxToken<'a, const MTU: usize> { pub struct TxToken<'a, const MTU: usize> {
tx: zerocopy_channel::Sender<'a, NoopRawMutex, PacketBuf<MTU>>, tx: zerocopy_channel::Sender<'a, NoopRawMutex, PacketBuf<MTU>>,
} }

View File

@ -2,6 +2,10 @@
name = "embassy-net-esp-hosted" name = "embassy-net-esp-hosted"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
description = "embassy-net driver for ESP-Hosted"
keywords = ["embedded", "esp-hosted", "embassy-net", "embedded-hal-async", "wifi", "async"]
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
license = "MIT OR Apache-2.0"
[dependencies] [dependencies]
defmt = { version = "0.3", optional = true } defmt = { version = "0.3", optional = true }
@ -15,8 +19,7 @@ embassy-net-driver-channel = { version = "0.2.0", path = "../embassy-net-driver-
embedded-hal = { version = "1.0.0-rc.3" } embedded-hal = { version = "1.0.0-rc.3" }
embedded-hal-async = { version = "=1.0.0-rc.3" } embedded-hal-async = { version = "=1.0.0-rc.3" }
noproto = { git="https://github.com/embassy-rs/noproto", rev = "f5e6d1f325b6ad4e344f60452b09576e24671f62", default-features = false, features = ["derive"] } noproto = "0.1.0"
#noproto = { version = "0.1", path = "/home/dirbaio/noproto", default-features = false, features = ["derive"] }
heapless = "0.8" heapless = "0.8"
[package.metadata.embassy_docs] [package.metadata.embassy_docs]

View File

@ -0,0 +1,27 @@
# ESP-Hosted `embassy-net` integration
[`embassy-net`](https://crates.io/crates/embassy-net) integration for Espressif SoCs running the the ESP-Hosted stack.
See [`examples`](https://github.com/embassy-rs/embassy/tree/main/examples/nrf52840) directory for usage examples with the nRF52840.
## Supported chips
- W5500
- W5100S
## Interoperability
This crate can run on any executor.
It supports any SPI driver implementing [`embedded-hal-async`](https://crates.io/crates/embedded-hal-async).
## License
This work is licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.

View File

@ -5,38 +5,54 @@ use heapless::String;
use crate::ioctl::Shared; use crate::ioctl::Shared;
use crate::proto::{self, CtrlMsg}; use crate::proto::{self, CtrlMsg};
/// Errors reported by control.
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error { pub enum Error {
/// The operation failed with the given error code.
Failed(u32), Failed(u32),
/// The operation timed out.
Timeout, Timeout,
/// Internal error.
Internal, Internal,
} }
/// Handle for managing the network and WiFI state.
pub struct Control<'a> { pub struct Control<'a> {
state_ch: ch::StateRunner<'a>, state_ch: ch::StateRunner<'a>,
shared: &'a Shared, shared: &'a Shared,
} }
/// WiFi mode.
#[allow(unused)] #[allow(unused)]
#[derive(Copy, Clone, PartialEq, Eq, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
enum WifiMode { enum WifiMode {
/// No mode.
None = 0, None = 0,
/// Client station.
Sta = 1, Sta = 1,
/// Access point mode.
Ap = 2, Ap = 2,
/// Repeater mode.
ApSta = 3, ApSta = 3,
} }
pub use proto::CtrlWifiSecProt as Security; pub use proto::CtrlWifiSecProt as Security;
/// WiFi status.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Status { pub struct Status {
/// Service Set Identifier.
pub ssid: String<32>, pub ssid: String<32>,
/// Basic Service Set Identifier.
pub bssid: [u8; 6], pub bssid: [u8; 6],
/// Received Signal Strength Indicator.
pub rssi: i32, pub rssi: i32,
/// WiFi channel.
pub channel: u32, pub channel: u32,
/// Security mode.
pub security: Security, pub security: Security,
} }
@ -65,6 +81,7 @@ impl<'a> Control<'a> {
Self { state_ch, shared } Self { state_ch, shared }
} }
/// Initialize device.
pub async fn init(&mut self) -> Result<(), Error> { pub async fn init(&mut self) -> Result<(), Error> {
debug!("wait for init event..."); debug!("wait for init event...");
self.shared.init_wait().await; self.shared.init_wait().await;
@ -82,6 +99,7 @@ impl<'a> Control<'a> {
Ok(()) Ok(())
} }
/// Get the current status.
pub async fn get_status(&mut self) -> Result<Status, Error> { pub async fn get_status(&mut self) -> Result<Status, Error> {
let req = proto::CtrlMsgReqGetApConfig {}; let req = proto::CtrlMsgReqGetApConfig {};
ioctl!(self, ReqGetApConfig, RespGetApConfig, req, resp); ioctl!(self, ReqGetApConfig, RespGetApConfig, req, resp);
@ -95,6 +113,7 @@ impl<'a> Control<'a> {
}) })
} }
/// Connect to the network identified by ssid using the provided password.
pub async fn connect(&mut self, ssid: &str, password: &str) -> Result<(), Error> { pub async fn connect(&mut self, ssid: &str, password: &str) -> Result<(), Error> {
let req = proto::CtrlMsgReqConnectAp { let req = proto::CtrlMsgReqConnectAp {
ssid: unwrap!(String::try_from(ssid)), ssid: unwrap!(String::try_from(ssid)),
@ -108,6 +127,7 @@ impl<'a> Control<'a> {
Ok(()) Ok(())
} }
/// Disconnect from any currently connected network.
pub async fn disconnect(&mut self) -> Result<(), Error> { pub async fn disconnect(&mut self) -> Result<(), Error> {
let req = proto::CtrlMsgReqGetStatus {}; let req = proto::CtrlMsgReqGetStatus {};
ioctl!(self, ReqDisconnectAp, RespDisconnectAp, req, resp); ioctl!(self, ReqDisconnectAp, RespDisconnectAp, req, resp);

View File

@ -1,4 +1,6 @@
#![no_std] #![no_std]
#![doc = include_str!("../README.md")]
#![warn(missing_docs)]
use embassy_futures::select::{select4, Either4}; use embassy_futures::select::{select4, Either4};
use embassy_net_driver_channel as ch; use embassy_net_driver_channel as ch;
@ -97,12 +99,14 @@ enum InterfaceType {
const MAX_SPI_BUFFER_SIZE: usize = 1600; const MAX_SPI_BUFFER_SIZE: usize = 1600;
const HEARTBEAT_MAX_GAP: Duration = Duration::from_secs(20); const HEARTBEAT_MAX_GAP: Duration = Duration::from_secs(20);
/// State for the esp-hosted driver.
pub struct State { pub struct State {
shared: Shared, shared: Shared,
ch: ch::State<MTU, 4, 4>, ch: ch::State<MTU, 4, 4>,
} }
impl State { impl State {
/// Create a new state.
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
shared: Shared::new(), shared: Shared::new(),
@ -111,8 +115,13 @@ impl State {
} }
} }
/// Type alias for network driver.
pub type NetDriver<'a> = ch::Device<'a, MTU>; pub type NetDriver<'a> = ch::Device<'a, MTU>;
/// Create a new esp-hosted driver using the provided state, SPI peripheral and pins.
///
/// Returns a device handle for interfacing with embassy-net, a control handle for
/// interacting with the driver, and a runner for communicating with the WiFi device.
pub async fn new<'a, SPI, IN, OUT>( pub async fn new<'a, SPI, IN, OUT>(
state: &'a mut State, state: &'a mut State,
spi: SPI, spi: SPI,
@ -144,6 +153,7 @@ where
(device, Control::new(state_ch, &state.shared), runner) (device, Control::new(state_ch, &state.shared), runner)
} }
/// Runner for communicating with the WiFi device.
pub struct Runner<'a, SPI, IN, OUT> { pub struct Runner<'a, SPI, IN, OUT> {
ch: ch::Runner<'a, MTU>, ch: ch::Runner<'a, MTU>,
state_ch: ch::StateRunner<'a>, state_ch: ch::StateRunner<'a>,
@ -166,6 +176,7 @@ where
{ {
async fn init(&mut self) {} async fn init(&mut self) {}
/// Run the packet processing.
pub async fn run(mut self) -> ! { pub async fn run(mut self) -> ! {
debug!("resetting..."); debug!("resetting...");
self.reset.set_low().unwrap(); self.reset.set_low().unwrap();

View File

@ -4,7 +4,7 @@ use heapless::{String, Vec};
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ScanResult { pub(crate) struct ScanResult {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub ssid: String<32>, pub ssid: String<32>,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -19,7 +19,7 @@ pub struct ScanResult {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ConnectedStaList { pub(crate) struct ConnectedStaList {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub mac: String<32>, pub mac: String<32>,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -29,14 +29,14 @@ pub struct ConnectedStaList {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqGetMacAddress { pub(crate) struct CtrlMsgReqGetMacAddress {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub mode: u32, pub mode: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespGetMacAddress { pub(crate) struct CtrlMsgRespGetMacAddress {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub mac: String<32>, pub mac: String<32>,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -45,11 +45,11 @@ pub struct CtrlMsgRespGetMacAddress {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqGetMode {} pub(crate) struct CtrlMsgReqGetMode {}
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespGetMode { pub(crate) struct CtrlMsgRespGetMode {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub mode: u32, pub mode: u32,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -58,32 +58,32 @@ pub struct CtrlMsgRespGetMode {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqSetMode { pub(crate) struct CtrlMsgReqSetMode {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub mode: u32, pub mode: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespSetMode { pub(crate) struct CtrlMsgRespSetMode {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqGetStatus {} pub(crate) struct CtrlMsgReqGetStatus {}
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespGetStatus { pub(crate) struct CtrlMsgRespGetStatus {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqSetMacAddress { pub(crate) struct CtrlMsgReqSetMacAddress {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub mac: String<32>, pub mac: String<32>,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -92,18 +92,18 @@ pub struct CtrlMsgReqSetMacAddress {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespSetMacAddress { pub(crate) struct CtrlMsgRespSetMacAddress {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqGetApConfig {} pub(crate) struct CtrlMsgReqGetApConfig {}
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespGetApConfig { pub(crate) struct CtrlMsgRespGetApConfig {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub ssid: String<32>, pub ssid: String<32>,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -120,7 +120,7 @@ pub struct CtrlMsgRespGetApConfig {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqConnectAp { pub(crate) struct CtrlMsgReqConnectAp {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub ssid: String<32>, pub ssid: String<32>,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -135,7 +135,7 @@ pub struct CtrlMsgReqConnectAp {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespConnectAp { pub(crate) struct CtrlMsgRespConnectAp {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -144,11 +144,11 @@ pub struct CtrlMsgRespConnectAp {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqGetSoftApConfig {} pub(crate) struct CtrlMsgReqGetSoftApConfig {}
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespGetSoftApConfig { pub(crate) struct CtrlMsgRespGetSoftApConfig {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub ssid: String<32>, pub ssid: String<32>,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -169,7 +169,7 @@ pub struct CtrlMsgRespGetSoftApConfig {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqStartSoftAp { pub(crate) struct CtrlMsgReqStartSoftAp {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub ssid: String<32>, pub ssid: String<32>,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -188,7 +188,7 @@ pub struct CtrlMsgReqStartSoftAp {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespStartSoftAp { pub(crate) struct CtrlMsgRespStartSoftAp {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -197,11 +197,11 @@ pub struct CtrlMsgRespStartSoftAp {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqScanResult {} pub(crate) struct CtrlMsgReqScanResult {}
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespScanResult { pub(crate) struct CtrlMsgRespScanResult {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub count: u32, pub count: u32,
#[noproto(repeated, tag = "2")] #[noproto(repeated, tag = "2")]
@ -212,11 +212,11 @@ pub struct CtrlMsgRespScanResult {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqSoftApConnectedSta {} pub(crate) struct CtrlMsgReqSoftApConnectedSta {}
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespSoftApConnectedSta { pub(crate) struct CtrlMsgRespSoftApConnectedSta {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub num: u32, pub num: u32,
#[noproto(repeated, tag = "2")] #[noproto(repeated, tag = "2")]
@ -227,43 +227,43 @@ pub struct CtrlMsgRespSoftApConnectedSta {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqOtaBegin {} pub(crate) struct CtrlMsgReqOtaBegin {}
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespOtaBegin { pub(crate) struct CtrlMsgRespOtaBegin {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqOtaWrite { pub(crate) struct CtrlMsgReqOtaWrite {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub ota_data: Vec<u8, 1024>, pub ota_data: Vec<u8, 1024>,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespOtaWrite { pub(crate) struct CtrlMsgRespOtaWrite {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqOtaEnd {} pub(crate) struct CtrlMsgReqOtaEnd {}
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespOtaEnd { pub(crate) struct CtrlMsgRespOtaEnd {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqVendorIeData { pub(crate) struct CtrlMsgReqVendorIeData {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub element_id: u32, pub element_id: u32,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -278,7 +278,7 @@ pub struct CtrlMsgReqVendorIeData {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqSetSoftApVendorSpecificIe { pub(crate) struct CtrlMsgReqSetSoftApVendorSpecificIe {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub enable: bool, pub enable: bool,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -291,32 +291,32 @@ pub struct CtrlMsgReqSetSoftApVendorSpecificIe {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespSetSoftApVendorSpecificIe { pub(crate) struct CtrlMsgRespSetSoftApVendorSpecificIe {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqSetWifiMaxTxPower { pub(crate) struct CtrlMsgReqSetWifiMaxTxPower {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub wifi_max_tx_power: u32, pub wifi_max_tx_power: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespSetWifiMaxTxPower { pub(crate) struct CtrlMsgRespSetWifiMaxTxPower {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqGetWifiCurrTxPower {} pub(crate) struct CtrlMsgReqGetWifiCurrTxPower {}
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespGetWifiCurrTxPower { pub(crate) struct CtrlMsgRespGetWifiCurrTxPower {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub wifi_curr_tx_power: u32, pub wifi_curr_tx_power: u32,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -325,7 +325,7 @@ pub struct CtrlMsgRespGetWifiCurrTxPower {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgReqConfigHeartbeat { pub(crate) struct CtrlMsgReqConfigHeartbeat {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub enable: bool, pub enable: bool,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -334,7 +334,7 @@ pub struct CtrlMsgReqConfigHeartbeat {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgRespConfigHeartbeat { pub(crate) struct CtrlMsgRespConfigHeartbeat {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
} }
@ -342,28 +342,28 @@ pub struct CtrlMsgRespConfigHeartbeat {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgEventEspInit { pub(crate) struct CtrlMsgEventEspInit {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub init_data: Vec<u8, 64>, pub init_data: Vec<u8, 64>,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgEventHeartbeat { pub(crate) struct CtrlMsgEventHeartbeat {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub hb_num: u32, pub hb_num: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgEventStationDisconnectFromAp { pub(crate) struct CtrlMsgEventStationDisconnectFromAp {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
} }
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsgEventStationDisconnectFromEspSoftAp { pub(crate) struct CtrlMsgEventStationDisconnectFromEspSoftAp {
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub resp: u32, pub resp: u32,
#[noproto(tag = "2")] #[noproto(tag = "2")]
@ -372,7 +372,7 @@ pub struct CtrlMsgEventStationDisconnectFromEspSoftAp {
#[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)] #[derive(Debug, Default, Clone, Eq, PartialEq, noproto::Message)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct CtrlMsg { pub(crate) struct CtrlMsg {
/// msg_type could be req, resp or Event /// msg_type could be req, resp or Event
#[noproto(tag = "1")] #[noproto(tag = "1")]
pub msg_type: CtrlMsgType, pub msg_type: CtrlMsgType,
@ -390,7 +390,7 @@ pub struct CtrlMsg {
/// union of all msg ids /// union of all msg ids
#[derive(Debug, Clone, Eq, PartialEq, noproto::Oneof)] #[derive(Debug, Clone, Eq, PartialEq, noproto::Oneof)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CtrlMsgPayload { pub(crate) enum CtrlMsgPayload {
/// * Requests * /// * Requests *
#[noproto(tag = "101")] #[noproto(tag = "101")]
ReqGetMacAddress(CtrlMsgReqGetMacAddress), ReqGetMacAddress(CtrlMsgReqGetMacAddress),
@ -492,7 +492,7 @@ pub enum CtrlMsgPayload {
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
#[repr(u32)] #[repr(u32)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CtrlVendorIeType { pub(crate) enum CtrlVendorIeType {
#[default] #[default]
Beacon = 0, Beacon = 0,
ProbeReq = 1, ProbeReq = 1,
@ -504,7 +504,7 @@ pub enum CtrlVendorIeType {
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
#[repr(u32)] #[repr(u32)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CtrlVendorIeid { pub(crate) enum CtrlVendorIeid {
#[default] #[default]
Id0 = 0, Id0 = 0,
Id1 = 1, Id1 = 1,
@ -513,7 +513,7 @@ pub enum CtrlVendorIeid {
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
#[repr(u32)] #[repr(u32)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CtrlWifiMode { pub(crate) enum CtrlWifiMode {
#[default] #[default]
None = 0, None = 0,
Sta = 1, Sta = 1,
@ -524,7 +524,7 @@ pub enum CtrlWifiMode {
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
#[repr(u32)] #[repr(u32)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CtrlWifiBw { pub(crate) enum CtrlWifiBw {
#[default] #[default]
BwInvalid = 0, BwInvalid = 0,
Ht20 = 1, Ht20 = 1,
@ -534,13 +534,15 @@ pub enum CtrlWifiBw {
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
#[repr(u32)] #[repr(u32)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CtrlWifiPowerSave { pub(crate) enum CtrlWifiPowerSave {
#[default] #[default]
PsInvalid = 0, PsInvalid = 0,
MinModem = 1, MinModem = 1,
MaxModem = 2, MaxModem = 2,
} }
/// Wifi Security Settings
#[allow(missing_docs)]
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
#[repr(u32)] #[repr(u32)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@ -560,7 +562,7 @@ pub enum CtrlWifiSecProt {
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
#[repr(u32)] #[repr(u32)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CtrlStatus { pub(crate) enum CtrlStatus {
#[default] #[default]
Connected = 0, Connected = 0,
NotConnected = 1, NotConnected = 1,
@ -573,7 +575,7 @@ pub enum CtrlStatus {
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
#[repr(u32)] #[repr(u32)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CtrlMsgType { pub(crate) enum CtrlMsgType {
#[default] #[default]
MsgTypeInvalid = 0, MsgTypeInvalid = 0,
Req = 1, Req = 1,
@ -585,7 +587,7 @@ pub enum CtrlMsgType {
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)] #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash, PartialOrd, Ord, noproto::Enumeration)]
#[repr(u32)] #[repr(u32)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum CtrlMsgId { pub(crate) enum CtrlMsgId {
#[default] #[default]
MsgIdInvalid = 0, MsgIdInvalid = 0,
/// * Request Msgs * /// * Request Msgs *

View File

@ -6,6 +6,7 @@ keywords = ["embedded", "tuntap", "embassy-net", "embedded-hal-async", "ethernet
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"] categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
edition = "2021" edition = "2021"
repository = "https://github.com/embassy-rs/embassy"
[dependencies] [dependencies]
embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
@ -16,4 +17,4 @@ libc = "0.2.101"
[package.metadata.embassy_docs] [package.metadata.embassy_docs]
src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-tuntap-v$VERSION/embassy-net-tuntap/src/" src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-tuntap-v$VERSION/embassy-net-tuntap/src/"
src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-tuntap/src/" src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-tuntap/src/"
target = "thumbv7em-none-eabi" target = "thumbv7em-none-eabi"

View File

@ -1,3 +1,5 @@
#![warn(missing_docs)]
#![doc = include_str!("../README.md")]
use std::io; use std::io;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
@ -7,12 +9,19 @@ use async_io::Async;
use embassy_net_driver::{self, Capabilities, Driver, HardwareAddress, LinkState}; use embassy_net_driver::{self, Capabilities, Driver, HardwareAddress, LinkState};
use log::*; use log::*;
/// Get the MTU of the given interface.
pub const SIOCGIFMTU: libc::c_ulong = 0x8921; pub const SIOCGIFMTU: libc::c_ulong = 0x8921;
/// Get the index of the given interface.
pub const _SIOCGIFINDEX: libc::c_ulong = 0x8933; pub const _SIOCGIFINDEX: libc::c_ulong = 0x8933;
/// Capture all packages.
pub const _ETH_P_ALL: libc::c_short = 0x0003; pub const _ETH_P_ALL: libc::c_short = 0x0003;
/// Set the interface flags.
pub const TUNSETIFF: libc::c_ulong = 0x400454CA; pub const TUNSETIFF: libc::c_ulong = 0x400454CA;
/// TUN device.
pub const _IFF_TUN: libc::c_int = 0x0001; pub const _IFF_TUN: libc::c_int = 0x0001;
/// TAP device.
pub const IFF_TAP: libc::c_int = 0x0002; pub const IFF_TAP: libc::c_int = 0x0002;
/// No packet information.
pub const IFF_NO_PI: libc::c_int = 0x1000; pub const IFF_NO_PI: libc::c_int = 0x1000;
const ETHERNET_HEADER_LEN: usize = 14; const ETHERNET_HEADER_LEN: usize = 14;
@ -47,6 +56,7 @@ fn ifreq_ioctl(lower: libc::c_int, ifreq: &mut ifreq, cmd: libc::c_ulong) -> io:
Ok(ifreq.ifr_data) Ok(ifreq.ifr_data)
} }
/// A TUN/TAP device.
#[derive(Debug)] #[derive(Debug)]
pub struct TunTap { pub struct TunTap {
fd: libc::c_int, fd: libc::c_int,
@ -60,6 +70,7 @@ impl AsRawFd for TunTap {
} }
impl TunTap { impl TunTap {
/// Create a new TUN/TAP device.
pub fn new(name: &str) -> io::Result<TunTap> { pub fn new(name: &str) -> io::Result<TunTap> {
unsafe { unsafe {
let fd = libc::open( let fd = libc::open(
@ -126,11 +137,13 @@ impl io::Write for TunTap {
} }
} }
/// A TUN/TAP device, wrapped in an async interface.
pub struct TunTapDevice { pub struct TunTapDevice {
device: Async<TunTap>, device: Async<TunTap>,
} }
impl TunTapDevice { impl TunTapDevice {
/// Create a new TUN/TAP device.
pub fn new(name: &str) -> io::Result<TunTapDevice> { pub fn new(name: &str) -> io::Result<TunTapDevice> {
Ok(Self { Ok(Self {
device: Async::new(TunTap::new(name)?)?, device: Async::new(TunTap::new(name)?)?,

View File

@ -6,6 +6,7 @@ keywords = ["embedded", "wiznet", "embassy-net", "embedded-hal-async", "ethernet
categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"] categories = ["embedded", "hardware-support", "no-std", "network-programming", "async"]
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
edition = "2021" edition = "2021"
repository = "https://github.com/embassy-rs/embassy"
[dependencies] [dependencies]
embedded-hal = { version = "1.0.0-rc.3" } embedded-hal = { version = "1.0.0-rc.3" }

View File

@ -1,3 +1,4 @@
//! Wiznet W5100s and W5500 family driver.
mod w5500; mod w5500;
pub use w5500::W5500; pub use w5500::W5500;
mod w5100s; mod w5100s;
@ -45,4 +46,5 @@ pub(crate) mod sealed {
} }
} }
/// Trait for Wiznet chips.
pub trait Chip: sealed::Chip {} pub trait Chip: sealed::Chip {}

View File

@ -4,6 +4,7 @@ const SOCKET_BASE: u16 = 0x400;
const TX_BASE: u16 = 0x4000; const TX_BASE: u16 = 0x4000;
const RX_BASE: u16 = 0x6000; const RX_BASE: u16 = 0x6000;
/// Wizard W5100S chip.
pub enum W5100S {} pub enum W5100S {}
impl super::Chip for W5100S {} impl super::Chip for W5100S {}

View File

@ -8,6 +8,7 @@ pub enum RegisterBlock {
RxBuf = 0x03, RxBuf = 0x03,
} }
/// Wiznet W5500 chip.
pub enum W5500 {} pub enum W5500 {}
impl super::Chip for W5500 {} impl super::Chip for W5500 {}

View File

@ -1,6 +1,7 @@
#![no_std] #![no_std]
#![allow(async_fn_in_trait)] #![allow(async_fn_in_trait)]
#![doc = include_str!("../README.md")] #![doc = include_str!("../README.md")]
#![warn(missing_docs)]
pub mod chip; pub mod chip;
mod device; mod device;
@ -47,6 +48,7 @@ pub struct Runner<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> {
/// You must call this in a background task for the driver to operate. /// You must call this in a background task for the driver to operate.
impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> { impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> {
/// Run the driver.
pub async fn run(mut self) -> ! { pub async fn run(mut self) -> ! {
let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
let mut tick = Ticker::every(Duration::from_millis(500)); let mut tick = Ticker::every(Duration::from_millis(500));

View File

@ -56,7 +56,6 @@ cortex-m = "0.7.6"
futures = { version = "0.3.17", default-features = false, features = ["async-await"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
rand_core = "0.6.3" rand_core = "0.6.3"
sdio-host = "0.5.0" sdio-host = "0.5.0"
embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
critical-section = "1.1" critical-section = "1.1"
stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2234f380f51d16d0398b8e547088b33ea623cc7c" } stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2234f380f51d16d0398b8e547088b33ea623cc7c" }
vcell = "0.1.3" vcell = "0.1.3"

View File

@ -130,7 +130,7 @@ impl RtcTimeProvider {
let weekday = day_of_week_from_u8(dr.wdu()).map_err(RtcError::InvalidDateTime)?; let weekday = day_of_week_from_u8(dr.wdu()).map_err(RtcError::InvalidDateTime)?;
let day = bcd2_to_byte((dr.dt(), dr.du())); let day = bcd2_to_byte((dr.dt(), dr.du()));
let month = bcd2_to_byte((dr.mt() as u8, dr.mu())); let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 2000_u16;
DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
}) })
@ -261,7 +261,7 @@ impl Rtc {
let (dt, du) = byte_to_bcd2(t.day() as u8); let (dt, du) = byte_to_bcd2(t.day() as u8);
let (mt, mu) = byte_to_bcd2(t.month() as u8); let (mt, mu) = byte_to_bcd2(t.month() as u8);
let yr = t.year() as u16; let yr = t.year() as u16;
let yr_offset = (yr - 1970_u16) as u8; let yr_offset = (yr - 2000_u16) as u8;
let (yt, yu) = byte_to_bcd2(yr_offset); let (yt, yu) = byte_to_bcd2(yr_offset);
use crate::pac::rtc::vals::Ampm; use crate::pac::rtc::vals::Ampm;

View File

@ -1538,53 +1538,3 @@ foreach_peripheral!(
impl Instance for peripherals::$inst {} impl Instance for peripherals::$inst {}
}; };
); );
#[cfg(feature = "embedded-sdmmc")]
mod sdmmc_rs {
use embedded_sdmmc::{Block, BlockCount, BlockDevice, BlockIdx};
use super::*;
impl<'d, T: Instance, Dma: SdmmcDma<T>> BlockDevice for Sdmmc<'d, T, Dma> {
type Error = Error;
async fn read(
&mut self,
blocks: &mut [Block],
start_block_idx: BlockIdx,
_reason: &str,
) -> Result<(), Self::Error> {
let mut address = start_block_idx.0;
for block in blocks.iter_mut() {
let block: &mut [u8; 512] = &mut block.contents;
// NOTE(unsafe) Block uses align(4)
let block = unsafe { &mut *(block as *mut _ as *mut DataBlock) };
self.read_block(address, block).await?;
address += 1;
}
Ok(())
}
async fn write(&mut self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> {
let mut address = start_block_idx.0;
for block in blocks.iter() {
let block: &[u8; 512] = &block.contents;
// NOTE(unsafe) DataBlock uses align 4
let block = unsafe { &*(block as *const _ as *const DataBlock) };
self.write_block(address, block).await?;
address += 1;
}
Ok(())
}
fn num_blocks(&self) -> Result<BlockCount, Self::Error> {
let card = self.card()?;
let count = card.csd.block_count();
Ok(BlockCount(count))
}
}
}

View File

@ -111,6 +111,20 @@ where
poll_fn(move |cx| self.poll_wait(cx)) poll_fn(move |cx| self.poll_wait(cx))
} }
/// non-blocking method to try and take the signal value.
pub fn try_take(&self) -> Option<T> {
self.state.lock(|cell| {
let state = cell.replace(State::None);
match state {
State::Signaled(res) => Some(res),
state => {
cell.set(state);
None
}
}
})
}
/// non-blocking method to check whether this signal has been signaled. /// non-blocking method to check whether this signal has been signaled.
pub fn signaled(&self) -> bool { pub fn signaled(&self) -> bool {
self.state.lock(|cell| { self.state.lock(|cell| {

View File

@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0"
[dependencies] [dependencies]
# Change stm32f429zi to your chip name, if necessary. # Change stm32f429zi to your chip name, if necessary.
embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "embedded-sdmmc", "chrono"] } embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = [ "defmt", "stm32f429zi", "unstable-pac", "memory-x", "time-driver-any", "exti", "chrono"] }
embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] }
embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } embassy-executor = { version = "0.4.0", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } embassy-time = { version = "0.2", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }