From e4ad1aa542ad28bed23532b3a0bee0d062454516 Mon Sep 17 00:00:00 2001 From: Alex Ferro Date: Sun, 16 Jul 2023 19:59:35 -0600 Subject: [PATCH 1/9] Embassy-rp I2C: Fix 1664 Change embassy-rp i2c.rs impl of embedded_hal_async::i2c::I2c::transaction to only do the call to setup() for address once per call to transactions. Calling setup multiple times results in I2C transactions being skipped on the bus, even across calls to transaction() or devices. --- embassy-rp/src/i2c.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs index 791c64554..9b85b2345 100644 --- a/embassy-rp/src/i2c.rs +++ b/embassy-rp/src/i2c.rs @@ -716,6 +716,9 @@ mod nightly { async fn transaction(&mut self, address: A, operations: &mut [Operation<'_>]) -> Result<(), Self::Error> { let addr: u16 = address.into(); + if operations.len() > 0 { + Self::setup(addr)?; + } let mut iterator = operations.iter_mut(); while let Some(op) = iterator.next() { @@ -723,11 +726,9 @@ mod nightly { match op { Operation::Read(buffer) => { - Self::setup(addr)?; self.read_async_internal(buffer, false, last).await?; } Operation::Write(buffer) => { - Self::setup(addr)?; self.write_async_internal(buffer.into_iter().cloned(), last).await?; } } From 55ac480cb000b466571feee712d4ff075a1c64f8 Mon Sep 17 00:00:00 2001 From: xoviat Date: Mon, 17 Jul 2023 16:24:09 -0500 Subject: [PATCH 2/9] stm32/eth: fix cfg(not(time)) --- embassy-stm32/src/eth/generic_smi.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/embassy-stm32/src/eth/generic_smi.rs b/embassy-stm32/src/eth/generic_smi.rs index 90631b175..2ed46ca2c 100644 --- a/embassy-stm32/src/eth/generic_smi.rs +++ b/embassy-stm32/src/eth/generic_smi.rs @@ -45,20 +45,19 @@ use self::phy_consts::*; pub struct GenericSMI { #[cfg(feature = "time")] poll_interval: Duration, + #[cfg(not(feature = "time"))] + _private: (), } impl GenericSMI { - #[cfg(feature = "time")] pub fn new() -> Self { Self { + #[cfg(feature = "time")] poll_interval: Duration::from_millis(500), + #[cfg(not(feature = "time"))] + _private: (), } } - - #[cfg(not(feature = "time"))] - pub fn new() -> Self { - Self {} - } } unsafe impl PHY for GenericSMI { @@ -102,6 +101,7 @@ unsafe impl PHY for GenericSMI { /// Public functions for the PHY impl GenericSMI { + #[cfg(feature = "time")] pub fn set_poll_interval(&mut self, poll_interval: Duration) { self.poll_interval = poll_interval } From f581831b86f1f3e46a1cc7a8c4d1a2baf3379e6a Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Tue, 18 Jul 2023 10:39:29 +0200 Subject: [PATCH 3/9] Make dual-stack work in embassy-net --- embassy-net/src/lib.rs | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index 0d0a986f6..f43e3797b 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -531,11 +531,14 @@ impl Inner { debug!(" IP address: {}", config.address); s.iface.update_ip_addrs(|addrs| { - if addrs.is_empty() { - addrs.push(IpCidr::Ipv4(config.address)).unwrap(); - } else { - addrs[0] = IpCidr::Ipv4(config.address); + if let Some((index, _)) = addrs + .iter() + .enumerate() + .find(|(_, &addr)| matches!(addr, IpCidr::Ipv4(_))) + { + addrs.remove(index); } + addrs.push(IpCidr::Ipv4(config.address)).unwrap(); }); #[cfg(feature = "medium-ethernet")] @@ -570,11 +573,14 @@ impl Inner { debug!(" IP address: {}", config.address); s.iface.update_ip_addrs(|addrs| { - if addrs.is_empty() { - addrs.push(IpCidr::Ipv6(config.address)).unwrap(); - } else { - addrs[0] = IpCidr::Ipv6(config.address); + if let Some((index, _)) = addrs + .iter() + .enumerate() + .find(|(_, &addr)| matches!(addr, IpCidr::Ipv6(_))) + { + addrs.remove(index); } + addrs.push(IpCidr::Ipv6(config.address)).unwrap(); }); #[cfg(feature = "medium-ethernet")] @@ -643,12 +649,19 @@ impl Inner { } #[allow(unused)] // used only with dhcp - fn unapply_config(&mut self, s: &mut SocketStack) { + fn unapply_config_v4(&mut self, s: &mut SocketStack) { #[cfg(feature = "medium-ethernet")] let medium = self.device.capabilities().medium; - debug!("Lost IP configuration"); - s.iface.update_ip_addrs(|ip_addrs| ip_addrs.clear()); + s.iface.update_ip_addrs(|ip_addrs| { + if let Some((index, _)) = ip_addrs + .iter() + .enumerate() + .find(|(index, &addr)| matches!(addr, IpCidr::Ipv4(_))) + { + ip_addrs.remove(index); + } + }); #[cfg(feature = "medium-ethernet")] if medium == Medium::Ethernet { #[cfg(feature = "proto-ipv4")] @@ -695,7 +708,7 @@ impl Inner { if self.link_up { match socket.poll() { None => {} - Some(dhcpv4::Event::Deconfigured) => self.unapply_config(s), + Some(dhcpv4::Event::Deconfigured) => self.unapply_config_v4(s), Some(dhcpv4::Event::Configured(config)) => { let config = StaticConfigV4 { address: config.address, @@ -707,7 +720,7 @@ impl Inner { } } else if old_link_up { socket.reset(); - self.unapply_config(s); + self.unapply_config_v4(s); } } //if old_link_up || self.link_up { From 6bf4717b0a17cf4ca3439f0b2726b7fb6f5f3b13 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Tue, 18 Jul 2023 10:57:05 +0200 Subject: [PATCH 4/9] cfg-gate `unapply_config_v4` --- embassy-net/src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index f43e3797b..ae595d0d6 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -648,16 +648,17 @@ impl Inner { socket.set_retry_config(config.retry_config); } - #[allow(unused)] // used only with dhcp + #[cfg(feature = "dhcpv4")] fn unapply_config_v4(&mut self, s: &mut SocketStack) { #[cfg(feature = "medium-ethernet")] let medium = self.device.capabilities().medium; debug!("Lost IP configuration"); s.iface.update_ip_addrs(|ip_addrs| { + #[cfg(feature = "proto-ipv4")] if let Some((index, _)) = ip_addrs .iter() .enumerate() - .find(|(index, &addr)| matches!(addr, IpCidr::Ipv4(_))) + .find(|(_, &addr)| matches!(addr, IpCidr::Ipv4(_))) { ip_addrs.remove(index); } From fc901f98564134368db3a92fb0644c5afe292f10 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 18 Jul 2023 13:54:41 +0200 Subject: [PATCH 5/9] ci: add check for no CRLF line endings. --- .github/ci/crlf.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100755 .github/ci/crlf.sh diff --git a/.github/ci/crlf.sh b/.github/ci/crlf.sh new file mode 100755 index 000000000..457510407 --- /dev/null +++ b/.github/ci/crlf.sh @@ -0,0 +1,17 @@ +#!/bin/bash +## on push branch~=gh-readonly-queue/main/.* +## on pull_request + +set -euo pipefail + +FILES_WITH_CRLF=$(find ! -path "./.git/*" -not -type d | xargs file -N | (grep " CRLF " || true)) + +if [ -z "$FILES_WITH_CRLF" ]; then + echo -e "No files with CRLF endings found." + exit 0 +else + NR_FILES=$(echo "$FILES_WITH_CRLF" | wc -l) + echo -e "ERROR: Found ${NR_FILES} files with CRLF endings." + echo "$FILES_WITH_CRLF" + exit "$NR_FILES" +fi \ No newline at end of file From 48957dce8767fb573527626b4a4a060fa3f1b98a Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 18 Jul 2023 14:14:25 +0200 Subject: [PATCH 6/9] Add gitattributes to control crlf conversion. --- .gitattributes | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..4db9edae7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,41 @@ +* text=auto + +*.adoc text +*.html text +*.in text +*.json text +*.md text +*.proto text +*.py text +*.rs text +*.service text +*.sh text +*.toml text +*.txt text +*.x text +*.yml text + +*.raw binary +*.bin binary +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.ico binary +*.mov binary +*.mp4 binary +*.mp3 binary +*.flv binary +*.fla binary +*.swf binary +*.gz binary +*.zip binary +*.7z binary +*.ttf binary +*.eot binary +*.woff binary +*.pyc binary +*.pdf binary +*.ez binary +*.bz2 binary +*.swp binary \ No newline at end of file From 10f59667879bc476004c78bc0d3d6a0c4f560e55 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 18 Jul 2023 14:17:44 +0200 Subject: [PATCH 7/9] Convert files to LF endings. --- embassy-nrf/src/pdm.rs | 588 +++++++++++++++--------------- embassy-stm32/src/qspi/mod.rs | 664 +++++++++++++++++----------------- 2 files changed, 626 insertions(+), 626 deletions(-) diff --git a/embassy-nrf/src/pdm.rs b/embassy-nrf/src/pdm.rs index 0e30f7002..efa1fbccc 100644 --- a/embassy-nrf/src/pdm.rs +++ b/embassy-nrf/src/pdm.rs @@ -1,294 +1,294 @@ -//! Pulse Density Modulation (PDM) mirophone driver. - -#![macro_use] - -use core::marker::PhantomData; -use core::sync::atomic::{compiler_fence, Ordering}; -use core::task::Poll; - -use embassy_hal_common::drop::OnDrop; -use embassy_hal_common::{into_ref, PeripheralRef}; -use futures::future::poll_fn; - -use crate::chip::EASY_DMA_SIZE; -use crate::gpio::sealed::Pin; -use crate::gpio::{AnyPin, Pin as GpioPin}; -use crate::interrupt::typelevel::Interrupt; -use crate::{interrupt, Peripheral}; - -/// Interrupt handler. -pub struct InterruptHandler { - _phantom: PhantomData, -} - -impl interrupt::typelevel::Handler for InterruptHandler { - unsafe fn on_interrupt() { - T::regs().intenclr.write(|w| w.end().clear()); - T::state().waker.wake(); - } -} - -/// PDM microphone interface -pub struct Pdm<'d, T: Instance> { - _peri: PeripheralRef<'d, T>, -} - -/// PDM error. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[non_exhaustive] -pub enum Error { - /// Buffer is too long. - BufferTooLong, - /// Buffer is empty - BufferZeroLength, - /// PDM is not running - NotRunning, -} - -static DUMMY_BUFFER: [i16; 1] = [0; 1]; - -impl<'d, T: Instance> Pdm<'d, T> { - /// Create PDM driver - pub fn new( - pdm: impl Peripheral

+ 'd, - _irq: impl interrupt::typelevel::Binding> + 'd, - clk: impl Peripheral

+ 'd, - din: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(pdm, clk, din); - Self::new_inner(pdm, clk.map_into(), din.map_into(), config) - } - - fn new_inner( - pdm: PeripheralRef<'d, T>, - clk: PeripheralRef<'d, AnyPin>, - din: PeripheralRef<'d, AnyPin>, - config: Config, - ) -> Self { - into_ref!(pdm); - - let r = T::regs(); - - // setup gpio pins - din.conf().write(|w| w.input().set_bit()); - r.psel.din.write(|w| unsafe { w.bits(din.psel_bits()) }); - clk.set_low(); - clk.conf().write(|w| w.dir().output()); - r.psel.clk.write(|w| unsafe { w.bits(clk.psel_bits()) }); - - // configure - // use default for - // - gain right - // - gain left - // - clk - // - ratio - r.mode.write(|w| { - w.edge().bit(config.edge == Edge::LeftRising); - w.operation().bit(config.operation_mode == OperationMode::Mono); - w - }); - r.gainl.write(|w| w.gainl().default_gain()); - r.gainr.write(|w| w.gainr().default_gain()); - - // IRQ - T::Interrupt::unpend(); - unsafe { T::Interrupt::enable() }; - - r.enable.write(|w| w.enable().set_bit()); - - Self { _peri: pdm } - } - - /// Start sampling microphon data into a dummy buffer - /// Usefull to start the microphon and keep it active between recording samples - pub async fn start(&mut self) { - let r = T::regs(); - - // start dummy sampling because microphon needs some setup time - r.sample - .ptr - .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); - r.sample - .maxcnt - .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); - - r.tasks_start.write(|w| unsafe { w.bits(1) }); - } - - /// Stop sampling microphon data inta a dummy buffer - pub async fn stop(&mut self) { - let r = T::regs(); - r.tasks_stop.write(|w| unsafe { w.bits(1) }); - r.events_started.reset(); - } - - /// Sample data into the given buffer. - pub async fn sample(&mut self, buffer: &mut [i16]) -> Result<(), Error> { - if buffer.len() == 0 { - return Err(Error::BufferZeroLength); - } - if buffer.len() > EASY_DMA_SIZE { - return Err(Error::BufferTooLong); - } - - let r = T::regs(); - - if r.events_started.read().bits() == 0 { - return Err(Error::NotRunning); - } - - let drop = OnDrop::new(move || { - r.intenclr.write(|w| w.end().clear()); - r.events_stopped.reset(); - - // reset to dummy buffer - r.sample - .ptr - .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); - r.sample - .maxcnt - .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); - - while r.events_stopped.read().bits() == 0 {} - }); - - // setup user buffer - let ptr = buffer.as_ptr(); - let len = buffer.len(); - r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(ptr as u32) }); - r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(len as _) }); - - // wait till the current sample is finished and the user buffer sample is started - Self::wait_for_sample().await; - - // reset the buffer back to the dummy buffer - r.sample - .ptr - .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); - r.sample - .maxcnt - .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); - - // wait till the user buffer is sampled - Self::wait_for_sample().await; - - drop.defuse(); - - Ok(()) - } - - async fn wait_for_sample() { - let r = T::regs(); - - r.events_end.reset(); - r.intenset.write(|w| w.end().set()); - - compiler_fence(Ordering::SeqCst); - - poll_fn(|cx| { - T::state().waker.register(cx.waker()); - if r.events_end.read().bits() != 0 { - return Poll::Ready(()); - } - Poll::Pending - }) - .await; - - compiler_fence(Ordering::SeqCst); - } -} - -/// PDM microphone driver Config -pub struct Config { - /// Use stero or mono operation - pub operation_mode: OperationMode, - /// On which edge the left channel should be samples - pub edge: Edge, -} - -impl Default for Config { - fn default() -> Self { - Self { - operation_mode: OperationMode::Mono, - edge: Edge::LeftFalling, - } - } -} - -/// PDM operation mode. -#[derive(PartialEq)] -pub enum OperationMode { - /// Mono (1 channel) - Mono, - /// Stereo (2 channels) - Stereo, -} - -/// PDM edge polarity -#[derive(PartialEq)] -pub enum Edge { - /// Left edge is rising - LeftRising, - /// Left edge is falling - LeftFalling, -} - -impl<'d, T: Instance> Drop for Pdm<'d, T> { - fn drop(&mut self) { - let r = T::regs(); - - r.tasks_stop.write(|w| unsafe { w.bits(1) }); - - r.enable.write(|w| w.enable().disabled()); - - r.psel.din.reset(); - r.psel.clk.reset(); - } -} - -pub(crate) mod sealed { - use embassy_sync::waitqueue::AtomicWaker; - - /// Peripheral static state - pub struct State { - pub waker: AtomicWaker, - } - - impl State { - pub const fn new() -> Self { - Self { - waker: AtomicWaker::new(), - } - } - } - - pub trait Instance { - fn regs() -> &'static crate::pac::pdm::RegisterBlock; - fn state() -> &'static State; - } -} - -/// PDM peripheral instance. -pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { - /// Interrupt for this peripheral. - type Interrupt: interrupt::typelevel::Interrupt; -} - -macro_rules! impl_pdm { - ($type:ident, $pac_type:ident, $irq:ident) => { - impl crate::pdm::sealed::Instance for peripherals::$type { - fn regs() -> &'static crate::pac::pdm::RegisterBlock { - unsafe { &*pac::$pac_type::ptr() } - } - fn state() -> &'static crate::pdm::sealed::State { - static STATE: crate::pdm::sealed::State = crate::pdm::sealed::State::new(); - &STATE - } - } - impl crate::pdm::Instance for peripherals::$type { - type Interrupt = crate::interrupt::typelevel::$irq; - } - }; -} +//! Pulse Density Modulation (PDM) mirophone driver. + +#![macro_use] + +use core::marker::PhantomData; +use core::sync::atomic::{compiler_fence, Ordering}; +use core::task::Poll; + +use embassy_hal_common::drop::OnDrop; +use embassy_hal_common::{into_ref, PeripheralRef}; +use futures::future::poll_fn; + +use crate::chip::EASY_DMA_SIZE; +use crate::gpio::sealed::Pin; +use crate::gpio::{AnyPin, Pin as GpioPin}; +use crate::interrupt::typelevel::Interrupt; +use crate::{interrupt, Peripheral}; + +/// Interrupt handler. +pub struct InterruptHandler { + _phantom: PhantomData, +} + +impl interrupt::typelevel::Handler for InterruptHandler { + unsafe fn on_interrupt() { + T::regs().intenclr.write(|w| w.end().clear()); + T::state().waker.wake(); + } +} + +/// PDM microphone interface +pub struct Pdm<'d, T: Instance> { + _peri: PeripheralRef<'d, T>, +} + +/// PDM error. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] +pub enum Error { + /// Buffer is too long. + BufferTooLong, + /// Buffer is empty + BufferZeroLength, + /// PDM is not running + NotRunning, +} + +static DUMMY_BUFFER: [i16; 1] = [0; 1]; + +impl<'d, T: Instance> Pdm<'d, T> { + /// Create PDM driver + pub fn new( + pdm: impl Peripheral

+ 'd, + _irq: impl interrupt::typelevel::Binding> + 'd, + clk: impl Peripheral

+ 'd, + din: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(pdm, clk, din); + Self::new_inner(pdm, clk.map_into(), din.map_into(), config) + } + + fn new_inner( + pdm: PeripheralRef<'d, T>, + clk: PeripheralRef<'d, AnyPin>, + din: PeripheralRef<'d, AnyPin>, + config: Config, + ) -> Self { + into_ref!(pdm); + + let r = T::regs(); + + // setup gpio pins + din.conf().write(|w| w.input().set_bit()); + r.psel.din.write(|w| unsafe { w.bits(din.psel_bits()) }); + clk.set_low(); + clk.conf().write(|w| w.dir().output()); + r.psel.clk.write(|w| unsafe { w.bits(clk.psel_bits()) }); + + // configure + // use default for + // - gain right + // - gain left + // - clk + // - ratio + r.mode.write(|w| { + w.edge().bit(config.edge == Edge::LeftRising); + w.operation().bit(config.operation_mode == OperationMode::Mono); + w + }); + r.gainl.write(|w| w.gainl().default_gain()); + r.gainr.write(|w| w.gainr().default_gain()); + + // IRQ + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; + + r.enable.write(|w| w.enable().set_bit()); + + Self { _peri: pdm } + } + + /// Start sampling microphon data into a dummy buffer + /// Usefull to start the microphon and keep it active between recording samples + pub async fn start(&mut self) { + let r = T::regs(); + + // start dummy sampling because microphon needs some setup time + r.sample + .ptr + .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); + r.sample + .maxcnt + .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); + + r.tasks_start.write(|w| unsafe { w.bits(1) }); + } + + /// Stop sampling microphon data inta a dummy buffer + pub async fn stop(&mut self) { + let r = T::regs(); + r.tasks_stop.write(|w| unsafe { w.bits(1) }); + r.events_started.reset(); + } + + /// Sample data into the given buffer. + pub async fn sample(&mut self, buffer: &mut [i16]) -> Result<(), Error> { + if buffer.len() == 0 { + return Err(Error::BufferZeroLength); + } + if buffer.len() > EASY_DMA_SIZE { + return Err(Error::BufferTooLong); + } + + let r = T::regs(); + + if r.events_started.read().bits() == 0 { + return Err(Error::NotRunning); + } + + let drop = OnDrop::new(move || { + r.intenclr.write(|w| w.end().clear()); + r.events_stopped.reset(); + + // reset to dummy buffer + r.sample + .ptr + .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); + r.sample + .maxcnt + .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); + + while r.events_stopped.read().bits() == 0 {} + }); + + // setup user buffer + let ptr = buffer.as_ptr(); + let len = buffer.len(); + r.sample.ptr.write(|w| unsafe { w.sampleptr().bits(ptr as u32) }); + r.sample.maxcnt.write(|w| unsafe { w.buffsize().bits(len as _) }); + + // wait till the current sample is finished and the user buffer sample is started + Self::wait_for_sample().await; + + // reset the buffer back to the dummy buffer + r.sample + .ptr + .write(|w| unsafe { w.sampleptr().bits(DUMMY_BUFFER.as_ptr() as u32) }); + r.sample + .maxcnt + .write(|w| unsafe { w.buffsize().bits(DUMMY_BUFFER.len() as _) }); + + // wait till the user buffer is sampled + Self::wait_for_sample().await; + + drop.defuse(); + + Ok(()) + } + + async fn wait_for_sample() { + let r = T::regs(); + + r.events_end.reset(); + r.intenset.write(|w| w.end().set()); + + compiler_fence(Ordering::SeqCst); + + poll_fn(|cx| { + T::state().waker.register(cx.waker()); + if r.events_end.read().bits() != 0 { + return Poll::Ready(()); + } + Poll::Pending + }) + .await; + + compiler_fence(Ordering::SeqCst); + } +} + +/// PDM microphone driver Config +pub struct Config { + /// Use stero or mono operation + pub operation_mode: OperationMode, + /// On which edge the left channel should be samples + pub edge: Edge, +} + +impl Default for Config { + fn default() -> Self { + Self { + operation_mode: OperationMode::Mono, + edge: Edge::LeftFalling, + } + } +} + +/// PDM operation mode. +#[derive(PartialEq)] +pub enum OperationMode { + /// Mono (1 channel) + Mono, + /// Stereo (2 channels) + Stereo, +} + +/// PDM edge polarity +#[derive(PartialEq)] +pub enum Edge { + /// Left edge is rising + LeftRising, + /// Left edge is falling + LeftFalling, +} + +impl<'d, T: Instance> Drop for Pdm<'d, T> { + fn drop(&mut self) { + let r = T::regs(); + + r.tasks_stop.write(|w| unsafe { w.bits(1) }); + + r.enable.write(|w| w.enable().disabled()); + + r.psel.din.reset(); + r.psel.clk.reset(); + } +} + +pub(crate) mod sealed { + use embassy_sync::waitqueue::AtomicWaker; + + /// Peripheral static state + pub struct State { + pub waker: AtomicWaker, + } + + impl State { + pub const fn new() -> Self { + Self { + waker: AtomicWaker::new(), + } + } + } + + pub trait Instance { + fn regs() -> &'static crate::pac::pdm::RegisterBlock; + fn state() -> &'static State; + } +} + +/// PDM peripheral instance. +pub trait Instance: Peripheral

+ sealed::Instance + 'static + Send { + /// Interrupt for this peripheral. + type Interrupt: interrupt::typelevel::Interrupt; +} + +macro_rules! impl_pdm { + ($type:ident, $pac_type:ident, $irq:ident) => { + impl crate::pdm::sealed::Instance for peripherals::$type { + fn regs() -> &'static crate::pac::pdm::RegisterBlock { + unsafe { &*pac::$pac_type::ptr() } + } + fn state() -> &'static crate::pdm::sealed::State { + static STATE: crate::pdm::sealed::State = crate::pdm::sealed::State::new(); + &STATE + } + } + impl crate::pdm::Instance for peripherals::$type { + type Interrupt = crate::interrupt::typelevel::$irq; + } + }; +} diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index e9db934bf..31b676088 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -1,332 +1,332 @@ -#![macro_use] - -pub mod enums; - -use embassy_hal_common::{into_ref, PeripheralRef}; -use enums::*; - -use crate::dma::Transfer; -use crate::gpio::sealed::AFType; -use crate::gpio::AnyPin; -use crate::pac::quadspi::Quadspi as Regs; -use crate::rcc::RccPeripheral; -use crate::{peripherals, Peripheral}; - -pub struct TransferConfig { - /// Instraction width (IMODE) - pub iwidth: QspiWidth, - /// Address width (ADMODE) - pub awidth: QspiWidth, - /// Data width (DMODE) - pub dwidth: QspiWidth, - /// Instruction Id - pub instruction: u8, - /// Flash memory address - pub address: Option, - /// Number of dummy cycles (DCYC) - pub dummy: DummyCycles, - /// Length of data - pub data_len: Option, -} - -impl Default for TransferConfig { - fn default() -> Self { - Self { - iwidth: QspiWidth::NONE, - awidth: QspiWidth::NONE, - dwidth: QspiWidth::NONE, - instruction: 0, - address: None, - dummy: DummyCycles::_0, - data_len: None, - } - } -} - -pub struct Config { - /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen. - /// If you need other value the whose predefined use `Other` variant. - pub memory_size: MemorySize, - /// Address size (8/16/24/32-bit) - pub address_size: AddressSize, - /// Scalar factor for generating CLK [0-255] - pub prescaler: u8, - /// Number of bytes to trigger FIFO threshold flag. - pub fifo_threshold: FIFOThresholdLevel, - /// Minimum number of cycles that chip select must be high between issued commands - pub cs_high_time: ChipSelectHightTime, -} - -impl Default for Config { - fn default() -> Self { - Self { - memory_size: MemorySize::Other(0), - address_size: AddressSize::_24bit, - prescaler: 128, - fifo_threshold: FIFOThresholdLevel::_17Bytes, - cs_high_time: ChipSelectHightTime::_5Cycle, - } - } -} - -#[allow(dead_code)] -pub struct Qspi<'d, T: Instance, Dma> { - _peri: PeripheralRef<'d, T>, - sck: Option>, - d0: Option>, - d1: Option>, - d2: Option>, - d3: Option>, - nss: Option>, - dma: PeripheralRef<'d, Dma>, - config: Config, -} - -impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { - pub fn new( - peri: impl Peripheral

+ 'd, - d0: impl Peripheral

> + 'd, - d1: impl Peripheral

> + 'd, - d2: impl Peripheral

> + 'd, - d3: impl Peripheral

> + 'd, - sck: impl Peripheral

> + 'd, - nss: impl Peripheral

> + 'd, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, d0, d1, d2, d3, sck, nss); - - sck.set_as_af(sck.af_num(), AFType::OutputPushPull); - sck.set_speed(crate::gpio::Speed::VeryHigh); - nss.set_as_af(nss.af_num(), AFType::OutputPushPull); - nss.set_speed(crate::gpio::Speed::VeryHigh); - d0.set_as_af(d0.af_num(), AFType::OutputPushPull); - d0.set_speed(crate::gpio::Speed::VeryHigh); - d1.set_as_af(d1.af_num(), AFType::OutputPushPull); - d1.set_speed(crate::gpio::Speed::VeryHigh); - d2.set_as_af(d2.af_num(), AFType::OutputPushPull); - d2.set_speed(crate::gpio::Speed::VeryHigh); - d3.set_as_af(d3.af_num(), AFType::OutputPushPull); - d3.set_speed(crate::gpio::Speed::VeryHigh); - - Self::new_inner( - peri, - Some(d0.map_into()), - Some(d1.map_into()), - Some(d2.map_into()), - Some(d3.map_into()), - Some(sck.map_into()), - Some(nss.map_into()), - dma, - config, - ) - } - - fn new_inner( - peri: impl Peripheral

+ 'd, - d0: Option>, - d1: Option>, - d2: Option>, - d3: Option>, - sck: Option>, - nss: Option>, - dma: impl Peripheral

+ 'd, - config: Config, - ) -> Self { - into_ref!(peri, dma); - - T::enable(); - T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); - - while T::REGS.sr().read().busy() {} - - T::REGS.cr().write(|w| { - w.set_prescaler(config.prescaler); - w.set_en(true); - }); - T::REGS.dcr().write(|w| { - w.set_fsize(config.memory_size.into()); - w.set_csht(config.cs_high_time.into()); - w.set_ckmode(false); - }); - - Self { - _peri: peri, - sck, - d0, - d1, - d2, - d3, - nss, - dma, - config, - } - } - - pub fn command(&mut self, transaction: TransferConfig) { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); - - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); - } - - pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); - - if let Some(len) = transaction.data_len { - let current_ar = T::REGS.ar().read().address(); - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectRead.into()); - }); - T::REGS.ar().write(|v| { - v.set_address(current_ar); - }); - - for idx in 0..len { - while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} - buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() }; - } - } - - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); - } - - pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { - T::REGS.cr().modify(|v| v.set_dmaen(false)); - self.setup_transaction(QspiMode::IndirectWrite, &transaction); - - if let Some(len) = transaction.data_len { - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectWrite.into()); - }); - - for idx in 0..len { - while !T::REGS.sr().read().ftf() {} - unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) }; - } - } - - while !T::REGS.sr().read().tcf() {} - T::REGS.fcr().modify(|v| v.set_ctcf(true)); - } - - pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) - where - Dma: QuadDma, - { - self.setup_transaction(QspiMode::IndirectWrite, &transaction); - - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectRead.into()); - }); - let current_ar = T::REGS.ar().read().address(); - T::REGS.ar().write(|v| { - v.set_address(current_ar); - }); - - let request = self.dma.request(); - let transfer = unsafe { - Transfer::new_read( - &mut self.dma, - request, - T::REGS.dr().as_ptr() as *mut u8, - buf, - Default::default(), - ) - }; - - T::REGS.cr().modify(|v| v.set_dmaen(true)); - - transfer.blocking_wait(); - } - - pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) - where - Dma: QuadDma, - { - self.setup_transaction(QspiMode::IndirectWrite, &transaction); - - T::REGS.ccr().modify(|v| { - v.set_fmode(QspiMode::IndirectWrite.into()); - }); - - let request = self.dma.request(); - let transfer = unsafe { - Transfer::new_write( - &mut self.dma, - request, - buf, - T::REGS.dr().as_ptr() as *mut u8, - Default::default(), - ) - }; - - T::REGS.cr().modify(|v| v.set_dmaen(true)); - - transfer.blocking_wait(); - } - - fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) { - T::REGS.fcr().modify(|v| { - v.set_csmf(true); - v.set_ctcf(true); - v.set_ctef(true); - v.set_ctof(true); - }); - - while T::REGS.sr().read().busy() {} - - if let Some(len) = transaction.data_len { - T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); - } - - T::REGS.ccr().write(|v| { - v.set_fmode(fmode.into()); - v.set_imode(transaction.iwidth.into()); - v.set_instruction(transaction.instruction); - v.set_admode(transaction.awidth.into()); - v.set_adsize(self.config.address_size.into()); - v.set_dmode(transaction.dwidth.into()); - v.set_abmode(QspiWidth::NONE.into()); - v.set_dcyc(transaction.dummy.into()); - }); - - if let Some(addr) = transaction.address { - T::REGS.ar().write(|v| { - v.set_address(addr); - }); - } - } -} - -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - const REGS: Regs; - } -} - -pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} - -pin_trait!(SckPin, Instance); -pin_trait!(D0Pin, Instance); -pin_trait!(D1Pin, Instance); -pin_trait!(D2Pin, Instance); -pin_trait!(D3Pin, Instance); -pin_trait!(NSSPin, Instance); - -dma_trait!(QuadDma, Instance); - -foreach_peripheral!( - (quadspi, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { - const REGS: Regs = crate::pac::$inst; - } - - impl Instance for peripherals::$inst {} - }; -); +#![macro_use] + +pub mod enums; + +use embassy_hal_common::{into_ref, PeripheralRef}; +use enums::*; + +use crate::dma::Transfer; +use crate::gpio::sealed::AFType; +use crate::gpio::AnyPin; +use crate::pac::quadspi::Quadspi as Regs; +use crate::rcc::RccPeripheral; +use crate::{peripherals, Peripheral}; + +pub struct TransferConfig { + /// Instraction width (IMODE) + pub iwidth: QspiWidth, + /// Address width (ADMODE) + pub awidth: QspiWidth, + /// Data width (DMODE) + pub dwidth: QspiWidth, + /// Instruction Id + pub instruction: u8, + /// Flash memory address + pub address: Option, + /// Number of dummy cycles (DCYC) + pub dummy: DummyCycles, + /// Length of data + pub data_len: Option, +} + +impl Default for TransferConfig { + fn default() -> Self { + Self { + iwidth: QspiWidth::NONE, + awidth: QspiWidth::NONE, + dwidth: QspiWidth::NONE, + instruction: 0, + address: None, + dummy: DummyCycles::_0, + data_len: None, + } + } +} + +pub struct Config { + /// Flash memory size representend as 2^[0-32], as reasonable minimum 1KiB(9) was chosen. + /// If you need other value the whose predefined use `Other` variant. + pub memory_size: MemorySize, + /// Address size (8/16/24/32-bit) + pub address_size: AddressSize, + /// Scalar factor for generating CLK [0-255] + pub prescaler: u8, + /// Number of bytes to trigger FIFO threshold flag. + pub fifo_threshold: FIFOThresholdLevel, + /// Minimum number of cycles that chip select must be high between issued commands + pub cs_high_time: ChipSelectHightTime, +} + +impl Default for Config { + fn default() -> Self { + Self { + memory_size: MemorySize::Other(0), + address_size: AddressSize::_24bit, + prescaler: 128, + fifo_threshold: FIFOThresholdLevel::_17Bytes, + cs_high_time: ChipSelectHightTime::_5Cycle, + } + } +} + +#[allow(dead_code)] +pub struct Qspi<'d, T: Instance, Dma> { + _peri: PeripheralRef<'d, T>, + sck: Option>, + d0: Option>, + d1: Option>, + d2: Option>, + d3: Option>, + nss: Option>, + dma: PeripheralRef<'d, Dma>, + config: Config, +} + +impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { + pub fn new( + peri: impl Peripheral

+ 'd, + d0: impl Peripheral

> + 'd, + d1: impl Peripheral

> + 'd, + d2: impl Peripheral

> + 'd, + d3: impl Peripheral

> + 'd, + sck: impl Peripheral

> + 'd, + nss: impl Peripheral

> + 'd, + dma: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(peri, d0, d1, d2, d3, sck, nss); + + sck.set_as_af(sck.af_num(), AFType::OutputPushPull); + sck.set_speed(crate::gpio::Speed::VeryHigh); + nss.set_as_af(nss.af_num(), AFType::OutputPushPull); + nss.set_speed(crate::gpio::Speed::VeryHigh); + d0.set_as_af(d0.af_num(), AFType::OutputPushPull); + d0.set_speed(crate::gpio::Speed::VeryHigh); + d1.set_as_af(d1.af_num(), AFType::OutputPushPull); + d1.set_speed(crate::gpio::Speed::VeryHigh); + d2.set_as_af(d2.af_num(), AFType::OutputPushPull); + d2.set_speed(crate::gpio::Speed::VeryHigh); + d3.set_as_af(d3.af_num(), AFType::OutputPushPull); + d3.set_speed(crate::gpio::Speed::VeryHigh); + + Self::new_inner( + peri, + Some(d0.map_into()), + Some(d1.map_into()), + Some(d2.map_into()), + Some(d3.map_into()), + Some(sck.map_into()), + Some(nss.map_into()), + dma, + config, + ) + } + + fn new_inner( + peri: impl Peripheral

+ 'd, + d0: Option>, + d1: Option>, + d2: Option>, + d3: Option>, + sck: Option>, + nss: Option>, + dma: impl Peripheral

+ 'd, + config: Config, + ) -> Self { + into_ref!(peri, dma); + + T::enable(); + T::REGS.cr().write(|w| w.set_fthres(config.fifo_threshold.into())); + + while T::REGS.sr().read().busy() {} + + T::REGS.cr().write(|w| { + w.set_prescaler(config.prescaler); + w.set_en(true); + }); + T::REGS.dcr().write(|w| { + w.set_fsize(config.memory_size.into()); + w.set_csht(config.cs_high_time.into()); + w.set_ckmode(false); + }); + + Self { + _peri: peri, + sck, + d0, + d1, + d2, + d3, + nss, + dma, + config, + } + } + + pub fn command(&mut self, transaction: TransferConfig) { + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); + } + + pub fn blocking_read(&mut self, buf: &mut [u8], transaction: TransferConfig) { + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); + + if let Some(len) = transaction.data_len { + let current_ar = T::REGS.ar().read().address(); + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectRead.into()); + }); + T::REGS.ar().write(|v| { + v.set_address(current_ar); + }); + + for idx in 0..len { + while !T::REGS.sr().read().tcf() && !T::REGS.sr().read().ftf() {} + buf[idx] = unsafe { (T::REGS.dr().as_ptr() as *mut u8).read_volatile() }; + } + } + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); + } + + pub fn blocking_write(&mut self, buf: &[u8], transaction: TransferConfig) { + T::REGS.cr().modify(|v| v.set_dmaen(false)); + self.setup_transaction(QspiMode::IndirectWrite, &transaction); + + if let Some(len) = transaction.data_len { + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectWrite.into()); + }); + + for idx in 0..len { + while !T::REGS.sr().read().ftf() {} + unsafe { (T::REGS.dr().as_ptr() as *mut u8).write_volatile(buf[idx]) }; + } + } + + while !T::REGS.sr().read().tcf() {} + T::REGS.fcr().modify(|v| v.set_ctcf(true)); + } + + pub fn blocking_read_dma(&mut self, buf: &mut [u8], transaction: TransferConfig) + where + Dma: QuadDma, + { + self.setup_transaction(QspiMode::IndirectWrite, &transaction); + + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectRead.into()); + }); + let current_ar = T::REGS.ar().read().address(); + T::REGS.ar().write(|v| { + v.set_address(current_ar); + }); + + let request = self.dma.request(); + let transfer = unsafe { + Transfer::new_read( + &mut self.dma, + request, + T::REGS.dr().as_ptr() as *mut u8, + buf, + Default::default(), + ) + }; + + T::REGS.cr().modify(|v| v.set_dmaen(true)); + + transfer.blocking_wait(); + } + + pub fn blocking_write_dma(&mut self, buf: &[u8], transaction: TransferConfig) + where + Dma: QuadDma, + { + self.setup_transaction(QspiMode::IndirectWrite, &transaction); + + T::REGS.ccr().modify(|v| { + v.set_fmode(QspiMode::IndirectWrite.into()); + }); + + let request = self.dma.request(); + let transfer = unsafe { + Transfer::new_write( + &mut self.dma, + request, + buf, + T::REGS.dr().as_ptr() as *mut u8, + Default::default(), + ) + }; + + T::REGS.cr().modify(|v| v.set_dmaen(true)); + + transfer.blocking_wait(); + } + + fn setup_transaction(&mut self, fmode: QspiMode, transaction: &TransferConfig) { + T::REGS.fcr().modify(|v| { + v.set_csmf(true); + v.set_ctcf(true); + v.set_ctef(true); + v.set_ctof(true); + }); + + while T::REGS.sr().read().busy() {} + + if let Some(len) = transaction.data_len { + T::REGS.dlr().write(|v| v.set_dl(len as u32 - 1)); + } + + T::REGS.ccr().write(|v| { + v.set_fmode(fmode.into()); + v.set_imode(transaction.iwidth.into()); + v.set_instruction(transaction.instruction); + v.set_admode(transaction.awidth.into()); + v.set_adsize(self.config.address_size.into()); + v.set_dmode(transaction.dwidth.into()); + v.set_abmode(QspiWidth::NONE.into()); + v.set_dcyc(transaction.dummy.into()); + }); + + if let Some(addr) = transaction.address { + T::REGS.ar().write(|v| { + v.set_address(addr); + }); + } + } +} + +pub(crate) mod sealed { + use super::*; + + pub trait Instance { + const REGS: Regs; + } +} + +pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} + +pin_trait!(SckPin, Instance); +pin_trait!(D0Pin, Instance); +pin_trait!(D1Pin, Instance); +pin_trait!(D2Pin, Instance); +pin_trait!(D3Pin, Instance); +pin_trait!(NSSPin, Instance); + +dma_trait!(QuadDma, Instance); + +foreach_peripheral!( + (quadspi, $inst:ident) => { + impl sealed::Instance for peripherals::$inst { + const REGS: Regs = crate::pac::$inst; + } + + impl Instance for peripherals::$inst {} + }; +); From 98576c17b6c29972074867499332365f7f3e89db Mon Sep 17 00:00:00 2001 From: ivmarkov Date: Tue, 18 Jul 2023 18:35:20 +0300 Subject: [PATCH 8/9] Fix multicast support (#1670) --- embassy-net/src/lib.rs | 62 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/embassy-net/src/lib.rs b/embassy-net/src/lib.rs index ae595d0d6..4fbafe752 100644 --- a/embassy-net/src/lib.rs +++ b/embassy-net/src/lib.rs @@ -479,30 +479,78 @@ impl Stack { } #[cfg(feature = "igmp")] -impl Stack { +impl Stack { /// Join a multicast group. - pub fn join_multicast_group(&self, addr: T) -> Result + pub async fn join_multicast_group(&self, addr: T) -> Result + where + T: Into, + { + let addr = addr.into(); + + poll_fn(move |cx| self.poll_join_multicast_group(addr, cx)).await + } + + /// Join a multicast group. + /// + /// When the send queue is full, this method will return `Poll::Pending` + /// and register the current task to be notified when the queue has space available. + pub fn poll_join_multicast_group(&self, addr: T, cx: &mut Context<'_>) -> Poll> where T: Into, { let addr = addr.into(); self.with_mut(|s, i| { - s.iface - .join_multicast_group(&mut i.device, addr, instant_to_smoltcp(Instant::now())) + let mut smoldev = DriverAdapter { + cx: Some(cx), + inner: &mut i.device, + }; + + match s + .iface + .join_multicast_group(&mut smoldev, addr, instant_to_smoltcp(Instant::now())) + { + Ok(announce_sent) => Poll::Ready(Ok(announce_sent)), + Err(MulticastError::Exhausted) => Poll::Pending, + Err(other) => Poll::Ready(Err(other)), + } }) } /// Leave a multicast group. - pub fn leave_multicast_group(&self, addr: T) -> Result + pub async fn leave_multicast_group(&self, addr: T) -> Result + where + T: Into, + { + let addr = addr.into(); + + poll_fn(move |cx| self.poll_leave_multicast_group(addr, cx)).await + } + + /// Leave a multicast group. + /// + /// When the send queue is full, this method will return `Poll::Pending` + /// and register the current task to be notified when the queue has space available. + pub fn poll_leave_multicast_group(&self, addr: T, cx: &mut Context<'_>) -> Poll> where T: Into, { let addr = addr.into(); self.with_mut(|s, i| { - s.iface - .leave_multicast_group(&mut i.device, addr, instant_to_smoltcp(Instant::now())) + let mut smoldev = DriverAdapter { + cx: Some(cx), + inner: &mut i.device, + }; + + match s + .iface + .leave_multicast_group(&mut smoldev, addr, instant_to_smoltcp(Instant::now())) + { + Ok(leave_sent) => Poll::Ready(Ok(leave_sent)), + Err(MulticastError::Exhausted) => Poll::Pending, + Err(other) => Poll::Ready(Err(other)), + } }) } From a1d3bc30fa44795e6e64ba0db8607f9ea65c55a2 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 18 Jul 2023 18:15:35 +0200 Subject: [PATCH 9/9] net-esp-hosted: build docs. --- .github/ci/doc.sh | 1 + embassy-net-esp-hosted/Cargo.toml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/.github/ci/doc.sh b/.github/ci/doc.sh index 9e9c78a42..06c6fa00b 100755 --- a/.github/ci/doc.sh +++ b/.github/ci/doc.sh @@ -37,6 +37,7 @@ docserver-builder -i ./embassy-usb-logger -o webroot/crates/embassy-usb-logger/g docserver-builder -i ./cyw43 -o webroot/crates/cyw43/git.zup docserver-builder -i ./cyw43-pio -o webroot/crates/cyw43-pio/git.zup docserver-builder -i ./embassy-net-w5500 -o webroot/crates/embassy-net-w5500/git.zup +docserver-builder -i ./embassy-net-esp-hosted -o webroot/crates/embassy-net-esp-hosted/git.zup docserver-builder -i ./embassy-stm32-wpan -o webroot/crates/embassy-stm32-wpan/git.zup --output-static webroot/static export KUBECONFIG=/ci/secrets/kubeconfig.yml diff --git a/embassy-net-esp-hosted/Cargo.toml b/embassy-net-esp-hosted/Cargo.toml index 26f5b40bd..0053c49a4 100644 --- a/embassy-net-esp-hosted/Cargo.toml +++ b/embassy-net-esp-hosted/Cargo.toml @@ -18,3 +18,9 @@ embedded-hal-async = { version = "=0.2.0-alpha.2" } noproto = { git="https://github.com/embassy-rs/noproto", default-features = false, features = ["derive"] } #noproto = { version = "0.1", path = "/home/dirbaio/noproto", default-features = false, features = ["derive"] } heapless = "0.7.16" + +[package.metadata.embassy_docs] +src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-esp-hosted-v$VERSION/embassy-net-esp-hosted/src/" +src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-esp-hosted/src/" +target = "thumbv7em-none-eabi" +features = ["defmt"] \ No newline at end of file