diff --git a/ci.sh b/ci.sh index cd82af2f1..d17f4e13e 100755 --- a/ci.sh +++ b/ci.sh @@ -124,6 +124,7 @@ cargo batch \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h755zi-cm7,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h725re,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-any,time \ + --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32h7b3ai,defmt,exti,time-driver-tim1,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l431cb,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l476vg,defmt,exti,time-driver-any,time \ --- build --release --manifest-path embassy-stm32/Cargo.toml --target thumbv7em-none-eabi --features stm32l422cb,defmt,exti,time-driver-any,time \ diff --git a/cyw43/src/fmt.rs b/cyw43/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/cyw43/src/fmt.rs +++ b/cyw43/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-boot-nrf/src/fmt.rs b/embassy-boot-nrf/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-boot-nrf/src/fmt.rs +++ b/embassy-boot-nrf/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-boot-rp/src/fmt.rs b/embassy-boot-rp/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-boot-rp/src/fmt.rs +++ b/embassy-boot-rp/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-boot-stm32/src/fmt.rs b/embassy-boot-stm32/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-boot-stm32/src/fmt.rs +++ b/embassy-boot-stm32/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-boot/src/boot_loader.rs b/embassy-boot/src/boot_loader.rs index ca1a1b10c..a38558056 100644 --- a/embassy-boot/src/boot_loader.rs +++ b/embassy-boot/src/boot_loader.rs @@ -183,29 +183,29 @@ impl BootLoader BootLoader Result { // Ensure we have enough progress pages to store copy progress diff --git a/embassy-boot/src/fmt.rs b/embassy-boot/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-boot/src/fmt.rs +++ b/embassy-boot/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs index 779c04263..71ce09def 100644 --- a/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs +++ b/embassy-embedded-hal/src/shared_bus/asynch/i2c.rs @@ -106,6 +106,11 @@ impl<'a, M: RawMutex, BUS: SetConfig> I2cDeviceWithConfig<'a, M, BUS> { pub fn new(bus: &'a Mutex, config: BUS::Config) -> Self { Self { bus, config } } + + /// Change the device's config at runtime + pub fn set_config(&mut self, config: BUS::Config) { + self.config = config; + } } impl<'a, M, BUS> i2c::ErrorType for I2cDeviceWithConfig<'a, M, BUS> diff --git a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs index 62b2c92a0..9890f218d 100644 --- a/embassy-embedded-hal/src/shared_bus/asynch/spi.rs +++ b/embassy-embedded-hal/src/shared_bus/asynch/spi.rs @@ -122,6 +122,11 @@ impl<'a, M: RawMutex, BUS: SetConfig, CS> SpiDeviceWithConfig<'a, M, BUS, CS> { pub fn new(bus: &'a Mutex, cs: CS, config: BUS::Config) -> Self { Self { bus, cs, config } } + + /// Change the device's config at runtime + pub fn set_config(&mut self, config: BUS::Config) { + self.config = config; + } } impl<'a, M, BUS, CS> spi::ErrorType for SpiDeviceWithConfig<'a, M, BUS, CS> diff --git a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs index 233c9e1fd..627767c8a 100644 --- a/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs +++ b/embassy-embedded-hal/src/shared_bus/blocking/i2c.rs @@ -67,9 +67,11 @@ where } fn transaction<'a>(&mut self, address: u8, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> { - let _ = address; - let _ = operations; - todo!() + self.bus.lock(|bus| { + bus.borrow_mut() + .transaction(address, operations) + .map_err(I2cDeviceError::I2c) + }) } } @@ -130,6 +132,11 @@ impl<'a, M: RawMutex, BUS: SetConfig> I2cDeviceWithConfig<'a, M, BUS> { pub fn new(bus: &'a Mutex>, config: BUS::Config) -> Self { Self { bus, config } } + + /// Change the device's config at runtime + pub fn set_config(&mut self, config: BUS::Config) { + self.config = config; + } } impl<'a, M, BUS> ErrorType for I2cDeviceWithConfig<'a, M, BUS> @@ -171,8 +178,10 @@ where } fn transaction<'a>(&mut self, address: u8, operations: &mut [Operation<'a>]) -> Result<(), Self::Error> { - let _ = address; - let _ = operations; - todo!() + self.bus.lock(|bus| { + let mut bus = bus.borrow_mut(); + bus.set_config(&self.config).map_err(|_| I2cDeviceError::Config)?; + bus.transaction(address, operations).map_err(I2cDeviceError::I2c) + }) } } diff --git a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs index 59b65bfbd..801899f9f 100644 --- a/embassy-embedded-hal/src/shared_bus/blocking/spi.rs +++ b/embassy-embedded-hal/src/shared_bus/blocking/spi.rs @@ -147,6 +147,11 @@ impl<'a, M: RawMutex, BUS: SetConfig, CS> SpiDeviceWithConfig<'a, M, BUS, CS> { pub fn new(bus: &'a Mutex>, cs: CS, config: BUS::Config) -> Self { Self { bus, cs, config } } + + /// Change the device's config at runtime + pub fn set_config(&mut self, config: BUS::Config) { + self.config = config; + } } impl<'a, M, BUS, CS> spi::ErrorType for SpiDeviceWithConfig<'a, M, BUS, CS> diff --git a/embassy-executor-macros/src/macros/task.rs b/embassy-executor-macros/src/macros/task.rs index 1efb2788b..96c6267b2 100644 --- a/embassy-executor-macros/src/macros/task.rs +++ b/embassy-executor-macros/src/macros/task.rs @@ -93,10 +93,21 @@ pub fn run(args: &[NestedMeta], f: syn::ItemFn) -> Result ::embassy_executor::SpawnToken { - type Fut = impl ::core::future::Future + 'static; + trait _EmbassyInternalTaskTrait { + type Fut: ::core::future::Future + 'static; + fn construct(#fargs) -> Self::Fut; + } + + impl _EmbassyInternalTaskTrait for () { + type Fut = impl core::future::Future + 'static; + fn construct(#fargs) -> Self::Fut { + #task_inner_ident(#(#full_args,)*) + } + } + const POOL_SIZE: usize = #pool_size; - static POOL: ::embassy_executor::raw::TaskPool = ::embassy_executor::raw::TaskPool::new(); - unsafe { POOL._spawn_async_fn(move || #task_inner_ident(#(#full_args,)*)) } + static POOL: ::embassy_executor::raw::TaskPool<<() as _EmbassyInternalTaskTrait>::Fut, POOL_SIZE> = ::embassy_executor::raw::TaskPool::new(); + unsafe { POOL._spawn_async_fn(move || <() as _EmbassyInternalTaskTrait>::construct(#(#full_args,)*)) } } }; #[cfg(not(feature = "nightly"))] diff --git a/embassy-executor-macros/src/util/ctxt.rs b/embassy-executor-macros/src/util/ctxt.rs index 74c872c3c..9c78cda01 100644 --- a/embassy-executor-macros/src/util/ctxt.rs +++ b/embassy-executor-macros/src/util/ctxt.rs @@ -7,7 +7,6 @@ use std::thread; use proc_macro2::TokenStream; use quote::{quote, ToTokens}; -use syn; /// A type to collect errors together and format them. /// diff --git a/embassy-executor/src/fmt.rs b/embassy-executor/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-executor/src/fmt.rs +++ b/embassy-executor/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-executor/src/raw/mod.rs b/embassy-executor/src/raw/mod.rs index 3d5e3ab9f..d9ea5c005 100644 --- a/embassy-executor/src/raw/mod.rs +++ b/embassy-executor/src/raw/mod.rs @@ -30,7 +30,7 @@ use core::ptr::NonNull; use core::task::{Context, Poll}; #[cfg(feature = "integrated-timers")] -use embassy_time_driver::{self, AlarmHandle}; +use embassy_time_driver::AlarmHandle; #[cfg(feature = "rtos-trace")] use rtos_trace::trace; diff --git a/embassy-executor/tests/test.rs b/embassy-executor/tests/test.rs index 2c2441dd5..348cc7dc4 100644 --- a/embassy-executor/tests/test.rs +++ b/embassy-executor/tests/test.rs @@ -1,4 +1,4 @@ -#![cfg_attr(feature = "nightly", feature(type_alias_impl_trait))] +#![cfg_attr(feature = "nightly", feature(impl_trait_in_assoc_type))] use std::boxed::Box; use std::future::poll_fn; diff --git a/embassy-futures/src/fmt.rs b/embassy-futures/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-futures/src/fmt.rs +++ b/embassy-futures/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-hal-internal/src/fmt.rs b/embassy-hal-internal/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-hal-internal/src/fmt.rs +++ b/embassy-hal-internal/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-hal-internal/src/interrupt.rs b/embassy-hal-internal/src/interrupt.rs index 19dabcf6f..5e64dce9d 100644 --- a/embassy-hal-internal/src/interrupt.rs +++ b/embassy-hal-internal/src/interrupt.rs @@ -30,14 +30,12 @@ macro_rules! interrupt_mod { pub mod typelevel { use super::InterruptExt; - mod sealed { - pub trait Interrupt {} - } + trait SealedInterrupt {} /// Type-level interrupt. /// /// This trait is implemented for all typelevel interrupt types in this module. - pub trait Interrupt: sealed::Interrupt { + pub trait Interrupt: SealedInterrupt { /// Interrupt enum variant. /// @@ -105,7 +103,7 @@ macro_rules! interrupt_mod { #[doc=stringify!($irqs)] #[doc=" typelevel interrupt."] pub enum $irqs {} - impl sealed::Interrupt for $irqs{} + impl SealedInterrupt for $irqs{} impl Interrupt for $irqs { const IRQ: super::Interrupt = super::Interrupt::$irqs; } diff --git a/embassy-net-adin1110/src/fmt.rs b/embassy-net-adin1110/src/fmt.rs index 12737c690..2ac42c557 100644 --- a/embassy-net-adin1110/src/fmt.rs +++ b/embassy-net-adin1110/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -83,14 +83,17 @@ macro_rules! todo { }; } +#[cfg(not(feature = "defmt"))] macro_rules! unreachable { ($($x:tt)*) => { - { - #[cfg(not(feature = "defmt"))] - ::core::unreachable!($($x)*); - #[cfg(feature = "defmt")] - ::defmt::unreachable!($($x)*); - } + ::core::unreachable!($($x)*) + }; +} + +#[cfg(feature = "defmt")] +macro_rules! unreachable { + ($($x:tt)*) => { + ::defmt::unreachable!($($x)*) }; } @@ -113,7 +116,7 @@ macro_rules! trace { #[cfg(feature = "defmt")] ::defmt::trace!($s $(, $x)*); #[cfg(not(any(feature = "log", feature="defmt")))] - let _ignored = ($( & $x ),*); + let _ = ($( & $x ),*); } }; } @@ -126,7 +129,7 @@ macro_rules! debug { #[cfg(feature = "defmt")] ::defmt::debug!($s $(, $x)*); #[cfg(not(any(feature = "log", feature="defmt")))] - let _ignored = ($( & $x ),*); + let _ = ($( & $x ),*); } }; } @@ -139,7 +142,7 @@ macro_rules! info { #[cfg(feature = "defmt")] ::defmt::info!($s $(, $x)*); #[cfg(not(any(feature = "log", feature="defmt")))] - let _ignored = ($( & $x ),*); + let _ = ($( & $x ),*); } }; } @@ -152,7 +155,7 @@ macro_rules! warn { #[cfg(feature = "defmt")] ::defmt::warn!($s $(, $x)*); #[cfg(not(any(feature = "log", feature="defmt")))] - let _ignored = ($( & $x ),*); + let _ = ($( & $x ),*); } }; } @@ -165,7 +168,7 @@ macro_rules! error { #[cfg(feature = "defmt")] ::defmt::error!($s $(, $x)*); #[cfg(not(any(feature = "log", feature="defmt")))] - let _ignored = ($( & $x ),*); + let _ = ($( & $x ),*); } }; } @@ -226,7 +229,7 @@ impl Try for Result { } } -pub struct Bytes<'a>(pub &'a [u8]); +pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { diff --git a/embassy-net-driver-channel/src/fmt.rs b/embassy-net-driver-channel/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-net-driver-channel/src/fmt.rs +++ b/embassy-net-driver-channel/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-net-enc28j60/src/fmt.rs b/embassy-net-enc28j60/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-net-enc28j60/src/fmt.rs +++ b/embassy-net-enc28j60/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-net-enc28j60/src/lib.rs b/embassy-net-enc28j60/src/lib.rs index f18134927..dda35f498 100644 --- a/embassy-net-enc28j60/src/lib.rs +++ b/embassy-net-enc28j60/src/lib.rs @@ -17,7 +17,6 @@ mod phy; mod traits; use core::cmp; -use core::convert::TryInto; use embassy_net_driver::{Capabilities, HardwareAddress, LinkState}; use embassy_time::Duration; @@ -645,8 +644,8 @@ where Self: 'a; fn receive(&mut self, cx: &mut core::task::Context) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { - let rx_buf = unsafe { &mut RX_BUF }; - let tx_buf = unsafe { &mut TX_BUF }; + let rx_buf = unsafe { &mut *core::ptr::addr_of_mut!(RX_BUF) }; + let tx_buf = unsafe { &mut *core::ptr::addr_of_mut!(TX_BUF) }; if let Some(n) = self.receive(rx_buf) { Some((RxToken { buf: &mut rx_buf[..n] }, TxToken { buf: tx_buf, eth: self })) } else { @@ -656,7 +655,7 @@ where } fn transmit(&mut self, _cx: &mut core::task::Context) -> Option> { - let tx_buf = unsafe { &mut TX_BUF }; + let tx_buf = unsafe { &mut *core::ptr::addr_of_mut!(TX_BUF) }; Some(TxToken { buf: tx_buf, eth: self }) } diff --git a/embassy-net-esp-hosted/src/fmt.rs b/embassy-net-esp-hosted/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-net-esp-hosted/src/fmt.rs +++ b/embassy-net-esp-hosted/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-net-ppp/src/fmt.rs b/embassy-net-ppp/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-net-ppp/src/fmt.rs +++ b/embassy-net-ppp/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-net-tuntap/src/lib.rs b/embassy-net-tuntap/src/lib.rs index de30934eb..56f55fba1 100644 --- a/embassy-net-tuntap/src/lib.rs +++ b/embassy-net-tuntap/src/lib.rs @@ -6,7 +6,7 @@ use std::os::unix::io::{AsRawFd, RawFd}; use std::task::Context; use async_io::Async; -use embassy_net_driver::{self, Capabilities, Driver, HardwareAddress, LinkState}; +use embassy_net_driver::{Capabilities, Driver, HardwareAddress, LinkState}; use log::*; /// Get the MTU of the given interface. diff --git a/embassy-net-wiznet/src/chip/mod.rs b/embassy-net-wiznet/src/chip/mod.rs index b987c2b36..e1f963d95 100644 --- a/embassy-net-wiznet/src/chip/mod.rs +++ b/embassy-net-wiznet/src/chip/mod.rs @@ -2,49 +2,40 @@ mod w5500; pub use w5500::W5500; mod w5100s; +use embedded_hal_async::spi::SpiDevice; pub use w5100s::W5100S; -pub(crate) mod sealed { - use embedded_hal_async::spi::SpiDevice; +pub(crate) trait SealedChip { + type Address; - pub trait Chip { - type Address; + const COMMON_MODE: Self::Address; + const COMMON_MAC: Self::Address; + const COMMON_SOCKET_INTR: Self::Address; + const COMMON_PHY_CFG: Self::Address; + const SOCKET_MODE: Self::Address; + const SOCKET_COMMAND: Self::Address; + const SOCKET_RXBUF_SIZE: Self::Address; + const SOCKET_TXBUF_SIZE: Self::Address; + const SOCKET_TX_FREE_SIZE: Self::Address; + const SOCKET_TX_DATA_WRITE_PTR: Self::Address; + const SOCKET_RECVD_SIZE: Self::Address; + const SOCKET_RX_DATA_READ_PTR: Self::Address; + const SOCKET_INTR_MASK: Self::Address; + const SOCKET_INTR: Self::Address; - const COMMON_MODE: Self::Address; - const COMMON_MAC: Self::Address; - const COMMON_SOCKET_INTR: Self::Address; - const COMMON_PHY_CFG: Self::Address; - const SOCKET_MODE: Self::Address; - const SOCKET_COMMAND: Self::Address; - const SOCKET_RXBUF_SIZE: Self::Address; - const SOCKET_TXBUF_SIZE: Self::Address; - const SOCKET_TX_FREE_SIZE: Self::Address; - const SOCKET_TX_DATA_WRITE_PTR: Self::Address; - const SOCKET_RECVD_SIZE: Self::Address; - const SOCKET_RX_DATA_READ_PTR: Self::Address; - const SOCKET_INTR_MASK: Self::Address; - const SOCKET_INTR: Self::Address; + const SOCKET_MODE_VALUE: u8; - const SOCKET_MODE_VALUE: u8; + const BUF_SIZE: u16; + const AUTO_WRAP: bool; - const BUF_SIZE: u16; - const AUTO_WRAP: bool; + fn rx_addr(addr: u16) -> Self::Address; + fn tx_addr(addr: u16) -> Self::Address; - fn rx_addr(addr: u16) -> Self::Address; - fn tx_addr(addr: u16) -> Self::Address; - - async fn bus_read( - spi: &mut SPI, - address: Self::Address, - data: &mut [u8], - ) -> Result<(), SPI::Error>; - async fn bus_write( - spi: &mut SPI, - address: Self::Address, - data: &[u8], - ) -> Result<(), SPI::Error>; - } + async fn bus_read(spi: &mut SPI, address: Self::Address, data: &mut [u8]) + -> Result<(), SPI::Error>; + async fn bus_write(spi: &mut SPI, address: Self::Address, data: &[u8]) -> Result<(), SPI::Error>; } /// Trait for Wiznet chips. -pub trait Chip: sealed::Chip {} +#[allow(private_bounds)] +pub trait Chip: SealedChip {} diff --git a/embassy-net-wiznet/src/chip/w5100s.rs b/embassy-net-wiznet/src/chip/w5100s.rs index 7d328bce5..23ce3ed83 100644 --- a/embassy-net-wiznet/src/chip/w5100s.rs +++ b/embassy-net-wiznet/src/chip/w5100s.rs @@ -8,7 +8,7 @@ const RX_BASE: u16 = 0x6000; pub enum W5100S {} impl super::Chip for W5100S {} -impl super::sealed::Chip for W5100S { +impl super::SealedChip for W5100S { type Address = u16; const COMMON_MODE: Self::Address = 0x00; diff --git a/embassy-net-wiznet/src/chip/w5500.rs b/embassy-net-wiznet/src/chip/w5500.rs index 16236126d..12e610ea2 100644 --- a/embassy-net-wiznet/src/chip/w5500.rs +++ b/embassy-net-wiznet/src/chip/w5500.rs @@ -12,7 +12,7 @@ pub enum RegisterBlock { pub enum W5500 {} impl super::Chip for W5500 {} -impl super::sealed::Chip for W5500 { +impl super::SealedChip for W5500 { type Address = (RegisterBlock, u16); const COMMON_MODE: Self::Address = (RegisterBlock::Common, 0x00); diff --git a/embassy-net/src/fmt.rs b/embassy-net/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-net/src/fmt.rs +++ b/embassy-net/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-nrf/src/fmt.rs b/embassy-nrf/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-nrf/src/fmt.rs +++ b/embassy-nrf/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index 3649ea61a..f2353f21d 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs @@ -473,10 +473,12 @@ impl sealed::Pin for AnyPin { // ==================== +#[cfg(not(feature = "_nrf51"))] pub(crate) trait PselBits { fn psel_bits(&self) -> u32; } +#[cfg(not(feature = "_nrf51"))] impl<'a, P: Pin> PselBits for Option> { #[inline] fn psel_bits(&self) -> u32 { diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 12f4ed0a0..4a28279a9 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -167,8 +167,10 @@ unsafe fn handle_gpiote_interrupt() { } } +#[cfg(not(feature = "_nrf51"))] struct BitIter(u32); +#[cfg(not(feature = "_nrf51"))] impl Iterator for BitIter { type Item = u32; diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 718f229a3..3457dd933 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -225,10 +225,31 @@ pub mod config { /// Config for the first stage DCDC (VDDH -> VDD), if disabled LDO will be used. #[cfg(feature = "nrf52840")] pub reg0: bool, + /// Configure the voltage of the first stage DCDC. It is stored in non-volatile memory (UICR.REGOUT0 register); pass None to not touch it. + #[cfg(feature = "nrf52840")] + pub reg0_voltage: Option, /// Config for the second stage DCDC (VDD -> DEC4), if disabled LDO will be used. pub reg1: bool, } + /// Output voltage setting for REG0 regulator stage. + #[cfg(feature = "nrf52840")] + pub enum Reg0Voltage { + /// 1.8 V + _1V8 = 0, + /// 2.1 V + _2V1 = 1, + /// 2.4 V + _2V4 = 2, + /// 2.7 V + _2V7 = 3, + /// 3.0 V + _3V0 = 4, + /// 3.3 V + _3v3 = 5, + //ERASED = 7, means 1.8V + } + /// Settings for enabling the built in DCDC converters. #[cfg(feature = "_nrf5340-app")] pub struct DcdcConfig { @@ -279,6 +300,8 @@ pub mod config { dcdc: DcdcConfig { #[cfg(feature = "nrf52840")] reg0: false, + #[cfg(feature = "nrf52840")] + reg0_voltage: None, reg1: false, }, #[cfg(feature = "_nrf5340-app")] @@ -337,6 +360,7 @@ mod consts { pub const UICR_PSELRESET2: *mut u32 = 0x10001204 as *mut u32; pub const UICR_NFCPINS: *mut u32 = 0x1000120C as *mut u32; pub const UICR_APPROTECT: *mut u32 = 0x10001208 as *mut u32; + pub const UICR_REGOUT0: *mut u32 = 0x10001304 as *mut u32; pub const APPROTECT_ENABLED: u32 = 0x0000_0000; pub const APPROTECT_DISABLED: u32 = 0x0000_005a; } @@ -493,6 +517,21 @@ pub fn init(config: config::Config) -> Peripherals { } } + #[cfg(feature = "nrf52840")] + unsafe { + if let Some(value) = config.dcdc.reg0_voltage { + let value = value as u32; + let res = uicr_write_masked(consts::UICR_REGOUT0, value, 0b00000000_00000000_00000000_00000111); + needs_reset |= res == WriteResult::Written; + if res == WriteResult::Failed { + warn!( + "Failed to set regulator voltage, as UICR is already programmed to some other setting, and can't be changed without erasing it.\n\ + To fix this, erase UICR manually, for example using `probe-rs erase` or `nrfjprog --eraseuicr`." + ); + } + } + } + if needs_reset { cortex_m::peripheral::SCB::sys_reset(); } diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index 3c35baee5..2970ad3f2 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs @@ -21,8 +21,6 @@ pub(crate) mod sealed { fn regs() -> &'static pac::timer0::RegisterBlock; } pub trait ExtendedInstance {} - - pub trait TimerType {} } /// Basic Timer instance. diff --git a/embassy-rp/src/dma.rs b/embassy-rp/src/dma.rs index 088a842a1..44aabce6b 100644 --- a/embassy-rp/src/dma.rs +++ b/embassy-rp/src/dma.rs @@ -96,7 +96,7 @@ pub unsafe fn write_repeated<'a, C: Channel, W: Word>( ) -> Transfer<'a, C> { copy_inner( ch, - &mut DUMMY as *const u32, + core::ptr::addr_of_mut!(DUMMY) as *const u32, to as *mut u32, len, W::size(), diff --git a/embassy-rp/src/flash.rs b/embassy-rp/src/flash.rs index 8bac93684..422b77400 100644 --- a/embassy-rp/src/flash.rs +++ b/embassy-rp/src/flash.rs @@ -420,8 +420,6 @@ impl<'d, T: Instance, const FLASH_SIZE: usize> embedded_storage_async::nor_flash #[allow(dead_code)] mod ram_helpers { - use core::marker::PhantomData; - use super::*; use crate::rom_data; diff --git a/embassy-rp/src/float/mod.rs b/embassy-rp/src/float/mod.rs index 945afff90..3ad6f1c50 100644 --- a/embassy-rp/src/float/mod.rs +++ b/embassy-rp/src/float/mod.rs @@ -89,6 +89,7 @@ pub(crate) trait Float: } /// Returns true if `self` is infinity + #[allow(unused)] fn is_infinity(self) -> bool { (self.repr() & (Self::EXPONENT_MASK | Self::SIGNIFICAND_MASK)) == Self::EXPONENT_MASK } diff --git a/embassy-rp/src/fmt.rs b/embassy-rp/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-rp/src/fmt.rs +++ b/embassy-rp/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index 405bddfd8..a84c00a2c 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -976,8 +976,6 @@ impl_pin!(PIN_QSPI_SD3, Bank::Qspi, 5); // ==================== mod eh02 { - use core::convert::Infallible; - use super::*; impl<'d> embedded_hal_02::digital::v2::InputPin for Input<'d> { diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index 7092b3fab..d91cea410 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -274,7 +274,7 @@ pub fn install_core0_stack_guard() -> Result<(), ()> { extern "C" { static mut _stack_end: usize; } - unsafe { install_stack_guard(&mut _stack_end as *mut usize) } + unsafe { install_stack_guard(core::ptr::addr_of_mut!(_stack_end)) } } #[inline(always)] @@ -354,6 +354,7 @@ pub fn init(config: config::Config) -> Peripherals { /// Extension trait for PAC regs, adding atomic xor/bitset/bitclear writes. trait RegExt { + #[allow(unused)] fn write_xor(&self, f: impl FnOnce(&mut T) -> R) -> R; fn write_set(&self, f: impl FnOnce(&mut T) -> R) -> R; fn write_clear(&self, f: impl FnOnce(&mut T) -> R) -> R; diff --git a/embassy-rp/src/relocate.rs b/embassy-rp/src/relocate.rs index 40cb2667b..34487819f 100644 --- a/embassy-rp/src/relocate.rs +++ b/embassy-rp/src/relocate.rs @@ -1,5 +1,3 @@ -use core::iter::Iterator; - use pio::{Program, SideSet, Wrap}; pub struct CodeIterator<'a, I> diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs index 7622539f1..da1157984 100644 --- a/embassy-rp/src/uart/buffered.rs +++ b/embassy-rp/src/uart/buffered.rs @@ -1,17 +1,11 @@ //! Buffered UART driver. -use core::future::{poll_fn, Future}; +use core::future::Future; use core::slice; -use core::task::Poll; -use atomic_polyfill::{AtomicU8, Ordering}; +use atomic_polyfill::AtomicU8; use embassy_hal_internal::atomic_ring_buffer::RingBuffer; -use embassy_sync::waitqueue::AtomicWaker; -use embassy_time::Timer; use super::*; -use crate::clocks::clk_peri_freq; -use crate::interrupt::typelevel::{Binding, Interrupt}; -use crate::{interrupt, RegExt}; pub struct State { tx_waker: AtomicWaker, diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index 905661d64..d68dee4a3 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs @@ -465,7 +465,6 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { trait Dir { fn dir() -> Direction; - fn waker(i: usize) -> &'static AtomicWaker; } /// Type for In direction. @@ -474,11 +473,6 @@ impl Dir for In { fn dir() -> Direction { Direction::In } - - #[inline] - fn waker(i: usize) -> &'static AtomicWaker { - &EP_IN_WAKERS[i] - } } /// Type for Out direction. @@ -487,11 +481,6 @@ impl Dir for Out { fn dir() -> Direction { Direction::Out } - - #[inline] - fn waker(i: usize) -> &'static AtomicWaker { - &EP_OUT_WAKERS[i] - } } /// Endpoint for RP USB driver. diff --git a/embassy-stm32-wpan/src/consts.rs b/embassy-stm32-wpan/src/consts.rs index bd70851ea..6aaef1d35 100644 --- a/embassy-stm32-wpan/src/consts.rs +++ b/embassy-stm32-wpan/src/consts.rs @@ -1,5 +1,3 @@ -use core::convert::TryFrom; - use crate::evt::CsEvt; use crate::PacketHeader; diff --git a/embassy-stm32-wpan/src/fmt.rs b/embassy-stm32-wpan/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-stm32-wpan/src/fmt.rs +++ b/embassy-stm32-wpan/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index d3626610e..7c6312f6c 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -70,7 +70,7 @@ rand_core = "0.6.3" sdio-host = "0.5.0" critical-section = "1.1" #stm32-metapac = { version = "15" } -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-c8b32ecae7d70cea2705095c4fc6bd5f59d238d5" } +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f84633553331c2d154ee72de779a40cbb10fd1bd" } vcell = "0.1.3" nb = "1.0.0" stm32-fmc = "0.3.0" @@ -94,7 +94,7 @@ critical-section = { version = "1.1", features = ["std"] } proc-macro2 = "1.0.36" quote = "1.0.15" #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-c8b32ecae7d70cea2705095c4fc6bd5f59d238d5", default-features = false, features = ["metadata"]} +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-f84633553331c2d154ee72de779a40cbb10fd1bd", default-features = false, features = ["metadata"]} [features] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index fe5236ed6..15bb8ea62 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -584,7 +584,7 @@ fn main() { }; g.extend(quote! { - impl crate::rcc::sealed::RccPeripheral for peripherals::#pname { + impl crate::rcc::SealedRccPeripheral for peripherals::#pname { fn frequency() -> crate::time::Hertz { #clock_frequency } @@ -826,20 +826,20 @@ fn main() { (("dcmi", "PIXCLK"), quote!(crate::dcmi::PixClkPin)), (("usb", "DP"), quote!(crate::usb::DpPin)), (("usb", "DM"), quote!(crate::usb::DmPin)), - (("otg", "DP"), quote!(crate::usb_otg::DpPin)), - (("otg", "DM"), quote!(crate::usb_otg::DmPin)), - (("otg", "ULPI_CK"), quote!(crate::usb_otg::UlpiClkPin)), - (("otg", "ULPI_DIR"), quote!(crate::usb_otg::UlpiDirPin)), - (("otg", "ULPI_NXT"), quote!(crate::usb_otg::UlpiNxtPin)), - (("otg", "ULPI_STP"), quote!(crate::usb_otg::UlpiStpPin)), - (("otg", "ULPI_D0"), quote!(crate::usb_otg::UlpiD0Pin)), - (("otg", "ULPI_D1"), quote!(crate::usb_otg::UlpiD1Pin)), - (("otg", "ULPI_D2"), quote!(crate::usb_otg::UlpiD2Pin)), - (("otg", "ULPI_D3"), quote!(crate::usb_otg::UlpiD3Pin)), - (("otg", "ULPI_D4"), quote!(crate::usb_otg::UlpiD4Pin)), - (("otg", "ULPI_D5"), quote!(crate::usb_otg::UlpiD5Pin)), - (("otg", "ULPI_D6"), quote!(crate::usb_otg::UlpiD6Pin)), - (("otg", "ULPI_D7"), quote!(crate::usb_otg::UlpiD7Pin)), + (("otg", "DP"), quote!(crate::usb::DpPin)), + (("otg", "DM"), quote!(crate::usb::DmPin)), + (("otg", "ULPI_CK"), quote!(crate::usb::UlpiClkPin)), + (("otg", "ULPI_DIR"), quote!(crate::usb::UlpiDirPin)), + (("otg", "ULPI_NXT"), quote!(crate::usb::UlpiNxtPin)), + (("otg", "ULPI_STP"), quote!(crate::usb::UlpiStpPin)), + (("otg", "ULPI_D0"), quote!(crate::usb::UlpiD0Pin)), + (("otg", "ULPI_D1"), quote!(crate::usb::UlpiD1Pin)), + (("otg", "ULPI_D2"), quote!(crate::usb::UlpiD2Pin)), + (("otg", "ULPI_D3"), quote!(crate::usb::UlpiD3Pin)), + (("otg", "ULPI_D4"), quote!(crate::usb::UlpiD4Pin)), + (("otg", "ULPI_D5"), quote!(crate::usb::UlpiD5Pin)), + (("otg", "ULPI_D6"), quote!(crate::usb::UlpiD6Pin)), + (("otg", "ULPI_D7"), quote!(crate::usb::UlpiD7Pin)), (("can", "TX"), quote!(crate::can::TxPin)), (("can", "RX"), quote!(crate::can::RxPin)), (("eth", "REF_CLK"), quote!(crate::eth::RefClkPin)), @@ -1486,7 +1486,7 @@ fn main() { #[crate::interrupt] unsafe fn #irq () { #( - ::on_irq(); + ::on_irq(); )* } } diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs index b27b99827..cecf67947 100644 --- a/embassy-stm32/src/adc/f1.rs +++ b/embassy-stm32/src/adc/f1.rs @@ -33,7 +33,7 @@ impl interrupt::typelevel::Handler for InterruptHandl pub struct Vref; impl AdcPin for Vref {} -impl super::sealed::AdcPin for Vref { +impl super::SealedAdcPin for Vref { fn channel(&self) -> u8 { 17 } @@ -41,7 +41,7 @@ impl super::sealed::AdcPin for Vref { pub struct Temperature; impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { 16 } diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs index efade1f64..c5581dba1 100644 --- a/embassy-stm32/src/adc/f3.rs +++ b/embassy-stm32/src/adc/f3.rs @@ -33,7 +33,7 @@ impl interrupt::typelevel::Handler for InterruptHandl pub struct Vref; impl AdcPin for Vref {} -impl super::sealed::AdcPin for Vref { +impl super::SealedAdcPin for Vref { fn channel(&self) -> u8 { 18 } @@ -48,7 +48,7 @@ impl Vref { pub struct Temperature; impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { 16 } @@ -102,7 +102,7 @@ impl<'d, T: Instance> Adc<'d, T> { } fn freq() -> Hertz { - ::frequency() + ::frequency() } pub fn sample_time_for_us(&self, us: u32) -> SampleTime { diff --git a/embassy-stm32/src/adc/f3_v1_1.rs b/embassy-stm32/src/adc/f3_v1_1.rs index f842893fa..672ace04f 100644 --- a/embassy-stm32/src/adc/f3_v1_1.rs +++ b/embassy-stm32/src/adc/f3_v1_1.rs @@ -65,7 +65,7 @@ fn update_vref(op: i8) { pub struct Vref(core::marker::PhantomData); impl AdcPin for Vref {} -impl super::sealed::AdcPin for Vref { +impl super::SealedAdcPin for Vref { fn channel(&self) -> u8 { 17 } @@ -124,7 +124,7 @@ impl Drop for Vref { pub struct Temperature(core::marker::PhantomData); impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { 16 } diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index 0d0d40549..ead2357ce 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs @@ -17,6 +17,8 @@ mod _version; #[allow(unused)] #[cfg(not(adc_f3_v2))] pub use _version::*; +#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] +use embassy_sync::waitqueue::AtomicWaker; #[cfg(not(any(adc_f1, adc_f3_v2)))] pub use crate::pac::adc::vals::Res as Resolution; @@ -31,63 +33,65 @@ pub struct Adc<'d, T: Instance> { sample_time: SampleTime, } -pub(crate) mod sealed { - #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] - use embassy_sync::waitqueue::AtomicWaker; +#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] +pub struct State { + pub waker: AtomicWaker, +} - #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] - pub struct State { - pub waker: AtomicWaker, - } - - #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] - impl State { - pub const fn new() -> Self { - Self { - waker: AtomicWaker::new(), - } +#[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] +impl State { + pub const fn new() -> Self { + Self { + waker: AtomicWaker::new(), } } +} - pub trait InterruptableInstance { - type Interrupt: crate::interrupt::typelevel::Interrupt; - } +trait SealedInstance { + #[allow(unused)] + fn regs() -> crate::pac::adc::Adc; + #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] + fn common_regs() -> crate::pac::adccommon::AdcCommon; + #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] + fn state() -> &'static State; +} - pub trait Instance: InterruptableInstance { - fn regs() -> crate::pac::adc::Adc; - #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))] - fn common_regs() -> crate::pac::adccommon::AdcCommon; - #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] - fn state() -> &'static State; - } +pub(crate) trait SealedAdcPin { + #[cfg(any(adc_v1, adc_l0, adc_v2))] + fn set_as_analog(&mut self) {} - pub trait AdcPin { - #[cfg(any(adc_v1, adc_l0, adc_v2))] - fn set_as_analog(&mut self) {} + #[allow(unused)] + fn channel(&self) -> u8; +} - fn channel(&self) -> u8; - } - - pub trait InternalChannel { - fn channel(&self) -> u8; - } +trait SealedInternalChannel { + #[allow(unused)] + fn channel(&self) -> u8; } /// ADC instance. #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5)))] -pub trait Instance: sealed::Instance + crate::Peripheral

{} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + crate::Peripheral

{ + type Interrupt: crate::interrupt::typelevel::Interrupt; +} /// ADC instance. #[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0, adc_h5))] -pub trait Instance: sealed::Instance + crate::Peripheral

+ crate::rcc::RccPeripheral {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + crate::Peripheral

+ crate::rcc::RccPeripheral { + type Interrupt: crate::interrupt::typelevel::Interrupt; +} /// ADC pin. -pub trait AdcPin: sealed::AdcPin {} +#[allow(private_bounds)] +pub trait AdcPin: SealedAdcPin {} /// ADC internal channel. -pub trait InternalChannel: sealed::InternalChannel {} +#[allow(private_bounds)] +pub trait InternalChannel: SealedInternalChannel {} foreach_adc!( ($inst:ident, $common_inst:ident, $clock:ident) => { - impl crate::adc::sealed::Instance for peripherals::$inst { + impl crate::adc::SealedInstance for peripherals::$inst { fn regs() -> crate::pac::adc::Adc { crate::pac::$inst } @@ -98,21 +102,15 @@ foreach_adc!( } #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))] - fn state() -> &'static sealed::State { - static STATE: sealed::State = sealed::State::new(); + fn state() -> &'static State { + static STATE: State = State::new(); &STATE } } - foreach_interrupt!( - ($inst,adc,ADC,GLOBAL,$irq:ident) => { - impl sealed::InterruptableInstance for peripherals::$inst { - type Interrupt = crate::interrupt::typelevel::$irq; - } - }; - ); - - impl crate::adc::Instance for peripherals::$inst {} + impl crate::adc::Instance for peripherals::$inst { + type Interrupt = crate::_generated::peripheral_interrupts::$inst::GLOBAL; + } }; ); @@ -120,10 +118,10 @@ macro_rules! impl_adc_pin { ($inst:ident, $pin:ident, $ch:expr) => { impl crate::adc::AdcPin for crate::peripherals::$pin {} - impl crate::adc::sealed::AdcPin for crate::peripherals::$pin { + impl crate::adc::SealedAdcPin for crate::peripherals::$pin { #[cfg(any(adc_v1, adc_l0, adc_v2))] fn set_as_analog(&mut self) { - ::set_as_analog(self); + ::set_as_analog(self); } fn channel(&self) -> u8 { diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs index a8dc6ce98..e9b46be80 100644 --- a/embassy-stm32/src/adc/v1.rs +++ b/embassy-stm32/src/adc/v1.rs @@ -39,7 +39,7 @@ pub struct Vbat; impl AdcPin for Vbat {} #[cfg(not(adc_l0))] -impl super::sealed::AdcPin for Vbat { +impl super::SealedAdcPin for Vbat { fn channel(&self) -> u8 { 18 } @@ -47,7 +47,7 @@ impl super::sealed::AdcPin for Vbat { pub struct Vref; impl AdcPin for Vref {} -impl super::sealed::AdcPin for Vref { +impl super::SealedAdcPin for Vref { fn channel(&self) -> u8 { 17 } @@ -55,7 +55,7 @@ impl super::sealed::AdcPin for Vref { pub struct Temperature; impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { 16 } diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index f6f7dbfcc..a43eb72db 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs @@ -16,7 +16,7 @@ pub const ADC_POWERUP_TIME_US: u32 = 3; pub struct VrefInt; impl AdcPin for VrefInt {} -impl super::sealed::AdcPin for VrefInt { +impl super::SealedAdcPin for VrefInt { fn channel(&self) -> u8 { 17 } @@ -31,7 +31,7 @@ impl VrefInt { pub struct Temperature; impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { cfg_if::cfg_if! { if #[cfg(any(stm32f2, stm32f40, stm32f41))] { @@ -52,7 +52,7 @@ impl Temperature { pub struct Vbat; impl AdcPin for Vbat {} -impl super::sealed::AdcPin for Vbat { +impl super::SealedAdcPin for Vbat { fn channel(&self) -> u8 { 18 } diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index 5f3512cad..8c9b47197 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs @@ -12,7 +12,7 @@ pub const VREF_CALIB_MV: u32 = 3000; pub struct VrefInt; impl AdcPin for VrefInt {} -impl super::sealed::AdcPin for VrefInt { +impl super::SealedAdcPin for VrefInt { fn channel(&self) -> u8 { cfg_if! { if #[cfg(adc_g0)] { @@ -29,7 +29,7 @@ impl super::sealed::AdcPin for VrefInt { pub struct Temperature; impl AdcPin for Temperature {} -impl super::sealed::AdcPin for Temperature { +impl super::SealedAdcPin for Temperature { fn channel(&self) -> u8 { cfg_if! { if #[cfg(adc_g0)] { @@ -46,7 +46,7 @@ impl super::sealed::AdcPin for Temperature { pub struct Vbat; impl AdcPin for Vbat {} -impl super::sealed::AdcPin for Vbat { +impl super::SealedAdcPin for Vbat { fn channel(&self) -> u8 { cfg_if! { if #[cfg(adc_g0)] { @@ -65,7 +65,7 @@ cfg_if! { if #[cfg(adc_h5)] { pub struct VddCore; impl AdcPin for VddCore {} - impl super::sealed::AdcPin for VddCore { + impl super::SealedAdcPin for VddCore { fn channel(&self) -> u8 { 6 } diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index 3fd047375..1ae25bea2 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs @@ -35,7 +35,7 @@ const VBAT_CHANNEL: u8 = 17; /// Internal voltage reference channel. pub struct VrefInt; impl InternalChannel for VrefInt {} -impl super::sealed::InternalChannel for VrefInt { +impl super::SealedInternalChannel for VrefInt { fn channel(&self) -> u8 { VREF_CHANNEL } @@ -44,7 +44,7 @@ impl super::sealed::InternalChannel for VrefInt { /// Internal temperature channel. pub struct Temperature; impl InternalChannel for Temperature {} -impl super::sealed::InternalChannel for Temperature { +impl super::SealedInternalChannel for Temperature { fn channel(&self) -> u8 { TEMP_CHANNEL } @@ -53,7 +53,7 @@ impl super::sealed::InternalChannel for Temperature { /// Internal battery voltage channel. pub struct Vbat; impl InternalChannel for Vbat {} -impl super::sealed::InternalChannel for Vbat { +impl super::SealedInternalChannel for Vbat { fn channel(&self) -> u8 { VBAT_CHANNEL } @@ -276,7 +276,7 @@ impl<'d, T: Instance> Adc<'d, T> { pub fn read

(&mut self, pin: &mut P) -> u16 where P: AdcPin, - P: crate::gpio::sealed::Pin, + P: crate::gpio::Pin, { pin.set_as_analog(); diff --git a/embassy-stm32/src/can/bx/mod.rs b/embassy-stm32/src/can/bx/mod.rs index 33e702c6e..a369ae6fd 100644 --- a/embassy-stm32/src/can/bx/mod.rs +++ b/embassy-stm32/src/can/bx/mod.rs @@ -28,7 +28,7 @@ pub mod filter; #[allow(clippy::all)] // generated code use core::cmp::{Ord, Ordering}; -use core::convert::{Infallible, Into, TryInto}; +use core::convert::Infallible; use core::marker::PhantomData; use core::mem; diff --git a/embassy-stm32/src/can/bxcan.rs b/embassy-stm32/src/can/bxcan.rs index bb7cc3d7f..017c5110d 100644 --- a/embassy-stm32/src/can/bxcan.rs +++ b/embassy-stm32/src/can/bxcan.rs @@ -1,4 +1,3 @@ -use core::convert::AsMut; use core::future::poll_fn; use core::marker::PhantomData; use core::ops::{Deref, DerefMut}; @@ -8,9 +7,12 @@ pub mod bx; pub use bx::{filter, Data, ExtendedId, Fifo, Frame, Header, Id, StandardId}; use embassy_hal_internal::{into_ref, PeripheralRef}; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::channel::Channel; +use embassy_sync::waitqueue::AtomicWaker; use futures::FutureExt; -use crate::gpio::sealed::AFType; +use crate::gpio::AFType; use crate::interrupt::typelevel::Interrupt; use crate::pac::can::vals::{Ide, Lec}; use crate::rcc::RccPeripheral; @@ -486,37 +488,30 @@ impl<'d, T: Instance> DerefMut for Can<'d, T> { } } -pub(crate) mod sealed { - use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; - use embassy_sync::channel::Channel; - use embassy_sync::waitqueue::AtomicWaker; +struct State { + pub tx_waker: AtomicWaker, + pub err_waker: AtomicWaker, + pub rx_queue: Channel, +} - use super::Envelope; - - pub struct State { - pub tx_waker: AtomicWaker, - pub err_waker: AtomicWaker, - pub rx_queue: Channel, - } - - impl State { - pub const fn new() -> Self { - Self { - tx_waker: AtomicWaker::new(), - err_waker: AtomicWaker::new(), - rx_queue: Channel::new(), - } +impl State { + pub const fn new() -> Self { + Self { + tx_waker: AtomicWaker::new(), + err_waker: AtomicWaker::new(), + rx_queue: Channel::new(), } } - - pub trait Instance { - fn regs() -> crate::pac::can::Can; - fn state() -> &'static State; - } +} + +trait SealedInstance { + fn regs() -> crate::pac::can::Can; + fn state() -> &'static State; } /// CAN instance trait. -pub trait Instance: sealed::Instance + RccPeripheral + 'static { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static { /// TX interrupt for this instance. type TXInterrupt: crate::interrupt::typelevel::Interrupt; /// RX0 interrupt for this instance. @@ -534,14 +529,14 @@ unsafe impl<'d, T: Instance> crate::can::bx::Instance for BxcanInstance<'d, T> { foreach_peripheral!( (can, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { fn regs() -> crate::pac::can::Can { crate::pac::$inst } - fn state() -> &'static sealed::State { - static STATE: sealed::State = sealed::State::new(); + fn state() -> &'static State { + static STATE: State = State::new(); &STATE } } diff --git a/embassy-stm32/src/can/fd/message_ram/mod.rs b/embassy-stm32/src/can/fd/message_ram/mod.rs index 830edf3bb..040a999b4 100644 --- a/embassy-stm32/src/can/fd/message_ram/mod.rs +++ b/embassy-stm32/src/can/fd/message_ram/mod.rs @@ -140,26 +140,6 @@ pub(crate) struct _TxBufferElement; impl generic::Readable for TxBufferElementHeader {} impl generic::Writable for TxBufferElementHeader {} -/// FdCan Message RAM instance. -/// -/// # Safety -/// -/// It is only safe to implement this trait, when: -/// -/// * The implementing type has ownership of the Message RAM, preventing any -/// other accesses to the register block. -/// * `MSG_RAM` is a pointer to the Message RAM block and can be safely accessed -/// for as long as ownership or a borrow of the implementing type is present. -pub unsafe trait Instance { - const MSG_RAM: *mut RegisterBlock; - fn msg_ram(&self) -> &RegisterBlock { - unsafe { &*Self::MSG_RAM } - } - fn msg_ram_mut(&mut self) -> &mut RegisterBlock { - unsafe { &mut *Self::MSG_RAM } - } -} - // Ensure the RegisterBlock is the same size as on pg 1957 of RM0440. static_assertions::assert_eq_size!(Filters, [u32; 28 + 16]); static_assertions::assert_eq_size!(Receive, [u32; 54]); diff --git a/embassy-stm32/src/can/fd/peripheral.rs b/embassy-stm32/src/can/fd/peripheral.rs index 682e13f4b..76b76afe1 100644 --- a/embassy-stm32/src/can/fd/peripheral.rs +++ b/embassy-stm32/src/can/fd/peripheral.rs @@ -325,17 +325,6 @@ impl Registers { */ } - /// Disables the CAN interface and returns back the raw peripheral it was created from. - #[inline] - pub fn free(mut self) { - //self.disable_interrupts(Interrupts::all()); - - //TODO check this! - self.enter_init_mode(); - self.set_power_down_mode(true); - //self.control.instance - } - /// Applies the settings of a new FdCanConfig See [`FdCanConfig`] #[inline] pub fn apply_config(&mut self, config: FdCanConfig) { @@ -419,55 +408,6 @@ impl Registers { self.leave_init_mode(config); } - /// Moves out of ConfigMode and into InternalLoopbackMode - #[inline] - pub fn into_internal_loopback(mut self, config: FdCanConfig) { - self.set_loopback_mode(LoopbackMode::Internal); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into ExternalLoopbackMode - #[inline] - pub fn into_external_loopback(mut self, config: FdCanConfig) { - self.set_loopback_mode(LoopbackMode::External); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into RestrictedOperationMode - #[inline] - pub fn into_restricted(mut self, config: FdCanConfig) { - self.set_restricted_operations(true); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into NormalOperationMode - #[inline] - pub fn into_normal(mut self, config: FdCanConfig) { - self.set_normal_operations(true); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into BusMonitoringMode - #[inline] - pub fn into_bus_monitoring(mut self, config: FdCanConfig) { - self.set_bus_monitoring_mode(true); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into Testmode - #[inline] - pub fn into_test_mode(mut self, config: FdCanConfig) { - self.set_test_mode(true); - self.leave_init_mode(config); - } - - /// Moves out of ConfigMode and into PoweredDownmode - #[inline] - pub fn into_powered_down(mut self, config: FdCanConfig) { - self.set_power_down_mode(true); - self.leave_init_mode(config); - } - /// Configures the bit timings. /// /// You can use to calculate the `btr` parameter. Enter @@ -565,6 +505,7 @@ impl Registers { /// Configures and resets the timestamp counter #[inline] + #[allow(unused)] pub fn set_timestamp_counter_source(&mut self, select: TimestampSource) { #[cfg(stm32h7)] let (tcp, tss) = match select { diff --git a/embassy-stm32/src/can/fdcan.rs b/embassy-stm32/src/can/fdcan.rs index fe8969a5a..4ea036ab4 100644 --- a/embassy-stm32/src/can/fdcan.rs +++ b/embassy-stm32/src/can/fdcan.rs @@ -5,10 +5,11 @@ use core::task::Poll; use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -use embassy_sync::channel::Channel; +use embassy_sync::channel::{Channel, DynamicReceiver, DynamicSender}; +use embassy_sync::waitqueue::AtomicWaker; use crate::can::fd::peripheral::Registers; -use crate::gpio::sealed::AFType; +use crate::gpio::AFType; use crate::interrupt::typelevel::Interrupt; use crate::rcc::RccPeripheral; use crate::{interrupt, peripherals, Peripheral}; @@ -53,8 +54,8 @@ impl interrupt::typelevel::Handler for IT0Interrup } match &T::state().tx_mode { - sealed::TxMode::NonBuffered(waker) => waker.wake(), - sealed::TxMode::ClassicBuffered(buf) => { + TxMode::NonBuffered(waker) => waker.wake(), + TxMode::ClassicBuffered(buf) => { if !T::registers().tx_queue_is_full() { match buf.tx_receiver.try_receive() { Ok(frame) => { @@ -64,7 +65,7 @@ impl interrupt::typelevel::Handler for IT0Interrup } } } - sealed::TxMode::FdBuffered(buf) => { + TxMode::FdBuffered(buf) => { if !T::registers().tx_queue_is_full() { match buf.tx_receiver.try_receive() { Ok(frame) => { @@ -467,14 +468,14 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> fn setup(self) -> Self { // We don't want interrupts being processed while we change modes. critical_section::with(|_| unsafe { - let rx_inner = sealed::ClassicBufferedRxInner { + let rx_inner = ClassicBufferedRxInner { rx_sender: self.rx_buf.sender().into(), }; - let tx_inner = sealed::ClassicBufferedTxInner { + let tx_inner = ClassicBufferedTxInner { tx_receiver: self.tx_buf.receiver().into(), }; - T::mut_state().rx_mode = sealed::RxMode::ClassicBuffered(rx_inner); - T::mut_state().tx_mode = sealed::TxMode::ClassicBuffered(tx_inner); + T::mut_state().rx_mode = RxMode::ClassicBuffered(rx_inner); + T::mut_state().tx_mode = TxMode::ClassicBuffered(tx_inner); }); self } @@ -509,8 +510,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr { fn drop(&mut self) { critical_section::with(|_| unsafe { - T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); - T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); }); } } @@ -585,14 +586,14 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> fn setup(self) -> Self { // We don't want interrupts being processed while we change modes. critical_section::with(|_| unsafe { - let rx_inner = sealed::FdBufferedRxInner { + let rx_inner = FdBufferedRxInner { rx_sender: self.rx_buf.sender().into(), }; - let tx_inner = sealed::FdBufferedTxInner { + let tx_inner = FdBufferedTxInner { tx_receiver: self.tx_buf.receiver().into(), }; - T::mut_state().rx_mode = sealed::RxMode::FdBuffered(rx_inner); - T::mut_state().tx_mode = sealed::TxMode::FdBuffered(tx_inner); + T::mut_state().rx_mode = RxMode::FdBuffered(rx_inner); + T::mut_state().tx_mode = TxMode::FdBuffered(tx_inner); }); self } @@ -627,8 +628,8 @@ impl<'c, 'd, T: Instance, const TX_BUF_SIZE: usize, const RX_BUF_SIZE: usize> Dr { fn drop(&mut self) { critical_section::with(|_| unsafe { - T::mut_state().rx_mode = sealed::RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); - T::mut_state().tx_mode = sealed::TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + T::mut_state().rx_mode = RxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); + T::mut_state().tx_mode = TxMode::NonBuffered(embassy_sync::waitqueue::AtomicWaker::new()); }); } } @@ -677,192 +678,180 @@ impl<'c, 'd, T: Instance> FdcanRx<'d, T> { } } -pub(crate) mod sealed { - use core::future::poll_fn; - use core::task::Poll; +struct ClassicBufferedRxInner { + rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>, +} +struct ClassicBufferedTxInner { + tx_receiver: DynamicReceiver<'static, ClassicFrame>, +} - use embassy_sync::channel::{DynamicReceiver, DynamicSender}; - use embassy_sync::waitqueue::AtomicWaker; +struct FdBufferedRxInner { + rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>, +} +struct FdBufferedTxInner { + tx_receiver: DynamicReceiver<'static, FdFrame>, +} - use super::CanHeader; - use crate::can::_version::{BusError, Timestamp}; - use crate::can::frame::{ClassicFrame, FdFrame}; +enum RxMode { + NonBuffered(AtomicWaker), + ClassicBuffered(ClassicBufferedRxInner), + FdBuffered(FdBufferedRxInner), +} - pub struct ClassicBufferedRxInner { - pub rx_sender: DynamicSender<'static, Result<(ClassicFrame, Timestamp), BusError>>, - } - pub struct ClassicBufferedTxInner { - pub tx_receiver: DynamicReceiver<'static, ClassicFrame>, - } - - pub struct FdBufferedRxInner { - pub rx_sender: DynamicSender<'static, Result<(FdFrame, Timestamp), BusError>>, - } - pub struct FdBufferedTxInner { - pub tx_receiver: DynamicReceiver<'static, FdFrame>, - } - - pub enum RxMode { - NonBuffered(AtomicWaker), - ClassicBuffered(ClassicBufferedRxInner), - FdBuffered(FdBufferedRxInner), - } - - impl RxMode { - pub fn register(&self, arg: &core::task::Waker) { - match self { - RxMode::NonBuffered(waker) => waker.register(arg), - _ => { - panic!("Bad Mode") - } - } - } - - pub fn on_interrupt(&self, fifonr: usize) { - T::regs().ir().write(|w| w.set_rfn(fifonr, true)); - match self { - RxMode::NonBuffered(waker) => { - waker.wake(); - } - RxMode::ClassicBuffered(buf) => { - if let Some(result) = self.read::() { - let _ = buf.rx_sender.try_send(result); - } - } - RxMode::FdBuffered(buf) => { - if let Some(result) = self.read::() { - let _ = buf.rx_sender.try_send(result); - } - } - } - } - - fn read(&self) -> Option> { - if let Some((msg, ts)) = T::registers().read(0) { - let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); - Some(Ok((msg, ts))) - } else if let Some((msg, ts)) = T::registers().read(1) { - let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); - Some(Ok((msg, ts))) - } else if let Some(err) = T::registers().curr_error() { - // TODO: this is probably wrong - Some(Err(err)) - } else { - None - } - } - - async fn read_async(&self) -> Result<(F, Timestamp), BusError> { - poll_fn(|cx| { - T::state().err_waker.register(cx.waker()); - self.register(cx.waker()); - match self.read::() { - Some(result) => Poll::Ready(result), - None => Poll::Pending, - } - }) - .await - } - - pub async fn read_classic(&self) -> Result<(ClassicFrame, Timestamp), BusError> { - self.read_async::().await - } - - pub async fn read_fd(&self) -> Result<(FdFrame, Timestamp), BusError> { - self.read_async::().await - } - } - - pub enum TxMode { - NonBuffered(AtomicWaker), - ClassicBuffered(ClassicBufferedTxInner), - FdBuffered(FdBufferedTxInner), - } - - impl TxMode { - pub fn register(&self, arg: &core::task::Waker) { - match self { - TxMode::NonBuffered(waker) => { - waker.register(arg); - } - _ => { - panic!("Bad mode"); - } - } - } - - /// Queues the message to be sent but exerts backpressure. If a lower-priority - /// frame is dropped from the mailbox, it is returned. If no lower-priority frames - /// can be replaced, this call asynchronously waits for a frame to be successfully - /// transmitted, then tries again. - async fn write_generic(&self, frame: &F) -> Option { - poll_fn(|cx| { - self.register(cx.waker()); - - if let Ok(dropped) = T::registers().write(frame) { - return Poll::Ready(dropped); - } - - // Couldn't replace any lower priority frames. Need to wait for some mailboxes - // to clear. - Poll::Pending - }) - .await - } - - /// Queues the message to be sent but exerts backpressure. If a lower-priority - /// frame is dropped from the mailbox, it is returned. If no lower-priority frames - /// can be replaced, this call asynchronously waits for a frame to be successfully - /// transmitted, then tries again. - pub async fn write(&self, frame: &ClassicFrame) -> Option { - self.write_generic::(frame).await - } - - /// Queues the message to be sent but exerts backpressure. If a lower-priority - /// frame is dropped from the mailbox, it is returned. If no lower-priority frames - /// can be replaced, this call asynchronously waits for a frame to be successfully - /// transmitted, then tries again. - pub async fn write_fd(&self, frame: &FdFrame) -> Option { - self.write_generic::(frame).await - } - } - - pub struct State { - pub rx_mode: RxMode, - pub tx_mode: TxMode, - pub ns_per_timer_tick: u64, - - pub err_waker: AtomicWaker, - } - - impl State { - pub const fn new() -> Self { - Self { - rx_mode: RxMode::NonBuffered(AtomicWaker::new()), - tx_mode: TxMode::NonBuffered(AtomicWaker::new()), - ns_per_timer_tick: 0, - err_waker: AtomicWaker::new(), +impl RxMode { + fn register(&self, arg: &core::task::Waker) { + match self { + RxMode::NonBuffered(waker) => waker.register(arg), + _ => { + panic!("Bad Mode") } } } - pub trait Instance { - const MSG_RAM_OFFSET: usize; + fn on_interrupt(&self, fifonr: usize) { + T::regs().ir().write(|w| w.set_rfn(fifonr, true)); + match self { + RxMode::NonBuffered(waker) => { + waker.wake(); + } + RxMode::ClassicBuffered(buf) => { + if let Some(result) = self.read::() { + let _ = buf.rx_sender.try_send(result); + } + } + RxMode::FdBuffered(buf) => { + if let Some(result) = self.read::() { + let _ = buf.rx_sender.try_send(result); + } + } + } + } - fn regs() -> &'static crate::pac::can::Fdcan; - fn registers() -> crate::can::fd::peripheral::Registers; - fn ram() -> &'static crate::pac::fdcanram::Fdcanram; - fn state() -> &'static State; - unsafe fn mut_state() -> &'static mut State; - fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp; + fn read(&self) -> Option> { + if let Some((msg, ts)) = T::registers().read(0) { + let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); + Some(Ok((msg, ts))) + } else if let Some((msg, ts)) = T::registers().read(1) { + let ts = T::calc_timestamp(T::state().ns_per_timer_tick, ts); + Some(Ok((msg, ts))) + } else if let Some(err) = T::registers().curr_error() { + // TODO: this is probably wrong + Some(Err(err)) + } else { + None + } + } + + async fn read_async(&self) -> Result<(F, Timestamp), BusError> { + poll_fn(|cx| { + T::state().err_waker.register(cx.waker()); + self.register(cx.waker()); + match self.read::() { + Some(result) => Poll::Ready(result), + None => Poll::Pending, + } + }) + .await + } + + async fn read_classic(&self) -> Result<(ClassicFrame, Timestamp), BusError> { + self.read_async::().await + } + + async fn read_fd(&self) -> Result<(FdFrame, Timestamp), BusError> { + self.read_async::().await } } +enum TxMode { + NonBuffered(AtomicWaker), + ClassicBuffered(ClassicBufferedTxInner), + FdBuffered(FdBufferedTxInner), +} + +impl TxMode { + fn register(&self, arg: &core::task::Waker) { + match self { + TxMode::NonBuffered(waker) => { + waker.register(arg); + } + _ => { + panic!("Bad mode"); + } + } + } + + /// Queues the message to be sent but exerts backpressure. If a lower-priority + /// frame is dropped from the mailbox, it is returned. If no lower-priority frames + /// can be replaced, this call asynchronously waits for a frame to be successfully + /// transmitted, then tries again. + async fn write_generic(&self, frame: &F) -> Option { + poll_fn(|cx| { + self.register(cx.waker()); + + if let Ok(dropped) = T::registers().write(frame) { + return Poll::Ready(dropped); + } + + // Couldn't replace any lower priority frames. Need to wait for some mailboxes + // to clear. + Poll::Pending + }) + .await + } + + /// Queues the message to be sent but exerts backpressure. If a lower-priority + /// frame is dropped from the mailbox, it is returned. If no lower-priority frames + /// can be replaced, this call asynchronously waits for a frame to be successfully + /// transmitted, then tries again. + async fn write(&self, frame: &ClassicFrame) -> Option { + self.write_generic::(frame).await + } + + /// Queues the message to be sent but exerts backpressure. If a lower-priority + /// frame is dropped from the mailbox, it is returned. If no lower-priority frames + /// can be replaced, this call asynchronously waits for a frame to be successfully + /// transmitted, then tries again. + async fn write_fd(&self, frame: &FdFrame) -> Option { + self.write_generic::(frame).await + } +} + +struct State { + pub rx_mode: RxMode, + pub tx_mode: TxMode, + pub ns_per_timer_tick: u64, + + pub err_waker: AtomicWaker, +} + +impl State { + const fn new() -> Self { + Self { + rx_mode: RxMode::NonBuffered(AtomicWaker::new()), + tx_mode: TxMode::NonBuffered(AtomicWaker::new()), + ns_per_timer_tick: 0, + err_waker: AtomicWaker::new(), + } + } +} + +trait SealedInstance { + const MSG_RAM_OFFSET: usize; + + fn regs() -> &'static crate::pac::can::Fdcan; + fn registers() -> crate::can::fd::peripheral::Registers; + fn state() -> &'static State; + unsafe fn mut_state() -> &'static mut State; + fn calc_timestamp(ns_per_timer_tick: u64, ts_val: u16) -> Timestamp; +} + /// Instance trait -pub trait Instance: sealed::Instance + RccPeripheral + 'static { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static { /// Interrupt 0 type IT0Interrupt: crate::interrupt::typelevel::Interrupt; - /// Interrupt 0 + /// Interrupt 1 type IT1Interrupt: crate::interrupt::typelevel::Interrupt; } @@ -871,7 +860,7 @@ pub struct FdcanInstance<'a, T>(PeripheralRef<'a, T>); macro_rules! impl_fdcan { ($inst:ident, $msg_ram_inst:ident, $msg_ram_offset:literal) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { const MSG_RAM_OFFSET: usize = $msg_ram_offset; fn regs() -> &'static crate::pac::can::Fdcan { @@ -880,14 +869,11 @@ macro_rules! impl_fdcan { fn registers() -> Registers { Registers{regs: &crate::pac::$inst, msgram: &crate::pac::$msg_ram_inst, msg_ram_offset: Self::MSG_RAM_OFFSET} } - fn ram() -> &'static crate::pac::fdcanram::Fdcanram { - &crate::pac::$msg_ram_inst + unsafe fn mut_state() -> &'static mut State { + static mut STATE: State = State::new(); + &mut *core::ptr::addr_of_mut!(STATE) } - unsafe fn mut_state() -> & 'static mut sealed::State { - static mut STATE: sealed::State = sealed::State::new(); - & mut STATE - } - fn state() -> &'static sealed::State { + fn state() -> &'static State { unsafe { peripherals::$inst::mut_state() } } diff --git a/embassy-stm32/src/crc/v1.rs b/embassy-stm32/src/crc/v1.rs index 0166ab819..f8909d438 100644 --- a/embassy-stm32/src/crc/v1.rs +++ b/embassy-stm32/src/crc/v1.rs @@ -2,7 +2,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::pac::CRC as PAC_CRC; use crate::peripherals::CRC; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::Peripheral; /// CRC driver. diff --git a/embassy-stm32/src/crc/v2v3.rs b/embassy-stm32/src/crc/v2v3.rs index 0c4ae55ce..46f5ea1be 100644 --- a/embassy-stm32/src/crc/v2v3.rs +++ b/embassy-stm32/src/crc/v2v3.rs @@ -3,7 +3,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; use crate::pac::crc::vals; use crate::pac::CRC as PAC_CRC; use crate::peripherals::CRC; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::Peripheral; /// CRC driver. diff --git a/embassy-stm32/src/cryp/mod.rs b/embassy-stm32/src/cryp/mod.rs index 74b095b6f..18b5ec918 100644 --- a/embassy-stm32/src/cryp/mod.rs +++ b/embassy-stm32/src/cryp/mod.rs @@ -1885,16 +1885,13 @@ impl<'d, T: Instance, DmaIn, DmaOut> Cryp<'d, T, DmaIn, DmaOut> { } } -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - fn regs() -> pac::cryp::Cryp; - } +trait SealedInstance { + fn regs() -> pac::cryp::Cryp; } /// CRYP instance trait. -pub trait Instance: sealed::Instance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { /// Interrupt for this CRYP instance. type Interrupt: interrupt::typelevel::Interrupt; } @@ -1905,7 +1902,7 @@ foreach_interrupt!( type Interrupt = crate::interrupt::typelevel::$irq; } - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { fn regs() -> crate::pac::cryp::Cryp { crate::pac::$inst } diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs index 60f9404c2..acfed8356 100644 --- a/embassy-stm32/src/dac/mod.rs +++ b/embassy-stm32/src/dac/mod.rs @@ -127,7 +127,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> { pub fn new( _peri: impl Peripheral

+ 'd, dma: impl Peripheral

+ 'd, - pin: impl Peripheral

+ crate::gpio::sealed::Pin> + 'd, + pin: impl Peripheral

+ crate::gpio::Pin> + 'd, ) -> Self { into_ref!(dma, pin); pin.set_as_analog(); @@ -392,8 +392,8 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { _peri: impl Peripheral

+ 'd, dma_ch1: impl Peripheral

+ 'd, dma_ch2: impl Peripheral

+ 'd, - pin_ch1: impl Peripheral

+ crate::gpio::sealed::Pin> + 'd, - pin_ch2: impl Peripheral

+ crate::gpio::sealed::Pin> + 'd, + pin_ch1: impl Peripheral

+ crate::gpio::Pin> + 'd, + pin_ch2: impl Peripheral

+ crate::gpio::Pin> + 'd, ) -> Self { into_ref!(dma_ch1, dma_ch2, pin_ch1, pin_ch2); pin_ch1.set_as_analog(); @@ -488,14 +488,13 @@ impl<'d, T: Instance, DMACh1, DMACh2> Dac<'d, T, DMACh1, DMACh2> { } } -pub(crate) mod sealed { - pub trait Instance { - fn regs() -> &'static crate::pac::dac::Dac; - } +trait SealedInstance { + fn regs() -> &'static crate::pac::dac::Dac; } /// DAC instance. -pub trait Instance: sealed::Instance + RccPeripheral + 'static {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static {} dma_trait!(DacDma1, Instance); dma_trait!(DacDma2, Instance); @@ -504,7 +503,7 @@ pub trait DacPin: crate::gpio::Pin + 'static {} foreach_peripheral!( (dac, $inst:ident) => { - impl crate::dac::sealed::Instance for peripherals::$inst { + impl crate::dac::SealedInstance for peripherals::$inst { fn regs() -> &'static crate::pac::dac::Dac { &crate::pac::$inst } diff --git a/embassy-stm32/src/dcmi.rs b/embassy-stm32/src/dcmi.rs index 826b04a4b..646ee2ce2 100644 --- a/embassy-stm32/src/dcmi.rs +++ b/embassy-stm32/src/dcmi.rs @@ -7,8 +7,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; use embassy_sync::waitqueue::AtomicWaker; use crate::dma::Transfer; -use crate::gpio::sealed::AFType; -use crate::gpio::Speed; +use crate::gpio::{AFType, Speed}; use crate::interrupt::typelevel::Interrupt; use crate::{interrupt, Peripheral}; @@ -431,14 +430,13 @@ where } } -mod sealed { - pub trait Instance: crate::rcc::RccPeripheral { - fn regs(&self) -> crate::pac::dcmi::Dcmi; - } +trait SealedInstance: crate::rcc::RccPeripheral { + fn regs(&self) -> crate::pac::dcmi::Dcmi; } /// DCMI instance. -pub trait Instance: sealed::Instance + 'static { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + 'static { /// Interrupt for this instance. type Interrupt: interrupt::typelevel::Interrupt; } @@ -465,7 +463,7 @@ pin_trait!(PixClkPin, Instance); #[allow(unused)] macro_rules! impl_peripheral { ($inst:ident, $irq:ident) => { - impl sealed::Instance for crate::peripherals::$inst { + impl SealedInstance for crate::peripherals::$inst { fn regs(&self) -> crate::pac::dcmi::Dcmi { crate::pac::$inst } diff --git a/embassy-stm32/src/dma/dmamux.rs b/embassy-stm32/src/dma/dmamux.rs index 1e9ab5944..dc7cd3a66 100644 --- a/embassy-stm32/src/dma/dmamux.rs +++ b/embassy-stm32/src/dma/dmamux.rs @@ -19,9 +19,7 @@ pub(crate) fn configure_dmamux(info: &DmamuxInfo, request: u8) { }); } -pub(crate) mod dmamux_sealed { - pub trait MuxChannel {} -} +pub(crate) trait SealedMuxChannel {} /// DMAMUX1 instance. pub struct DMAMUX1; @@ -30,14 +28,15 @@ pub struct DMAMUX1; pub struct DMAMUX2; /// DMAMUX channel trait. -pub trait MuxChannel: dmamux_sealed::MuxChannel { +#[allow(private_bounds)] +pub trait MuxChannel: SealedMuxChannel { /// DMAMUX instance this channel is on. type Mux; } macro_rules! dmamux_channel_impl { ($channel_peri:ident, $dmamux:ident) => { - impl crate::dma::dmamux_sealed::MuxChannel for crate::peripherals::$channel_peri {} + impl crate::dma::SealedMuxChannel for crate::peripherals::$channel_peri {} impl crate::dma::MuxChannel for crate::peripherals::$channel_peri { type Mux = crate::dma::$dmamux; } diff --git a/embassy-stm32/src/dma/mod.rs b/embassy-stm32/src/dma/mod.rs index d5e88a20a..7e3681469 100644 --- a/embassy-stm32/src/dma/mod.rs +++ b/embassy-stm32/src/dma/mod.rs @@ -39,17 +39,18 @@ pub type Request = u8; #[cfg(not(any(dma_v2, bdma_v2, gpdma, dmamux)))] pub type Request = (); -pub(crate) mod sealed { - pub trait Channel { - fn id(&self) -> u8; - } - pub trait ChannelInterrupt { - unsafe fn on_irq(); - } +pub(crate) trait SealedChannel { + fn id(&self) -> u8; +} + +pub(crate) trait ChannelInterrupt { + #[cfg_attr(not(feature = "rt"), allow(unused))] + unsafe fn on_irq(); } /// DMA channel. -pub trait Channel: sealed::Channel + Peripheral

+ Into + 'static { +#[allow(private_bounds)] +pub trait Channel: SealedChannel + Peripheral

+ Into + 'static { /// Type-erase (degrade) this pin into an `AnyChannel`. /// /// This converts DMA channel singletons (`DMA1_CH3`, `DMA2_CH1`, ...), which @@ -63,12 +64,12 @@ pub trait Channel: sealed::Channel + Peripheral

+ Into + ' macro_rules! dma_channel_impl { ($channel_peri:ident, $index:expr) => { - impl crate::dma::sealed::Channel for crate::peripherals::$channel_peri { + impl crate::dma::SealedChannel for crate::peripherals::$channel_peri { fn id(&self) -> u8 { $index } } - impl crate::dma::sealed::ChannelInterrupt for crate::peripherals::$channel_peri { + impl crate::dma::ChannelInterrupt for crate::peripherals::$channel_peri { unsafe fn on_irq() { crate::dma::AnyChannel { id: $index }.on_irq(); } @@ -96,7 +97,7 @@ impl AnyChannel { } } -impl sealed::Channel for AnyChannel { +impl SealedChannel for AnyChannel { fn id(&self) -> u8 { self.id } diff --git a/embassy-stm32/src/dma/word.rs b/embassy-stm32/src/dma/word.rs index a72c4b7d9..fb1bde860 100644 --- a/embassy-stm32/src/dma/word.rs +++ b/embassy-stm32/src/dma/word.rs @@ -20,14 +20,13 @@ impl WordSize { } } -mod sealed { - pub trait Word {} -} +trait SealedWord {} /// DMA word trait. /// /// This is implemented for u8, u16, u32, etc. -pub trait Word: sealed::Word + Default + Copy + 'static { +#[allow(private_bounds)] +pub trait Word: SealedWord + Default + Copy + 'static { /// Word size fn size() -> WordSize; /// Amount of bits of this word size. @@ -36,7 +35,7 @@ pub trait Word: sealed::Word + Default + Copy + 'static { macro_rules! impl_word { (_, $T:ident, $bits:literal, $size:ident) => { - impl sealed::Word for $T {} + impl SealedWord for $T {} impl Word for $T { fn bits() -> usize { $bits diff --git a/embassy-stm32/src/eth/mod.rs b/embassy-stm32/src/eth/mod.rs index 71fe09c3f..bfe8a60d6 100644 --- a/embassy-stm32/src/eth/mod.rs +++ b/embassy-stm32/src/eth/mod.rs @@ -177,16 +177,15 @@ pub unsafe trait PHY { fn poll_link(&mut self, sm: &mut S, cx: &mut Context) -> bool; } -pub(crate) mod sealed { - pub trait Instance { - fn regs() -> crate::pac::eth::Eth; - } +trait SealedInstance { + fn regs() -> crate::pac::eth::Eth; } /// Ethernet instance. -pub trait Instance: sealed::Instance + RccPeripheral + Send + 'static {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + Send + 'static {} -impl sealed::Instance for crate::peripherals::ETH { +impl SealedInstance for crate::peripherals::ETH { fn regs() -> crate::pac::eth::Eth { crate::pac::ETH } diff --git a/embassy-stm32/src/eth/v1/mod.rs b/embassy-stm32/src/eth/v1/mod.rs index e5b7b0452..6f0174def 100644 --- a/embassy-stm32/src/eth/v1/mod.rs +++ b/embassy-stm32/src/eth/v1/mod.rs @@ -12,15 +12,14 @@ use stm32_metapac::eth::vals::{Apcs, Cr, Dm, DmaomrSr, Fes, Ftf, Ifg, MbProgress pub(crate) use self::rx_desc::{RDes, RDesRing}; pub(crate) use self::tx_desc::{TDes, TDesRing}; use super::*; -use crate::gpio::sealed::{AFType, Pin as __GpioPin}; -use crate::gpio::AnyPin; +use crate::gpio::{AFType, AnyPin, SealedPin}; use crate::interrupt::InterruptExt; #[cfg(eth_v1a)] use crate::pac::AFIO; #[cfg(any(eth_v1b, eth_v1c))] use crate::pac::SYSCFG; use crate::pac::{ETH, RCC}; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::{interrupt, Peripheral}; /// Interrupt handler. @@ -149,8 +148,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { #[cfg(any(eth_v1b, eth_v1c))] config_pins!(ref_clk, mdio, mdc, crs, rx_d0, rx_d1, tx_d0, tx_d1, tx_en); - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); + let dma = T::regs().ethernet_dma(); + let mac = T::regs().ethernet_mac(); // Reset and wait dma.dmabmr().modify(|w| w.set_sr(true)); @@ -192,7 +191,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { // TODO MTU size setting not found for v1 ethernet, check if correct - let hclk = ::frequency(); + let hclk = ::frequency(); let hclk_mhz = hclk.0 / 1_000_000; // Set the MDC clock frequency in the range 1MHz - 2.5MHz @@ -235,8 +234,8 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { fence(Ordering::SeqCst); - let mac = ETH.ethernet_mac(); - let dma = ETH.ethernet_dma(); + let mac = T::regs().ethernet_mac(); + let dma = T::regs().ethernet_dma(); mac.maccr().modify(|w| { w.set_re(true); @@ -275,7 +274,7 @@ pub struct EthernetStationManagement { unsafe impl StationManagement for EthernetStationManagement { fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { - let mac = ETH.ethernet_mac(); + let mac = T::regs().ethernet_mac(); mac.macmiiar().modify(|w| { w.set_pa(phy_addr); @@ -289,7 +288,7 @@ unsafe impl StationManagement for EthernetStationManagement { } fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { - let mac = ETH.ethernet_mac(); + let mac = T::regs().ethernet_mac(); mac.macmiidr().write(|w| w.set_md(val)); mac.macmiiar().modify(|w| { @@ -305,8 +304,8 @@ unsafe impl StationManagement for EthernetStationManagement { impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { fn drop(&mut self) { - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); + let dma = T::regs().ethernet_dma(); + let mac = T::regs().ethernet_mac(); // Disable the TX DMA and wait for any previous transmissions to be completed dma.dmaomr().modify(|w| w.set_st(St::STOPPED)); diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index 8d69561d4..c6e015022 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -7,11 +7,10 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; pub(crate) use self::descriptors::{RDes, RDesRing, TDes, TDesRing}; use super::*; -use crate::gpio::sealed::{AFType, Pin as _}; -use crate::gpio::{AnyPin, Speed}; +use crate::gpio::{AFType, AnyPin, SealedPin as _, Speed}; use crate::interrupt::InterruptExt; use crate::pac::ETH; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::{interrupt, Peripheral}; /// Interrupt handler. @@ -207,9 +206,9 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { phy: P, mac_addr: [u8; 6], ) -> Self { - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); + let dma = T::regs().ethernet_dma(); + let mac = T::regs().ethernet_mac(); + let mtl = T::regs().ethernet_mtl(); // Reset and wait dma.dmamr().modify(|w| w.set_swr(true)); @@ -265,7 +264,7 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { w.set_rbsz(RX_BUFFER_SIZE as u16); }); - let hclk = ::frequency(); + let hclk = ::frequency(); let hclk_mhz = hclk.0 / 1_000_000; // Set the MDC clock frequency in the range 1MHz - 2.5MHz @@ -296,9 +295,9 @@ impl<'d, T: Instance, P: PHY> Ethernet<'d, T, P> { fence(Ordering::SeqCst); - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); - let dma = ETH.ethernet_dma(); + let mac = T::regs().ethernet_mac(); + let mtl = T::regs().ethernet_mtl(); + let dma = T::regs().ethernet_dma(); mac.maccr().modify(|w| { w.set_re(true); @@ -334,7 +333,7 @@ pub struct EthernetStationManagement { unsafe impl StationManagement for EthernetStationManagement { fn smi_read(&mut self, phy_addr: u8, reg: u8) -> u16 { - let mac = ETH.ethernet_mac(); + let mac = T::regs().ethernet_mac(); mac.macmdioar().modify(|w| { w.set_pa(phy_addr); @@ -348,7 +347,7 @@ unsafe impl StationManagement for EthernetStationManagement { } fn smi_write(&mut self, phy_addr: u8, reg: u8, val: u16) { - let mac = ETH.ethernet_mac(); + let mac = T::regs().ethernet_mac(); mac.macmdiodr().write(|w| w.set_md(val)); mac.macmdioar().modify(|w| { @@ -364,9 +363,9 @@ unsafe impl StationManagement for EthernetStationManagement { impl<'d, T: Instance, P: PHY> Drop for Ethernet<'d, T, P> { fn drop(&mut self) { - let dma = ETH.ethernet_dma(); - let mac = ETH.ethernet_mac(); - let mtl = ETH.ethernet_mtl(); + let dma = T::regs().ethernet_dma(); + let mac = T::regs().ethernet_mac(); + let mtl = T::regs().ethernet_mtl(); // Disable the TX DMA and wait for any previous transmissions to be completed dma.dmactx_cr().modify(|w| w.set_st(false)); diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index bd10ba158..8d5dae436 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs @@ -330,12 +330,11 @@ macro_rules! impl_irq { foreach_exti_irq!(impl_irq); -pub(crate) mod sealed { - pub trait Channel {} -} +trait SealedChannel {} /// EXTI channel trait. -pub trait Channel: sealed::Channel + Sized { +#[allow(private_bounds)] +pub trait Channel: SealedChannel + Sized { /// Get the EXTI channel number. fn number(&self) -> u8; @@ -359,7 +358,7 @@ pub struct AnyChannel { } impl_peripheral!(AnyChannel); -impl sealed::Channel for AnyChannel {} +impl SealedChannel for AnyChannel {} impl Channel for AnyChannel { fn number(&self) -> u8 { self.number @@ -368,7 +367,7 @@ impl Channel for AnyChannel { macro_rules! impl_exti { ($type:ident, $number:expr) => { - impl sealed::Channel for peripherals::$type {} + impl SealedChannel for peripherals::$type {} impl Channel for peripherals::$type { fn number(&self) -> u8 { $number diff --git a/embassy-stm32/src/flash/f0.rs b/embassy-stm32/src/flash/f0.rs index e0c76e6b2..e2f135208 100644 --- a/embassy-stm32/src/flash/f0.rs +++ b/embassy-stm32/src/flash/f0.rs @@ -1,4 +1,3 @@ -use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; diff --git a/embassy-stm32/src/flash/f1f3.rs b/embassy-stm32/src/flash/f1f3.rs index e7790369a..b16354a74 100644 --- a/embassy-stm32/src/flash/f1f3.rs +++ b/embassy-stm32/src/flash/f1f3.rs @@ -1,4 +1,3 @@ -use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; diff --git a/embassy-stm32/src/flash/f4.rs b/embassy-stm32/src/flash/f4.rs index 57447bea5..00e61f2d2 100644 --- a/embassy-stm32/src/flash/f4.rs +++ b/embassy-stm32/src/flash/f4.rs @@ -1,4 +1,3 @@ -use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, AtomicBool, Ordering}; diff --git a/embassy-stm32/src/flash/f7.rs b/embassy-stm32/src/flash/f7.rs index 0f512bbc4..72de0b445 100644 --- a/embassy-stm32/src/flash/f7.rs +++ b/embassy-stm32/src/flash/f7.rs @@ -1,4 +1,3 @@ -use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; diff --git a/embassy-stm32/src/flash/g.rs b/embassy-stm32/src/flash/g.rs index b69c4343b..6a5adc941 100644 --- a/embassy-stm32/src/flash/g.rs +++ b/embassy-stm32/src/flash/g.rs @@ -1,4 +1,3 @@ -use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; diff --git a/embassy-stm32/src/flash/h7.rs b/embassy-stm32/src/flash/h7.rs index 743925e17..e32a82eef 100644 --- a/embassy-stm32/src/flash/h7.rs +++ b/embassy-stm32/src/flash/h7.rs @@ -1,4 +1,3 @@ -use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; diff --git a/embassy-stm32/src/flash/u5.rs b/embassy-stm32/src/flash/u5.rs index 3787082f9..580c490da 100644 --- a/embassy-stm32/src/flash/u5.rs +++ b/embassy-stm32/src/flash/u5.rs @@ -1,4 +1,3 @@ -use core::convert::TryInto; use core::ptr::write_volatile; use core::sync::atomic::{fence, Ordering}; diff --git a/embassy-stm32/src/fmc.rs b/embassy-stm32/src/fmc.rs index 9d731a512..aced69878 100644 --- a/embassy-stm32/src/fmc.rs +++ b/embassy-stm32/src/fmc.rs @@ -3,8 +3,7 @@ use core::marker::PhantomData; use embassy_hal_internal::into_ref; -use crate::gpio::sealed::AFType; -use crate::gpio::{Pull, Speed}; +use crate::gpio::{AFType, Pull, Speed}; use crate::Peripheral; /// FMC driver @@ -44,7 +43,7 @@ where /// Get the kernel clock currently in use for this FMC instance. pub fn source_clock_hz(&self) -> u32 { - ::frequency().0 + ::frequency().0 } } @@ -69,7 +68,7 @@ where } fn source_clock_hz(&self) -> u32 { - ::frequency().0 + ::frequency().0 } } @@ -201,18 +200,17 @@ impl<'d, T: Instance> Fmc<'d, T> { )); } -pub(crate) mod sealed { - pub trait Instance: crate::rcc::sealed::RccPeripheral { - const REGS: crate::pac::fmc::Fmc; - } +trait SealedInstance: crate::rcc::SealedRccPeripheral { + const REGS: crate::pac::fmc::Fmc; } /// FMC instance trait. -pub trait Instance: sealed::Instance + 'static {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + 'static {} foreach_peripheral!( (fmc, $inst:ident) => { - impl crate::fmc::sealed::Instance for crate::peripherals::$inst { + impl crate::fmc::SealedInstance for crate::peripherals::$inst { const REGS: crate::pac::fmc::Fmc = crate::pac::$inst; } impl crate::fmc::Instance for crate::peripherals::$inst {} diff --git a/embassy-stm32/src/fmt.rs b/embassy-stm32/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-stm32/src/fmt.rs +++ b/embassy-stm32/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 00e3e1727..33f22f676 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs @@ -6,7 +6,6 @@ use core::convert::Infallible; use critical_section::CriticalSection; use embassy_hal_internal::{impl_peripheral, into_ref, PeripheralRef}; -use self::sealed::Pin as _; use crate::pac::gpio::{self, vals}; use crate::{pac, peripherals, Peripheral}; @@ -129,6 +128,18 @@ impl<'d> Flex<'d> { }); } + /// Put the pin into AF mode, unchecked. + /// + /// This puts the pin into the AF mode, with the requested number, pull and speed. This is + /// completely unchecked, it can attach the pin to literally any peripheral, so use with care. + #[inline] + pub fn set_as_af_unchecked(&mut self, af_num: u8, af_type: AFType, pull: Pull, speed: Speed) { + critical_section::with(|_| { + self.pin.set_as_af_pull(af_num, af_type, pull); + self.pin.set_speed(speed); + }); + } + /// Get whether the pin input level is high. #[inline] pub fn is_high(&self) -> bool { @@ -508,172 +519,168 @@ pub enum OutputType { OpenDrain, } -impl From for sealed::AFType { +impl From for AFType { fn from(value: OutputType) -> Self { match value { - OutputType::OpenDrain => sealed::AFType::OutputOpenDrain, - OutputType::PushPull => sealed::AFType::OutputPushPull, + OutputType::OpenDrain => AFType::OutputOpenDrain, + OutputType::PushPull => AFType::OutputPushPull, } } } -#[allow(missing_docs)] -pub(crate) mod sealed { - use super::*; +/// Alternate function type settings +#[derive(Debug, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum AFType { + /// Input + Input, + /// Output, drive the pin both high or low. + OutputPushPull, + /// Output, drive the pin low, or don't drive it at all if the output level is high. + OutputOpenDrain, +} - /// Alternate function type settings - #[derive(Debug, Copy, Clone)] - #[cfg_attr(feature = "defmt", derive(defmt::Format))] - pub enum AFType { - /// Input - Input, - /// Output, drive the pin both high or low. - OutputPushPull, - /// Output, drive the pin low, or don't drive it at all if the output level is high. - OutputOpenDrain, +pub(crate) trait SealedPin { + fn pin_port(&self) -> u8; + + #[inline] + fn _pin(&self) -> u8 { + self.pin_port() % 16 + } + #[inline] + fn _port(&self) -> u8 { + self.pin_port() / 16 } - pub trait Pin { - fn pin_port(&self) -> u8; + #[inline] + fn block(&self) -> gpio::Gpio { + pac::GPIO(self._port() as _) + } - #[inline] - fn _pin(&self) -> u8 { - self.pin_port() % 16 - } - #[inline] - fn _port(&self) -> u8 { - self.pin_port() / 16 - } + /// Set the output as high. + #[inline] + fn set_high(&self) { + let n = self._pin() as _; + self.block().bsrr().write(|w| w.set_bs(n, true)); + } - #[inline] - fn block(&self) -> gpio::Gpio { - pac::GPIO(self._port() as _) - } + /// Set the output as low. + #[inline] + fn set_low(&self) { + let n = self._pin() as _; + self.block().bsrr().write(|w| w.set_br(n, true)); + } - /// Set the output as high. - #[inline] - fn set_high(&self) { - let n = self._pin() as _; - self.block().bsrr().write(|w| w.set_bs(n, true)); - } + #[inline] + fn set_as_af(&self, af_num: u8, af_type: AFType) { + self.set_as_af_pull(af_num, af_type, Pull::None); + } - /// Set the output as low. - #[inline] - fn set_low(&self) { - let n = self._pin() as _; - self.block().bsrr().write(|w| w.set_br(n, true)); - } + #[cfg(gpio_v1)] + #[inline] + fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { + // F1 uses the AFIO register for remapping. + // For now, this is not implemented, so af_num is ignored + // _af_num should be zero here, since it is not set by stm32-data + let r = self.block(); + let n = self._pin() as usize; + let crlh = if n < 8 { 0 } else { 1 }; + match af_type { + AFType::Input => { + let cnf = match pull { + Pull::Up => { + r.bsrr().write(|w| w.set_bs(n, true)); + vals::CnfIn::PULL + } + Pull::Down => { + r.bsrr().write(|w| w.set_br(n, true)); + vals::CnfIn::PULL + } + Pull::None => vals::CnfIn::FLOATING, + }; - #[inline] - fn set_as_af(&self, af_num: u8, af_type: AFType) { - self.set_as_af_pull(af_num, af_type, Pull::None); + r.cr(crlh).modify(|w| { + w.set_mode(n % 8, vals::Mode::INPUT); + w.set_cnf_in(n % 8, cnf); + }); + } + AFType::OutputPushPull => { + r.cr(crlh).modify(|w| { + w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); + w.set_cnf_out(n % 8, vals::CnfOut::ALTPUSHPULL); + }); + } + AFType::OutputOpenDrain => { + r.cr(crlh).modify(|w| { + w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); + w.set_cnf_out(n % 8, vals::CnfOut::ALTOPENDRAIN); + }); + } } + } + + #[cfg(gpio_v2)] + #[inline] + fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { + let pin = self._pin() as usize; + let block = self.block(); + block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num)); + match af_type { + AFType::Input => {} + AFType::OutputPushPull => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::PUSHPULL)), + AFType::OutputOpenDrain => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::OPENDRAIN)), + } + block.pupdr().modify(|w| w.set_pupdr(pin, pull.into())); + + block.moder().modify(|w| w.set_moder(pin, vals::Moder::ALTERNATE)); + } + + #[inline] + fn set_as_analog(&self) { + let pin = self._pin() as usize; + let block = self.block(); + #[cfg(gpio_v1)] + { + let crlh = if pin < 8 { 0 } else { 1 }; + block.cr(crlh).modify(|w| { + w.set_mode(pin % 8, vals::Mode::INPUT); + w.set_cnf_in(pin % 8, vals::CnfIn::ANALOG); + }); + } + #[cfg(gpio_v2)] + block.moder().modify(|w| w.set_moder(pin, vals::Moder::ANALOG)); + } + + /// Set the pin as "disconnected", ie doing nothing and consuming the lowest + /// amount of power possible. + /// + /// This is currently the same as set_as_analog but is semantically different really. + /// Drivers should set_as_disconnected pins when dropped. + #[inline] + fn set_as_disconnected(&self) { + self.set_as_analog(); + } + + #[inline] + fn set_speed(&self, speed: Speed) { + let pin = self._pin() as usize; #[cfg(gpio_v1)] - #[inline] - fn set_as_af_pull(&self, _af_num: u8, af_type: AFType, pull: Pull) { - // F1 uses the AFIO register for remapping. - // For now, this is not implemented, so af_num is ignored - // _af_num should be zero here, since it is not set by stm32-data - let r = self.block(); - let n = self._pin() as usize; - let crlh = if n < 8 { 0 } else { 1 }; - match af_type { - AFType::Input => { - let cnf = match pull { - Pull::Up => { - r.bsrr().write(|w| w.set_bs(n, true)); - vals::CnfIn::PULL - } - Pull::Down => { - r.bsrr().write(|w| w.set_br(n, true)); - vals::CnfIn::PULL - } - Pull::None => vals::CnfIn::FLOATING, - }; - - r.cr(crlh).modify(|w| { - w.set_mode(n % 8, vals::Mode::INPUT); - w.set_cnf_in(n % 8, cnf); - }); - } - AFType::OutputPushPull => { - r.cr(crlh).modify(|w| { - w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); - w.set_cnf_out(n % 8, vals::CnfOut::ALTPUSHPULL); - }); - } - AFType::OutputOpenDrain => { - r.cr(crlh).modify(|w| { - w.set_mode(n % 8, vals::Mode::OUTPUT50MHZ); - w.set_cnf_out(n % 8, vals::CnfOut::ALTOPENDRAIN); - }); - } - } + { + let crlh = if pin < 8 { 0 } else { 1 }; + self.block().cr(crlh).modify(|w| { + w.set_mode(pin % 8, speed.into()); + }); } #[cfg(gpio_v2)] - #[inline] - fn set_as_af_pull(&self, af_num: u8, af_type: AFType, pull: Pull) { - let pin = self._pin() as usize; - let block = self.block(); - block.afr(pin / 8).modify(|w| w.set_afr(pin % 8, af_num)); - match af_type { - AFType::Input => {} - AFType::OutputPushPull => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::PUSHPULL)), - AFType::OutputOpenDrain => block.otyper().modify(|w| w.set_ot(pin, vals::Ot::OPENDRAIN)), - } - block.pupdr().modify(|w| w.set_pupdr(pin, pull.into())); - - block.moder().modify(|w| w.set_moder(pin, vals::Moder::ALTERNATE)); - } - - #[inline] - fn set_as_analog(&self) { - let pin = self._pin() as usize; - let block = self.block(); - #[cfg(gpio_v1)] - { - let crlh = if pin < 8 { 0 } else { 1 }; - block.cr(crlh).modify(|w| { - w.set_mode(pin % 8, vals::Mode::INPUT); - w.set_cnf_in(pin % 8, vals::CnfIn::ANALOG); - }); - } - #[cfg(gpio_v2)] - block.moder().modify(|w| w.set_moder(pin, vals::Moder::ANALOG)); - } - - /// Set the pin as "disconnected", ie doing nothing and consuming the lowest - /// amount of power possible. - /// - /// This is currently the same as set_as_analog but is semantically different really. - /// Drivers should set_as_disconnected pins when dropped. - #[inline] - fn set_as_disconnected(&self) { - self.set_as_analog(); - } - - #[inline] - fn set_speed(&self, speed: Speed) { - let pin = self._pin() as usize; - - #[cfg(gpio_v1)] - { - let crlh = if pin < 8 { 0 } else { 1 }; - self.block().cr(crlh).modify(|w| { - w.set_mode(pin % 8, speed.into()); - }); - } - - #[cfg(gpio_v2)] - self.block().ospeedr().modify(|w| w.set_ospeedr(pin, speed.into())); - } + self.block().ospeedr().modify(|w| w.set_ospeedr(pin, speed.into())); } } /// GPIO pin trait. -pub trait Pin: Peripheral

+ Into + sealed::Pin + Sized + 'static { +#[allow(private_bounds)] +pub trait Pin: Peripheral

+ Into + SealedPin + Sized + 'static { /// EXTI channel assigned to this pin. /// /// For example, PC4 uses EXTI4. @@ -737,7 +744,7 @@ impl Pin for AnyPin { #[cfg(feature = "exti")] type ExtiChannel = crate::exti::AnyChannel; } -impl sealed::Pin for AnyPin { +impl SealedPin for AnyPin { #[inline] fn pin_port(&self) -> u8 { self.pin_port @@ -752,7 +759,7 @@ foreach_pin!( #[cfg(feature = "exti")] type ExtiChannel = peripherals::$exti_ch; } - impl sealed::Pin for peripherals::$pin_name { + impl SealedPin for peripherals::$pin_name { #[inline] fn pin_port(&self) -> u8 { $port_num * 16 + $pin_num @@ -769,7 +776,7 @@ foreach_pin!( pub(crate) unsafe fn init(_cs: CriticalSection) { #[cfg(afio)] - ::enable_and_reset_with_cs(_cs); + ::enable_and_reset_with_cs(_cs); crate::_generated::init_gpio(); @@ -833,6 +840,18 @@ impl<'d> embedded_hal_02::digital::v2::ToggleableOutputPin for Output<'d> { } } +impl<'d> embedded_hal_02::digital::v2::InputPin for OutputOpenDrain<'d> { + type Error = Infallible; + + fn is_high(&self) -> Result { + Ok(self.is_high()) + } + + fn is_low(&self) -> Result { + Ok(self.is_low()) + } +} + impl<'d> embedded_hal_02::digital::v2::OutputPin for OutputOpenDrain<'d> { type Error = Infallible; @@ -1049,9 +1068,3 @@ impl<'d> embedded_hal_1::digital::StatefulOutputPin for Flex<'d> { Ok((*self).is_set_low()) } } - -/// Low-level GPIO manipulation. -#[cfg(feature = "unstable-pac")] -pub mod low_level { - pub use super::sealed::*; -} diff --git a/embassy-stm32/src/hash/mod.rs b/embassy-stm32/src/hash/mod.rs index b47814f8b..787d5b1c9 100644 --- a/embassy-stm32/src/hash/mod.rs +++ b/embassy-stm32/src/hash/mod.rs @@ -17,7 +17,7 @@ use crate::dma::NoDma; use crate::dma::Transfer; use crate::interrupt::typelevel::Interrupt; use crate::peripherals::HASH; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::{interrupt, pac, peripherals, Peripheral}; #[cfg(hash_v1)] @@ -561,16 +561,13 @@ impl<'d, T: Instance, D> Hash<'d, T, D> { } } -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - fn regs() -> pac::hash::Hash; - } +trait SealedInstance { + fn regs() -> pac::hash::Hash; } /// HASH instance trait. -pub trait Instance: sealed::Instance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { /// Interrupt for this HASH instance. type Interrupt: interrupt::typelevel::Interrupt; } @@ -581,7 +578,7 @@ foreach_interrupt!( type Interrupt = crate::interrupt::typelevel::$irq; } - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { fn regs() -> crate::pac::hash::Hash { crate::pac::$inst } diff --git a/embassy-stm32/src/hrtim/mod.rs b/embassy-stm32/src/hrtim/mod.rs index 3ec646fc3..02e45819c 100644 --- a/embassy-stm32/src/hrtim/mod.rs +++ b/embassy-stm32/src/hrtim/mod.rs @@ -7,9 +7,7 @@ use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; pub use traits::Instance; -#[allow(unused_imports)] -use crate::gpio::sealed::{AFType, Pin}; -use crate::gpio::AnyPin; +use crate::gpio::{AFType, AnyPin}; use crate::time::Hertz; use crate::Peripheral; @@ -54,16 +52,13 @@ pub struct ChF { phantom: PhantomData, } -mod sealed { - use super::Instance; - - pub trait AdvancedChannel { - fn raw() -> usize; - } +trait SealedAdvancedChannel { + fn raw() -> usize; } /// Advanced channel instance trait. -pub trait AdvancedChannel: sealed::AdvancedChannel {} +#[allow(private_bounds)] +pub trait AdvancedChannel: SealedAdvancedChannel {} /// HRTIM PWM pin. pub struct PwmPin<'d, T, C> { @@ -113,7 +108,7 @@ macro_rules! advanced_channel_impl { } } - impl sealed::AdvancedChannel for $channel { + impl SealedAdvancedChannel for $channel { fn raw() -> usize { $ch_num } diff --git a/embassy-stm32/src/hrtim/traits.rs b/embassy-stm32/src/hrtim/traits.rs index dcc2b9ef4..75f9971e2 100644 --- a/embassy-stm32/src/hrtim/traits.rs +++ b/embassy-stm32/src/hrtim/traits.rs @@ -1,4 +1,4 @@ -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::RccPeripheral; use crate::time::Hertz; #[repr(u8)] @@ -72,94 +72,92 @@ impl Prescaler { } } -pub(crate) mod sealed { - use super::*; +pub(crate) trait SealedInstance: RccPeripheral { + fn regs() -> crate::pac::hrtim::Hrtim; - pub trait Instance: RccPeripheral { - fn regs() -> crate::pac::hrtim::Hrtim; + #[allow(unused)] + fn set_master_frequency(frequency: Hertz) { + let f = frequency.0; - fn set_master_frequency(frequency: Hertz) { - let f = frequency.0; + // TODO: wire up HRTIM to the RCC mux infra. + //#[cfg(stm32f334)] + //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; + //#[cfg(not(stm32f334))] + let timer_f = Self::frequency().0; - // TODO: wire up HRTIM to the RCC mux infra. - //#[cfg(stm32f334)] - //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; - //#[cfg(not(stm32f334))] - let timer_f = Self::frequency().0; + let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); + let psc = if Self::regs().isr().read().dllrdy() { + Prescaler::compute_min_high_res(psc_min) + } else { + Prescaler::compute_min_low_res(psc_min) + }; - let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); - let psc = if Self::regs().isr().read().dllrdy() { - Prescaler::compute_min_high_res(psc_min) - } else { - Prescaler::compute_min_low_res(psc_min) - }; + let timer_f = 32 * (timer_f / psc as u32); + let per: u16 = (timer_f / f) as u16; - let timer_f = 32 * (timer_f / psc as u32); - let per: u16 = (timer_f / f) as u16; + let regs = Self::regs(); - let regs = Self::regs(); + regs.mcr().modify(|w| w.set_ckpsc(psc.into())); + regs.mper().modify(|w| w.set_mper(per)); + } - regs.mcr().modify(|w| w.set_ckpsc(psc.into())); - regs.mper().modify(|w| w.set_mper(per)); - } + fn set_channel_frequency(channel: usize, frequency: Hertz) { + let f = frequency.0; - fn set_channel_frequency(channel: usize, frequency: Hertz) { - let f = frequency.0; + // TODO: wire up HRTIM to the RCC mux infra. + //#[cfg(stm32f334)] + //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; + //#[cfg(not(stm32f334))] + let timer_f = Self::frequency().0; - // TODO: wire up HRTIM to the RCC mux infra. - //#[cfg(stm32f334)] - //let timer_f = unsafe { crate::rcc::get_freqs() }.hrtim.unwrap_or(Self::frequency()).0; - //#[cfg(not(stm32f334))] - let timer_f = Self::frequency().0; + let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); + let psc = if Self::regs().isr().read().dllrdy() { + Prescaler::compute_min_high_res(psc_min) + } else { + Prescaler::compute_min_low_res(psc_min) + }; - let psc_min = (timer_f / f) / (u16::MAX as u32 / 32); - let psc = if Self::regs().isr().read().dllrdy() { - Prescaler::compute_min_high_res(psc_min) - } else { - Prescaler::compute_min_low_res(psc_min) - }; + let timer_f = 32 * (timer_f / psc as u32); + let per: u16 = (timer_f / f) as u16; - let timer_f = 32 * (timer_f / psc as u32); - let per: u16 = (timer_f / f) as u16; + let regs = Self::regs(); - let regs = Self::regs(); + regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into())); + regs.tim(channel).per().modify(|w| w.set_per(per)); + } - regs.tim(channel).cr().modify(|w| w.set_ckpsc(psc.into())); - regs.tim(channel).per().modify(|w| w.set_per(per)); - } + /// Set the dead time as a proportion of max_duty + fn set_channel_dead_time(channel: usize, dead_time: u16) { + let regs = Self::regs(); - /// Set the dead time as a proportion of max_duty - fn set_channel_dead_time(channel: usize, dead_time: u16) { - let regs = Self::regs(); + let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into(); - let channel_psc: Prescaler = regs.tim(channel).cr().read().ckpsc().into(); + // The dead-time base clock runs 4 times slower than the hrtim base clock + // u9::MAX = 511 + let psc_min = (channel_psc as u32 * dead_time as u32) / (4 * 511); + let psc = if Self::regs().isr().read().dllrdy() { + Prescaler::compute_min_high_res(psc_min) + } else { + Prescaler::compute_min_low_res(psc_min) + }; - // The dead-time base clock runs 4 times slower than the hrtim base clock - // u9::MAX = 511 - let psc_min = (channel_psc as u32 * dead_time as u32) / (4 * 511); - let psc = if Self::regs().isr().read().dllrdy() { - Prescaler::compute_min_high_res(psc_min) - } else { - Prescaler::compute_min_low_res(psc_min) - }; + let dt_val = (psc as u32 * dead_time as u32) / (4 * channel_psc as u32); - let dt_val = (psc as u32 * dead_time as u32) / (4 * channel_psc as u32); - - regs.tim(channel).dt().modify(|w| { - w.set_dtprsc(psc.into()); - w.set_dtf(dt_val as u16); - w.set_dtr(dt_val as u16); - }); - } + regs.tim(channel).dt().modify(|w| { + w.set_dtprsc(psc.into()); + w.set_dtf(dt_val as u16); + w.set_dtr(dt_val as u16); + }); } } /// HRTIM instance trait. -pub trait Instance: sealed::Instance + 'static {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + 'static {} foreach_interrupt! { ($inst:ident, hrtim, HRTIM, MASTER, $irq:ident) => { - impl sealed::Instance for crate::peripherals::$inst { + impl SealedInstance for crate::peripherals::$inst { fn regs() -> crate::pac::hrtim::Hrtim { crate::pac::$inst } diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 2416005b5..f1b11cc44 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs @@ -14,8 +14,7 @@ use embassy_sync::waitqueue::AtomicWaker; use embassy_time::{Duration, Instant}; use crate::dma::NoDma; -use crate::gpio::sealed::AFType; -use crate::gpio::Pull; +use crate::gpio::{AFType, Pull}; use crate::interrupt::typelevel::Interrupt; use crate::time::Hertz; use crate::{interrupt, peripherals}; @@ -175,30 +174,27 @@ impl Timeout { } } -pub(crate) mod sealed { - use super::*; +struct State { + #[allow(unused)] + waker: AtomicWaker, +} - pub struct State { - #[allow(unused)] - pub waker: AtomicWaker, - } - - impl State { - pub const fn new() -> Self { - Self { - waker: AtomicWaker::new(), - } +impl State { + const fn new() -> Self { + Self { + waker: AtomicWaker::new(), } } - - pub trait Instance: crate::rcc::RccPeripheral { - fn regs() -> crate::pac::i2c::I2c; - fn state() -> &'static State; - } +} + +trait SealedInstance: crate::rcc::RccPeripheral { + fn regs() -> crate::pac::i2c::I2c; + fn state() -> &'static State; } /// I2C peripheral instance -pub trait Instance: sealed::Instance + 'static { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + 'static { /// Event interrupt for this instance type EventInterrupt: interrupt::typelevel::Interrupt; /// Error interrupt for this instance @@ -234,13 +230,13 @@ impl interrupt::typelevel::Handler for ErrorInte foreach_peripheral!( (i2c, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { fn regs() -> crate::pac::i2c::I2c { crate::pac::$inst } - fn state() -> &'static sealed::State { - static STATE: sealed::State = sealed::State::new(); + fn state() -> &'static State { + static STATE: State = State::new(); &STATE } } @@ -311,10 +307,10 @@ impl<'d, T: Instance> embedded_hal_1::i2c::I2c for I2c<'d, T, NoDma, NoDma> { fn transaction( &mut self, - _address: u8, - _operations: &mut [embedded_hal_1::i2c::Operation<'_>], + address: u8, + operations: &mut [embedded_hal_1::i2c::Operation<'_>], ) -> Result<(), Self::Error> { - todo!(); + self.blocking_transaction(address, operations) } } diff --git a/embassy-stm32/src/i2c/v1.rs b/embassy-stm32/src/i2c/v1.rs index cbbc201de..9f29ed5e0 100644 --- a/embassy-stm32/src/i2c/v1.rs +++ b/embassy-stm32/src/i2c/v1.rs @@ -10,11 +10,11 @@ use core::task::Poll; use embassy_embedded_hal::SetConfig; use embassy_futures::select::{select, Either}; use embassy_hal_internal::drop::OnDrop; +use embedded_hal_1::i2c::Operation; use super::*; use crate::dma::Transfer; use crate::pac::i2c; -use crate::time::Hertz; // /!\ /!\ // /!\ Implementation note! /!\ @@ -41,6 +41,68 @@ pub unsafe fn on_interrupt() { }); } +/// Frame type in I2C transaction. +/// +/// This tells each method what kind of framing to use, to generate a (repeated) start condition (ST +/// or SR), and/or a stop condition (SP). For read operations, this also controls whether to send an +/// ACK or NACK after the last byte received. +/// +/// For write operations, the following options are identical because they differ only in the (N)ACK +/// treatment relevant for read operations: +/// +/// - `FirstFrame` and `FirstAndNextFrame` +/// - `NextFrame` and `LastFrameNoStop` +/// +/// Abbreviations used below: +/// +/// - `ST` = start condition +/// - `SR` = repeated start condition +/// - `SP` = stop condition +#[derive(Copy, Clone)] +enum FrameOptions { + /// `[ST/SR]+[NACK]+[SP]` First frame (of this type) in operation and last frame overall in this + /// transaction. + FirstAndLastFrame, + /// `[ST/SR]+[NACK]` First frame of this type in transaction, last frame in a read operation but + /// not the last frame overall. + FirstFrame, + /// `[ST/SR]+[ACK]` First frame of this type in transaction, neither last frame overall nor last + /// frame in a read operation. + FirstAndNextFrame, + /// `[ACK]` Middle frame in a read operation (neither first nor last). + NextFrame, + /// `[NACK]+[SP]` Last frame overall in this transaction but not the first frame. + LastFrame, + /// `[NACK]` Last frame in a read operation but not last frame overall in this transaction. + LastFrameNoStop, +} + +impl FrameOptions { + /// Sends start or repeated start condition before transfer. + fn send_start(self) -> bool { + match self { + Self::FirstAndLastFrame | Self::FirstFrame | Self::FirstAndNextFrame => true, + Self::NextFrame | Self::LastFrame | Self::LastFrameNoStop => false, + } + } + + /// Sends stop condition after transfer. + fn send_stop(self) -> bool { + match self { + Self::FirstAndLastFrame | Self::LastFrame => true, + Self::FirstFrame | Self::FirstAndNextFrame | Self::NextFrame | Self::LastFrameNoStop => false, + } + } + + /// Sends NACK after last byte received, indicating end of read operation. + fn send_nack(self) -> bool { + match self { + Self::FirstAndLastFrame | Self::FirstFrame | Self::LastFrame | Self::LastFrameNoStop => true, + Self::FirstAndNextFrame | Self::NextFrame => false, + } + } +} + impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { pub(crate) fn init(&mut self, freq: Hertz, _config: Config) { T::regs().cr1().modify(|reg| { @@ -124,46 +186,57 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(sr1) } - fn write_bytes(&mut self, addr: u8, bytes: &[u8], timeout: Timeout) -> Result<(), Error> { - // Send a START condition + fn write_bytes(&mut self, addr: u8, bytes: &[u8], timeout: Timeout, frame: FrameOptions) -> Result<(), Error> { + if frame.send_start() { + // Send a START condition - T::regs().cr1().modify(|reg| { - reg.set_start(true); - }); + T::regs().cr1().modify(|reg| { + reg.set_start(true); + }); - // Wait until START condition was generated - while !Self::check_and_clear_error_flags()?.start() { - timeout.check()?; + // Wait until START condition was generated + while !Self::check_and_clear_error_flags()?.start() { + timeout.check()?; + } + + // Also wait until signalled we're master and everything is waiting for us + while { + Self::check_and_clear_error_flags()?; + + let sr2 = T::regs().sr2().read(); + !sr2.msl() && !sr2.busy() + } { + timeout.check()?; + } + + // Set up current address, we're trying to talk to + T::regs().dr().write(|reg| reg.set_dr(addr << 1)); + + // Wait until address was sent + // Wait for the address to be acknowledged + // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. + while !Self::check_and_clear_error_flags()?.addr() { + timeout.check()?; + } + + // Clear condition by reading SR2 + let _ = T::regs().sr2().read(); } - // Also wait until signalled we're master and everything is waiting for us - while { - Self::check_and_clear_error_flags()?; - - let sr2 = T::regs().sr2().read(); - !sr2.msl() && !sr2.busy() - } { - timeout.check()?; - } - - // Set up current address, we're trying to talk to - T::regs().dr().write(|reg| reg.set_dr(addr << 1)); - - // Wait until address was sent - // Wait for the address to be acknowledged - // Check for any I2C errors. If a NACK occurs, the ADDR bit will never be set. - while !Self::check_and_clear_error_flags()?.addr() { - timeout.check()?; - } - - // Clear condition by reading SR2 - let _ = T::regs().sr2().read(); - // Send bytes for c in bytes { self.send_byte(*c, timeout)?; } + if frame.send_stop() { + // Send a STOP condition + T::regs().cr1().modify(|reg| reg.set_stop(true)); + // Wait for STOP condition to transmit. + while T::regs().cr1().read().stop() { + timeout.check()?; + } + } + // Fallthrough is success Ok(()) } @@ -205,8 +278,18 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { Ok(value) } - fn blocking_read_timeout(&mut self, addr: u8, buffer: &mut [u8], timeout: Timeout) -> Result<(), Error> { - if let Some((last, buffer)) = buffer.split_last_mut() { + fn blocking_read_timeout( + &mut self, + addr: u8, + buffer: &mut [u8], + timeout: Timeout, + frame: FrameOptions, + ) -> Result<(), Error> { + let Some((last, buffer)) = buffer.split_last_mut() else { + return Err(Error::Overrun); + }; + + if frame.send_start() { // Send a START condition and set ACK bit T::regs().cr1().modify(|reg| { reg.set_start(true); @@ -237,49 +320,45 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { // Clear condition by reading SR2 let _ = T::regs().sr2().read(); + } - // Receive bytes into buffer - for c in buffer { - *c = self.recv_byte(timeout)?; - } + // Receive bytes into buffer + for c in buffer { + *c = self.recv_byte(timeout)?; + } - // Prepare to send NACK then STOP after next byte - T::regs().cr1().modify(|reg| { + // Prepare to send NACK then STOP after next byte + T::regs().cr1().modify(|reg| { + if frame.send_nack() { reg.set_ack(false); + } + if frame.send_stop() { reg.set_stop(true); - }); + } + }); - // Receive last byte - *last = self.recv_byte(timeout)?; + // Receive last byte + *last = self.recv_byte(timeout)?; + if frame.send_stop() { // Wait for the STOP to be sent. while T::regs().cr1().read().stop() { timeout.check()?; } - - // Fallthrough is success - Ok(()) - } else { - Err(Error::Overrun) } + + // Fallthrough is success + Ok(()) } /// Blocking read. pub fn blocking_read(&mut self, addr: u8, read: &mut [u8]) -> Result<(), Error> { - self.blocking_read_timeout(addr, read, self.timeout()) + self.blocking_read_timeout(addr, read, self.timeout(), FrameOptions::FirstAndLastFrame) } /// Blocking write. pub fn blocking_write(&mut self, addr: u8, write: &[u8]) -> Result<(), Error> { - let timeout = self.timeout(); - - self.write_bytes(addr, write, timeout)?; - // Send a STOP condition - T::regs().cr1().modify(|reg| reg.set_stop(true)); - // Wait for STOP condition to transmit. - while T::regs().cr1().read().stop() { - timeout.check()?; - } + self.write_bytes(addr, write, self.timeout(), FrameOptions::FirstAndLastFrame)?; // Fallthrough is success Ok(()) @@ -287,10 +366,85 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { /// Blocking write, restart, read. pub fn blocking_write_read(&mut self, addr: u8, write: &[u8], read: &mut [u8]) -> Result<(), Error> { + // Check empty read buffer before starting transaction. Otherwise, we would not generate the + // stop condition below. + if read.is_empty() { + return Err(Error::Overrun); + } + let timeout = self.timeout(); - self.write_bytes(addr, write, timeout)?; - self.blocking_read_timeout(addr, read, timeout)?; + self.write_bytes(addr, write, timeout, FrameOptions::FirstFrame)?; + self.blocking_read_timeout(addr, read, timeout, FrameOptions::FirstAndLastFrame)?; + + Ok(()) + } + + /// Blocking transaction with operations. + /// + /// Consecutive operations of same type are merged. See [transaction contract] for details. + /// + /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction + pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { + // Check empty read buffer before starting transaction. Otherwise, we would not generate the + // stop condition below. + if operations.iter().any(|op| match op { + Operation::Read(read) => read.is_empty(), + Operation::Write(_) => false, + }) { + return Err(Error::Overrun); + } + + let timeout = self.timeout(); + + let mut operations = operations.iter_mut(); + + let mut prev_op: Option<&mut Operation<'_>> = None; + let mut next_op = operations.next(); + + while let Some(op) = next_op { + next_op = operations.next(); + + // Check if this is the first frame of this type. This is the case for the first overall + // frame in the transaction and whenever the type of operation changes. + let first_frame = + match (prev_op.as_ref(), &op) { + (None, _) => true, + (Some(Operation::Read(_)), Operation::Write(_)) + | (Some(Operation::Write(_)), Operation::Read(_)) => true, + (Some(Operation::Read(_)), Operation::Read(_)) + | (Some(Operation::Write(_)), Operation::Write(_)) => false, + }; + + let frame = match (first_frame, next_op.as_ref()) { + // If this is the first frame of this type, we generate a (repeated) start condition + // but have to consider the next operation: if it is the last, we generate the final + // stop condition. Otherwise, we branch on the operation: with read operations, only + // the last byte overall (before a write operation or the end of the transaction) is + // to be NACK'd, i.e. if another read operation follows, we must ACK this last byte. + (true, None) => FrameOptions::FirstAndLastFrame, + // Make sure to keep sending ACK for last byte in read operation when it is followed + // by another consecutive read operation. If the current operation is write, this is + // identical to `FirstFrame`. + (true, Some(Operation::Read(_))) => FrameOptions::FirstAndNextFrame, + // Otherwise, send NACK for last byte (in read operation). (For write, this does not + // matter and could also be `FirstAndNextFrame`.) + (true, Some(Operation::Write(_))) => FrameOptions::FirstFrame, + + // If this is not the first frame of its type, we do not generate a (repeated) start + // condition. Otherwise, we branch the same way as above. + (false, None) => FrameOptions::LastFrame, + (false, Some(Operation::Read(_))) => FrameOptions::NextFrame, + (false, Some(Operation::Write(_))) => FrameOptions::LastFrameNoStop, + }; + + match op { + Operation::Read(read) => self.blocking_read_timeout(addr, read, timeout, frame)?, + Operation::Write(write) => self.write_bytes(addr, write, timeout, frame)?, + } + + prev_op = Some(op); + } Ok(()) } diff --git a/embassy-stm32/src/i2c/v2.rs b/embassy-stm32/src/i2c/v2.rs index bd3abaac1..8baf2849d 100644 --- a/embassy-stm32/src/i2c/v2.rs +++ b/embassy-stm32/src/i2c/v2.rs @@ -4,11 +4,11 @@ use core::task::Poll; use embassy_embedded_hal::SetConfig; use embassy_hal_internal::drop::OnDrop; +use embedded_hal_1::i2c::Operation; use super::*; use crate::dma::Transfer; use crate::pac::i2c; -use crate::time::Hertz; pub(crate) unsafe fn on_interrupt() { let regs = T::regs(); @@ -579,6 +579,17 @@ impl<'d, T: Instance, TXDMA, RXDMA> I2c<'d, T, TXDMA, RXDMA> { // Automatic Stop } + /// Blocking transaction with operations. + /// + /// Consecutive operations of same type are merged. See [transaction contract] for details. + /// + /// [transaction contract]: embedded_hal_1::i2c::I2c::transaction + pub fn blocking_transaction(&mut self, addr: u8, operations: &mut [Operation<'_>]) -> Result<(), Error> { + let _ = addr; + let _ = operations; + todo!() + } + /// Blocking write multiple buffers. /// /// The buffers are concatenated in a single write transaction. diff --git a/embassy-stm32/src/i2s.rs b/embassy-stm32/src/i2s.rs index fa9ec0532..c5a606b21 100644 --- a/embassy-stm32/src/i2s.rs +++ b/embassy-stm32/src/i2s.rs @@ -1,8 +1,7 @@ //! Inter-IC Sound (I2S) use embassy_hal_internal::into_ref; -use crate::gpio::sealed::{AFType, Pin as _}; -use crate::gpio::AnyPin; +use crate::gpio::{AFType, AnyPin, SealedPin}; use crate::pac::spi::vals; use crate::spi::{Config as SpiConfig, *}; use crate::time::Hertz; diff --git a/embassy-stm32/src/ipcc.rs b/embassy-stm32/src/ipcc.rs index 523719bb9..4d535cce2 100644 --- a/embassy-stm32/src/ipcc.rs +++ b/embassy-stm32/src/ipcc.rs @@ -4,11 +4,12 @@ use core::future::poll_fn; use core::sync::atomic::{compiler_fence, Ordering}; use core::task::Poll; -use self::sealed::Instance; +use embassy_sync::waitqueue::AtomicWaker; + use crate::interrupt; use crate::interrupt::typelevel::Interrupt; use crate::peripherals::IPCC; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; /// Interrupt handler. pub struct ReceiveInterruptHandler {} @@ -207,7 +208,7 @@ impl Ipcc { } } -impl sealed::Instance for crate::peripherals::IPCC { +impl SealedInstance for crate::peripherals::IPCC { fn regs() -> crate::pac::ipcc::Ipcc { crate::pac::IPCC } @@ -216,58 +217,52 @@ impl sealed::Instance for crate::peripherals::IPCC { crate::pac::PWR.cr4().modify(|w| w.set_c2boot(enabled)); } - fn state() -> &'static self::sealed::State { - static STATE: self::sealed::State = self::sealed::State::new(); + fn state() -> &'static State { + static STATE: State = State::new(); &STATE } } -pub(crate) mod sealed { - use embassy_sync::waitqueue::AtomicWaker; +struct State { + rx_wakers: [AtomicWaker; 6], + tx_wakers: [AtomicWaker; 6], +} - use super::*; +impl State { + const fn new() -> Self { + const WAKER: AtomicWaker = AtomicWaker::new(); - pub struct State { - rx_wakers: [AtomicWaker; 6], - tx_wakers: [AtomicWaker; 6], - } - - impl State { - pub const fn new() -> Self { - const WAKER: AtomicWaker = AtomicWaker::new(); - - Self { - rx_wakers: [WAKER; 6], - tx_wakers: [WAKER; 6], - } - } - - pub const fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { - match channel { - IpccChannel::Channel1 => &self.rx_wakers[0], - IpccChannel::Channel2 => &self.rx_wakers[1], - IpccChannel::Channel3 => &self.rx_wakers[2], - IpccChannel::Channel4 => &self.rx_wakers[3], - IpccChannel::Channel5 => &self.rx_wakers[4], - IpccChannel::Channel6 => &self.rx_wakers[5], - } - } - - pub const fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { - match channel { - IpccChannel::Channel1 => &self.tx_wakers[0], - IpccChannel::Channel2 => &self.tx_wakers[1], - IpccChannel::Channel3 => &self.tx_wakers[2], - IpccChannel::Channel4 => &self.tx_wakers[3], - IpccChannel::Channel5 => &self.tx_wakers[4], - IpccChannel::Channel6 => &self.tx_wakers[5], - } + Self { + rx_wakers: [WAKER; 6], + tx_wakers: [WAKER; 6], } } - pub trait Instance: crate::rcc::RccPeripheral { - fn regs() -> crate::pac::ipcc::Ipcc; - fn set_cpu2(enabled: bool); - fn state() -> &'static State; + const fn rx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { + match channel { + IpccChannel::Channel1 => &self.rx_wakers[0], + IpccChannel::Channel2 => &self.rx_wakers[1], + IpccChannel::Channel3 => &self.rx_wakers[2], + IpccChannel::Channel4 => &self.rx_wakers[3], + IpccChannel::Channel5 => &self.rx_wakers[4], + IpccChannel::Channel6 => &self.rx_wakers[5], + } + } + + const fn tx_waker_for(&self, channel: IpccChannel) -> &AtomicWaker { + match channel { + IpccChannel::Channel1 => &self.tx_wakers[0], + IpccChannel::Channel2 => &self.tx_wakers[1], + IpccChannel::Channel3 => &self.tx_wakers[2], + IpccChannel::Channel4 => &self.tx_wakers[3], + IpccChannel::Channel5 => &self.tx_wakers[4], + IpccChannel::Channel6 => &self.tx_wakers[5], + } } } + +trait SealedInstance: crate::rcc::RccPeripheral { + fn regs() -> crate::pac::ipcc::Ipcc; + fn set_cpu2(enabled: bool); + fn state() -> &'static State; +} diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index b38b5c29d..6a3d1c463 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -79,10 +79,8 @@ pub mod ucpd; pub mod uid; #[cfg(usart)] pub mod usart; -#[cfg(usb)] +#[cfg(any(usb, otg))] pub mod usb; -#[cfg(otg)] -pub mod usb_otg; #[cfg(iwdg)] pub mod wdg; @@ -107,10 +105,10 @@ pub use crate::_generated::interrupt; /// Example of how to bind one interrupt: /// /// ```rust,ignore -/// use embassy_stm32::{bind_interrupts, usb_otg, peripherals}; +/// use embassy_stm32::{bind_interrupts, usb, peripherals}; /// /// bind_interrupts!(struct Irqs { -/// OTG_FS => usb_otg::InterruptHandler; +/// OTG_FS => usb::InterruptHandler; /// }); /// ``` /// @@ -160,7 +158,7 @@ pub(crate) use stm32_metapac as pac; use crate::interrupt::Priority; #[cfg(feature = "rt")] pub use crate::pac::NVIC_PRIO_BITS; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; /// `embassy-stm32` global configuration. #[non_exhaustive] diff --git a/embassy-stm32/src/opamp.rs b/embassy-stm32/src/opamp.rs index cf531e266..a3b4352c0 100644 --- a/embassy-stm32/src/opamp.rs +++ b/embassy-stm32/src/opamp.rs @@ -81,8 +81,8 @@ impl<'d, T: Instance> OpAmp<'d, T> { /// [`OpAmpOutput`] is dropped. pub fn buffer_ext( &'d mut self, - in_pin: impl Peripheral

+ crate::gpio::sealed::Pin>, - out_pin: impl Peripheral

+ crate::gpio::sealed::Pin> + 'd, + in_pin: impl Peripheral

+ crate::gpio::Pin>, + out_pin: impl Peripheral

+ crate::gpio::Pin> + 'd, gain: OpAmpGain, ) -> OpAmpOutput<'d, T> { into_ref!(in_pin); @@ -122,7 +122,7 @@ impl<'d, T: Instance> OpAmp<'d, T> { #[cfg(opamp_g4)] pub fn buffer_int( &'d mut self, - pin: impl Peripheral

+ crate::gpio::sealed::Pin>, + pin: impl Peripheral

+ crate::gpio::Pin>, gain: OpAmpGain, ) -> OpAmpInternalOutput<'d, T> { into_ref!(pin); @@ -166,37 +166,39 @@ impl<'d, T: Instance> Drop for OpAmpInternalOutput<'d, T> { } } -/// Opamp instance trait. -pub trait Instance: sealed::Instance + 'static {} - -pub(crate) mod sealed { - pub trait Instance { - fn regs() -> crate::pac::opamp::Opamp; - } - - pub trait NonInvertingPin { - fn channel(&self) -> u8; - } - - pub trait InvertingPin { - fn channel(&self) -> u8; - } - - pub trait OutputPin {} +pub(crate) trait SealedInstance { + fn regs() -> crate::pac::opamp::Opamp; } +pub(crate) trait SealedNonInvertingPin { + fn channel(&self) -> u8; +} + +pub(crate) trait SealedInvertingPin { + #[allow(unused)] + fn channel(&self) -> u8; +} + +pub(crate) trait SealedOutputPin {} + +/// Opamp instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + 'static {} /// Non-inverting pin trait. -pub trait NonInvertingPin: sealed::NonInvertingPin {} +#[allow(private_bounds)] +pub trait NonInvertingPin: SealedNonInvertingPin {} /// Inverting pin trait. -pub trait InvertingPin: sealed::InvertingPin {} +#[allow(private_bounds)] +pub trait InvertingPin: SealedInvertingPin {} /// Output pin trait. -pub trait OutputPin: sealed::OutputPin {} +#[allow(private_bounds)] +pub trait OutputPin: SealedOutputPin {} macro_rules! impl_opamp_external_output { ($inst:ident, $adc:ident, $ch:expr) => { foreach_adc!( ($adc, $common_inst:ident, $adc_clock:ident) => { - impl<'d> crate::adc::sealed::AdcPin + impl<'d> crate::adc::SealedAdcPin for OpAmpOutput<'d, crate::peripherals::$inst> { fn channel(&self) -> u8 { @@ -242,7 +244,7 @@ macro_rules! impl_opamp_internal_output { ($inst:ident, $adc:ident, $ch:expr) => { foreach_adc!( ($adc, $common_inst:ident, $adc_clock:ident) => { - impl<'d> crate::adc::sealed::AdcPin + impl<'d> crate::adc::SealedAdcPin for OpAmpInternalOutput<'d, crate::peripherals::$inst> { fn channel(&self) -> u8 { @@ -291,7 +293,7 @@ foreach_peripheral!( foreach_peripheral! { (opamp, $inst:ident) => { - impl sealed::Instance for crate::peripherals::$inst { + impl SealedInstance for crate::peripherals::$inst { fn regs() -> crate::pac::opamp::Opamp { crate::pac::$inst } @@ -306,7 +308,7 @@ foreach_peripheral! { macro_rules! impl_opamp_vp_pin { ($inst:ident, $pin:ident, $ch:expr) => { impl crate::opamp::NonInvertingPin for crate::peripherals::$pin {} - impl crate::opamp::sealed::NonInvertingPin for crate::peripherals::$pin { + impl crate::opamp::SealedNonInvertingPin for crate::peripherals::$pin { fn channel(&self) -> u8 { $ch } @@ -318,6 +320,6 @@ macro_rules! impl_opamp_vp_pin { macro_rules! impl_opamp_vout_pin { ($inst:ident, $pin:ident) => { impl crate::opamp::OutputPin for crate::peripherals::$pin {} - impl crate::opamp::sealed::OutputPin for crate::peripherals::$pin {} + impl crate::opamp::SealedOutputPin for crate::peripherals::$pin {} }; } diff --git a/embassy-stm32/src/qspi/mod.rs b/embassy-stm32/src/qspi/mod.rs index 8a709a89e..3c054e666 100644 --- a/embassy-stm32/src/qspi/mod.rs +++ b/embassy-stm32/src/qspi/mod.rs @@ -8,8 +8,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; use enums::*; use crate::dma::Transfer; -use crate::gpio::sealed::AFType; -use crate::gpio::{AnyPin, Pull}; +use crate::gpio::{AFType, AnyPin, Pull}; use crate::pac::quadspi::Quadspi as Regs; use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; @@ -381,16 +380,13 @@ impl<'d, T: Instance, Dma> Qspi<'d, T, Dma> { } } -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - const REGS: Regs; - } +trait SealedInstance { + const REGS: Regs; } /// QSPI instance trait. -pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} +#[allow(private_bounds)] +pub trait Instance: Peripheral

+ SealedInstance + RccPeripheral {} pin_trait!(SckPin, Instance); pin_trait!(BK1D0Pin, Instance); @@ -409,7 +405,7 @@ dma_trait!(QuadDma, Instance); foreach_peripheral!( (quadspi, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { const REGS: Regs = crate::pac::$inst; } diff --git a/embassy-stm32/src/rcc/hsi48.rs b/embassy-stm32/src/rcc/hsi48.rs index 19a8c8cb9..6f0d7b379 100644 --- a/embassy-stm32/src/rcc/hsi48.rs +++ b/embassy-stm32/src/rcc/hsi48.rs @@ -2,7 +2,7 @@ use crate::pac::crs::vals::Syncsrc; use crate::pac::{CRS, RCC}; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; use crate::time::Hertz; /// HSI48 speed diff --git a/embassy-stm32/src/rcc/mco.rs b/embassy-stm32/src/rcc/mco.rs index 654943bc1..d8604e07e 100644 --- a/embassy-stm32/src/rcc/mco.rs +++ b/embassy-stm32/src/rcc/mco.rs @@ -2,8 +2,7 @@ use core::marker::PhantomData; use embassy_hal_internal::into_ref; -use crate::gpio::sealed::AFType; -use crate::gpio::Speed; +use crate::gpio::{AFType, Speed}; #[cfg(not(any(stm32f1, rcc_f0v1, rcc_f3v1, rcc_f37)))] pub use crate::pac::rcc::vals::Mcopre as McoPrescaler; #[cfg(not(any(rcc_f2, rcc_f410, rcc_f4, rcc_f7, rcc_h50, rcc_h5, rcc_h7ab, rcc_h7rm0433, rcc_h7)))] @@ -19,23 +18,25 @@ pub enum McoPrescaler { DIV1, } -pub(crate) mod sealed { - pub trait McoInstance { - type Source; - unsafe fn apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler); - } -} +pub(crate) trait SealedMcoInstance {} -pub trait McoInstance: sealed::McoInstance + 'static {} +#[allow(private_bounds)] +pub trait McoInstance: SealedMcoInstance + 'static { + type Source; + + #[doc(hidden)] + unsafe fn _apply_clock_settings(source: Self::Source, prescaler: super::McoPrescaler); +} pin_trait!(McoPin, McoInstance); macro_rules! impl_peri { ($peri:ident, $source:ident, $set_source:ident, $set_prescaler:ident) => { - impl sealed::McoInstance for peripherals::$peri { + impl SealedMcoInstance for peripherals::$peri {} + impl McoInstance for peripherals::$peri { type Source = $source; - unsafe fn apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) { + unsafe fn _apply_clock_settings(source: Self::Source, _prescaler: McoPrescaler) { #[cfg(not(any(stm32u5, stm32wba)))] let r = RCC.cfgr(); #[cfg(any(stm32u5, stm32wba))] @@ -48,8 +49,6 @@ macro_rules! impl_peri { }); } } - - impl McoInstance for peripherals::$peri {} }; } @@ -79,7 +78,7 @@ impl<'d, T: McoInstance> Mco<'d, T> { into_ref!(pin); critical_section::with(|_| unsafe { - T::apply_clock_settings(source, prescaler); + T::_apply_clock_settings(source, prescaler); pin.set_as_af(pin.af_num(), AFType::OutputPushPull); pin.set_speed(Speed::VeryHigh); }); diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 910ebe205..d53d02203 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs @@ -10,6 +10,7 @@ pub use bd::*; #[cfg(any(mco, mco1, mco2))] mod mco; +use critical_section::CriticalSection; #[cfg(any(mco, mco1, mco2))] pub use mco::*; @@ -32,6 +33,7 @@ mod _version; pub use _version::*; pub use crate::_generated::{mux, Clocks}; +use crate::time::Hertz; #[cfg(feature = "low-power")] /// Must be written within a critical section @@ -63,29 +65,21 @@ pub(crate) unsafe fn get_freqs() -> &'static Clocks { CLOCK_FREQS.assume_init_ref() } -#[cfg(feature = "unstable-pac")] -pub mod low_level { - pub use super::sealed::*; -} +pub(crate) trait SealedRccPeripheral { + fn frequency() -> crate::time::Hertz; + fn enable_and_reset_with_cs(cs: CriticalSection); + fn disable_with_cs(cs: CriticalSection); -pub(crate) mod sealed { - use critical_section::CriticalSection; - - pub trait RccPeripheral { - fn frequency() -> crate::time::Hertz; - fn enable_and_reset_with_cs(cs: CriticalSection); - fn disable_with_cs(cs: CriticalSection); - - fn enable_and_reset() { - critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) - } - fn disable() { - critical_section::with(|cs| Self::disable_with_cs(cs)) - } + fn enable_and_reset() { + critical_section::with(|cs| Self::enable_and_reset_with_cs(cs)) + } + fn disable() { + critical_section::with(|cs| Self::disable_with_cs(cs)) } } -pub trait RccPeripheral: sealed::RccPeripheral + 'static {} +#[allow(private_bounds)] +pub trait RccPeripheral: SealedRccPeripheral + 'static {} #[allow(unused)] mod util { @@ -116,3 +110,12 @@ mod util { Ok(Some(x)) } } + +/// Get the kernel clocok frequency of the peripheral `T`. +/// +/// # Panics +/// +/// Panics if the clock is not active. +pub fn frequency() -> Hertz { + T::frequency() +} diff --git a/embassy-stm32/src/rng.rs b/embassy-stm32/src/rng.rs index ca641f352..7a228e4a4 100644 --- a/embassy-stm32/src/rng.rs +++ b/embassy-stm32/src/rng.rs @@ -222,16 +222,13 @@ impl<'d, T: Instance> RngCore for Rng<'d, T> { impl<'d, T: Instance> CryptoRng for Rng<'d, T> {} -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - fn regs() -> pac::rng::Rng; - } +trait SealedInstance { + fn regs() -> pac::rng::Rng; } /// RNG instance trait. -pub trait Instance: sealed::Instance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { +#[allow(private_bounds)] +pub trait Instance: SealedInstance + Peripheral

+ crate::rcc::RccPeripheral + 'static + Send { /// Interrupt for this RNG instance. type Interrupt: interrupt::typelevel::Interrupt; } @@ -242,7 +239,7 @@ foreach_interrupt!( type Interrupt = crate::interrupt::typelevel::$irq; } - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { fn regs() -> crate::pac::rng::Rng { crate::pac::$inst } diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index ef92fa4bb..bab8cf4a3 100644 --- a/embassy-stm32/src/rtc/datetime.rs +++ b/embassy-stm32/src/rtc/datetime.rs @@ -1,13 +1,10 @@ #[cfg(feature = "chrono")] -use core::convert::From; - -#[cfg(feature = "chrono")] -use chrono::{self, Datelike, NaiveDate, Timelike, Weekday}; +use chrono::{Datelike, NaiveDate, Timelike, Weekday}; #[cfg(any(feature = "defmt", feature = "time"))] use crate::peripherals::RTC; #[cfg(any(feature = "defmt", feature = "time"))] -use crate::rtc::sealed::Instance; +use crate::rtc::SealedInstance; /// Represents an instant in time that can be substracted to compute a duration pub struct RtcInstant { diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 169505501..00abe9356 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs @@ -31,7 +31,6 @@ pub use _version::*; use embassy_hal_internal::Peripheral; use crate::peripherals::RTC; -use crate::rtc::sealed::Instance; #[allow(dead_code)] #[repr(u8)] @@ -212,7 +211,7 @@ impl Rtc { /// Create a new RTC instance. pub fn new(_rtc: impl Peripheral

, rtc_config: RtcConfig) -> Self { #[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))] - ::enable_and_reset(); + ::enable_and_reset(); let mut this = Self { #[cfg(feature = "low-power")] @@ -437,7 +436,7 @@ impl Rtc { .fpr(0) .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); - ::WakeupInterrupt::unpend(); + ::WakeupInterrupt::unpend(); }); } @@ -449,8 +448,8 @@ impl Rtc { use crate::interrupt::typelevel::Interrupt; use crate::pac::EXTI; - ::WakeupInterrupt::unpend(); - unsafe { ::WakeupInterrupt::enable() }; + ::WakeupInterrupt::unpend(); + unsafe { ::WakeupInterrupt::enable() }; EXTI.rtsr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); EXTI.imr(0).modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); @@ -477,34 +476,30 @@ pub(crate) fn bcd2_to_byte(bcd: (u8, u8)) -> u8 { tmp + (value & 0x0F) } -pub(crate) mod sealed { - use crate::pac::rtc::Rtc; +trait SealedInstance { + const BACKUP_REGISTER_COUNT: usize; - pub trait Instance { - const BACKUP_REGISTER_COUNT: usize; + #[cfg(feature = "low-power")] + const EXTI_WAKEUP_LINE: usize; - #[cfg(feature = "low-power")] - const EXTI_WAKEUP_LINE: usize; + #[cfg(feature = "low-power")] + type WakeupInterrupt: crate::interrupt::typelevel::Interrupt; - #[cfg(feature = "low-power")] - type WakeupInterrupt: crate::interrupt::typelevel::Interrupt; - - fn regs() -> Rtc { - crate::pac::RTC - } - - /// Read content of the backup register. - /// - /// The registers retain their values during wakes from standby mode or system resets. They also - /// retain their value when Vdd is switched off as long as V_BAT is powered. - fn read_backup_register(rtc: &Rtc, register: usize) -> Option; - - /// Set content of the backup register. - /// - /// The registers retain their values during wakes from standby mode or system resets. They also - /// retain their value when Vdd is switched off as long as V_BAT is powered. - fn write_backup_register(rtc: &Rtc, register: usize, value: u32); - - // fn apply_config(&mut self, rtc_config: RtcConfig); + fn regs() -> crate::pac::rtc::Rtc { + crate::pac::RTC } + + /// Read content of the backup register. + /// + /// The registers retain their values during wakes from standby mode or system resets. They also + /// retain their value when Vdd is switched off as long as V_BAT is powered. + fn read_backup_register(rtc: &crate::pac::rtc::Rtc, register: usize) -> Option; + + /// Set content of the backup register. + /// + /// The registers retain their values during wakes from standby mode or system resets. They also + /// retain their value when Vdd is switched off as long as V_BAT is powered. + fn write_backup_register(rtc: &crate::pac::rtc::Rtc, register: usize, value: u32); + + // fn apply_config(&mut self, rtc_config: RtcConfig); } diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs index 1eda097a7..92f9de846 100644 --- a/embassy-stm32/src/rtc/v2.rs +++ b/embassy-stm32/src/rtc/v2.rs @@ -1,9 +1,8 @@ use stm32_metapac::rtc::vals::{Osel, Pol}; -use super::sealed; +use super::SealedInstance; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; -use crate::rtc::sealed::Instance; #[allow(dead_code)] impl super::Rtc { @@ -126,7 +125,7 @@ impl super::Rtc { } } -impl sealed::Instance for crate::peripherals::RTC { +impl SealedInstance for crate::peripherals::RTC { const BACKUP_REGISTER_COUNT: usize = 20; #[cfg(all(feature = "low-power", stm32f4))] diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 3d44a52ff..8a78d16e1 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs @@ -1,9 +1,9 @@ use stm32_metapac::rtc::vals::{Calp, Calw16, Calw8, Fmt, Key, Osel, Pol, TampalrmType}; -use super::{sealed, RtcCalibrationCyclePeriod}; +use super::RtcCalibrationCyclePeriod; use crate::pac::rtc::Rtc; use crate::peripherals::RTC; -use crate::rtc::sealed::Instance; +use crate::rtc::SealedInstance; impl super::Rtc { /// Applies the RTC config @@ -126,7 +126,7 @@ impl super::Rtc { } } -impl sealed::Instance for crate::peripherals::RTC { +impl SealedInstance for crate::peripherals::RTC { const BACKUP_REGISTER_COUNT: usize = 32; #[cfg(all(feature = "low-power", stm32g4))] diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 02f96f8a9..54dd81524 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -6,12 +6,10 @@ use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; -use self::sealed::WhichSubBlock; pub use crate::dma::word; #[cfg(not(gpdma))] use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, Request, TransferOptions, WritableRingBuffer}; -use crate::gpio::sealed::{AFType, Pin as _}; -use crate::gpio::AnyPin; +use crate::gpio::{AFType, AnyPin, SealedPin as _}; use crate::pac::sai::{vals, Sai as Regs}; use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; @@ -386,6 +384,7 @@ impl OutputDrive { /// Master clock divider. #[derive(Copy, Clone, PartialEq)] #[allow(missing_docs)] +#[cfg(any(sai_v1, sai_v2))] pub enum MasterClockDivider { MasterClockDisabled, Div1, @@ -406,8 +405,79 @@ pub enum MasterClockDivider { Div30, } +/// Master clock divider. +#[derive(Copy, Clone, PartialEq)] +#[allow(missing_docs)] +#[cfg(any(sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] +pub enum MasterClockDivider { + MasterClockDisabled, + Div1, + Div2, + Div3, + Div4, + Div5, + Div6, + Div7, + Div8, + Div9, + Div10, + Div11, + Div12, + Div13, + Div14, + Div15, + Div16, + Div17, + Div18, + Div19, + Div20, + Div21, + Div22, + Div23, + Div24, + Div25, + Div26, + Div27, + Div28, + Div29, + Div30, + Div31, + Div32, + Div33, + Div34, + Div35, + Div36, + Div37, + Div38, + Div39, + Div40, + Div41, + Div42, + Div43, + Div44, + Div45, + Div46, + Div47, + Div48, + Div49, + Div50, + Div51, + Div52, + Div53, + Div54, + Div55, + Div56, + Div57, + Div58, + Div59, + Div60, + Div61, + Div62, + Div63, +} + impl MasterClockDivider { - #[cfg(any(sai_v1, sai_v2, sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + #[cfg(any(sai_v1, sai_v2))] const fn mckdiv(&self) -> u8 { match self { MasterClockDivider::MasterClockDisabled => 0, @@ -429,6 +499,76 @@ impl MasterClockDivider { MasterClockDivider::Div30 => 15, } } + + #[cfg(any(sai_v3_2pdm, sai_v3_4pdm, sai_v4_2pdm, sai_v4_4pdm))] + const fn mckdiv(&self) -> u8 { + match self { + MasterClockDivider::MasterClockDisabled => 0, + MasterClockDivider::Div1 => 1, + MasterClockDivider::Div2 => 2, + MasterClockDivider::Div3 => 3, + MasterClockDivider::Div4 => 4, + MasterClockDivider::Div5 => 5, + MasterClockDivider::Div6 => 6, + MasterClockDivider::Div7 => 7, + MasterClockDivider::Div8 => 8, + MasterClockDivider::Div9 => 9, + MasterClockDivider::Div10 => 10, + MasterClockDivider::Div11 => 11, + MasterClockDivider::Div12 => 12, + MasterClockDivider::Div13 => 13, + MasterClockDivider::Div14 => 14, + MasterClockDivider::Div15 => 15, + MasterClockDivider::Div16 => 16, + MasterClockDivider::Div17 => 17, + MasterClockDivider::Div18 => 18, + MasterClockDivider::Div19 => 19, + MasterClockDivider::Div20 => 20, + MasterClockDivider::Div21 => 21, + MasterClockDivider::Div22 => 22, + MasterClockDivider::Div23 => 23, + MasterClockDivider::Div24 => 24, + MasterClockDivider::Div25 => 25, + MasterClockDivider::Div26 => 26, + MasterClockDivider::Div27 => 27, + MasterClockDivider::Div28 => 28, + MasterClockDivider::Div29 => 29, + MasterClockDivider::Div30 => 30, + MasterClockDivider::Div31 => 31, + MasterClockDivider::Div32 => 32, + MasterClockDivider::Div33 => 33, + MasterClockDivider::Div34 => 34, + MasterClockDivider::Div35 => 35, + MasterClockDivider::Div36 => 36, + MasterClockDivider::Div37 => 37, + MasterClockDivider::Div38 => 38, + MasterClockDivider::Div39 => 39, + MasterClockDivider::Div40 => 40, + MasterClockDivider::Div41 => 41, + MasterClockDivider::Div42 => 42, + MasterClockDivider::Div43 => 43, + MasterClockDivider::Div44 => 44, + MasterClockDivider::Div45 => 45, + MasterClockDivider::Div46 => 46, + MasterClockDivider::Div47 => 47, + MasterClockDivider::Div48 => 48, + MasterClockDivider::Div49 => 49, + MasterClockDivider::Div50 => 50, + MasterClockDivider::Div51 => 51, + MasterClockDivider::Div52 => 52, + MasterClockDivider::Div53 => 53, + MasterClockDivider::Div54 => 54, + MasterClockDivider::Div55 => 55, + MasterClockDivider::Div56 => 56, + MasterClockDivider::Div57 => 57, + MasterClockDivider::Div58 => 58, + MasterClockDivider::Div59 => 59, + MasterClockDivider::Div60 => 60, + MasterClockDivider::Div61 => 61, + MasterClockDivider::Div62 => 62, + MasterClockDivider::Div63 => 63, + } + } } /// [`SAI`] configuration. @@ -899,43 +1039,42 @@ impl<'d, T: Instance, W: word::Word> Drop for Sai<'d, T, W> { } } -pub(crate) mod sealed { - use super::*; +trait SealedInstance { + const REGS: Regs; +} - pub trait Instance { - const REGS: Regs; - } +#[derive(Copy, Clone)] +enum WhichSubBlock { + A = 0, + B = 1, +} - #[derive(Copy, Clone)] - pub enum WhichSubBlock { - A = 0, - B = 1, - } - - pub trait SubBlock { - const WHICH: WhichSubBlock; - } +trait SealedSubBlock { + const WHICH: WhichSubBlock; } /// Sub-block instance trait. -pub trait SubBlockInstance: sealed::SubBlock {} +#[allow(private_bounds)] +pub trait SubBlockInstance: SealedSubBlock {} /// Sub-block A. pub enum A {} -impl sealed::SubBlock for A { +impl SealedSubBlock for A { const WHICH: WhichSubBlock = WhichSubBlock::A; } impl SubBlockInstance for A {} /// Sub-block B. pub enum B {} -impl sealed::SubBlock for B { +impl SealedSubBlock for B { const WHICH: WhichSubBlock = WhichSubBlock::B; } impl SubBlockInstance for B {} /// SAI instance trait. -pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} +#[allow(private_bounds)] +pub trait Instance: Peripheral

+ SealedInstance + RccPeripheral {} + pin_trait!(SckPin, Instance, SubBlockInstance); pin_trait!(FsPin, Instance, SubBlockInstance); pin_trait!(SdPin, Instance, SubBlockInstance); @@ -945,7 +1084,7 @@ dma_trait!(Dma, Instance, SubBlockInstance); foreach_peripheral!( (sai, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { const REGS: Regs = crate::pac::$inst; } diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index fa1f710d8..f79a11606 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs @@ -13,8 +13,7 @@ use embassy_sync::waitqueue::AtomicWaker; use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; use crate::dma::NoDma; -use crate::gpio::sealed::{AFType, Pin}; -use crate::gpio::{AnyPin, Pull, Speed}; +use crate::gpio::{AFType, AnyPin, Pull, SealedPin, Speed}; use crate::interrupt::typelevel::Interrupt; use crate::pac::sdmmc::Sdmmc as RegBlock; use crate::rcc::RccPeripheral; @@ -1418,21 +1417,17 @@ impl Cmd { ////////////////////////////////////////////////////// -pub(crate) mod sealed { - use super::*; - - pub trait Instance { - type Interrupt: interrupt::typelevel::Interrupt; - - fn regs() -> RegBlock; - fn state() -> &'static AtomicWaker; - } - - pub trait Pins {} +trait SealedInstance { + fn regs() -> RegBlock; + fn state() -> &'static AtomicWaker; } /// SDMMC instance trait. -pub trait Instance: sealed::Instance + RccPeripheral + 'static {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static { + /// Interrupt for this instance. + type Interrupt: interrupt::typelevel::Interrupt; +} pin_trait!(CkPin, Instance); pin_trait!(CmdPin, Instance); @@ -1459,9 +1454,7 @@ impl SdmmcDma for NoDma {} foreach_peripheral!( (sdmmc, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { - type Interrupt = crate::interrupt::typelevel::$inst; - + impl SealedInstance for peripherals::$inst { fn regs() -> RegBlock { crate::pac::$inst } @@ -1472,6 +1465,8 @@ foreach_peripheral!( } } - impl Instance for peripherals::$inst {} + impl Instance for peripherals::$inst { + type Interrupt = crate::interrupt::typelevel::$inst; + } }; ); diff --git a/embassy-stm32/src/spi/mod.rs b/embassy-stm32/src/spi/mod.rs index b517f640a..0b38c4288 100644 --- a/embassy-stm32/src/spi/mod.rs +++ b/embassy-stm32/src/spi/mod.rs @@ -9,8 +9,7 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; pub use embedded_hal_02::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; use crate::dma::{slice_ptr_parts, word, Transfer}; -use crate::gpio::sealed::{AFType, Pin as _}; -use crate::gpio::{AnyPin, Pull}; +use crate::gpio::{AFType, AnyPin, Pull, SealedPin as _}; use crate::pac::spi::{regs, vals, Spi as Regs}; use crate::rcc::RccPeripheral; use crate::time::Hertz; @@ -210,7 +209,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { // see RM0453 rev 1 section 7.2.13 page 291 // The SUBGHZSPI_SCK frequency is obtained by PCLK3 divided by two. // The SUBGHZSPI_SCK clock maximum speed must not exceed 16 MHz. - let pclk3_freq = ::frequency().0; + let pclk3_freq = ::frequency().0; let freq = Hertz(core::cmp::min(pclk3_freq / 2, 16_000_000)); let mut config = Config::default(); config.mode = MODE_0; @@ -271,13 +270,13 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { if mosi.is_none() { w.set_rxonly(vals::Rxonly::OUTPUTDISABLED); } - w.set_dff(::CONFIG) + w.set_dff(::CONFIG) }); } #[cfg(spi_v2)] { T::REGS.cr2().modify(|w| { - let (ds, frxth) = ::CONFIG; + let (ds, frxth) = ::CONFIG; w.set_frxth(frxth); w.set_ds(ds); w.set_ssoe(false); @@ -317,7 +316,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { T::REGS.cfg1().modify(|w| { w.set_crcen(false); w.set_mbr(br); - w.set_dsize(::CONFIG); + w.set_dsize(::CONFIG); w.set_fthlv(vals::Fthlv::ONEFRAME); }); T::REGS.cr2().modify(|w| { @@ -336,7 +335,7 @@ impl<'d, T: Instance, Tx, Rx> Spi<'d, T, Tx, Rx> { miso, txdma, rxdma, - current_word_size: ::CONFIG, + current_word_size: ::CONFIG, } } @@ -975,24 +974,21 @@ impl<'d, T: Instance, Tx: TxDma, Rx: RxDma, W: Word> embedded_hal_async::s } } -pub(crate) mod sealed { - use super::*; +pub(crate) trait SealedInstance { + const REGS: Regs; +} - pub trait Instance { - const REGS: Regs; - } - - pub trait Word { - const CONFIG: word_impl::Config; - } +trait SealedWord { + const CONFIG: word_impl::Config; } /// Word sizes usable for SPI. -pub trait Word: word::Word + sealed::Word {} +#[allow(private_bounds)] +pub trait Word: word::Word + SealedWord {} macro_rules! impl_word { ($T:ty, $config:expr) => { - impl sealed::Word for $T { + impl SealedWord for $T { const CONFIG: Config = $config; } impl Word for $T {} @@ -1068,7 +1064,8 @@ mod word_impl { } /// SPI instance trait. -pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} +#[allow(private_bounds)] +pub trait Instance: Peripheral

+ SealedInstance + RccPeripheral {} pin_trait!(SckPin, Instance); pin_trait!(MosiPin, Instance); @@ -1082,7 +1079,7 @@ dma_trait!(TxDma, Instance); foreach_peripheral!( (spi, $inst:ident) => { - impl sealed::Instance for peripherals::$inst { + impl SealedInstance for peripherals::$inst { const REGS: Regs = crate::pac::$inst; } diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs index 37b2e7526..cc8161276 100644 --- a/embassy-stm32/src/time_driver.rs +++ b/embassy-stm32/src/time_driver.rs @@ -1,7 +1,6 @@ #![allow(non_snake_case)] use core::cell::Cell; -use core::convert::TryInto; use core::sync::atomic::{compiler_fence, AtomicU32, AtomicU8, Ordering}; use core::{mem, ptr}; @@ -9,16 +8,16 @@ use critical_section::CriticalSection; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::blocking_mutex::Mutex; use embassy_time_driver::{AlarmHandle, Driver, TICK_HZ}; -use stm32_metapac::timer::regs; +use stm32_metapac::timer::{regs, TimGp16}; use crate::interrupt::typelevel::Interrupt; use crate::pac::timer::vals; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::SealedRccPeripheral; #[cfg(feature = "low-power")] use crate::rtc::Rtc; #[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))] -use crate::timer::sealed::AdvancedControlInstance; -use crate::timer::sealed::{CoreInstance, GeneralPurpose16bitInstance as Instance}; +use crate::timer::AdvancedInstance1Channel; +use crate::timer::CoreInstance; use crate::{interrupt, peripherals}; // NOTE regarding ALARM_COUNT: @@ -208,6 +207,10 @@ foreach_interrupt! { }; } +fn regs_gp16() -> TimGp16 { + unsafe { TimGp16::from_ptr(T::regs()) } +} + // Clock timekeeping works with something we call "periods", which are time intervals // of 2^15 ticks. The Clock counter value is 16 bits, so one "overflow cycle" is 2 periods. // @@ -272,9 +275,9 @@ embassy_time_driver::time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { impl RtcDriver { fn init(&'static self, cs: critical_section::CriticalSection) { - let r = T::regs_gp16(); + let r = regs_gp16(); - ::enable_and_reset_with_cs(cs); + ::enable_and_reset_with_cs(cs); let timer_freq = T::frequency(); @@ -287,7 +290,7 @@ impl RtcDriver { Ok(n) => n, }; - r.psc().write(|w| w.set_psc(psc)); + r.psc().write_value(psc); r.arr().write(|w| w.set_arr(u16::MAX)); // Set URS, generate update and clear URS @@ -309,9 +312,9 @@ impl RtcDriver { #[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))] { - ::CaptureCompareInterrupt::unpend(); + ::CaptureCompareInterrupt::unpend(); unsafe { - ::CaptureCompareInterrupt::enable(); + ::CaptureCompareInterrupt::enable(); } } @@ -319,7 +322,7 @@ impl RtcDriver { } fn on_interrupt(&self) { - let r = T::regs_gp16(); + let r = regs_gp16(); // XXX: reduce the size of this critical section ? critical_section::with(|cs| { @@ -350,7 +353,7 @@ impl RtcDriver { } fn next_period(&self) { - let r = T::regs_gp16(); + let r = regs_gp16(); // We only modify the period from the timer interrupt, so we know this can't race. let period = self.period.load(Ordering::Relaxed) + 1; @@ -414,7 +417,7 @@ impl RtcDriver { /// Add the given offset to the current time fn add_time(&self, offset: embassy_time::Duration, cs: CriticalSection) { let offset = offset.as_ticks(); - let cnt = T::regs_gp16().cnt().read().cnt() as u32; + let cnt = regs_gp16().cnt().read().cnt() as u32; let period = self.period.load(Ordering::SeqCst); // Correct the race, if it exists @@ -440,7 +443,7 @@ impl RtcDriver { let period = if cnt > u16::MAX as u32 / 2 { period + 1 } else { period }; self.period.store(period, Ordering::SeqCst); - T::regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16)); + regs_gp16().cnt().write(|w| w.set_cnt(cnt as u16)); // Now, recompute all alarms for i in 0..ALARM_COUNT { @@ -497,7 +500,7 @@ impl RtcDriver { .unwrap() .start_wakeup_alarm(time_until_next_alarm, cs); - T::regs_gp16().cr1().modify(|w| w.set_cen(false)); + regs_gp16().cr1().modify(|w| w.set_cen(false)); Ok(()) } @@ -507,7 +510,7 @@ impl RtcDriver { #[cfg(feature = "low-power")] /// Resume the timer with the given offset pub(crate) fn resume_time(&self) { - if T::regs_gp16().cr1().read().cen() { + if regs_gp16().cr1().read().cen() { // Time isn't currently stopped return; @@ -516,14 +519,14 @@ impl RtcDriver { critical_section::with(|cs| { self.stop_wakeup_alarm(cs); - T::regs_gp16().cr1().modify(|w| w.set_cen(true)); + regs_gp16().cr1().modify(|w| w.set_cen(true)); }) } } impl Driver for RtcDriver { fn now(&self) -> u64 { - let r = T::regs_gp16(); + let r = regs_gp16(); let period = self.period.load(Ordering::Relaxed); compiler_fence(Ordering::Acquire); @@ -554,7 +557,7 @@ impl Driver for RtcDriver { fn set_alarm(&self, alarm: AlarmHandle, timestamp: u64) -> bool { critical_section::with(|cs| { - let r = T::regs_gp16(); + let r = regs_gp16(); let n = alarm.id() as usize; let alarm = self.get_alarm(cs, alarm); diff --git a/embassy-stm32/src/timer/complementary_pwm.rs b/embassy-stm32/src/timer/complementary_pwm.rs index 72f1ec864..a892646cf 100644 --- a/embassy-stm32/src/timer/complementary_pwm.rs +++ b/embassy-stm32/src/timer/complementary_pwm.rs @@ -5,12 +5,15 @@ use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; use stm32_metapac::timer::vals::Ckd; -use super::simple_pwm::*; -use super::*; -#[allow(unused_imports)] -use crate::gpio::sealed::{AFType, Pin}; +use super::low_level::{CountingMode, OutputPolarity, Timer}; +use super::simple_pwm::{Ch1, Ch2, Ch3, Ch4, PwmPin}; +use super::{ + AdvancedInstance4Channel, Channel, Channel1ComplementaryPin, Channel2ComplementaryPin, Channel3ComplementaryPin, + Channel4ComplementaryPin, +}; use crate::gpio::{AnyPin, OutputType}; use crate::time::Hertz; +use crate::timer::low_level::OutputCompareMode; use crate::Peripheral; /// Complementary PWM pin wrapper. @@ -23,7 +26,7 @@ pub struct ComplementaryPwmPin<'d, T, C> { macro_rules! complementary_channel_impl { ($new_chx:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwmPin<'d, T, $channel> { + impl<'d, T: AdvancedInstance4Channel> ComplementaryPwmPin<'d, T, $channel> { #[doc = concat!("Create a new ", stringify!($channel), " complementary PWM pin instance.")] pub fn $new_chx(pin: impl Peripheral

> + 'd, output_type: OutputType) -> Self { into_ref!(pin); @@ -48,11 +51,11 @@ complementary_channel_impl!(new_ch3, Ch3, Channel3ComplementaryPin); complementary_channel_impl!(new_ch4, Ch4, Channel4ComplementaryPin); /// PWM driver with support for standard and complementary outputs. -pub struct ComplementaryPwm<'d, T> { - inner: PeripheralRef<'d, T>, +pub struct ComplementaryPwm<'d, T: AdvancedInstance4Channel> { + inner: Timer<'d, T>, } -impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { +impl<'d, T: AdvancedInstance4Channel> ComplementaryPwm<'d, T> { /// Create a new complementary PWM driver. #[allow(clippy::too_many_arguments)] pub fn new( @@ -72,11 +75,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { } fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz, counting_mode: CountingMode) -> Self { - into_ref!(tim); - - T::enable_and_reset(); - - let mut this = Self { inner: tim }; + let mut this = Self { inner: Timer::new(tim) }; this.inner.set_counting_mode(counting_mode); this.set_frequency(freq); @@ -123,7 +122,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { /// /// This value depends on the configured frequency and the timer's clock rate from RCC. pub fn get_max_duty(&self) -> u16 { - self.inner.get_max_compare_value() + 1 + self.inner.get_max_compare_value() as u16 + 1 } /// Set the duty for a given channel. @@ -131,7 +130,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. pub fn set_duty(&mut self, channel: Channel, duty: u16) { assert!(duty <= self.get_max_duty()); - self.inner.set_compare_value(channel, duty) + self.inner.set_compare_value(channel, duty as _) } /// Set the output polarity for a given channel. @@ -149,7 +148,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> { } } -impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { +impl<'d, T: AdvancedInstance4Channel> embedded_hal_02::Pwm for ComplementaryPwm<'d, T> { type Channel = Channel; type Time = Hertz; type Duty = u16; @@ -169,16 +168,16 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> embedded_hal_02::Pwm for C } fn get_duty(&self, channel: Self::Channel) -> Self::Duty { - self.inner.get_compare_value(channel) + self.inner.get_compare_value(channel) as u16 } fn get_max_duty(&self) -> Self::Duty { - self.inner.get_max_compare_value() + 1 + self.inner.get_max_compare_value() as u16 + 1 } fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { assert!(duty <= self.get_max_duty()); - self.inner.set_compare_value(channel, duty) + self.inner.set_compare_value(channel, duty as u32) } fn set_period

(&mut self, period: P) diff --git a/embassy-stm32/src/timer/low_level.rs b/embassy-stm32/src/timer/low_level.rs new file mode 100644 index 000000000..a5d942314 --- /dev/null +++ b/embassy-stm32/src/timer/low_level.rs @@ -0,0 +1,638 @@ +//! Low-level timer driver. +//! +//! This is an unopinionated, very low-level driver for all STM32 timers. It allows direct register +//! manipulation with the `regs_*()` methods, and has utility functions that are thin wrappers +//! over the registers. +//! +//! The available functionality depends on the timer type. + +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; + +use super::*; +use crate::pac::timer::vals; +use crate::time::Hertz; + +/// Input capture mode. +#[derive(Clone, Copy)] +pub enum InputCaptureMode { + /// Rising edge only. + Rising, + /// Falling edge only. + Falling, + /// Both rising or falling edges. + BothEdges, +} + +/// Input TI selection. +#[derive(Clone, Copy)] +pub enum InputTISelection { + /// Normal + Normal, + /// Alternate + Alternate, + /// TRC + TRC, +} + +impl From for stm32_metapac::timer::vals::CcmrInputCcs { + fn from(tisel: InputTISelection) -> Self { + match tisel { + InputTISelection::Normal => stm32_metapac::timer::vals::CcmrInputCcs::TI4, + InputTISelection::Alternate => stm32_metapac::timer::vals::CcmrInputCcs::TI3, + InputTISelection::TRC => stm32_metapac::timer::vals::CcmrInputCcs::TRC, + } + } +} + +/// Timer counting mode. +#[repr(u8)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +pub enum CountingMode { + #[default] + /// The timer counts up to the reload value and then resets back to 0. + EdgeAlignedUp, + /// The timer counts down to 0 and then resets back to the reload value. + EdgeAlignedDown, + /// The timer counts up to the reload value and then counts back to 0. + /// + /// The output compare interrupt flags of channels configured in output are + /// set when the counter is counting down. + CenterAlignedDownInterrupts, + /// The timer counts up to the reload value and then counts back to 0. + /// + /// The output compare interrupt flags of channels configured in output are + /// set when the counter is counting up. + CenterAlignedUpInterrupts, + /// The timer counts up to the reload value and then counts back to 0. + /// + /// The output compare interrupt flags of channels configured in output are + /// set when the counter is counting both up or down. + CenterAlignedBothInterrupts, +} + +impl CountingMode { + /// Return whether this mode is edge-aligned (up or down). + pub fn is_edge_aligned(&self) -> bool { + matches!(self, CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown) + } + + /// Return whether this mode is center-aligned. + pub fn is_center_aligned(&self) -> bool { + matches!( + self, + CountingMode::CenterAlignedDownInterrupts + | CountingMode::CenterAlignedUpInterrupts + | CountingMode::CenterAlignedBothInterrupts + ) + } +} + +impl From for (vals::Cms, vals::Dir) { + fn from(value: CountingMode) -> Self { + match value { + CountingMode::EdgeAlignedUp => (vals::Cms::EDGEALIGNED, vals::Dir::UP), + CountingMode::EdgeAlignedDown => (vals::Cms::EDGEALIGNED, vals::Dir::DOWN), + CountingMode::CenterAlignedDownInterrupts => (vals::Cms::CENTERALIGNED1, vals::Dir::UP), + CountingMode::CenterAlignedUpInterrupts => (vals::Cms::CENTERALIGNED2, vals::Dir::UP), + CountingMode::CenterAlignedBothInterrupts => (vals::Cms::CENTERALIGNED3, vals::Dir::UP), + } + } +} + +impl From<(vals::Cms, vals::Dir)> for CountingMode { + fn from(value: (vals::Cms, vals::Dir)) -> Self { + match value { + (vals::Cms::EDGEALIGNED, vals::Dir::UP) => CountingMode::EdgeAlignedUp, + (vals::Cms::EDGEALIGNED, vals::Dir::DOWN) => CountingMode::EdgeAlignedDown, + (vals::Cms::CENTERALIGNED1, _) => CountingMode::CenterAlignedDownInterrupts, + (vals::Cms::CENTERALIGNED2, _) => CountingMode::CenterAlignedUpInterrupts, + (vals::Cms::CENTERALIGNED3, _) => CountingMode::CenterAlignedBothInterrupts, + } + } +} + +/// Output compare mode. +#[derive(Clone, Copy)] +pub enum OutputCompareMode { + /// The comparison between the output compare register TIMx_CCRx and + /// the counter TIMx_CNT has no effect on the outputs. + /// (this mode is used to generate a timing base). + Frozen, + /// Set channel to active level on match. OCxREF signal is forced high when the + /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). + ActiveOnMatch, + /// Set channel to inactive level on match. OCxREF signal is forced low when the + /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). + InactiveOnMatch, + /// Toggle - OCxREF toggles when TIMx_CNT=TIMx_CCRx. + Toggle, + /// Force inactive level - OCxREF is forced low. + ForceInactive, + /// Force active level - OCxREF is forced high. + ForceActive, + /// PWM mode 1 - In upcounting, channel is active as long as TIMx_CNTTIMx_CCRx else active (OCxREF=1). + PwmMode1, + /// PWM mode 2 - In upcounting, channel is inactive as long as + /// TIMx_CNTTIMx_CCRx else inactive. + PwmMode2, + // TODO: there's more modes here depending on the chip family. +} + +impl From for stm32_metapac::timer::vals::Ocm { + fn from(mode: OutputCompareMode) -> Self { + match mode { + OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN, + OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH, + OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH, + OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE, + OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE, + OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE, + OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1, + OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2, + } + } +} + +/// Timer output pin polarity. +#[derive(Clone, Copy)] +pub enum OutputPolarity { + /// Active high (higher duty value makes the pin spend more time high). + ActiveHigh, + /// Active low (higher duty value makes the pin spend more time low). + ActiveLow, +} + +impl From for bool { + fn from(mode: OutputPolarity) -> Self { + match mode { + OutputPolarity::ActiveHigh => false, + OutputPolarity::ActiveLow => true, + } + } +} + +/// Low-level timer driver. +pub struct Timer<'d, T: CoreInstance> { + tim: PeripheralRef<'d, T>, +} + +impl<'d, T: CoreInstance> Drop for Timer<'d, T> { + fn drop(&mut self) { + T::disable() + } +} + +impl<'d, T: CoreInstance> Timer<'d, T> { + /// Create a new timer driver. + pub fn new(tim: impl Peripheral

+ 'd) -> Self { + into_ref!(tim); + + T::enable_and_reset(); + + Self { tim } + } + + /// Get access to the virutal core 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_core(&self) -> crate::pac::timer::TimCore { + unsafe { crate::pac::timer::TimCore::from_ptr(T::regs()) } + } + + #[cfg(not(stm32l0))] + fn regs_gp32_unchecked(&self) -> crate::pac::timer::TimGp32 { + unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } + } + + /// Start the timer. + pub fn start(&self) { + self.regs_core().cr1().modify(|r| r.set_cen(true)); + } + + /// Stop the timer. + pub fn stop(&self) { + self.regs_core().cr1().modify(|r| r.set_cen(false)); + } + + /// Reset the counter value to 0 + pub fn reset(&self) { + self.regs_core().cnt().write(|r| r.set_cnt(0)); + } + + /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. + /// + /// This means that in the default edge-aligned mode, + /// the timer counter will wrap around at the same frequency as is being set. + /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved + /// because it needs to count up and down. + pub fn set_frequency(&self, frequency: Hertz) { + let f = frequency.0; + assert!(f > 0); + let timer_f = T::frequency().0; + + match T::BITS { + TimerBits::Bits16 => { + let pclk_ticks_per_timer_period = timer_f / f; + let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into()); + let divide_by = pclk_ticks_per_timer_period / (u32::from(psc) + 1); + + // the timer counts `0..=arr`, we want it to count `0..divide_by` + let arr = unwrap!(u16::try_from(divide_by - 1)); + + let regs = self.regs_core(); + regs.psc().write_value(psc); + regs.arr().write(|r| r.set_arr(arr)); + + regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); + regs.egr().write(|r| r.set_ug(true)); + regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); + } + #[cfg(not(stm32l0))] + TimerBits::Bits32 => { + let pclk_ticks_per_timer_period = (timer_f / f) as u64; + let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); + let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()); + + let regs = self.regs_gp32_unchecked(); + regs.psc().write_value(psc); + regs.arr().write_value(arr); + + regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); + regs.egr().write(|r| r.set_ug(true)); + regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); + } + } + } + + /// Clear update interrupt. + /// + /// Returns whether the update interrupt flag was set. + pub fn clear_update_interrupt(&self) -> bool { + let regs = self.regs_core(); + let sr = regs.sr().read(); + if sr.uif() { + regs.sr().modify(|r| { + r.set_uif(false); + }); + true + } else { + false + } + } + + /// Enable/disable the update interrupt. + pub fn enable_update_interrupt(&self, enable: bool) { + self.regs_core().dier().modify(|r| r.set_uie(enable)); + } + + /// Enable/disable autoreload preload. + pub fn set_autoreload_preload(&self, enable: bool) { + self.regs_core().cr1().modify(|r| r.set_arpe(enable)); + } + + /// Get the timer frequency. + pub fn get_frequency(&self) -> Hertz { + let timer_f = T::frequency(); + + match T::BITS { + TimerBits::Bits16 => { + let regs = self.regs_core(); + let arr = regs.arr().read().arr(); + let psc = regs.psc().read(); + + timer_f / arr / (psc + 1) + } + #[cfg(not(stm32l0))] + TimerBits::Bits32 => { + let regs = self.regs_gp32_unchecked(); + let arr = regs.arr().read(); + let psc = regs.psc().read(); + + timer_f / arr / (psc + 1) + } + } + } +} + +impl<'d, T: BasicNoCr2Instance> Timer<'d, T> { + /// Get access to the Baisc 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_basic_no_cr2(&self) -> crate::pac::timer::TimBasicNoCr2 { + unsafe { crate::pac::timer::TimBasicNoCr2::from_ptr(T::regs()) } + } + + /// Enable/disable the update dma. + pub fn enable_update_dma(&self, enable: bool) { + self.regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable)); + } + + /// Get the update dma enable/disable state. + pub fn get_update_dma_state(&self) -> bool { + self.regs_basic_no_cr2().dier().read().ude() + } +} + +impl<'d, T: BasicInstance> Timer<'d, T> { + /// Get access to the Baisc 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_basic(&self) -> crate::pac::timer::TimBasic { + unsafe { crate::pac::timer::TimBasic::from_ptr(T::regs()) } + } +} + +impl<'d, T: GeneralInstance1Channel> Timer<'d, T> { + /// Get access to the general purpose 1 channel 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_1ch(&self) -> crate::pac::timer::Tim1ch { + unsafe { crate::pac::timer::Tim1ch::from_ptr(T::regs()) } + } + + /// Set clock divider. + pub fn set_clock_division(&self, ckd: vals::Ckd) { + self.regs_1ch().cr1().modify(|r| r.set_ckd(ckd)); + } + + /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. + pub fn get_max_compare_value(&self) -> u32 { + match T::BITS { + TimerBits::Bits16 => self.regs_1ch().arr().read().arr() as u32, + #[cfg(not(stm32l0))] + TimerBits::Bits32 => self.regs_gp32_unchecked().arr().read(), + } + } +} + +impl<'d, T: GeneralInstance2Channel> Timer<'d, T> { + /// Get access to the general purpose 2 channel 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_2ch(&self) -> crate::pac::timer::Tim2ch { + unsafe { crate::pac::timer::Tim2ch::from_ptr(T::regs()) } + } +} + +impl<'d, T: GeneralInstance4Channel> Timer<'d, T> { + /// Get access to the general purpose 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_gp16(&self) -> crate::pac::timer::TimGp16 { + unsafe { crate::pac::timer::TimGp16::from_ptr(T::regs()) } + } + + /// Enable timer outputs. + pub fn enable_outputs(&self) { + self.tim.enable_outputs() + } + + /// Set counting mode. + pub fn set_counting_mode(&self, mode: CountingMode) { + let (cms, dir) = mode.into(); + + let timer_enabled = self.regs_core().cr1().read().cen(); + // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running. + // Changing direction is discouraged while the timer is running. + assert!(!timer_enabled); + + self.regs_gp16().cr1().modify(|r| r.set_dir(dir)); + self.regs_gp16().cr1().modify(|r| r.set_cms(cms)) + } + + /// Get counting mode. + pub fn get_counting_mode(&self) -> CountingMode { + let cr1 = self.regs_gp16().cr1().read(); + (cr1.cms(), cr1.dir()).into() + } + + /// Set input capture filter. + pub fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) { + let raw_channel = channel.index(); + self.regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icf(raw_channel % 2, icf)); + } + + /// Clear input interrupt. + pub fn clear_input_interrupt(&self, channel: Channel) { + self.regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false)); + } + + /// Enable input interrupt. + pub fn enable_input_interrupt(&self, channel: Channel, enable: bool) { + self.regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable)); + } + + /// Set input capture prescaler. + pub fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) { + let raw_channel = channel.index(); + self.regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icpsc(raw_channel % 2, factor)); + } + + /// Set input TI selection. + pub fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) { + let raw_channel = channel.index(); + self.regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); + } + + /// Set input capture mode. + pub fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) { + self.regs_gp16().ccer().modify(|r| match mode { + InputCaptureMode::Rising => { + r.set_ccnp(channel.index(), false); + r.set_ccp(channel.index(), false); + } + InputCaptureMode::Falling => { + r.set_ccnp(channel.index(), false); + r.set_ccp(channel.index(), true); + } + InputCaptureMode::BothEdges => { + r.set_ccnp(channel.index(), true); + r.set_ccp(channel.index(), true); + } + }); + } + + /// Set output compare mode. + pub fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) { + let raw_channel: usize = channel.index(); + self.regs_gp16() + .ccmr_output(raw_channel / 2) + .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); + } + + /// Set output polarity. + pub fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { + self.regs_gp16() + .ccer() + .modify(|w| w.set_ccp(channel.index(), polarity.into())); + } + + /// Enable/disable a channel. + pub fn enable_channel(&self, channel: Channel, enable: bool) { + self.regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); + } + + /// Get enable/disable state of a channel + pub fn get_channel_enable_state(&self, channel: Channel) -> bool { + self.regs_gp16().ccer().read().cce(channel.index()) + } + + /// Set compare value for a channel. + pub fn set_compare_value(&self, channel: Channel, value: u32) { + match T::BITS { + TimerBits::Bits16 => { + let value = unwrap!(u16::try_from(value)); + self.regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); + } + #[cfg(not(stm32l0))] + TimerBits::Bits32 => { + self.regs_gp32_unchecked().ccr(channel.index()).write_value(value); + } + } + } + + /// Get compare value for a channel. + pub fn get_compare_value(&self, channel: Channel) -> u32 { + match T::BITS { + TimerBits::Bits16 => self.regs_gp16().ccr(channel.index()).read().ccr() as u32, + #[cfg(not(stm32l0))] + TimerBits::Bits32 => self.regs_gp32_unchecked().ccr(channel.index()).read(), + } + } + + /// Get capture value for a channel. + pub fn get_capture_value(&self, channel: Channel) -> u32 { + self.get_compare_value(channel) + } + + /// Set output compare preload. + pub fn set_output_compare_preload(&self, channel: Channel, preload: bool) { + let channel_index = channel.index(); + self.regs_gp16() + .ccmr_output(channel_index / 2) + .modify(|w| w.set_ocpe(channel_index % 2, preload)); + } + + /// Get capture compare DMA selection + pub fn get_cc_dma_selection(&self) -> vals::Ccds { + self.regs_gp16().cr2().read().ccds() + } + + /// Set capture compare DMA selection + pub fn set_cc_dma_selection(&self, ccds: vals::Ccds) { + self.regs_gp16().cr2().modify(|w| w.set_ccds(ccds)) + } + + /// Get capture compare DMA enable state + pub fn get_cc_dma_enable_state(&self, channel: Channel) -> bool { + self.regs_gp16().dier().read().ccde(channel.index()) + } + + /// Set capture compare DMA enable state + pub fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { + self.regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) + } +} + +#[cfg(not(stm32l0))] +impl<'d, T: GeneralInstance32bit4Channel> Timer<'d, T> { + /// Get access to the general purpose 32bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_gp32(&self) -> crate::pac::timer::TimGp32 { + unsafe { crate::pac::timer::TimGp32::from_ptr(T::regs()) } + } +} + +#[cfg(not(stm32l0))] +impl<'d, T: AdvancedInstance1Channel> Timer<'d, T> { + /// Get access to the general purpose 1 channel with one complementary 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_1ch_cmp(&self) -> crate::pac::timer::Tim1chCmp { + unsafe { crate::pac::timer::Tim1chCmp::from_ptr(T::regs()) } + } + + /// Set clock divider for the dead time. + pub fn set_dead_time_clock_division(&self, value: vals::Ckd) { + self.regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value)); + } + + /// Set dead time, as a fraction of the max duty value. + pub fn set_dead_time_value(&self, value: u8) { + self.regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value)); + } + + /// Set state of MOE-bit in BDTR register to en-/disable output + pub fn set_moe(&self, enable: bool) { + self.regs_1ch_cmp().bdtr().modify(|w| w.set_moe(enable)); + } +} + +#[cfg(not(stm32l0))] +impl<'d, T: AdvancedInstance2Channel> Timer<'d, T> { + /// Get access to the general purpose 2 channel with one complementary 16bit timer registers. + /// + /// Note: This works even if the timer is more capable, because registers + /// for the less capable timers are a subset. This allows writing a driver + /// for a given set of capabilities, and having it transparently work with + /// more capable timers. + pub fn regs_2ch_cmp(&self) -> crate::pac::timer::Tim2chCmp { + unsafe { crate::pac::timer::Tim2chCmp::from_ptr(T::regs()) } + } +} + +#[cfg(not(stm32l0))] +impl<'d, T: AdvancedInstance4Channel> Timer<'d, T> { + /// Get access to the advanced timer registers. + pub fn regs_advanced(&self) -> crate::pac::timer::TimAdv { + unsafe { crate::pac::timer::TimAdv::from_ptr(T::regs()) } + } + + /// Set complementary output polarity. + pub fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { + self.regs_advanced() + .ccer() + .modify(|w| w.set_ccnp(channel.index(), polarity.into())); + } + + /// Enable/disable a complementary channel. + pub fn enable_complementary_channel(&self, channel: Channel, enable: bool) { + self.regs_advanced() + .ccer() + .modify(|w| w.set_ccne(channel.index(), enable)); + } +} diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index ef893c7f5..2ba6b3f11 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -1,490 +1,13 @@ //! Timers, PWM, quadrature decoder. -//! - -//! Timer inheritance -//! - -// sealed: -// -// Core -------------------------> 1CH -------------------------> 1CH_CMP -// | | ^ | -// +--> Basic_NoCr2 --> Basic +--> 2CH --> GP16 --> GP32 | +--> 2CH_CMP --> ADV -// | | | ^ | | ^ ^ -// | | +------|--|--------------|-----------+ | -// | +--------------------+ +--------------|-----------|---------+ -// | | | | -// | +--------------------------------------|-----------+ -// +----------------------------------------------------+ - -//! ```text -//! BasicInstance --> CaptureCompare16bitInstance --+--> ComplementaryCaptureCompare16bitInstance -//! | -//! +--> CaptureCompare32bitInstance -//! ``` -//! -//! Mapping: -//! -//! | trait | timer | -//! | :----------------------------------------: | ------------------------------------------------------------------------------------------------- | -//! | [BasicInstance] | Basic Timer | -//! | [CaptureCompare16bitInstance] | 1-channel Timer, 2-channel Timer, General Purpose 16-bit Timer | -//! | [CaptureCompare32bitInstance] | General Purpose 32-bit Timer | -//! | [ComplementaryCaptureCompare16bitInstance] | 1-channel with one complentary Timer, 2-channel with one complentary Timer, Advance Control Timer | #[cfg(not(stm32l0))] pub mod complementary_pwm; +pub mod low_level; pub mod qei; pub mod simple_pwm; -use stm32_metapac::timer::vals; - use crate::interrupt; use crate::rcc::RccPeripheral; -use crate::time::Hertz; - -/// Low-level timer access. -#[cfg(feature = "unstable-pac")] -pub mod low_level { - pub use super::sealed::*; -} - -pub(crate) mod sealed { - use super::*; - - /// Virtual Core 16-bit timer instance. - pub trait CoreInstance: RccPeripheral { - /// Interrupt for this timer. - type Interrupt: interrupt::typelevel::Interrupt; - - /// Get access to the virutal core 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_core() -> crate::pac::timer::TimCore; - - /// Start the timer. - fn start(&self) { - Self::regs_core().cr1().modify(|r| r.set_cen(true)); - } - - /// Stop the timer. - fn stop(&self) { - Self::regs_core().cr1().modify(|r| r.set_cen(false)); - } - - /// Reset the counter value to 0 - fn reset(&self) { - Self::regs_core().cnt().write(|r| r.set_cnt(0)); - } - - /// Set the frequency of how many times per second the timer counts up to the max value or down to 0. - /// - /// This means that in the default edge-aligned mode, - /// the timer counter will wrap around at the same frequency as is being set. - /// In center-aligned mode (which not all timers support), the wrap-around frequency is effectively halved - /// because it needs to count up and down. - fn set_frequency(&self, frequency: Hertz) { - let f = frequency.0; - let timer_f = Self::frequency().0; - assert!(f > 0); - let pclk_ticks_per_timer_period = timer_f / f; - let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into()); - let divide_by = pclk_ticks_per_timer_period / (u32::from(psc) + 1); - - // the timer counts `0..=arr`, we want it to count `0..divide_by` - let arr = unwrap!(u16::try_from(divide_by - 1)); - - let regs = Self::regs_core(); - regs.psc().write(|r| r.set_psc(psc)); - regs.arr().write(|r| r.set_arr(arr)); - - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); - } - - /// Clear update interrupt. - /// - /// Returns whether the update interrupt flag was set. - fn clear_update_interrupt(&self) -> bool { - let regs = Self::regs_core(); - let sr = regs.sr().read(); - if sr.uif() { - regs.sr().modify(|r| { - r.set_uif(false); - }); - true - } else { - false - } - } - - /// Enable/disable the update interrupt. - fn enable_update_interrupt(&self, enable: bool) { - Self::regs_core().dier().modify(|r| r.set_uie(enable)); - } - - /// Enable/disable autoreload preload. - fn set_autoreload_preload(&self, enable: bool) { - Self::regs_core().cr1().modify(|r| r.set_arpe(enable)); - } - - /// Get the timer frequency. - fn get_frequency(&self) -> Hertz { - let timer_f = Self::frequency(); - - let regs = Self::regs_core(); - let arr = regs.arr().read().arr(); - let psc = regs.psc().read().psc(); - - timer_f / arr / (psc + 1) - } - } - - /// Virtual Basic without CR2 16-bit timer instance. - pub trait BasicNoCr2Instance: CoreInstance { - /// Get access to the Baisc 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2; - - /// Enable/disable the update dma. - fn enable_update_dma(&self, enable: bool) { - Self::regs_basic_no_cr2().dier().modify(|r| r.set_ude(enable)); - } - - /// Get the update dma enable/disable state. - fn get_update_dma_state(&self) -> bool { - Self::regs_basic_no_cr2().dier().read().ude() - } - } - - /// Basic 16-bit timer instance. - pub trait BasicInstance: BasicNoCr2Instance { - /// Get access to the Baisc 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_basic() -> crate::pac::timer::TimBasic; - } - - /// Gneral-purpose 1 channel 16-bit timer instance. - pub trait GeneralPurpose1ChannelInstance: CoreInstance { - /// Get access to the general purpose 1 channel 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_1ch() -> crate::pac::timer::Tim1ch; - - /// Set clock divider. - fn set_clock_division(&self, ckd: vals::Ckd) { - Self::regs_1ch().cr1().modify(|r| r.set_ckd(ckd)); - } - - /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. - fn get_max_compare_value(&self) -> u16 { - Self::regs_1ch().arr().read().arr() - } - } - - /// Gneral-purpose 1 channel 16-bit timer instance. - pub trait GeneralPurpose2ChannelInstance: GeneralPurpose1ChannelInstance { - /// Get access to the general purpose 2 channel 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_2ch() -> crate::pac::timer::Tim2ch; - } - - /// Gneral-purpose 16-bit timer instance. - pub trait GeneralPurpose16bitInstance: BasicInstance + GeneralPurpose2ChannelInstance { - /// Get access to the general purpose 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_gp16() -> crate::pac::timer::TimGp16; - - /// Set counting mode. - fn set_counting_mode(&self, mode: CountingMode) { - let (cms, dir) = mode.into(); - - let timer_enabled = Self::regs_core().cr1().read().cen(); - // Changing from edge aligned to center aligned (and vice versa) is not allowed while the timer is running. - // Changing direction is discouraged while the timer is running. - assert!(!timer_enabled); - - Self::regs_gp16().cr1().modify(|r| r.set_dir(dir)); - Self::regs_gp16().cr1().modify(|r| r.set_cms(cms)) - } - - /// Get counting mode. - fn get_counting_mode(&self) -> CountingMode { - let cr1 = Self::regs_gp16().cr1().read(); - (cr1.cms(), cr1.dir()).into() - } - - /// Set input capture filter. - fn set_input_capture_filter(&self, channel: Channel, icf: vals::FilterValue) { - let raw_channel = channel.index(); - Self::regs_gp16() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_icf(raw_channel % 2, icf)); - } - - /// Clear input interrupt. - fn clear_input_interrupt(&self, channel: Channel) { - Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.index(), false)); - } - - /// Enable input interrupt. - fn enable_input_interrupt(&self, channel: Channel, enable: bool) { - Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.index(), enable)); - } - - /// Set input capture prescaler. - fn set_input_capture_prescaler(&self, channel: Channel, factor: u8) { - let raw_channel = channel.index(); - Self::regs_gp16() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_icpsc(raw_channel % 2, factor)); - } - - /// Set input TI selection. - fn set_input_ti_selection(&self, channel: Channel, tisel: InputTISelection) { - let raw_channel = channel.index(); - Self::regs_gp16() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); - } - - /// Set input capture mode. - fn set_input_capture_mode(&self, channel: Channel, mode: InputCaptureMode) { - Self::regs_gp16().ccer().modify(|r| match mode { - InputCaptureMode::Rising => { - r.set_ccnp(channel.index(), false); - r.set_ccp(channel.index(), false); - } - InputCaptureMode::Falling => { - r.set_ccnp(channel.index(), false); - r.set_ccp(channel.index(), true); - } - InputCaptureMode::BothEdges => { - r.set_ccnp(channel.index(), true); - r.set_ccp(channel.index(), true); - } - }); - } - - /// Set output compare mode. - fn set_output_compare_mode(&self, channel: Channel, mode: OutputCompareMode) { - let raw_channel: usize = channel.index(); - Self::regs_gp16() - .ccmr_output(raw_channel / 2) - .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); - } - - /// Set output polarity. - fn set_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { - Self::regs_gp16() - .ccer() - .modify(|w| w.set_ccp(channel.index(), polarity.into())); - } - - /// Enable/disable a channel. - fn enable_channel(&self, channel: Channel, enable: bool) { - Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.index(), enable)); - } - - /// Get enable/disable state of a channel - fn get_channel_enable_state(&self, channel: Channel) -> bool { - Self::regs_gp16().ccer().read().cce(channel.index()) - } - - /// Set compare value for a channel. - fn set_compare_value(&self, channel: Channel, value: u16) { - Self::regs_gp16().ccr(channel.index()).modify(|w| w.set_ccr(value)); - } - - /// Get capture value for a channel. - fn get_capture_value(&self, channel: Channel) -> u16 { - Self::regs_gp16().ccr(channel.index()).read().ccr() - } - - /// Get compare value for a channel. - fn get_compare_value(&self, channel: Channel) -> u16 { - Self::regs_gp16().ccr(channel.index()).read().ccr() - } - - /// Set output compare preload. - fn set_output_compare_preload(&self, channel: Channel, preload: bool) { - let channel_index = channel.index(); - Self::regs_gp16() - .ccmr_output(channel_index / 2) - .modify(|w| w.set_ocpe(channel_index % 2, preload)); - } - - /// Get capture compare DMA selection - fn get_cc_dma_selection(&self) -> super::vals::Ccds { - Self::regs_gp16().cr2().read().ccds() - } - - /// Set capture compare DMA selection - fn set_cc_dma_selection(&self, ccds: super::vals::Ccds) { - Self::regs_gp16().cr2().modify(|w| w.set_ccds(ccds)) - } - - /// Get capture compare DMA enable state - fn get_cc_dma_enable_state(&self, channel: Channel) -> bool { - Self::regs_gp16().dier().read().ccde(channel.index()) - } - - /// Set capture compare DMA enable state - fn set_cc_dma_enable_state(&self, channel: Channel, ccde: bool) { - Self::regs_gp16().dier().modify(|w| w.set_ccde(channel.index(), ccde)) - } - } - - #[cfg(not(stm32l0))] - /// Gneral-purpose 32-bit timer instance. - pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { - /// Get access to the general purpose 32bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_gp32() -> crate::pac::timer::TimGp32; - - /// Set timer frequency. - fn set_frequency(&self, frequency: Hertz) { - let f = frequency.0; - assert!(f > 0); - let timer_f = Self::frequency().0; - let pclk_ticks_per_timer_period = (timer_f / f) as u64; - let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); - let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()); - - let regs = Self::regs_gp32(); - regs.psc().write(|r| r.set_psc(psc)); - regs.arr().write_value(arr); - - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); - } - - /// Get timer frequency. - fn get_frequency(&self) -> Hertz { - let timer_f = Self::frequency(); - - let regs = Self::regs_gp32(); - let arr = regs.arr().read(); - let psc = regs.psc().read().psc(); - - timer_f / arr / (psc + 1) - } - - /// Set comapre value for a channel. - fn set_compare_value(&self, channel: Channel, value: u32) { - Self::regs_gp32().ccr(channel.index()).write_value(value); - } - - /// Get capture value for a channel. - fn get_capture_value(&self, channel: Channel) -> u32 { - Self::regs_gp32().ccr(channel.index()).read() - } - - /// Get max compare value. This depends on the timer frequency and the clock frequency from RCC. - fn get_max_compare_value(&self) -> u32 { - Self::regs_gp32().arr().read() - } - - /// Get compare value for a channel. - fn get_compare_value(&self, channel: Channel) -> u32 { - Self::regs_gp32().ccr(channel.index()).read() - } - } - - #[cfg(not(stm32l0))] - /// Gneral-purpose 1 channel with one complementary 16-bit timer instance. - pub trait GeneralPurpose1ChannelComplementaryInstance: BasicNoCr2Instance + GeneralPurpose1ChannelInstance { - /// Get access to the general purpose 1 channel with one complementary 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp; - - /// Set clock divider for the dead time. - fn set_dead_time_clock_division(&self, value: vals::Ckd) { - Self::regs_1ch_cmp().cr1().modify(|w| w.set_ckd(value)); - } - - /// Set dead time, as a fraction of the max duty value. - fn set_dead_time_value(&self, value: u8) { - Self::regs_1ch_cmp().bdtr().modify(|w| w.set_dtg(value)); - } - - /// Set state of MOE-bit in BDTR register to en-/disable output - fn set_moe(&self, enable: bool) { - Self::regs_1ch_cmp().bdtr().modify(|w| w.set_moe(enable)); - } - } - - #[cfg(not(stm32l0))] - /// Gneral-purpose 2 channel with one complementary 16-bit timer instance. - pub trait GeneralPurpose2ChannelComplementaryInstance: - BasicInstance + GeneralPurpose2ChannelInstance + GeneralPurpose1ChannelComplementaryInstance - { - /// Get access to the general purpose 2 channel with one complementary 16bit timer registers. - /// - /// Note: This works even if the timer is more capable, because registers - /// for the less capable timers are a subset. This allows writing a driver - /// for a given set of capabilities, and having it transparently work with - /// more capable timers. - fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp; - } - - #[cfg(not(stm32l0))] - /// Advanced control timer instance. - pub trait AdvancedControlInstance: - GeneralPurpose2ChannelComplementaryInstance + GeneralPurpose16bitInstance - { - /// Capture compare interrupt for this timer. - type CaptureCompareInterrupt: interrupt::typelevel::Interrupt; - - /// Get access to the advanced timer registers. - fn regs_advanced() -> crate::pac::timer::TimAdv; - - /// Set complementary output polarity. - fn set_complementary_output_polarity(&self, channel: Channel, polarity: OutputPolarity) { - Self::regs_advanced() - .ccer() - .modify(|w| w.set_ccnp(channel.index(), polarity.into())); - } - - /// Enable/disable a complementary channel. - fn enable_complementary_channel(&self, channel: Channel, enable: bool) { - Self::regs_advanced() - .ccer() - .modify(|w| w.set_ccne(channel.index(), enable)); - } - } -} /// Timer channel. #[derive(Clone, Copy)] @@ -511,181 +34,44 @@ impl Channel { } } -/// Input capture mode. -#[derive(Clone, Copy)] -pub enum InputCaptureMode { - /// Rising edge only. - Rising, - /// Falling edge only. - Falling, - /// Both rising or falling edges. - BothEdges, +/// Amount of bits of a timer. +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum TimerBits { + /// 16 bits. + Bits16, + /// 32 bits. + #[cfg(not(stm32l0))] + Bits32, } -/// Input TI selection. -#[derive(Clone, Copy)] -pub enum InputTISelection { - /// Normal - Normal, - /// Alternate - Alternate, - /// TRC - TRC, -} +/// Core timer instance. +pub trait CoreInstance: RccPeripheral + 'static { + /// Interrupt for this timer. + type Interrupt: interrupt::typelevel::Interrupt; -impl From for stm32_metapac::timer::vals::CcmrInputCcs { - fn from(tisel: InputTISelection) -> Self { - match tisel { - InputTISelection::Normal => stm32_metapac::timer::vals::CcmrInputCcs::TI4, - InputTISelection::Alternate => stm32_metapac::timer::vals::CcmrInputCcs::TI3, - InputTISelection::TRC => stm32_metapac::timer::vals::CcmrInputCcs::TRC, - } - } -} + /// Amount of bits this timer has. + const BITS: TimerBits; -/// Timer counting mode. -#[repr(u8)] -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] -pub enum CountingMode { - #[default] - /// The timer counts up to the reload value and then resets back to 0. - EdgeAlignedUp, - /// The timer counts down to 0 and then resets back to the reload value. - EdgeAlignedDown, - /// The timer counts up to the reload value and then counts back to 0. + /// Registers for this timer. /// - /// The output compare interrupt flags of channels configured in output are - /// set when the counter is counting down. - CenterAlignedDownInterrupts, - /// The timer counts up to the reload value and then counts back to 0. - /// - /// The output compare interrupt flags of channels configured in output are - /// set when the counter is counting up. - CenterAlignedUpInterrupts, - /// The timer counts up to the reload value and then counts back to 0. - /// - /// The output compare interrupt flags of channels configured in output are - /// set when the counter is counting both up or down. - CenterAlignedBothInterrupts, + /// This is a raw pointer to the register block. The actual register block layout varies depending on the timer type. + fn regs() -> *mut (); } +/// Cut-down basic timer instance. +pub trait BasicNoCr2Instance: CoreInstance {} +/// Basic timer instance. +pub trait BasicInstance: BasicNoCr2Instance {} -impl CountingMode { - /// Return whether this mode is edge-aligned (up or down). - pub fn is_edge_aligned(&self) -> bool { - matches!(self, CountingMode::EdgeAlignedUp | CountingMode::EdgeAlignedDown) - } +/// General-purpose 16-bit timer with 1 channel instance. +pub trait GeneralInstance1Channel: CoreInstance {} - /// Return whether this mode is center-aligned. - pub fn is_center_aligned(&self) -> bool { - matches!( - self, - CountingMode::CenterAlignedDownInterrupts - | CountingMode::CenterAlignedUpInterrupts - | CountingMode::CenterAlignedBothInterrupts - ) - } -} +/// General-purpose 16-bit timer with 2 channels instance. +pub trait GeneralInstance2Channel: GeneralInstance1Channel {} -impl From for (vals::Cms, vals::Dir) { - fn from(value: CountingMode) -> Self { - match value { - CountingMode::EdgeAlignedUp => (vals::Cms::EDGEALIGNED, vals::Dir::UP), - CountingMode::EdgeAlignedDown => (vals::Cms::EDGEALIGNED, vals::Dir::DOWN), - CountingMode::CenterAlignedDownInterrupts => (vals::Cms::CENTERALIGNED1, vals::Dir::UP), - CountingMode::CenterAlignedUpInterrupts => (vals::Cms::CENTERALIGNED2, vals::Dir::UP), - CountingMode::CenterAlignedBothInterrupts => (vals::Cms::CENTERALIGNED3, vals::Dir::UP), - } - } -} - -impl From<(vals::Cms, vals::Dir)> for CountingMode { - fn from(value: (vals::Cms, vals::Dir)) -> Self { - match value { - (vals::Cms::EDGEALIGNED, vals::Dir::UP) => CountingMode::EdgeAlignedUp, - (vals::Cms::EDGEALIGNED, vals::Dir::DOWN) => CountingMode::EdgeAlignedDown, - (vals::Cms::CENTERALIGNED1, _) => CountingMode::CenterAlignedDownInterrupts, - (vals::Cms::CENTERALIGNED2, _) => CountingMode::CenterAlignedUpInterrupts, - (vals::Cms::CENTERALIGNED3, _) => CountingMode::CenterAlignedBothInterrupts, - } - } -} - -/// Output compare mode. -#[derive(Clone, Copy)] -pub enum OutputCompareMode { - /// The comparison between the output compare register TIMx_CCRx and - /// the counter TIMx_CNT has no effect on the outputs. - /// (this mode is used to generate a timing base). - Frozen, - /// Set channel to active level on match. OCxREF signal is forced high when the - /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). - ActiveOnMatch, - /// Set channel to inactive level on match. OCxREF signal is forced low when the - /// counter TIMx_CNT matches the capture/compare register x (TIMx_CCRx). - InactiveOnMatch, - /// Toggle - OCxREF toggles when TIMx_CNT=TIMx_CCRx. - Toggle, - /// Force inactive level - OCxREF is forced low. - ForceInactive, - /// Force active level - OCxREF is forced high. - ForceActive, - /// PWM mode 1 - In upcounting, channel is active as long as TIMx_CNTTIMx_CCRx else active (OCxREF=1). - PwmMode1, - /// PWM mode 2 - In upcounting, channel is inactive as long as - /// TIMx_CNTTIMx_CCRx else inactive. - PwmMode2, - // TODO: there's more modes here depending on the chip family. -} - -impl From for stm32_metapac::timer::vals::Ocm { - fn from(mode: OutputCompareMode) -> Self { - match mode { - OutputCompareMode::Frozen => stm32_metapac::timer::vals::Ocm::FROZEN, - OutputCompareMode::ActiveOnMatch => stm32_metapac::timer::vals::Ocm::ACTIVEONMATCH, - OutputCompareMode::InactiveOnMatch => stm32_metapac::timer::vals::Ocm::INACTIVEONMATCH, - OutputCompareMode::Toggle => stm32_metapac::timer::vals::Ocm::TOGGLE, - OutputCompareMode::ForceInactive => stm32_metapac::timer::vals::Ocm::FORCEINACTIVE, - OutputCompareMode::ForceActive => stm32_metapac::timer::vals::Ocm::FORCEACTIVE, - OutputCompareMode::PwmMode1 => stm32_metapac::timer::vals::Ocm::PWMMODE1, - OutputCompareMode::PwmMode2 => stm32_metapac::timer::vals::Ocm::PWMMODE2, - } - } -} - -/// Timer output pin polarity. -#[derive(Clone, Copy)] -pub enum OutputPolarity { - /// Active high (higher duty value makes the pin spend more time high). - ActiveHigh, - /// Active low (higher duty value makes the pin spend more time low). - ActiveLow, -} - -impl From for bool { - fn from(mode: OutputPolarity) -> Self { - match mode { - OutputPolarity::ActiveHigh => false, - OutputPolarity::ActiveLow => true, - } - } -} - -/// Basic 16-bit timer instance. -pub trait BasicInstance: sealed::BasicInstance + sealed::BasicNoCr2Instance + sealed::CoreInstance + 'static {} - -// It's just a General-purpose 16-bit timer instance. -/// Capture Compare timer instance. -pub trait CaptureCompare16bitInstance: - BasicInstance - + sealed::GeneralPurpose2ChannelInstance - + sealed::GeneralPurpose1ChannelInstance - + sealed::GeneralPurpose16bitInstance - + 'static -{ - // SimplePwm<'d, T> is implemented for T: CaptureCompare16bitInstance +/// General-purpose 16-bit timer with 4 channels instance. +pub trait GeneralInstance4Channel: BasicInstance + GeneralInstance2Channel { + // SimplePwm<'d, T> is implemented for T: GeneralInstance4Channel // Advanced timers implement this trait, but the output needs to be // enabled explicitly. // To support general-purpose and advanced timers, this function is added @@ -694,296 +80,149 @@ pub trait CaptureCompare16bitInstance: fn enable_outputs(&self) {} } -#[cfg(not(stm32l0))] -// It's just a General-purpose 32-bit timer instance. -/// Capture Compare 32-bit timer instance. -pub trait CaptureCompare32bitInstance: - CaptureCompare16bitInstance + sealed::GeneralPurpose32bitInstance + 'static -{ +/// General-purpose 32-bit timer with 4 channels instance. +pub trait GeneralInstance32bit4Channel: GeneralInstance4Channel {} + +/// Advanced 16-bit timer with 1 channel instance. +pub trait AdvancedInstance1Channel: BasicNoCr2Instance + GeneralInstance1Channel { + /// Capture compare interrupt for this timer. + type CaptureCompareInterrupt: interrupt::typelevel::Interrupt; } +/// Advanced 16-bit timer with 2 channels instance. -#[cfg(not(stm32l0))] -// It's just a Advanced Control timer instance. -/// Complementary Capture Compare 32-bit timer instance. -pub trait ComplementaryCaptureCompare16bitInstance: - CaptureCompare16bitInstance - + sealed::GeneralPurpose1ChannelComplementaryInstance - + sealed::GeneralPurpose2ChannelComplementaryInstance - + sealed::AdvancedControlInstance - + 'static -{ -} +pub trait AdvancedInstance2Channel: BasicInstance + GeneralInstance2Channel + AdvancedInstance1Channel {} -pin_trait!(Channel1Pin, CaptureCompare16bitInstance); -pin_trait!(Channel2Pin, CaptureCompare16bitInstance); -pin_trait!(Channel3Pin, CaptureCompare16bitInstance); -pin_trait!(Channel4Pin, CaptureCompare16bitInstance); -pin_trait!(ExternalTriggerPin, CaptureCompare16bitInstance); +/// Advanced 16-bit timer with 4 channels instance. +pub trait AdvancedInstance4Channel: AdvancedInstance2Channel + GeneralInstance4Channel {} -cfg_if::cfg_if! { - if #[cfg(not(stm32l0))] { - pin_trait!(Channel1ComplementaryPin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(Channel2ComplementaryPin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(Channel3ComplementaryPin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(Channel4ComplementaryPin, ComplementaryCaptureCompare16bitInstance); +pin_trait!(Channel1Pin, GeneralInstance4Channel); +pin_trait!(Channel2Pin, GeneralInstance4Channel); +pin_trait!(Channel3Pin, GeneralInstance4Channel); +pin_trait!(Channel4Pin, GeneralInstance4Channel); +pin_trait!(ExternalTriggerPin, GeneralInstance4Channel); - pin_trait!(BreakInputPin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(BreakInput2Pin, ComplementaryCaptureCompare16bitInstance); +pin_trait!(Channel1ComplementaryPin, AdvancedInstance4Channel); +pin_trait!(Channel2ComplementaryPin, AdvancedInstance4Channel); +pin_trait!(Channel3ComplementaryPin, AdvancedInstance4Channel); +pin_trait!(Channel4ComplementaryPin, AdvancedInstance4Channel); - pin_trait!(BreakInputComparator1Pin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(BreakInputComparator2Pin, ComplementaryCaptureCompare16bitInstance); +pin_trait!(BreakInputPin, AdvancedInstance4Channel); +pin_trait!(BreakInput2Pin, AdvancedInstance4Channel); - pin_trait!(BreakInput2Comparator1Pin, ComplementaryCaptureCompare16bitInstance); - pin_trait!(BreakInput2Comparator2Pin, ComplementaryCaptureCompare16bitInstance); - } -} +pin_trait!(BreakInputComparator1Pin, AdvancedInstance4Channel); +pin_trait!(BreakInputComparator2Pin, AdvancedInstance4Channel); + +pin_trait!(BreakInput2Comparator1Pin, AdvancedInstance4Channel); +pin_trait!(BreakInput2Comparator2Pin, AdvancedInstance4Channel); + +// Update Event trigger DMA for every timer +dma_trait!(UpDma, BasicInstance); + +dma_trait!(Ch1Dma, GeneralInstance4Channel); +dma_trait!(Ch2Dma, GeneralInstance4Channel); +dma_trait!(Ch3Dma, GeneralInstance4Channel); +dma_trait!(Ch4Dma, GeneralInstance4Channel); #[allow(unused)] macro_rules! impl_core_timer { - ($inst:ident, $irq:ident) => { - impl sealed::CoreInstance for crate::peripherals::$inst { - type Interrupt = crate::interrupt::typelevel::$irq; + ($inst:ident, $bits:expr) => { + impl CoreInstance for crate::peripherals::$inst { + type Interrupt = crate::_generated::peripheral_interrupts::$inst::UP; - fn regs_core() -> crate::pac::timer::TimCore { - unsafe { crate::pac::timer::TimCore::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} + const BITS: TimerBits = $bits; -#[allow(unused)] -macro_rules! impl_basic_no_cr2_timer { - ($inst:ident) => { - impl sealed::BasicNoCr2Instance for crate::peripherals::$inst { - fn regs_basic_no_cr2() -> crate::pac::timer::TimBasicNoCr2 { - unsafe { crate::pac::timer::TimBasicNoCr2::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_basic_timer { - ($inst:ident) => { - impl sealed::BasicInstance for crate::peripherals::$inst { - fn regs_basic() -> crate::pac::timer::TimBasic { - unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_1ch_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose1ChannelInstance for crate::peripherals::$inst { - fn regs_1ch() -> crate::pac::timer::Tim1ch { - unsafe { crate::pac::timer::Tim1ch::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_2ch_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose2ChannelInstance for crate::peripherals::$inst { - fn regs_2ch() -> crate::pac::timer::Tim2ch { - unsafe { crate::pac::timer::Tim2ch::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_gp16_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { - fn regs_gp16() -> crate::pac::timer::TimGp16 { - unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_gp32_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose32bitInstance for crate::peripherals::$inst { - fn regs_gp32() -> crate::pac::timer::TimGp32 { - crate::pac::$inst - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_1ch_cmp_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose1ChannelComplementaryInstance for crate::peripherals::$inst { - fn regs_1ch_cmp() -> crate::pac::timer::Tim1chCmp { - unsafe { crate::pac::timer::Tim1chCmp::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_2ch_cmp_timer { - ($inst:ident) => { - impl sealed::GeneralPurpose2ChannelComplementaryInstance for crate::peripherals::$inst { - fn regs_2ch_cmp() -> crate::pac::timer::Tim2chCmp { - unsafe { crate::pac::timer::Tim2chCmp::from_ptr(crate::pac::$inst.as_ptr()) } - } - } - }; -} - -#[allow(unused)] -macro_rules! impl_adv_timer { - ($inst:ident, $irq:ident) => { - impl sealed::AdvancedControlInstance for crate::peripherals::$inst { - type CaptureCompareInterrupt = crate::interrupt::typelevel::$irq; - - fn regs_advanced() -> crate::pac::timer::TimAdv { - unsafe { crate::pac::timer::TimAdv::from_ptr(crate::pac::$inst.as_ptr()) } + fn regs() -> *mut () { + crate::pac::$inst.as_ptr() } } }; } foreach_interrupt! { - ($inst:ident, timer, TIM_BASIC, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} }; ($inst:ident, timer, TIM_1CH, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst {} }; - ($inst:ident, timer, TIM_2CH, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst {} }; ($inst:ident, timer, TIM_GP16, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst {} }; ($inst:ident, timer, TIM_GP32, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); - impl_gp32_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits32); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst {} - impl CaptureCompare32bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst {} + impl GeneralInstance32bit4Channel for crate::peripherals::$inst {} }; ($inst:ident, timer, TIM_1CH_CMP, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); - impl_1ch_cmp_timer!($inst); - impl_2ch_cmp_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst { - /// Enable timer outputs. - fn enable_outputs(&self) { - use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; - self.set_moe(true); - } - } - impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::() }} + impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } + impl AdvancedInstance2Channel for crate::peripherals::$inst {} + impl AdvancedInstance4Channel for crate::peripherals::$inst {} }; - ($inst:ident, timer, TIM_1CH_CMP, CC, $irq:ident) => { - impl_adv_timer!($inst, $irq); - }; - ($inst:ident, timer, TIM_2CH_CMP, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); - impl_1ch_cmp_timer!($inst); - impl_2ch_cmp_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst { - /// Enable timer outputs. - fn enable_outputs(&self) { - use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; - self.set_moe(true); - } - } - impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::() }} + impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } + impl AdvancedInstance2Channel for crate::peripherals::$inst {} + impl AdvancedInstance4Channel for crate::peripherals::$inst {} }; - ($inst:ident, timer, TIM_2CH_CMP, CC, $irq:ident) => { - impl_adv_timer!($inst, $irq); - }; - ($inst:ident, timer, TIM_ADV, UP, $irq:ident) => { - impl_core_timer!($inst, $irq); - impl_basic_no_cr2_timer!($inst); - impl_basic_timer!($inst); - impl_1ch_timer!($inst); - impl_2ch_timer!($inst); - impl_gp16_timer!($inst); - impl_1ch_cmp_timer!($inst); - impl_2ch_cmp_timer!($inst); + impl_core_timer!($inst, TimerBits::Bits16); + impl BasicNoCr2Instance for crate::peripherals::$inst {} impl BasicInstance for crate::peripherals::$inst {} - impl CaptureCompare16bitInstance for crate::peripherals::$inst { - /// Enable timer outputs. - fn enable_outputs(&self) { - use crate::timer::sealed::GeneralPurpose1ChannelComplementaryInstance; - self.set_moe(true); - } - } - impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} - }; - ($inst:ident, timer, TIM_ADV, CC, $irq:ident) => { - impl_adv_timer!($inst, $irq); + impl GeneralInstance1Channel for crate::peripherals::$inst {} + impl GeneralInstance2Channel for crate::peripherals::$inst {} + impl GeneralInstance4Channel for crate::peripherals::$inst { fn enable_outputs(&self) { set_moe::() }} + impl AdvancedInstance1Channel for crate::peripherals::$inst { type CaptureCompareInterrupt = crate::_generated::peripheral_interrupts::$inst::CC; } + impl AdvancedInstance2Channel for crate::peripherals::$inst {} + impl AdvancedInstance4Channel for crate::peripherals::$inst {} }; } -// Update Event trigger DMA for every timer -dma_trait!(UpDma, BasicInstance); - -dma_trait!(Ch1Dma, CaptureCompare16bitInstance); -dma_trait!(Ch2Dma, CaptureCompare16bitInstance); -dma_trait!(Ch3Dma, CaptureCompare16bitInstance); -dma_trait!(Ch4Dma, CaptureCompare16bitInstance); +#[cfg(not(stm32l0))] +#[allow(unused)] +fn set_moe() { + unsafe { crate::pac::timer::Tim1chCmp::from_ptr(T::regs()) } + .bdtr() + .modify(|w| w.set_moe(true)); +} diff --git a/embassy-stm32/src/timer/qei.rs b/embassy-stm32/src/timer/qei.rs index 59efb72ba..ab9879be6 100644 --- a/embassy-stm32/src/timer/qei.rs +++ b/embassy-stm32/src/timer/qei.rs @@ -3,10 +3,11 @@ use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; +use stm32_metapac::timer::vals; -use super::*; -use crate::gpio::sealed::AFType; -use crate::gpio::AnyPin; +use super::low_level::Timer; +use super::{Channel1Pin, Channel2Pin, GeneralInstance4Channel}; +use crate::gpio::{AFType, AnyPin}; use crate::Peripheral; /// Counting direction @@ -30,7 +31,7 @@ pub struct QeiPin<'d, T, Channel> { macro_rules! channel_impl { ($new_chx:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: CaptureCompare16bitInstance> QeiPin<'d, T, $channel> { + impl<'d, T: GeneralInstance4Channel> QeiPin<'d, T, $channel> { #[doc = concat!("Create a new ", stringify!($channel), " QEI pin instance.")] pub fn $new_chx(pin: impl Peripheral

> + 'd) -> Self { into_ref!(pin); @@ -53,29 +54,28 @@ channel_impl!(new_ch1, Ch1, Channel1Pin); channel_impl!(new_ch2, Ch2, Channel2Pin); /// Quadrature decoder driver. -pub struct Qei<'d, T> { - _inner: PeripheralRef<'d, T>, +pub struct Qei<'d, T: GeneralInstance4Channel> { + inner: Timer<'d, T>, } -impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { +impl<'d, T: GeneralInstance4Channel> Qei<'d, T> { /// Create a new quadrature decoder driver. pub fn new(tim: impl Peripheral

+ 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self { Self::new_inner(tim) } fn new_inner(tim: impl Peripheral

+ 'd) -> Self { - into_ref!(tim); - - T::enable_and_reset(); + let inner = Timer::new(tim); + let r = inner.regs_gp16(); // Configure TxC1 and TxC2 as captures - T::regs_gp16().ccmr_input(0).modify(|w| { + r.ccmr_input(0).modify(|w| { w.set_ccs(0, vals::CcmrInputCcs::TI4); w.set_ccs(1, vals::CcmrInputCcs::TI4); }); // enable and configure to capture on rising edge - T::regs_gp16().ccer().modify(|w| { + r.ccer().modify(|w| { w.set_cce(0, true); w.set_cce(1, true); @@ -83,19 +83,19 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { w.set_ccp(1, false); }); - T::regs_gp16().smcr().modify(|w| { + r.smcr().modify(|w| { w.set_sms(vals::Sms::ENCODER_MODE_3); }); - T::regs_gp16().arr().modify(|w| w.set_arr(u16::MAX)); - T::regs_gp16().cr1().modify(|w| w.set_cen(true)); + r.arr().modify(|w| w.set_arr(u16::MAX)); + r.cr1().modify(|w| w.set_cen(true)); - Self { _inner: tim } + Self { inner } } /// Get direction. pub fn read_direction(&self) -> Direction { - match T::regs_gp16().cr1().read().dir() { + match self.inner.regs_gp16().cr1().read().dir() { vals::Dir::DOWN => Direction::Downcounting, vals::Dir::UP => Direction::Upcounting, } @@ -103,6 +103,6 @@ impl<'d, T: CaptureCompare16bitInstance> Qei<'d, T> { /// Get count. pub fn count(&self) -> u16 { - T::regs_gp16().cnt().read().cnt() + self.inner.regs_gp16().cnt().read().cnt() } } diff --git a/embassy-stm32/src/timer/simple_pwm.rs b/embassy-stm32/src/timer/simple_pwm.rs index 6df2f66ec..b54e9a0d6 100644 --- a/embassy-stm32/src/timer/simple_pwm.rs +++ b/embassy-stm32/src/timer/simple_pwm.rs @@ -4,9 +4,8 @@ use core::marker::PhantomData; use embassy_hal_internal::{into_ref, PeripheralRef}; -use super::*; -#[allow(unused_imports)] -use crate::gpio::sealed::{AFType, Pin}; +use super::low_level::{CountingMode, OutputCompareMode, OutputPolarity, Timer}; +use super::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance4Channel}; use crate::gpio::{AnyPin, OutputType}; use crate::time::Hertz; use crate::Peripheral; @@ -30,7 +29,7 @@ pub struct PwmPin<'d, T, C> { macro_rules! channel_impl { ($new_chx:ident, $channel:ident, $pin_trait:ident) => { - impl<'d, T: CaptureCompare16bitInstance> PwmPin<'d, T, $channel> { + impl<'d, T: GeneralInstance4Channel> PwmPin<'d, T, $channel> { #[doc = concat!("Create a new ", stringify!($channel), " PWM pin instance.")] pub fn $new_chx(pin: impl Peripheral

> + 'd, output_type: OutputType) -> Self { into_ref!(pin); @@ -55,11 +54,11 @@ channel_impl!(new_ch3, Ch3, Channel3Pin); channel_impl!(new_ch4, Ch4, Channel4Pin); /// Simple PWM driver. -pub struct SimplePwm<'d, T> { - inner: PeripheralRef<'d, T>, +pub struct SimplePwm<'d, T: GeneralInstance4Channel> { + inner: Timer<'d, T>, } -impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { +impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Create a new simple PWM driver. pub fn new( tim: impl Peripheral

+ 'd, @@ -74,15 +73,11 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { } fn new_inner(tim: impl Peripheral

+ 'd, freq: Hertz, counting_mode: CountingMode) -> Self { - into_ref!(tim); - - T::enable_and_reset(); - - let mut this = Self { inner: tim }; + let mut this = Self { inner: Timer::new(tim) }; this.inner.set_counting_mode(counting_mode); this.set_frequency(freq); - this.inner.enable_outputs(); // Required for advanced timers, see CaptureCompare16bitInstance for details + this.inner.enable_outputs(); // Required for advanced timers, see GeneralInstance4Channel for details this.inner.start(); [Channel::Ch1, Channel::Ch2, Channel::Ch3, Channel::Ch4] @@ -127,14 +122,14 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { /// Get max duty value. /// /// This value depends on the configured frequency and the timer's clock rate from RCC. - pub fn get_max_duty(&self) -> u16 { + pub fn get_max_duty(&self) -> u32 { self.inner.get_max_compare_value() + 1 } /// Set the duty for a given channel. /// /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. - pub fn set_duty(&mut self, channel: Channel, duty: u16) { + pub fn set_duty(&mut self, channel: Channel, duty: u32) { assert!(duty <= self.get_max_duty()); self.inner.set_compare_value(channel, duty) } @@ -142,7 +137,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { /// Get the duty for a given channel. /// /// The value ranges from 0 for 0% duty, to [`get_max_duty`](Self::get_max_duty) for 100% duty, both included. - pub fn get_duty(&self, channel: Channel) -> u16 { + pub fn get_duty(&self, channel: Channel) -> u32 { self.inner.get_compare_value(channel) } @@ -166,8 +161,6 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { channel: Channel, duty: &[u16], ) { - assert!(duty.iter().all(|v| *v <= self.get_max_duty())); - into_ref!(dma); #[allow(clippy::let_unit_value)] // eg. stm32f334 @@ -202,7 +195,7 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { &mut dma, req, duty, - T::regs_1ch().ccr(channel.index()).as_ptr() as *mut _, + self.inner.regs_1ch().ccr(channel.index()).as_ptr() as *mut _, dma_transfer_option, ) .await @@ -228,22 +221,20 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { macro_rules! impl_waveform_chx { ($fn_name:ident, $dma_ch:ident, $cc_ch:ident) => { - impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> { + impl<'d, T: GeneralInstance4Channel> SimplePwm<'d, T> { /// Generate a sequence of PWM waveform /// /// Note: /// you will need to provide corresponding TIMx_CHy DMA channel to use this method. pub async fn $fn_name(&mut self, dma: impl Peripheral

>, duty: &[u16]) { - use super::vals::Ccds; - - assert!(duty.iter().all(|v| *v <= self.get_max_duty())); + use crate::pac::timer::vals::Ccds; into_ref!(dma); #[allow(clippy::let_unit_value)] // eg. stm32f334 let req = dma.request(); - let cc_channel = super::Channel::$cc_ch; + let cc_channel = Channel::$cc_ch; let original_duty_state = self.get_duty(cc_channel); let original_enable_state = self.is_enabled(cc_channel); @@ -280,7 +271,7 @@ macro_rules! impl_waveform_chx { &mut dma, req, duty, - T::regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, + self.inner.regs_gp16().ccr(cc_channel.index()).as_ptr() as *mut _, dma_transfer_option, ) .await @@ -315,10 +306,10 @@ impl_waveform_chx!(waveform_ch2, Ch2Dma, Ch2); impl_waveform_chx!(waveform_ch3, Ch3Dma, Ch3); impl_waveform_chx!(waveform_ch4, Ch4Dma, Ch4); -impl<'d, T: CaptureCompare16bitInstance> embedded_hal_02::Pwm for SimplePwm<'d, T> { +impl<'d, T: GeneralInstance4Channel> embedded_hal_02::Pwm for SimplePwm<'d, T> { type Channel = Channel; type Time = Hertz; - type Duty = u16; + type Duty = u32; fn disable(&mut self, channel: Self::Channel) { self.inner.enable_channel(channel, false); diff --git a/embassy-stm32/src/ucpd.rs b/embassy-stm32/src/ucpd.rs index 9c37d2c04..fe614b811 100644 --- a/embassy-stm32/src/ucpd.rs +++ b/embassy-stm32/src/ucpd.rs @@ -16,11 +16,12 @@ use core::future::poll_fn; use core::marker::PhantomData; -use core::sync::atomic::Ordering; +use core::sync::atomic::{AtomicBool, Ordering}; use core::task::Poll; use embassy_hal_internal::drop::OnDrop; use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; +use embassy_sync::waitqueue::AtomicWaker; use crate::dma::{AnyChannel, Request, Transfer, TransferOptions}; use crate::interrupt; @@ -555,50 +556,47 @@ impl interrupt::typelevel::Handler for InterruptHandl } } -/// UCPD instance trait. -pub trait Instance: sealed::Instance + RccPeripheral {} +struct State { + waker: AtomicWaker, + // Inverted logic for a default state of 0 so that the data goes into the .bss section. + drop_not_ready: AtomicBool, +} -mod sealed { - use core::sync::atomic::AtomicBool; - - use embassy_sync::waitqueue::AtomicWaker; - - pub struct State { - pub waker: AtomicWaker, - // Inverted logic for a default state of 0 so that the data goes into the .bss section. - pub drop_not_ready: AtomicBool, - } - - impl State { - pub const fn new() -> Self { - Self { - waker: AtomicWaker::new(), - drop_not_ready: AtomicBool::new(false), - } +impl State { + pub const fn new() -> Self { + Self { + waker: AtomicWaker::new(), + drop_not_ready: AtomicBool::new(false), } } +} - pub trait Instance { - type Interrupt: crate::interrupt::typelevel::Interrupt; - const REGS: crate::pac::ucpd::Ucpd; - fn state() -> &'static crate::ucpd::sealed::State; - } +trait SealedInstance { + const REGS: crate::pac::ucpd::Ucpd; + fn state() -> &'static State; +} + +/// UCPD instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral { + /// Interrupt for this instance. + type Interrupt: crate::interrupt::typelevel::Interrupt; } foreach_interrupt!( ($inst:ident, ucpd, UCPD, GLOBAL, $irq:ident) => { - impl sealed::Instance for crate::peripherals::$inst { - type Interrupt = crate::interrupt::typelevel::$irq; - + impl SealedInstance for crate::peripherals::$inst { const REGS: crate::pac::ucpd::Ucpd = crate::pac::$inst; - fn state() -> &'static crate::ucpd::sealed::State { - static STATE: crate::ucpd::sealed::State = crate::ucpd::sealed::State::new(); + fn state() -> &'static State { + static STATE: State = State::new(); &STATE } } - impl Instance for crate::peripherals::$inst {} + impl Instance for crate::peripherals::$inst { + type Interrupt = crate::interrupt::typelevel::$irq; + } }; ); diff --git a/embassy-stm32/src/uid.rs b/embassy-stm32/src/uid.rs index aa13586f8..5e38532bd 100644 --- a/embassy-stm32/src/uid.rs +++ b/embassy-stm32/src/uid.rs @@ -27,5 +27,5 @@ pub fn uid_hex_bytes() -> &'static [u8; 24] { LOADED = true; } }); - unsafe { &UID_HEX } + unsafe { &*core::ptr::addr_of!(UID_HEX) } } diff --git a/embassy-stm32/src/usart/buffered.rs b/embassy-stm32/src/usart/buffered.rs index c11e3382f..51862e185 100644 --- a/embassy-stm32/src/usart/buffered.rs +++ b/embassy-stm32/src/usart/buffered.rs @@ -1,13 +1,10 @@ -use core::future::poll_fn; use core::slice; -use core::sync::atomic::{AtomicBool, Ordering}; -use core::task::Poll; +use core::sync::atomic::AtomicBool; use embassy_hal_internal::atomic_ring_buffer::RingBuffer; use embassy_sync::waitqueue::AtomicWaker; use super::*; -use crate::interrupt::typelevel::Interrupt; /// Interrupt handler. pub struct InterruptHandler { @@ -55,7 +52,7 @@ impl interrupt::typelevel::Handler for Interrupt // FIXME: Should we disable any further RX interrupts when the buffer becomes full. } - if state.rx_buf.is_full() { + if !state.rx_buf.is_empty() { state.rx_waker.wake(); } } diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index ea727b010..7ab33043a 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs @@ -10,10 +10,11 @@ use core::task::Poll; use embassy_embedded_hal::SetConfig; use embassy_hal_internal::drop::OnDrop; use embassy_hal_internal::{into_ref, PeripheralRef}; +use embassy_sync::waitqueue::AtomicWaker; use futures::future::{select, Either}; use crate::dma::{NoDma, Transfer}; -use crate::gpio::sealed::AFType; +use crate::gpio::AFType; use crate::interrupt::typelevel::Interrupt; #[allow(unused_imports)] #[cfg(not(any(usart_v1, usart_v2)))] @@ -1326,8 +1327,6 @@ mod ringbuffered; #[cfg(not(gpdma))] pub use ringbuffered::RingBufferedUartRx; -use self::sealed::Kind; - #[cfg(any(usart_v1, usart_v2))] fn tdr(r: crate::pac::usart::Usart) -> *mut u8 { r.dr().as_ptr() as _ @@ -1370,52 +1369,50 @@ fn clear_interrupt_flags(r: Regs, sr: regs::Isr) { r.icr().write(|w| *w = regs::Icr(sr.0)); } -pub(crate) mod sealed { - use embassy_sync::waitqueue::AtomicWaker; +#[derive(Clone, Copy, PartialEq, Eq)] +enum Kind { + Uart, + #[cfg(any(usart_v3, usart_v4))] + #[allow(unused)] + Lpuart, +} - use super::*; +struct State { + rx_waker: AtomicWaker, +} - #[derive(Clone, Copy, PartialEq, Eq)] - pub enum Kind { - Uart, - #[cfg(any(usart_v3, usart_v4))] - Lpuart, - } - - pub struct State { - pub rx_waker: AtomicWaker, - pub tx_waker: AtomicWaker, - } - - impl State { - pub const fn new() -> Self { - Self { - rx_waker: AtomicWaker::new(), - tx_waker: AtomicWaker::new(), - } +impl State { + const fn new() -> Self { + Self { + rx_waker: AtomicWaker::new(), } } - - pub trait BasicInstance: crate::rcc::RccPeripheral { - const KIND: Kind; - type Interrupt: interrupt::typelevel::Interrupt; - - fn regs() -> Regs; - fn state() -> &'static State; - - fn buffered_state() -> &'static buffered::State; - } - - pub trait FullInstance: BasicInstance { - fn regs_uart() -> crate::pac::usart::Usart; - } +} + +trait SealedBasicInstance: crate::rcc::RccPeripheral { + const KIND: Kind; + + fn regs() -> Regs; + fn state() -> &'static State; + + fn buffered_state() -> &'static buffered::State; +} + +trait SealedFullInstance: SealedBasicInstance { + #[allow(unused)] + fn regs_uart() -> crate::pac::usart::Usart; } /// Basic UART driver instance -pub trait BasicInstance: Peripheral

+ sealed::BasicInstance + 'static + Send {} +#[allow(private_bounds)] +pub trait BasicInstance: Peripheral

+ SealedBasicInstance + 'static + Send { + /// Interrupt for this instance. + type Interrupt: interrupt::typelevel::Interrupt; +} /// Full UART driver instance -pub trait FullInstance: sealed::FullInstance {} +#[allow(private_bounds)] +pub trait FullInstance: SealedFullInstance {} pin_trait!(RxPin, BasicInstance); pin_trait!(TxPin, BasicInstance); @@ -1429,16 +1426,15 @@ dma_trait!(RxDma, BasicInstance); macro_rules! impl_usart { ($inst:ident, $irq:ident, $kind:expr) => { - impl sealed::BasicInstance for crate::peripherals::$inst { + impl SealedBasicInstance for crate::peripherals::$inst { const KIND: Kind = $kind; - type Interrupt = crate::interrupt::typelevel::$irq; fn regs() -> Regs { unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) } } - fn state() -> &'static crate::usart::sealed::State { - static STATE: crate::usart::sealed::State = crate::usart::sealed::State::new(); + fn state() -> &'static crate::usart::State { + static STATE: crate::usart::State = crate::usart::State::new(); &STATE } @@ -1448,7 +1444,9 @@ macro_rules! impl_usart { } } - impl BasicInstance for peripherals::$inst {} + impl BasicInstance for peripherals::$inst { + type Interrupt = crate::interrupt::typelevel::$irq; + } }; } @@ -1460,7 +1458,7 @@ foreach_interrupt!( ($inst:ident, usart, $block:ident, $signal_name:ident, $irq:ident) => { impl_usart!($inst, $irq, Kind::Uart); - impl sealed::FullInstance for peripherals::$inst { + impl SealedFullInstance for peripherals::$inst { fn regs_uart() -> crate::pac::usart::Usart { crate::pac::$inst } diff --git a/embassy-stm32/src/usb/mod.rs b/embassy-stm32/src/usb/mod.rs index 4debd4e54..1e3c44167 100644 --- a/embassy-stm32/src/usb/mod.rs +++ b/embassy-stm32/src/usb/mod.rs @@ -1,37 +1,69 @@ //! Universal Serial Bus (USB) -use crate::interrupt; -use crate::rcc::RccPeripheral; +#[cfg_attr(usb, path = "usb.rs")] +#[cfg_attr(otg, path = "otg.rs")] +mod _version; +pub use _version::*; -mod usb; -pub use usb::*; +use crate::interrupt::typelevel::Interrupt; +use crate::rcc::SealedRccPeripheral; -pub(crate) mod sealed { - pub trait Instance { - fn regs() -> crate::pac::usb::Usb; +/// clock, power initialization stuff that's common for USB and OTG. +fn common_init() { + // Check the USB clock is enabled and running at exactly 48 MHz. + // frequency() will panic if not enabled + let freq = T::frequency(); + // Check frequency is within the 0.25% tolerance allowed by the spec. + // Clock might not be exact 48Mhz due to rounding errors in PLL calculation, or if the user + // has tight clock restrictions due to something else (like audio). + if freq.0.abs_diff(48_000_000) > 120_000 { + panic!( + "USB clock should be 48Mhz but is {} Hz. Please double-check your RCC settings.", + freq.0 + ) } + + #[cfg(any(stm32l4, stm32l5, stm32wb))] + critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true))); + + #[cfg(pwr_h5)] + critical_section::with(|_| crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true))); + + #[cfg(stm32h7)] + { + // If true, VDD33USB is generated by internal regulator from VDD50USB + // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo) + // TODO: unhardcode + let internal_regulator = false; + + // Enable USB power + critical_section::with(|_| { + crate::pac::PWR.cr3().modify(|w| { + w.set_usb33den(true); + w.set_usbregen(internal_regulator); + }) + }); + + // Wait for USB power to stabilize + while !crate::pac::PWR.cr3().read().usb33rdy() {} + } + + #[cfg(stm32u5)] + { + // Enable USB power + critical_section::with(|_| { + crate::pac::PWR.svmcr().modify(|w| { + w.set_usv(true); + w.set_uvmen(true); + }) + }); + + // Wait for USB power to stabilize + while !crate::pac::PWR.svmsr().read().vddusbrdy() {} + } + + T::Interrupt::unpend(); + unsafe { T::Interrupt::enable() }; + + ::enable_and_reset(); } - -/// USB instance trait. -pub trait Instance: sealed::Instance + RccPeripheral + 'static { - /// Interrupt for this USB instance. - type Interrupt: interrupt::typelevel::Interrupt; -} - -// Internal PHY pins -pin_trait!(DpPin, Instance); -pin_trait!(DmPin, Instance); - -foreach_interrupt!( - ($inst:ident, usb, $block:ident, LP, $irq:ident) => { - impl sealed::Instance for crate::peripherals::$inst { - fn regs() -> crate::pac::usb::Usb { - crate::pac::$inst - } - } - - impl Instance for crate::peripherals::$inst { - type Interrupt = crate::interrupt::typelevel::$irq; - } - }; -); diff --git a/embassy-stm32/src/usb_otg/usb.rs b/embassy-stm32/src/usb/otg.rs similarity index 89% rename from embassy-stm32/src/usb_otg/usb.rs rename to embassy-stm32/src/usb/otg.rs index 373697ec8..b0e7067bd 100644 --- a/embassy-stm32/src/usb_otg/usb.rs +++ b/embassy-stm32/src/usb/otg.rs @@ -6,17 +6,16 @@ use core::task::Poll; use embassy_hal_internal::{into_ref, Peripheral}; use embassy_sync::waitqueue::AtomicWaker; use embassy_usb_driver::{ - self, Bus as _, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, - EndpointOut, EndpointType, Event, Unsupported, + Bus as _, Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointIn, EndpointInfo, EndpointOut, + EndpointType, Event, Unsupported, }; use futures::future::poll_fn; -use super::*; -use crate::gpio::sealed::AFType; +use crate::gpio::AFType; use crate::interrupt; use crate::interrupt::typelevel::Interrupt; use crate::pac::otg::{regs, vals}; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::{RccPeripheral, SealedRccPeripheral}; use crate::time::Hertz; /// Interrupt handler. @@ -561,8 +560,7 @@ impl<'d, T: Instance> Bus<'d, T> { impl<'d, T: Instance> Bus<'d, T> { fn init(&mut self) { - #[cfg(stm32l4)] - critical_section::with(|_| crate::pac::PWR.cr2().modify(|w| w.set_usv(true))); + super::common_init::(); #[cfg(stm32f7)] { @@ -590,22 +588,6 @@ impl<'d, T: Instance> Bus<'d, T> { #[cfg(stm32h7)] { - // If true, VDD33USB is generated by internal regulator from VDD50USB - // If false, VDD33USB and VDD50USB must be suplied directly with 3.3V (default on nucleo) - // TODO: unhardcode - let internal_regulator = false; - - // Enable USB power - critical_section::with(|_| { - crate::pac::PWR.cr3().modify(|w| { - w.set_usb33den(true); - w.set_usbregen(internal_regulator); - }) - }); - - // Wait for USB power to stabilize - while !crate::pac::PWR.cr3().read().usb33rdy() {} - // Enable ULPI clock if external PHY is used let ulpien = !self.phy_type.internal(); critical_section::with(|_| { @@ -626,25 +608,6 @@ impl<'d, T: Instance> Bus<'d, T> { }); } - #[cfg(stm32u5)] - { - // Enable USB power - critical_section::with(|_| { - crate::pac::PWR.svmcr().modify(|w| { - w.set_usv(true); - w.set_uvmen(true); - }) - }); - - // Wait for USB power to stabilize - while !crate::pac::PWR.svmsr().read().vddusbrdy() {} - } - - ::enable_and_reset(); - - T::Interrupt::unpend(); - unsafe { T::Interrupt::enable() }; - let r = T::regs(); let core_id = r.cid().read().0; trace!("Core id {:08x}", core_id); @@ -846,7 +809,7 @@ impl<'d, T: Instance> Bus<'d, T> { fn disable(&mut self) { T::Interrupt::disable(); - ::disable(); + ::disable(); #[cfg(stm32l4)] crate::pac::PWR.cr2().modify(|w| w.set_usv(false)); @@ -1469,3 +1432,158 @@ fn calculate_trdt(speed: vals::Dspd, ahb_freq: Hertz) -> u8 { fn quirk_setup_late_cnak(r: crate::pac::otg::Otg) -> bool { r.cid().read().0 & 0xf000 == 0x1000 } + +// Using Instance::ENDPOINT_COUNT requires feature(const_generic_expr) so just define maximum eps +const MAX_EP_COUNT: usize = 9; + +trait SealedInstance { + const HIGH_SPEED: bool; + const FIFO_DEPTH_WORDS: u16; + const ENDPOINT_COUNT: usize; + + fn regs() -> crate::pac::otg::Otg; + fn state() -> &'static super::State<{ MAX_EP_COUNT }>; +} + +/// USB instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static { + /// Interrupt for this USB instance. + type Interrupt: interrupt::typelevel::Interrupt; +} + +// Internal PHY pins +pin_trait!(DpPin, Instance); +pin_trait!(DmPin, Instance); + +// External PHY pins +pin_trait!(UlpiClkPin, Instance); +pin_trait!(UlpiDirPin, Instance); +pin_trait!(UlpiNxtPin, Instance); +pin_trait!(UlpiStpPin, Instance); +pin_trait!(UlpiD0Pin, Instance); +pin_trait!(UlpiD1Pin, Instance); +pin_trait!(UlpiD2Pin, Instance); +pin_trait!(UlpiD3Pin, Instance); +pin_trait!(UlpiD4Pin, Instance); +pin_trait!(UlpiD5Pin, Instance); +pin_trait!(UlpiD6Pin, Instance); +pin_trait!(UlpiD7Pin, Instance); + +foreach_interrupt!( + (USB_OTG_FS, otg, $block:ident, GLOBAL, $irq:ident) => { + impl SealedInstance for crate::peripherals::USB_OTG_FS { + const HIGH_SPEED: bool = false; + + cfg_if::cfg_if! { + if #[cfg(stm32f1)] { + const FIFO_DEPTH_WORDS: u16 = 128; + const ENDPOINT_COUNT: usize = 8; + } else if #[cfg(any( + stm32f2, + stm32f401, + stm32f405, + stm32f407, + stm32f411, + stm32f415, + stm32f417, + stm32f427, + stm32f429, + stm32f437, + stm32f439, + ))] { + const FIFO_DEPTH_WORDS: u16 = 320; + const ENDPOINT_COUNT: usize = 4; + } else if #[cfg(any( + stm32f412, + stm32f413, + stm32f423, + stm32f446, + stm32f469, + stm32f479, + stm32f7, + stm32l4, + stm32u5, + ))] { + const FIFO_DEPTH_WORDS: u16 = 320; + const ENDPOINT_COUNT: usize = 6; + } else if #[cfg(stm32g0x1)] { + const FIFO_DEPTH_WORDS: u16 = 512; + const ENDPOINT_COUNT: usize = 8; + } else if #[cfg(stm32h7)] { + const FIFO_DEPTH_WORDS: u16 = 1024; + const ENDPOINT_COUNT: usize = 9; + } else if #[cfg(stm32u5)] { + const FIFO_DEPTH_WORDS: u16 = 320; + const ENDPOINT_COUNT: usize = 6; + } else { + compile_error!("USB_OTG_FS peripheral is not supported by this chip."); + } + } + + fn regs() -> crate::pac::otg::Otg { + crate::pac::USB_OTG_FS + } + + fn state() -> &'static State { + static STATE: State = State::new(); + &STATE + } + } + + impl Instance for crate::peripherals::USB_OTG_FS { + type Interrupt = crate::interrupt::typelevel::$irq; + } + }; + + (USB_OTG_HS, otg, $block:ident, GLOBAL, $irq:ident) => { + impl SealedInstance for crate::peripherals::USB_OTG_HS { + const HIGH_SPEED: bool = true; + + cfg_if::cfg_if! { + if #[cfg(any( + stm32f2, + stm32f405, + stm32f407, + stm32f415, + stm32f417, + stm32f427, + stm32f429, + stm32f437, + stm32f439, + ))] { + const FIFO_DEPTH_WORDS: u16 = 1024; + const ENDPOINT_COUNT: usize = 6; + } else if #[cfg(any( + stm32f446, + stm32f469, + stm32f479, + stm32f7, + stm32h7, + ))] { + const FIFO_DEPTH_WORDS: u16 = 1024; + const ENDPOINT_COUNT: usize = 9; + } else if #[cfg(stm32u5)] { + const FIFO_DEPTH_WORDS: u16 = 1024; + const ENDPOINT_COUNT: usize = 9; + } else { + compile_error!("USB_OTG_HS peripheral is not supported by this chip."); + } + } + + fn regs() -> crate::pac::otg::Otg { + // OTG HS registers are a superset of FS registers + unsafe { crate::pac::otg::Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) } + } + + fn state() -> &'static State { + static STATE: State = State::new(); + &STATE + } + } + + impl Instance for crate::peripherals::USB_OTG_HS { + type Interrupt = crate::interrupt::typelevel::$irq; + } + }; +); diff --git a/embassy-stm32/src/usb/usb.rs b/embassy-stm32/src/usb/usb.rs index be321a19b..f48808cb3 100644 --- a/embassy-stm32/src/usb/usb.rs +++ b/embassy-stm32/src/usb/usb.rs @@ -12,12 +12,10 @@ use embassy_usb_driver::{ Direction, EndpointAddress, EndpointAllocError, EndpointError, EndpointInfo, EndpointType, Event, Unsupported, }; -use super::{DmPin, DpPin, Instance}; -use crate::interrupt::typelevel::Interrupt; use crate::pac::usb::regs; use crate::pac::usb::vals::{EpType, Stat}; use crate::pac::USBRAM; -use crate::rcc::sealed::RccPeripheral; +use crate::rcc::RccPeripheral; use crate::{interrupt, Peripheral}; /// Interrupt handler. @@ -259,19 +257,11 @@ impl<'d, T: Instance> Driver<'d, T> { dm: impl Peripheral

> + 'd, ) -> Self { into_ref!(dp, dm); - T::Interrupt::unpend(); - unsafe { T::Interrupt::enable() }; + + super::common_init::(); let regs = T::regs(); - #[cfg(any(stm32l4, stm32l5, stm32wb))] - crate::pac::PWR.cr2().modify(|w| w.set_usv(true)); - - #[cfg(pwr_h5)] - crate::pac::PWR.usbscr().modify(|w| w.set_usb33sv(true)); - - ::enable_and_reset(); - regs.cntr().write(|w| { w.set_pdwn(false); w.set_fres(true); @@ -287,8 +277,8 @@ impl<'d, T: Instance> Driver<'d, T> { #[cfg(not(stm32l1))] { - dp.set_as_af(dp.af_num(), crate::gpio::sealed::AFType::OutputPushPull); - dm.set_as_af(dm.af_num(), crate::gpio::sealed::AFType::OutputPushPull); + dp.set_as_af(dp.af_num(), crate::gpio::AFType::OutputPushPull); + dm.set_as_af(dm.af_num(), crate::gpio::AFType::OutputPushPull); } #[cfg(stm32l1)] let _ = (dp, dm); // suppress "unused" warnings. @@ -647,7 +637,6 @@ impl<'d, T: Instance> driver::Bus for Bus<'d, T> { trait Dir { fn dir() -> Direction; - fn waker(i: usize) -> &'static AtomicWaker; } /// Marker type for the "IN" direction. @@ -656,11 +645,6 @@ impl Dir for In { fn dir() -> Direction { Direction::In } - - #[inline] - fn waker(i: usize) -> &'static AtomicWaker { - &EP_IN_WAKERS[i] - } } /// Marker type for the "OUT" direction. @@ -669,11 +653,6 @@ impl Dir for Out { fn dir() -> Direction { Direction::Out } - - #[inline] - fn waker(i: usize) -> &'static AtomicWaker { - &EP_OUT_WAKERS[i] - } } /// USB endpoint. @@ -1057,3 +1036,32 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { }); } } + +trait SealedInstance { + fn regs() -> crate::pac::usb::Usb; +} + +/// USB instance trait. +#[allow(private_bounds)] +pub trait Instance: SealedInstance + RccPeripheral + 'static { + /// Interrupt for this USB instance. + type Interrupt: interrupt::typelevel::Interrupt; +} + +// Internal PHY pins +pin_trait!(DpPin, Instance); +pin_trait!(DmPin, Instance); + +foreach_interrupt!( + ($inst:ident, usb, $block:ident, LP, $irq:ident) => { + impl SealedInstance for crate::peripherals::$inst { + fn regs() -> crate::pac::usb::Usb { + crate::pac::$inst + } + } + + impl Instance for crate::peripherals::$inst { + type Interrupt = crate::interrupt::typelevel::$irq; + } + }; +); diff --git a/embassy-stm32/src/usb_otg/mod.rs b/embassy-stm32/src/usb_otg/mod.rs deleted file mode 100644 index 0649e684b..000000000 --- a/embassy-stm32/src/usb_otg/mod.rs +++ /dev/null @@ -1,163 +0,0 @@ -//! USB On The Go (OTG) - -use crate::rcc::RccPeripheral; -use crate::{interrupt, peripherals}; - -mod usb; -pub use usb::*; - -// Using Instance::ENDPOINT_COUNT requires feature(const_generic_expr) so just define maximum eps -const MAX_EP_COUNT: usize = 9; - -pub(crate) mod sealed { - pub trait Instance { - const HIGH_SPEED: bool; - const FIFO_DEPTH_WORDS: u16; - const ENDPOINT_COUNT: usize; - - fn regs() -> crate::pac::otg::Otg; - fn state() -> &'static super::State<{ super::MAX_EP_COUNT }>; - } -} - -/// USB OTG instance. -pub trait Instance: sealed::Instance + RccPeripheral { - /// Interrupt for this USB OTG instance. - type Interrupt: interrupt::typelevel::Interrupt; -} - -// Internal PHY pins -pin_trait!(DpPin, Instance); -pin_trait!(DmPin, Instance); - -// External PHY pins -pin_trait!(UlpiClkPin, Instance); -pin_trait!(UlpiDirPin, Instance); -pin_trait!(UlpiNxtPin, Instance); -pin_trait!(UlpiStpPin, Instance); -pin_trait!(UlpiD0Pin, Instance); -pin_trait!(UlpiD1Pin, Instance); -pin_trait!(UlpiD2Pin, Instance); -pin_trait!(UlpiD3Pin, Instance); -pin_trait!(UlpiD4Pin, Instance); -pin_trait!(UlpiD5Pin, Instance); -pin_trait!(UlpiD6Pin, Instance); -pin_trait!(UlpiD7Pin, Instance); - -foreach_interrupt!( - (USB_OTG_FS, otg, $block:ident, GLOBAL, $irq:ident) => { - impl sealed::Instance for peripherals::USB_OTG_FS { - const HIGH_SPEED: bool = false; - - cfg_if::cfg_if! { - if #[cfg(stm32f1)] { - const FIFO_DEPTH_WORDS: u16 = 128; - const ENDPOINT_COUNT: usize = 8; - } else if #[cfg(any( - stm32f2, - stm32f401, - stm32f405, - stm32f407, - stm32f411, - stm32f415, - stm32f417, - stm32f427, - stm32f429, - stm32f437, - stm32f439, - ))] { - const FIFO_DEPTH_WORDS: u16 = 320; - const ENDPOINT_COUNT: usize = 4; - } else if #[cfg(any( - stm32f412, - stm32f413, - stm32f423, - stm32f446, - stm32f469, - stm32f479, - stm32f7, - stm32l4, - stm32u5, - ))] { - const FIFO_DEPTH_WORDS: u16 = 320; - const ENDPOINT_COUNT: usize = 6; - } else if #[cfg(stm32g0x1)] { - const FIFO_DEPTH_WORDS: u16 = 512; - const ENDPOINT_COUNT: usize = 8; - } else if #[cfg(stm32h7)] { - const FIFO_DEPTH_WORDS: u16 = 1024; - const ENDPOINT_COUNT: usize = 9; - } else if #[cfg(stm32u5)] { - const FIFO_DEPTH_WORDS: u16 = 320; - const ENDPOINT_COUNT: usize = 6; - } else { - compile_error!("USB_OTG_FS peripheral is not supported by this chip."); - } - } - - fn regs() -> crate::pac::otg::Otg { - crate::pac::USB_OTG_FS - } - - fn state() -> &'static State { - static STATE: State = State::new(); - &STATE - } - } - - impl Instance for peripherals::USB_OTG_FS { - type Interrupt = crate::interrupt::typelevel::$irq; - } - }; - - (USB_OTG_HS, otg, $block:ident, GLOBAL, $irq:ident) => { - impl sealed::Instance for peripherals::USB_OTG_HS { - const HIGH_SPEED: bool = true; - - cfg_if::cfg_if! { - if #[cfg(any( - stm32f2, - stm32f405, - stm32f407, - stm32f415, - stm32f417, - stm32f427, - stm32f429, - stm32f437, - stm32f439, - ))] { - const FIFO_DEPTH_WORDS: u16 = 1024; - const ENDPOINT_COUNT: usize = 6; - } else if #[cfg(any( - stm32f446, - stm32f469, - stm32f479, - stm32f7, - stm32h7, - ))] { - const FIFO_DEPTH_WORDS: u16 = 1024; - const ENDPOINT_COUNT: usize = 9; - } else if #[cfg(stm32u5)] { - const FIFO_DEPTH_WORDS: u16 = 1024; - const ENDPOINT_COUNT: usize = 9; - } else { - compile_error!("USB_OTG_HS peripheral is not supported by this chip."); - } - } - - fn regs() -> crate::pac::otg::Otg { - // OTG HS registers are a superset of FS registers - unsafe { crate::pac::otg::Otg::from_ptr(crate::pac::USB_OTG_HS.as_ptr()) } - } - - fn state() -> &'static State { - static STATE: State = State::new(); - &STATE - } - } - - impl Instance for peripherals::USB_OTG_HS { - type Interrupt = crate::interrupt::typelevel::$irq; - } - }; -); diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs index 2ff0db09e..ab21c4b6b 100644 --- a/embassy-stm32/src/wdg/mod.rs +++ b/embassy-stm32/src/wdg/mod.rs @@ -80,18 +80,17 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> { } } -mod sealed { - pub trait Instance { - fn regs() -> crate::pac::iwdg::Iwdg; - } +trait SealedInstance { + fn regs() -> crate::pac::iwdg::Iwdg; } /// IWDG instance trait. -pub trait Instance: sealed::Instance {} +#[allow(private_bounds)] +pub trait Instance: SealedInstance {} foreach_peripheral!( (iwdg, $inst:ident) => { - impl sealed::Instance for crate::peripherals::$inst { + impl SealedInstance for crate::peripherals::$inst { fn regs() -> crate::pac::iwdg::Iwdg { crate::pac::$inst } diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml index 85673026c..aaf6fab1d 100644 --- a/embassy-sync/Cargo.toml +++ b/embassy-sync/Cargo.toml @@ -20,7 +20,7 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-sync/ target = "thumbv7em-none-eabi" [features] -std = [] +std = ["critical-section/std"] turbowakers = [] [dependencies] diff --git a/embassy-sync/src/fmt.rs b/embassy-sync/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-sync/src/fmt.rs +++ b/embassy-sync/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-sync/src/lib.rs b/embassy-sync/src/lib.rs index d88c76db5..61b173e80 100644 --- a/embassy-sync/src/lib.rs +++ b/embassy-sync/src/lib.rs @@ -13,6 +13,7 @@ mod ring_buffer; pub mod blocking_mutex; pub mod channel; pub mod mutex; +pub mod once_lock; pub mod pipe; pub mod priority_channel; pub mod pubsub; diff --git a/embassy-sync/src/once_lock.rs b/embassy-sync/src/once_lock.rs new file mode 100644 index 000000000..31cc99711 --- /dev/null +++ b/embassy-sync/src/once_lock.rs @@ -0,0 +1,236 @@ +//! Syncronization primitive for initializing a value once, allowing others to await a reference to the value. + +use core::cell::Cell; +use core::future::poll_fn; +use core::mem::MaybeUninit; +use core::sync::atomic::{AtomicBool, Ordering}; +use core::task::Poll; + +/// The `OnceLock` is a synchronization primitive that allows for +/// initializing a value once, and allowing others to `.await` a +/// reference to the value. This is useful for lazy initialization of +/// a static value. +/// +/// **Note**: this implementation uses a busy loop to poll the value, +/// which is not as efficient as registering a dedicated `Waker`. +/// However, the if the usecase for is to initialize a static variable +/// relatively early in the program life cycle, it should be fine. +/// +/// # Example +/// ``` +/// use futures_executor::block_on; +/// use embassy_sync::once_lock::OnceLock; +/// +/// // Define a static value that will be lazily initialized +/// static VALUE: OnceLock = OnceLock::new(); +/// +/// let f = async { +/// +/// // Initialize the value +/// let reference = VALUE.get_or_init(|| 20); +/// assert_eq!(reference, &20); +/// +/// // Wait for the value to be initialized +/// // and get a static reference it +/// assert_eq!(VALUE.get().await, &20); +/// +/// }; +/// block_on(f) +/// ``` +pub struct OnceLock { + init: AtomicBool, + data: Cell>, +} + +unsafe impl Sync for OnceLock {} + +impl OnceLock { + /// Create a new uninitialized `OnceLock`. + pub const fn new() -> Self { + Self { + init: AtomicBool::new(false), + data: Cell::new(MaybeUninit::zeroed()), + } + } + + /// Get a reference to the underlying value, waiting for it to be set. + /// If the value is already set, this will return immediately. + pub async fn get(&self) -> &T { + poll_fn(|cx| match self.try_get() { + Some(data) => Poll::Ready(data), + None => { + cx.waker().wake_by_ref(); + Poll::Pending + } + }) + .await + } + + /// Try to get a reference to the underlying value if it exists. + pub fn try_get(&self) -> Option<&T> { + if self.init.load(Ordering::Relaxed) { + Some(unsafe { self.get_ref_unchecked() }) + } else { + None + } + } + + /// Set the underlying value. If the value is already set, this will return an error with the given value. + pub fn init(&self, value: T) -> Result<(), T> { + // Critical section is required to ensure that the value is + // not simultaniously initialized elsewhere at the same time. + critical_section::with(|_| { + // If the value is not set, set it and return Ok. + if !self.init.load(Ordering::Relaxed) { + self.data.set(MaybeUninit::new(value)); + self.init.store(true, Ordering::Relaxed); + Ok(()) + + // Otherwise return an error with the given value. + } else { + Err(value) + } + }) + } + + /// Get a reference to the underlying value, initializing it if it does not exist. + pub fn get_or_init(&self, f: F) -> &T + where + F: FnOnce() -> T, + { + // Critical section is required to ensure that the value is + // not simultaniously initialized elsewhere at the same time. + critical_section::with(|_| { + // If the value is not set, set it. + if !self.init.load(Ordering::Relaxed) { + self.data.set(MaybeUninit::new(f())); + self.init.store(true, Ordering::Relaxed); + } + }); + + // Return a reference to the value. + unsafe { self.get_ref_unchecked() } + } + + /// Consume the `OnceLock`, returning the underlying value if it was initialized. + pub fn into_inner(self) -> Option { + if self.init.load(Ordering::Relaxed) { + Some(unsafe { self.data.into_inner().assume_init() }) + } else { + None + } + } + + /// Take the underlying value if it was initialized, uninitializing the `OnceLock` in the process. + pub fn take(&mut self) -> Option { + // If the value is set, uninitialize the lock and return the value. + critical_section::with(|_| { + if self.init.load(Ordering::Relaxed) { + let val = unsafe { self.data.replace(MaybeUninit::zeroed()).assume_init() }; + self.init.store(false, Ordering::Relaxed); + Some(val) + + // Otherwise return None. + } else { + None + } + }) + } + + /// Check if the value has been set. + pub fn is_set(&self) -> bool { + self.init.load(Ordering::Relaxed) + } + + /// Get a reference to the underlying value. + /// # Safety + /// Must only be used if a value has been set. + unsafe fn get_ref_unchecked(&self) -> &T { + (*self.data.as_ptr()).assume_init_ref() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn once_lock() { + let lock = OnceLock::new(); + assert_eq!(lock.try_get(), None); + assert_eq!(lock.is_set(), false); + + let v = 42; + assert_eq!(lock.init(v), Ok(())); + assert_eq!(lock.is_set(), true); + assert_eq!(lock.try_get(), Some(&v)); + assert_eq!(lock.try_get(), Some(&v)); + + let v = 43; + assert_eq!(lock.init(v), Err(v)); + assert_eq!(lock.is_set(), true); + assert_eq!(lock.try_get(), Some(&42)); + } + + #[test] + fn once_lock_get_or_init() { + let lock = OnceLock::new(); + assert_eq!(lock.try_get(), None); + assert_eq!(lock.is_set(), false); + + let v = lock.get_or_init(|| 42); + assert_eq!(v, &42); + assert_eq!(lock.is_set(), true); + assert_eq!(lock.try_get(), Some(&42)); + + let v = lock.get_or_init(|| 43); + assert_eq!(v, &42); + assert_eq!(lock.is_set(), true); + assert_eq!(lock.try_get(), Some(&42)); + } + + #[test] + fn once_lock_static() { + static LOCK: OnceLock = OnceLock::new(); + + let v: &'static i32 = LOCK.get_or_init(|| 42); + assert_eq!(v, &42); + + let v: &'static i32 = LOCK.get_or_init(|| 43); + assert_eq!(v, &42); + } + + #[futures_test::test] + async fn once_lock_async() { + static LOCK: OnceLock = OnceLock::new(); + + assert!(LOCK.init(42).is_ok()); + + let v: &'static i32 = LOCK.get().await; + assert_eq!(v, &42); + } + + #[test] + fn once_lock_into_inner() { + let lock: OnceLock = OnceLock::new(); + + let v = lock.get_or_init(|| 42); + assert_eq!(v, &42); + + assert_eq!(lock.into_inner(), Some(42)); + } + + #[test] + fn once_lock_take_init() { + let mut lock: OnceLock = OnceLock::new(); + + assert_eq!(lock.get_or_init(|| 42), &42); + assert_eq!(lock.is_set(), true); + + assert_eq!(lock.take(), Some(42)); + assert_eq!(lock.is_set(), false); + + assert_eq!(lock.get_or_init(|| 43), &43); + assert_eq!(lock.is_set(), true); + } +} diff --git a/embassy-sync/src/signal.rs b/embassy-sync/src/signal.rs index d75750ce7..520f1a896 100644 --- a/embassy-sync/src/signal.rs +++ b/embassy-sync/src/signal.rs @@ -125,7 +125,7 @@ where }) } - /// non-blocking method to check whether this signal has been signaled. + /// non-blocking method to check whether this signal has been signaled. This does not clear the signal. pub fn signaled(&self) -> bool { self.state.lock(|cell| { let state = cell.replace(State::None); diff --git a/embassy-time/src/fmt.rs b/embassy-time/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-time/src/fmt.rs +++ b/embassy-time/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-usb-dfu/src/fmt.rs b/embassy-usb-dfu/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-usb-dfu/src/fmt.rs +++ b/embassy-usb-dfu/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-usb-logger/src/lib.rs b/embassy-usb-logger/src/lib.rs index da5ff0f36..34d1ca663 100644 --- a/embassy-usb-logger/src/lib.rs +++ b/embassy-usb-logger/src/lib.rs @@ -16,7 +16,6 @@ type CS = embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; /// The logger state containing buffers that must live as long as the USB peripheral. pub struct LoggerState<'d> { state: State<'d>, - device_descriptor: [u8; 32], config_descriptor: [u8; 128], bos_descriptor: [u8; 16], msos_descriptor: [u8; 256], @@ -28,7 +27,6 @@ impl<'d> LoggerState<'d> { pub fn new() -> Self { Self { state: State::new(), - device_descriptor: [0; 32], config_descriptor: [0; 128], bos_descriptor: [0; 16], msos_descriptor: [0; 256], @@ -74,7 +72,6 @@ impl UsbLogger { let mut builder = Builder::new( driver, config, - &mut state.device_descriptor, &mut state.config_descriptor, &mut state.bos_descriptor, &mut state.msos_descriptor, @@ -151,7 +148,17 @@ struct Writer<'d, const N: usize>(&'d Pipe); impl<'d, const N: usize> core::fmt::Write for Writer<'d, N> { fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { - let _ = self.0.try_write(s.as_bytes()); + // The Pipe is implemented in such way that we cannot + // write across the wraparound discontinuity. + let b = s.as_bytes(); + if let Ok(n) = self.0.try_write(b) { + if n < b.len() { + // We wrote some data but not all, attempt again + // as the reason might be a wraparound in the + // ring buffer, which resolves on second attempt. + let _ = self.0.try_write(&b[n..]); + } + } Ok(()) } } diff --git a/embassy-usb/src/builder.rs b/embassy-usb/src/builder.rs index c4705d041..c06107396 100644 --- a/embassy-usb/src/builder.rs +++ b/embassy-usb/src/builder.rs @@ -128,7 +128,6 @@ pub struct Builder<'d, D: Driver<'d>> { driver: D, next_string_index: u8, - device_descriptor: DescriptorWriter<'d>, config_descriptor: DescriptorWriter<'d>, bos_descriptor: BosWriter<'d>, @@ -144,7 +143,6 @@ impl<'d, D: Driver<'d>> Builder<'d, D> { pub fn new( driver: D, config: Config<'d>, - device_descriptor_buf: &'d mut [u8], config_descriptor_buf: &'d mut [u8], bos_descriptor_buf: &'d mut [u8], msos_descriptor_buf: &'d mut [u8], @@ -167,11 +165,9 @@ impl<'d, D: Driver<'d>> Builder<'d, D> { _ => panic!("invalid max_packet_size_0, the allowed values are 8, 16, 32 or 64"), } - let mut device_descriptor = DescriptorWriter::new(device_descriptor_buf); let mut config_descriptor = DescriptorWriter::new(config_descriptor_buf); let mut bos_descriptor = BosWriter::new(DescriptorWriter::new(bos_descriptor_buf)); - device_descriptor.device(&config); config_descriptor.configuration(&config); bos_descriptor.bos(); @@ -183,7 +179,6 @@ impl<'d, D: Driver<'d>> Builder<'d, D> { control_buf, next_string_index: STRING_INDEX_CUSTOM_START, - device_descriptor, config_descriptor, bos_descriptor, @@ -199,7 +194,6 @@ impl<'d, D: Driver<'d>> Builder<'d, D> { self.bos_descriptor.end_bos(); // Log the number of allocator bytes actually used in descriptor buffers - info!("USB: device_descriptor used: {}", self.device_descriptor.position()); info!("USB: config_descriptor used: {}", self.config_descriptor.position()); info!("USB: bos_descriptor used: {}", self.bos_descriptor.writer.position()); info!("USB: msos_descriptor used: {}", msos_descriptor.len()); @@ -209,7 +203,6 @@ impl<'d, D: Driver<'d>> Builder<'d, D> { self.driver, self.config, self.handlers, - self.device_descriptor.into_buf(), self.config_descriptor.into_buf(), self.bos_descriptor.writer.into_buf(), msos_descriptor, diff --git a/embassy-usb/src/descriptor.rs b/embassy-usb/src/descriptor.rs index fa83ef583..eb3d1f53a 100644 --- a/embassy-usb/src/descriptor.rs +++ b/embassy-usb/src/descriptor.rs @@ -82,30 +82,6 @@ impl<'a> DescriptorWriter<'a> { self.position = start + length; } - pub(crate) fn device(&mut self, config: &Config) { - self.write( - descriptor_type::DEVICE, - &[ - 0x10, - 0x02, // bcdUSB 2.1 - config.device_class, // bDeviceClass - config.device_sub_class, // bDeviceSubClass - config.device_protocol, // bDeviceProtocol - config.max_packet_size_0, // bMaxPacketSize0 - config.vendor_id as u8, - (config.vendor_id >> 8) as u8, // idVendor - config.product_id as u8, - (config.product_id >> 8) as u8, // idProduct - config.device_release as u8, - (config.device_release >> 8) as u8, // bcdDevice - config.manufacturer.map_or(0, |_| 1), // iManufacturer - config.product.map_or(0, |_| 2), // iProduct - config.serial_number.map_or(0, |_| 3), // iSerialNumber - 1, // bNumConfigurations - ], - ); - } - pub(crate) fn configuration(&mut self, config: &Config) { self.num_interfaces_mark = Some(self.position + 4); @@ -269,6 +245,33 @@ impl<'a> DescriptorWriter<'a> { } } +/// Create a new Device Descriptor array. +/// +/// All device descriptors are always 18 bytes, so there's no need for +/// a variable-length buffer or DescriptorWriter. +pub(crate) fn device_descriptor(config: &Config) -> [u8; 18] { + [ + 18, // bLength + 0x01, // bDescriptorType + 0x10, + 0x02, // bcdUSB 2.1 + config.device_class, // bDeviceClass + config.device_sub_class, // bDeviceSubClass + config.device_protocol, // bDeviceProtocol + config.max_packet_size_0, // bMaxPacketSize0 + config.vendor_id as u8, + (config.vendor_id >> 8) as u8, // idVendor + config.product_id as u8, + (config.product_id >> 8) as u8, // idProduct + config.device_release as u8, + (config.device_release >> 8) as u8, // bcdDevice + config.manufacturer.map_or(0, |_| 1), // iManufacturer + config.product.map_or(0, |_| 2), // iProduct + config.serial_number.map_or(0, |_| 3), // iSerialNumber + 1, // bNumConfigurations + ] +} + /// A writer for Binary Object Store descriptor. pub struct BosWriter<'a> { pub(crate) writer: DescriptorWriter<'a>, diff --git a/embassy-usb/src/fmt.rs b/embassy-usb/src/fmt.rs index 78e583c1c..2ac42c557 100644 --- a/embassy-usb/src/fmt.rs +++ b/embassy-usb/src/fmt.rs @@ -1,5 +1,5 @@ #![macro_use] -#![allow(unused_macros)] +#![allow(unused)] use core::fmt::{Debug, Display, LowerHex}; @@ -229,7 +229,6 @@ impl Try for Result { } } -#[allow(unused)] pub(crate) struct Bytes<'a>(pub &'a [u8]); impl<'a> Debug for Bytes<'a> { diff --git a/embassy-usb/src/lib.rs b/embassy-usb/src/lib.rs index 241e33a78..d58950838 100644 --- a/embassy-usb/src/lib.rs +++ b/embassy-usb/src/lib.rs @@ -168,8 +168,6 @@ struct Interface { #[derive(PartialEq, Eq, Copy, Clone, Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct UsbBufferReport { - /// Number of device descriptor bytes used - pub device_descriptor_used: usize, /// Number of config descriptor bytes used pub config_descriptor_used: usize, /// Number of bos descriptor bytes used @@ -191,7 +189,7 @@ struct Inner<'d, D: Driver<'d>> { bus: D::Bus, config: Config<'d>, - device_descriptor: &'d [u8], + device_descriptor: [u8; 18], config_descriptor: &'d [u8], bos_descriptor: &'d [u8], msos_descriptor: crate::msos::MsOsDescriptorSet<'d>, @@ -217,7 +215,6 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { driver: D, config: Config<'d>, handlers: Vec<&'d mut dyn Handler, MAX_HANDLER_COUNT>, - device_descriptor: &'d [u8], config_descriptor: &'d [u8], bos_descriptor: &'d [u8], msos_descriptor: crate::msos::MsOsDescriptorSet<'d>, @@ -227,6 +224,7 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { // Start the USB bus. // This prevent further allocation by consuming the driver. let (bus, control) = driver.start(config.max_packet_size_0 as u16); + let device_descriptor = descriptor::device_descriptor(&config); Self { control_buf, @@ -256,7 +254,6 @@ impl<'d, D: Driver<'d>> UsbDevice<'d, D> { /// Useful for tuning buffer sizes for actual usage pub fn buffer_usage(&self) -> UsbBufferReport { UsbBufferReport { - device_descriptor_used: self.inner.device_descriptor.len(), config_descriptor_used: self.inner.config_descriptor.len(), bos_descriptor_used: self.inner.bos_descriptor.len(), msos_descriptor_used: self.inner.msos_descriptor.len(), @@ -720,7 +717,7 @@ impl<'d, D: Driver<'d>> Inner<'d, D> { match dtype { descriptor_type::BOS => InResponse::Accepted(self.bos_descriptor), - descriptor_type::DEVICE => InResponse::Accepted(self.device_descriptor), + descriptor_type::DEVICE => InResponse::Accepted(&self.device_descriptor), descriptor_type::CONFIGURATION => InResponse::Accepted(self.config_descriptor), descriptor_type::STRING => { if index == 0 { diff --git a/embassy-usb/src/msos.rs b/embassy-usb/src/msos.rs index 3858c0f51..25936d084 100644 --- a/embassy-usb/src/msos.rs +++ b/embassy-usb/src/msos.rs @@ -226,27 +226,21 @@ pub mod windows_version { pub const WIN10: u32 = 0x0A000000; } -mod sealed { - use core::mem::size_of; +/// A trait for descriptors +trait Descriptor: Sized { + const TYPE: DescriptorType; - /// A trait for descriptors - pub trait Descriptor: Sized { - const TYPE: super::DescriptorType; - - /// The size of the descriptor's header. - fn size(&self) -> usize { - size_of::() - } - - fn write_to(&self, buf: &mut [u8]); + /// The size of the descriptor's header. + fn size(&self) -> usize { + size_of::() } - pub trait DescriptorSet: Descriptor { - const LENGTH_OFFSET: usize; - } + fn write_to(&self, buf: &mut [u8]); } -use sealed::*; +trait DescriptorSet: Descriptor { + const LENGTH_OFFSET: usize; +} /// Copies the data of `t` into `buf`. /// @@ -255,7 +249,7 @@ use sealed::*; unsafe fn transmute_write_to(t: &T, buf: &mut [u8]) { let bytes = core::slice::from_raw_parts((t as *const T) as *const u8, size_of::()); assert!(buf.len() >= bytes.len(), "MS OS descriptor buffer full"); - (&mut buf[..bytes.len()]).copy_from_slice(bytes); + buf[..bytes.len()].copy_from_slice(bytes); } /// Table 9. Microsoft OS 2.0 descriptor wDescriptorType values. @@ -412,9 +406,11 @@ impl DescriptorSet for FunctionSubsetHeader { // Feature Descriptors /// A marker trait for feature descriptors that are valid at the device level. +#[allow(private_bounds)] pub trait DeviceLevelDescriptor: Descriptor {} /// A marker trait for feature descriptors that are valid at the function level. +#[allow(private_bounds)] pub trait FunctionLevelDescriptor: Descriptor {} /// Table 13. Microsoft OS 2.0 compatible ID descriptor. @@ -444,9 +440,9 @@ impl CompatibleIdFeatureDescriptor { pub fn new(compatible_id: &str, sub_compatible_id: &str) -> Self { assert!(compatible_id.len() <= 8 && sub_compatible_id.len() <= 8); let mut cid = [0u8; 8]; - (&mut cid[..compatible_id.len()]).copy_from_slice(compatible_id.as_bytes()); + cid[..compatible_id.len()].copy_from_slice(compatible_id.as_bytes()); let mut scid = [0u8; 8]; - (&mut scid[..sub_compatible_id.len()]).copy_from_slice(sub_compatible_id.as_bytes()); + scid[..sub_compatible_id.len()].copy_from_slice(sub_compatible_id.as_bytes()); Self::new_raw(cid, scid) } diff --git a/examples/boot/application/stm32wb-dfu/src/main.rs b/examples/boot/application/stm32wb-dfu/src/main.rs index 37c3d7d90..929d6802c 100644 --- a/examples/boot/application/stm32wb-dfu/src/main.rs +++ b/examples/boot/application/stm32wb-dfu/src/main.rs @@ -41,7 +41,6 @@ async fn main(_spawner: Spawner) { config.product = Some("USB-DFU Runtime example"); config.serial_number = Some("1235678"); - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -49,7 +48,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], diff --git a/examples/boot/bootloader/stm32wb-dfu/src/main.rs b/examples/boot/bootloader/stm32wb-dfu/src/main.rs index d989fbfdf..093b39f9d 100644 --- a/examples/boot/bootloader/stm32wb-dfu/src/main.rs +++ b/examples/boot/bootloader/stm32wb-dfu/src/main.rs @@ -49,7 +49,6 @@ fn main() -> ! { let mut buffer = AlignedBuffer([0; WRITE_SIZE]); let updater = BlockingFirmwareUpdater::new(fw_config, &mut buffer.0[..]); - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 4096]; @@ -57,7 +56,6 @@ fn main() -> ! { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], diff --git a/examples/nrf52840/src/bin/usb_ethernet.rs b/examples/nrf52840/src/bin/usb_ethernet.rs index 3469c6e5f..a7e5c2668 100644 --- a/examples/nrf52840/src/bin/usb_ethernet.rs +++ b/examples/nrf52840/src/bin/usb_ethernet.rs @@ -70,7 +70,6 @@ async fn main(spawner: Spawner) { config.device_protocol = 0x01; // Create embassy-usb DeviceBuilder using the driver and config. - static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static MSOS_DESC: StaticCell<[u8; 128]> = StaticCell::new(); @@ -78,7 +77,6 @@ async fn main(spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut DEVICE_DESC.init([0; 256])[..], &mut CONFIG_DESC.init([0; 256])[..], &mut BOS_DESC.init([0; 256])[..], &mut MSOS_DESC.init([0; 128])[..], diff --git a/examples/nrf52840/src/bin/usb_hid_keyboard.rs b/examples/nrf52840/src/bin/usb_hid_keyboard.rs index 3e86590c4..52f081487 100644 --- a/examples/nrf52840/src/bin/usb_hid_keyboard.rs +++ b/examples/nrf52840/src/bin/usb_hid_keyboard.rs @@ -50,7 +50,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut msos_descriptor = [0; 256]; @@ -63,7 +62,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut msos_descriptor, diff --git a/examples/nrf52840/src/bin/usb_hid_mouse.rs b/examples/nrf52840/src/bin/usb_hid_mouse.rs index 04ad841b7..5d2837793 100644 --- a/examples/nrf52840/src/bin/usb_hid_mouse.rs +++ b/examples/nrf52840/src/bin/usb_hid_mouse.rs @@ -43,7 +43,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut msos_descriptor = [0; 256]; @@ -55,7 +54,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut msos_descriptor, diff --git a/examples/nrf52840/src/bin/usb_serial.rs b/examples/nrf52840/src/bin/usb_serial.rs index aff539b1b..02048e692 100644 --- a/examples/nrf52840/src/bin/usb_serial.rs +++ b/examples/nrf52840/src/bin/usb_serial.rs @@ -48,7 +48,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut msos_descriptor = [0; 256]; @@ -59,7 +58,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut msos_descriptor, diff --git a/examples/nrf52840/src/bin/usb_serial_multitask.rs b/examples/nrf52840/src/bin/usb_serial_multitask.rs index 4e8118fb8..895cca8b9 100644 --- a/examples/nrf52840/src/bin/usb_serial_multitask.rs +++ b/examples/nrf52840/src/bin/usb_serial_multitask.rs @@ -67,7 +67,6 @@ async fn main(spawner: Spawner) { let state = STATE.init(State::new()); // Create embassy-usb DeviceBuilder using the driver and config. - static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static MSOS_DESC: StaticCell<[u8; 128]> = StaticCell::new(); @@ -75,7 +74,6 @@ async fn main(spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut DEVICE_DESC.init([0; 256])[..], &mut CONFIG_DESC.init([0; 256])[..], &mut BOS_DESC.init([0; 256])[..], &mut MSOS_DESC.init([0; 128])[..], diff --git a/examples/nrf52840/src/bin/usb_serial_winusb.rs b/examples/nrf52840/src/bin/usb_serial_winusb.rs index 060f9ba94..c6675a3d3 100644 --- a/examples/nrf52840/src/bin/usb_serial_winusb.rs +++ b/examples/nrf52840/src/bin/usb_serial_winusb.rs @@ -53,7 +53,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut msos_descriptor = [0; 256]; @@ -64,7 +63,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut msos_descriptor, diff --git a/examples/rp/src/bin/multicore.rs b/examples/rp/src/bin/multicore.rs index c7b087476..7cb546c91 100644 --- a/examples/rp/src/bin/multicore.rs +++ b/examples/rp/src/bin/multicore.rs @@ -30,10 +30,14 @@ fn main() -> ! { let p = embassy_rp::init(Default::default()); let led = Output::new(p.PIN_25, Level::Low); - spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { - let executor1 = EXECUTOR1.init(Executor::new()); - executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); - }); + spawn_core1( + p.CORE1, + unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, + move || { + let executor1 = EXECUTOR1.init(Executor::new()); + executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(led)))); + }, + ); let executor0 = EXECUTOR0.init(Executor::new()); executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); diff --git a/examples/rp/src/bin/pio_uart.rs b/examples/rp/src/bin/pio_uart.rs index a07f1c180..53b696309 100644 --- a/examples/rp/src/bin/pio_uart.rs +++ b/examples/rp/src/bin/pio_uart.rs @@ -60,7 +60,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -70,7 +69,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs index 01f0d5967..f1b124efa 100644 --- a/examples/rp/src/bin/usb_ethernet.rs +++ b/examples/rp/src/bin/usb_ethernet.rs @@ -64,14 +64,12 @@ async fn main(spawner: Spawner) { config.device_protocol = 0x01; // Create embassy-usb DeviceBuilder using the driver and config. - static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new(); let mut builder = Builder::new( driver, config, - &mut DEVICE_DESC.init([0; 256])[..], &mut CONFIG_DESC.init([0; 256])[..], &mut BOS_DESC.init([0; 256])[..], &mut [], // no msos descriptors diff --git a/examples/rp/src/bin/usb_hid_keyboard.rs b/examples/rp/src/bin/usb_hid_keyboard.rs index b5ac16245..710be8d13 100644 --- a/examples/rp/src/bin/usb_hid_keyboard.rs +++ b/examples/rp/src/bin/usb_hid_keyboard.rs @@ -36,7 +36,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; // You can also add a Microsoft OS descriptor. @@ -50,7 +49,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut msos_descriptor, diff --git a/examples/rp/src/bin/usb_hid_mouse.rs b/examples/rp/src/bin/usb_hid_mouse.rs index afebd8813..e8b399cb1 100644 --- a/examples/rp/src/bin/usb_hid_mouse.rs +++ b/examples/rp/src/bin/usb_hid_mouse.rs @@ -39,7 +39,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; // You can also add a Microsoft OS descriptor. @@ -53,7 +52,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut msos_descriptor, diff --git a/examples/rp/src/bin/usb_midi.rs b/examples/rp/src/bin/usb_midi.rs index 95306a35c..11db1b2e1 100644 --- a/examples/rp/src/bin/usb_midi.rs +++ b/examples/rp/src/bin/usb_midi.rs @@ -46,7 +46,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -54,7 +53,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/rp/src/bin/usb_raw.rs b/examples/rp/src/bin/usb_raw.rs index a6c8a5b2e..97e7e0244 100644 --- a/examples/rp/src/bin/usb_raw.rs +++ b/examples/rp/src/bin/usb_raw.rs @@ -93,7 +93,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut msos_descriptor = [0; 256]; @@ -106,7 +105,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut msos_descriptor, diff --git a/examples/rp/src/bin/usb_raw_bulk.rs b/examples/rp/src/bin/usb_raw_bulk.rs index 0dc8e9f72..331c3da4c 100644 --- a/examples/rp/src/bin/usb_raw_bulk.rs +++ b/examples/rp/src/bin/usb_raw_bulk.rs @@ -71,7 +71,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut msos_descriptor = [0; 256]; @@ -80,7 +79,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut msos_descriptor, diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs index ab24a994c..3c9bc96dd 100644 --- a/examples/rp/src/bin/usb_serial.rs +++ b/examples/rp/src/bin/usb_serial.rs @@ -46,7 +46,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -56,7 +55,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/rp/src/bin/usb_serial_with_logger.rs b/examples/rp/src/bin/usb_serial_with_logger.rs index 4ba4fc25c..f9cfdef94 100644 --- a/examples/rp/src/bin/usb_serial_with_logger.rs +++ b/examples/rp/src/bin/usb_serial_with_logger.rs @@ -46,7 +46,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -57,7 +56,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/std/src/bin/net.rs b/examples/std/src/bin/net.rs index dad93d0a1..59813d8cb 100644 --- a/examples/std/src/bin/net.rs +++ b/examples/std/src/bin/net.rs @@ -1,5 +1,3 @@ -use std::default::Default; - use clap::Parser; use embassy_executor::{Executor, Spawner}; use embassy_net::tcp::TcpSocket; diff --git a/examples/std/src/bin/net_dns.rs b/examples/std/src/bin/net_dns.rs index fca1e076e..3b6a3de37 100644 --- a/examples/std/src/bin/net_dns.rs +++ b/examples/std/src/bin/net_dns.rs @@ -1,5 +1,3 @@ -use std::default::Default; - use clap::Parser; use embassy_executor::{Executor, Spawner}; use embassy_net::dns::DnsQueryType; diff --git a/examples/std/src/bin/tcp_accept.rs b/examples/std/src/bin/tcp_accept.rs index 00ccd83a7..e8b6eaa6c 100644 --- a/examples/std/src/bin/tcp_accept.rs +++ b/examples/std/src/bin/tcp_accept.rs @@ -1,5 +1,4 @@ use core::fmt::Write as _; -use std::default::Default; use clap::Parser; use embassy_executor::{Executor, Spawner}; diff --git a/examples/stm32f1/src/bin/usb_serial.rs b/examples/stm32f1/src/bin/usb_serial.rs index 1ae6c1dee..ee99acf41 100644 --- a/examples/stm32f1/src/bin/usb_serial.rs +++ b/examples/stm32f1/src/bin/usb_serial.rs @@ -60,7 +60,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 7]; @@ -70,7 +69,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32f2/src/bin/pll.rs b/examples/stm32f2/src/bin/pll.rs index e32f283d1..e39e2daec 100644 --- a/examples/stm32f2/src/bin/pll.rs +++ b/examples/stm32f2/src/bin/pll.rs @@ -1,8 +1,6 @@ #![no_std] #![no_main] -use core::convert::TryFrom; - use defmt::*; use embassy_executor::Spawner; use embassy_stm32::time::Hertz; diff --git a/examples/stm32f3/src/bin/usb_serial.rs b/examples/stm32f3/src/bin/usb_serial.rs index ee1c43afd..5760f2c1c 100644 --- a/examples/stm32f3/src/bin/usb_serial.rs +++ b/examples/stm32f3/src/bin/usb_serial.rs @@ -54,7 +54,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 7]; @@ -64,7 +63,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32f4/src/bin/usb_ethernet.rs b/examples/stm32f4/src/bin/usb_ethernet.rs index a196259a8..d2cbeea1b 100644 --- a/examples/stm32f4/src/bin/usb_ethernet.rs +++ b/examples/stm32f4/src/bin/usb_ethernet.rs @@ -7,8 +7,8 @@ use embassy_net::tcp::TcpSocket; use embassy_net::{Stack, StackResources}; use embassy_stm32::rng::{self, Rng}; use embassy_stm32::time::Hertz; -use embassy_stm32::usb_otg::Driver; -use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; +use embassy_stm32::usb::Driver; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::{Builder, UsbDevice}; @@ -36,7 +36,7 @@ async fn net_task(stack: &'static Stack>) -> ! { } bind_interrupts!(struct Irqs { - OTG_FS => usb_otg::InterruptHandler; + OTG_FS => usb::InterruptHandler; HASH_RNG => rng::InterruptHandler; }); @@ -63,13 +63,14 @@ async fn main(spawner: Spawner) { config.rcc.apb1_pre = APBPrescaler::DIV4; config.rcc.apb2_pre = APBPrescaler::DIV2; config.rcc.sys = Sysclk::PLL1_P; + config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q; } let p = embassy_stm32::init(config); // Create the driver, from the HAL. static OUTPUT_BUFFER: StaticCell<[u8; 256]> = StaticCell::new(); let ep_out_buffer = &mut OUTPUT_BUFFER.init([0; 256])[..]; - let mut config = embassy_stm32::usb_otg::Config::default(); + let mut config = embassy_stm32::usb::Config::default(); config.vbus_detection = true; let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, ep_out_buffer, config); @@ -88,14 +89,12 @@ async fn main(spawner: Spawner) { config.device_protocol = 0x01; // Create embassy-usb DeviceBuilder using the driver and config. - static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new(); let mut builder = Builder::new( driver, config, - &mut DEVICE_DESC.init([0; 256])[..], &mut CONFIG_DESC.init([0; 256])[..], &mut BOS_DESC.init([0; 256])[..], &mut [], // no msos descriptors diff --git a/examples/stm32f4/src/bin/usb_hid_keyboard.rs b/examples/stm32f4/src/bin/usb_hid_keyboard.rs index 19b5971fb..a799b4e72 100644 --- a/examples/stm32f4/src/bin/usb_hid_keyboard.rs +++ b/examples/stm32f4/src/bin/usb_hid_keyboard.rs @@ -8,8 +8,8 @@ use embassy_executor::Spawner; use embassy_stm32::exti::ExtiInput; use embassy_stm32::gpio::Pull; use embassy_stm32::time::Hertz; -use embassy_stm32::usb_otg::Driver; -use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; +use embassy_stm32::usb::Driver; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::class::hid::{HidReaderWriter, ReportId, RequestHandler, State}; use embassy_usb::control::OutResponse; use embassy_usb::{Builder, Handler}; @@ -18,7 +18,7 @@ use usbd_hid::descriptor::{KeyboardReport, SerializedDescriptor}; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { - OTG_FS => usb_otg::InterruptHandler; + OTG_FS => usb::InterruptHandler; }); #[embassy_executor::main] @@ -42,12 +42,13 @@ async fn main(_spawner: Spawner) { config.rcc.apb1_pre = APBPrescaler::DIV4; config.rcc.apb2_pre = APBPrescaler::DIV2; config.rcc.sys = Sysclk::PLL1_P; + config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q; } let p = embassy_stm32::init(config); // Create the driver, from the HAL. let mut ep_out_buffer = [0u8; 256]; - let mut config = embassy_stm32::usb_otg::Config::default(); + let mut config = embassy_stm32::usb::Config::default(); config.vbus_detection = true; let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); @@ -68,7 +69,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; // You can also add a Microsoft OS descriptor. @@ -83,7 +83,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut msos_descriptor, diff --git a/examples/stm32f4/src/bin/usb_hid_mouse.rs b/examples/stm32f4/src/bin/usb_hid_mouse.rs index c98792880..0bc236119 100644 --- a/examples/stm32f4/src/bin/usb_hid_mouse.rs +++ b/examples/stm32f4/src/bin/usb_hid_mouse.rs @@ -4,8 +4,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::time::Hertz; -use embassy_stm32::usb_otg::Driver; -use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; +use embassy_stm32::usb::Driver; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_time::Timer; use embassy_usb::class::hid::{HidWriter, ReportId, RequestHandler, State}; use embassy_usb::control::OutResponse; @@ -15,7 +15,7 @@ use usbd_hid::descriptor::{MouseReport, SerializedDescriptor}; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { - OTG_FS => usb_otg::InterruptHandler; + OTG_FS => usb::InterruptHandler; }); #[embassy_executor::main] @@ -39,12 +39,13 @@ async fn main(_spawner: Spawner) { config.rcc.apb1_pre = APBPrescaler::DIV4; config.rcc.apb2_pre = APBPrescaler::DIV2; config.rcc.sys = Sysclk::PLL1_P; + config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q; } let p = embassy_stm32::init(config); // Create the driver, from the HAL. let mut ep_out_buffer = [0u8; 256]; - let mut config = embassy_stm32::usb_otg::Config::default(); + let mut config = embassy_stm32::usb::Config::default(); config.vbus_detection = true; let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); @@ -63,7 +64,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -75,7 +75,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32f4/src/bin/usb_raw.rs b/examples/stm32f4/src/bin/usb_raw.rs index afff55187..4e583aeb8 100644 --- a/examples/stm32f4/src/bin/usb_raw.rs +++ b/examples/stm32f4/src/bin/usb_raw.rs @@ -52,8 +52,8 @@ use defmt::*; use embassy_executor::Spawner; use embassy_stm32::time::Hertz; -use embassy_stm32::usb_otg::Driver; -use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; +use embassy_stm32::usb::Driver; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::control::{InResponse, OutResponse, Recipient, Request, RequestType}; use embassy_usb::msos::{self, windows_version}; use embassy_usb::types::InterfaceNumber; @@ -66,7 +66,7 @@ use {defmt_rtt as _, panic_probe as _}; const DEVICE_INTERFACE_GUIDS: &[&str] = &["{DAC2087C-63FA-458D-A55D-827C0762DEC7}"]; bind_interrupts!(struct Irqs { - OTG_FS => usb_otg::InterruptHandler; + OTG_FS => usb::InterruptHandler; }); #[embassy_executor::main] @@ -92,12 +92,13 @@ async fn main(_spawner: Spawner) { config.rcc.apb1_pre = APBPrescaler::DIV4; config.rcc.apb2_pre = APBPrescaler::DIV2; config.rcc.sys = Sysclk::PLL1_P; + config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q; } let p = embassy_stm32::init(config); // Create the driver, from the HAL. let mut ep_out_buffer = [0u8; 256]; - let mut config = embassy_stm32::usb_otg::Config::default(); + let mut config = embassy_stm32::usb::Config::default(); config.vbus_detection = true; let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); @@ -116,7 +117,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut msos_descriptor = [0; 256]; @@ -129,7 +129,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut msos_descriptor, diff --git a/examples/stm32f4/src/bin/usb_serial.rs b/examples/stm32f4/src/bin/usb_serial.rs index 58d994a61..f3a375d31 100644 --- a/examples/stm32f4/src/bin/usb_serial.rs +++ b/examples/stm32f4/src/bin/usb_serial.rs @@ -4,8 +4,8 @@ use defmt::{panic, *}; use embassy_executor::Spawner; use embassy_stm32::time::Hertz; -use embassy_stm32::usb_otg::{Driver, Instance}; -use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; +use embassy_stm32::usb::{Driver, Instance}; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::driver::EndpointError; use embassy_usb::Builder; @@ -13,7 +13,7 @@ use futures::future::join; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { - OTG_FS => usb_otg::InterruptHandler; + OTG_FS => usb::InterruptHandler; }); #[embassy_executor::main] @@ -39,12 +39,13 @@ async fn main(_spawner: Spawner) { config.rcc.apb1_pre = APBPrescaler::DIV4; config.rcc.apb2_pre = APBPrescaler::DIV2; config.rcc.sys = Sysclk::PLL1_P; + config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q; } let p = embassy_stm32::init(config); // Create the driver, from the HAL. let mut ep_out_buffer = [0u8; 256]; - let mut config = embassy_stm32::usb_otg::Config::default(); + let mut config = embassy_stm32::usb::Config::default(); config.vbus_detection = true; let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); @@ -63,7 +64,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -73,7 +73,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32f4/src/bin/ws2812_pwm.rs b/examples/stm32f4/src/bin/ws2812_pwm.rs index 6122cea2d..cbaff75fc 100644 --- a/examples/stm32f4/src/bin/ws2812_pwm.rs +++ b/examples/stm32f4/src/bin/ws2812_pwm.rs @@ -15,8 +15,9 @@ use embassy_executor::Spawner; use embassy_stm32::gpio::OutputType; use embassy_stm32::time::khz; +use embassy_stm32::timer::low_level::CountingMode; use embassy_stm32::timer::simple_pwm::{PwmPin, SimplePwm}; -use embassy_stm32::timer::{Channel, CountingMode}; +use embassy_stm32::timer::Channel; use embassy_time::{Duration, Ticker, Timer}; use {defmt_rtt as _, panic_probe as _}; @@ -60,7 +61,7 @@ async fn main(_spawner: Spawner) { // construct ws2812 non-return-to-zero (NRZ) code bit by bit // ws2812 only need 24 bits for each LED, but we add one bit more to keep PWM output low - let max_duty = ws2812_pwm.get_max_duty(); + let max_duty = ws2812_pwm.get_max_duty() as u16; let n0 = 8 * max_duty / 25; // ws2812 Bit 0 high level timing let n1 = 2 * n0; // ws2812 Bit 1 high level timing diff --git a/examples/stm32f7/src/bin/usb_serial.rs b/examples/stm32f7/src/bin/usb_serial.rs index 97daf6bd1..39a5512f4 100644 --- a/examples/stm32f7/src/bin/usb_serial.rs +++ b/examples/stm32f7/src/bin/usb_serial.rs @@ -4,8 +4,8 @@ use defmt::{panic, *}; use embassy_executor::Spawner; use embassy_stm32::time::Hertz; -use embassy_stm32::usb_otg::{Driver, Instance}; -use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; +use embassy_stm32::usb::{Driver, Instance}; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::driver::EndpointError; use embassy_usb::Builder; @@ -13,7 +13,7 @@ use futures::future::join; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { - OTG_FS => usb_otg::InterruptHandler; + OTG_FS => usb::InterruptHandler; }); #[embassy_executor::main] @@ -39,12 +39,13 @@ async fn main(_spawner: Spawner) { config.rcc.apb1_pre = APBPrescaler::DIV4; config.rcc.apb2_pre = APBPrescaler::DIV2; config.rcc.sys = Sysclk::PLL1_P; + config.rcc.mux.clk48sel = mux::Clk48sel::PLL1_Q; } let p = embassy_stm32::init(config); // Create the driver, from the HAL. let mut ep_out_buffer = [0u8; 256]; - let mut config = embassy_stm32::usb_otg::Config::default(); + let mut config = embassy_stm32::usb::Config::default(); config.vbus_detection = true; let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); @@ -63,7 +64,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -73,7 +73,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32g0/src/bin/usb_serial.rs b/examples/stm32g0/src/bin/usb_serial.rs index 8b9915626..162dfd86b 100644 --- a/examples/stm32g0/src/bin/usb_serial.rs +++ b/examples/stm32g0/src/bin/usb_serial.rs @@ -36,7 +36,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 7]; @@ -46,7 +45,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32g4/src/bin/usb_serial.rs b/examples/stm32g4/src/bin/usb_serial.rs index dc95aa6e5..dbe8f27c1 100644 --- a/examples/stm32g4/src/bin/usb_serial.rs +++ b/examples/stm32g4/src/bin/usb_serial.rs @@ -56,7 +56,6 @@ async fn main(_spawner: Spawner) { config.device_protocol = 0x01; config.composite_with_iads = true; - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -66,7 +65,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32h5/src/bin/usb_serial.rs b/examples/stm32h5/src/bin/usb_serial.rs index 83477c8fa..4f86bb342 100644 --- a/examples/stm32h5/src/bin/usb_serial.rs +++ b/examples/stm32h5/src/bin/usb_serial.rs @@ -65,7 +65,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -75,7 +74,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32h7/src/bin/camera.rs b/examples/stm32h7/src/bin/camera.rs index e5a104baf..170a5aa28 100644 --- a/examples/stm32h7/src/bin/camera.rs +++ b/examples/stm32h7/src/bin/camera.rs @@ -78,9 +78,9 @@ async fn main(_spawner: Spawner) { ); defmt::info!("attempting capture"); - defmt::unwrap!(dcmi.capture(unsafe { &mut FRAME }).await); + defmt::unwrap!(dcmi.capture(unsafe { &mut *core::ptr::addr_of_mut!(FRAME) }).await); - defmt::info!("captured frame: {:x}", unsafe { &FRAME }); + defmt::info!("captured frame: {:x}", unsafe { &*core::ptr::addr_of!(FRAME) }); defmt::info!("main loop running"); loop { diff --git a/examples/stm32h7/src/bin/dac_dma.rs b/examples/stm32h7/src/bin/dac_dma.rs index feec28993..3a9887e3c 100644 --- a/examples/stm32h7/src/bin/dac_dma.rs +++ b/examples/stm32h7/src/bin/dac_dma.rs @@ -6,9 +6,9 @@ use embassy_executor::Spawner; use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; use embassy_stm32::pac::timer::vals::Mms; use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; -use embassy_stm32::rcc::low_level::RccPeripheral; +use embassy_stm32::rcc::frequency; use embassy_stm32::time::Hertz; -use embassy_stm32::timer::low_level::BasicInstance; +use embassy_stm32::timer::low_level::Timer; use micromath::F32Ext; use {defmt_rtt as _, panic_probe as _}; @@ -51,19 +51,19 @@ async fn main(spawner: Spawner) { // Obtain two independent channels (p.DAC1 can only be consumed once, though!) let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); - spawner.spawn(dac_task1(dac_ch1)).ok(); - spawner.spawn(dac_task2(dac_ch2)).ok(); + spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); + spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); } #[embassy_executor::task] -async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { +async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { let data: &[u8; 256] = &calculate_array::<256>(); - info!("TIM6 frequency is {}", TIM6::frequency()); + info!("TIM6 frequency is {}", frequency::()); const FREQUENCY: Hertz = Hertz::hz(200); // Compute the reload value such that we obtain the FREQUENCY for the sine - let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32; + let reload: u32 = (frequency::().0 / FREQUENCY.0) / data.len() as u32; // Depends on your clock and on the specific chip used, you may need higher or lower values here if reload < 10 { @@ -74,17 +74,17 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { dac.set_triggering(true); dac.enable(); - TIM6::enable_and_reset(); - TIM6::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM6::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM6::regs_basic().cr1().modify(|w| { + let tim = Timer::new(tim); + tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + tim.regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); }); debug!( "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", - TIM6::frequency(), + frequency::(), FREQUENCY, reload, reload as u16, @@ -99,22 +99,22 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { } #[embassy_executor::task] -async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { +async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { let data: &[u8; 256] = &calculate_array::<256>(); - info!("TIM7 frequency is {}", TIM7::frequency()); + info!("TIM7 frequency is {}", frequency::()); const FREQUENCY: Hertz = Hertz::hz(600); - let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32; + let reload: u32 = (frequency::().0 / FREQUENCY.0) / data.len() as u32; if reload < 10 { error!("Reload value {} below threshold!", reload); } - TIM7::enable_and_reset(); - TIM7::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM7::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM7::regs_basic().cr1().modify(|w| { + let tim = Timer::new(tim); + tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + tim.regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); }); @@ -125,7 +125,7 @@ async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { debug!( "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", - TIM7::frequency(), + frequency::(), FREQUENCY, reload, reload as u16, diff --git a/examples/stm32h7/src/bin/eth.rs b/examples/stm32h7/src/bin/eth.rs index cd9a27fcd..7c7964ecd 100644 --- a/examples/stm32h7/src/bin/eth.rs +++ b/examples/stm32h7/src/bin/eth.rs @@ -64,19 +64,21 @@ async fn main(spawner: Spawner) -> ! { let mac_addr = [0x00, 0x00, 0xDE, 0xAD, 0xBE, 0xEF]; static PACKETS: StaticCell> = StaticCell::new(); + // warning: Not all STM32H7 devices have the exact same pins here + // for STM32H747XIH, replace p.PB13 for PG12 let device = Ethernet::new( PACKETS.init(PacketQueue::<4, 4>::new()), p.ETH, Irqs, - p.PA1, - p.PA2, - p.PC1, - p.PA7, - p.PC4, - p.PC5, - p.PG13, - p.PB13, - p.PG11, + p.PA1, // ref_clk + p.PA2, // mdio + p.PC1, // eth_mdc + p.PA7, // CRS_DV: Carrier Sense + p.PC4, // RX_D0: Received Bit 0 + p.PC5, // RX_D1: Received Bit 1 + p.PG13, // TX_D0: Transmit Bit 0 + p.PB13, // TX_D1: Transmit Bit 1 + p.PG11, // TX_EN: Transmit Enable GenericSMI::new(0), mac_addr, ); diff --git a/examples/stm32h7/src/bin/low_level_timer_api.rs b/examples/stm32h7/src/bin/low_level_timer_api.rs index 049d9967d..a95b44b74 100644 --- a/examples/stm32h7/src/bin/low_level_timer_api.rs +++ b/examples/stm32h7/src/bin/low_level_timer_api.rs @@ -3,11 +3,11 @@ use defmt::*; use embassy_executor::Spawner; -use embassy_stm32::gpio::low_level::AFType; -use embassy_stm32::gpio::Speed; +use embassy_stm32::gpio::{AFType, Flex, Pull, Speed}; use embassy_stm32::time::{khz, Hertz}; -use embassy_stm32::timer::*; -use embassy_stm32::{into_ref, Config, Peripheral, PeripheralRef}; +use embassy_stm32::timer::low_level::{OutputCompareMode, Timer as LLTimer}; +use embassy_stm32::timer::{Channel, Channel1Pin, Channel2Pin, Channel3Pin, Channel4Pin, GeneralInstance32bit4Channel}; +use embassy_stm32::{into_ref, Config, Peripheral}; use embassy_time::Timer; use {defmt_rtt as _, panic_probe as _}; @@ -56,11 +56,15 @@ async fn main(_spawner: Spawner) { Timer::after_millis(300).await; } } -pub struct SimplePwm32<'d, T: CaptureCompare32bitInstance> { - inner: PeripheralRef<'d, T>, +pub struct SimplePwm32<'d, T: GeneralInstance32bit4Channel> { + tim: LLTimer<'d, T>, + _ch1: Flex<'d>, + _ch2: Flex<'d>, + _ch3: Flex<'d>, + _ch4: Flex<'d>, } -impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { +impl<'d, T: GeneralInstance32bit4Channel> SimplePwm32<'d, T> { pub fn new( tim: impl Peripheral

+ 'd, ch1: impl Peripheral

> + 'd, @@ -69,25 +73,33 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { ch4: impl Peripheral

> + 'd, freq: Hertz, ) -> Self { - into_ref!(tim, ch1, ch2, ch3, ch4); + into_ref!(ch1, ch2, ch3, ch4); - T::enable_and_reset(); + let af1 = ch1.af_num(); + let af2 = ch2.af_num(); + let af3 = ch3.af_num(); + let af4 = ch4.af_num(); + let mut ch1 = Flex::new(ch1); + let mut ch2 = Flex::new(ch2); + let mut ch3 = Flex::new(ch3); + let mut ch4 = Flex::new(ch4); + ch1.set_as_af_unchecked(af1, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); + ch2.set_as_af_unchecked(af2, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); + ch3.set_as_af_unchecked(af3, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); + ch4.set_as_af_unchecked(af4, AFType::OutputPushPull, Pull::None, Speed::VeryHigh); - ch1.set_speed(Speed::VeryHigh); - ch1.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch2.set_speed(Speed::VeryHigh); - ch2.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch3.set_speed(Speed::VeryHigh); - ch3.set_as_af(ch1.af_num(), AFType::OutputPushPull); - ch4.set_speed(Speed::VeryHigh); - ch4.set_as_af(ch1.af_num(), AFType::OutputPushPull); - - let mut this = Self { inner: tim }; + let mut this = Self { + tim: LLTimer::new(tim), + _ch1: ch1, + _ch2: ch2, + _ch3: ch3, + _ch4: ch4, + }; this.set_frequency(freq); - this.inner.start(); + this.tim.start(); - let r = T::regs_gp32(); + let r = this.tim.regs_gp32(); r.ccmr_output(0) .modify(|w| w.set_ocm(0, OutputCompareMode::PwmMode1.into())); r.ccmr_output(0) @@ -101,23 +113,26 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> { } pub fn enable(&mut self, channel: Channel) { - T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), true)); + self.tim.regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), true)); } pub fn disable(&mut self, channel: Channel) { - T::regs_gp32().ccer().modify(|w| w.set_cce(channel.index(), false)); + self.tim + .regs_gp32() + .ccer() + .modify(|w| w.set_cce(channel.index(), false)); } pub fn set_frequency(&mut self, freq: Hertz) { - ::set_frequency(&mut self.inner, freq); + self.tim.set_frequency(freq); } pub fn get_max_duty(&self) -> u32 { - T::regs_gp32().arr().read() + self.tim.regs_gp32().arr().read() } pub fn set_duty(&mut self, channel: Channel, duty: u32) { defmt::assert!(duty < self.get_max_duty()); - T::regs_gp32().ccr(channel.index()).write_value(duty) + self.tim.regs_gp32().ccr(channel.index()).write_value(duty) } } diff --git a/examples/stm32h7/src/bin/usb_serial.rs b/examples/stm32h7/src/bin/usb_serial.rs index d81efb541..576506ad3 100644 --- a/examples/stm32h7/src/bin/usb_serial.rs +++ b/examples/stm32h7/src/bin/usb_serial.rs @@ -3,8 +3,8 @@ use defmt::{panic, *}; use embassy_executor::Spawner; -use embassy_stm32::usb_otg::{Driver, Instance}; -use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; +use embassy_stm32::usb::{Driver, Instance}; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::driver::EndpointError; use embassy_usb::Builder; @@ -12,7 +12,7 @@ use futures::future::join; use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { - OTG_FS => usb_otg::InterruptHandler; + OTG_FS => usb::InterruptHandler; }); #[embassy_executor::main] @@ -40,12 +40,13 @@ async fn main(_spawner: Spawner) { config.rcc.apb3_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.apb4_pre = APBPrescaler::DIV2; // 100 Mhz config.rcc.voltage_scale = VoltageScale::Scale1; + config.rcc.mux.usbsel = mux::Usbsel::HSI48; } let p = embassy_stm32::init(config); // Create the driver, from the HAL. let mut ep_out_buffer = [0u8; 256]; - let mut config = embassy_stm32::usb_otg::Config::default(); + let mut config = embassy_stm32::usb::Config::default(); config.vbus_detection = true; let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); @@ -64,7 +65,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -74,7 +74,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32l1/src/bin/usb_serial.rs b/examples/stm32l1/src/bin/usb_serial.rs index f738ea358..653bbd6d2 100644 --- a/examples/stm32l1/src/bin/usb_serial.rs +++ b/examples/stm32l1/src/bin/usb_serial.rs @@ -46,7 +46,6 @@ async fn main(_spawner: Spawner) { config.device_protocol = 0x01; config.composite_with_iads = true; - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -56,7 +55,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32l4/src/bin/dac_dma.rs b/examples/stm32l4/src/bin/dac_dma.rs index f227812cd..d01b016c0 100644 --- a/examples/stm32l4/src/bin/dac_dma.rs +++ b/examples/stm32l4/src/bin/dac_dma.rs @@ -6,9 +6,9 @@ use embassy_executor::Spawner; use embassy_stm32::dac::{DacCh1, DacCh2, ValueArray}; use embassy_stm32::pac::timer::vals::Mms; use embassy_stm32::peripherals::{DAC1, DMA1_CH3, DMA1_CH4, TIM6, TIM7}; -use embassy_stm32::rcc::low_level::RccPeripheral; +use embassy_stm32::rcc::frequency; use embassy_stm32::time::Hertz; -use embassy_stm32::timer::low_level::BasicInstance; +use embassy_stm32::timer::low_level::Timer; use micromath::F32Ext; use {defmt_rtt as _, panic_probe as _}; @@ -22,19 +22,19 @@ async fn main(spawner: Spawner) { // Obtain two independent channels (p.DAC1 can only be consumed once, though!) let (dac_ch1, dac_ch2) = embassy_stm32::dac::Dac::new(p.DAC1, p.DMA1_CH3, p.DMA1_CH4, p.PA4, p.PA5).split(); - spawner.spawn(dac_task1(dac_ch1)).ok(); - spawner.spawn(dac_task2(dac_ch2)).ok(); + spawner.spawn(dac_task1(p.TIM6, dac_ch1)).ok(); + spawner.spawn(dac_task2(p.TIM7, dac_ch2)).ok(); } #[embassy_executor::task] -async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { +async fn dac_task1(tim: TIM6, mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { let data: &[u8; 256] = &calculate_array::<256>(); - info!("TIM6 frequency is {}", TIM6::frequency()); + info!("TIM6 frequency is {}", frequency::()); const FREQUENCY: Hertz = Hertz::hz(200); // Compute the reload value such that we obtain the FREQUENCY for the sine - let reload: u32 = (TIM6::frequency().0 / FREQUENCY.0) / data.len() as u32; + let reload: u32 = (frequency::().0 / FREQUENCY.0) / data.len() as u32; // Depends on your clock and on the specific chip used, you may need higher or lower values here if reload < 10 { @@ -45,17 +45,17 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { dac.set_triggering(true); dac.enable(); - TIM6::enable_and_reset(); - TIM6::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM6::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM6::regs_basic().cr1().modify(|w| { + let tim = Timer::new(tim); + tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + tim.regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); }); debug!( "TIM6 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", - TIM6::frequency(), + frequency::(), FREQUENCY, reload, reload as u16, @@ -70,22 +70,22 @@ async fn dac_task1(mut dac: DacCh1<'static, DAC1, DMA1_CH3>) { } #[embassy_executor::task] -async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { +async fn dac_task2(tim: TIM7, mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { let data: &[u8; 256] = &calculate_array::<256>(); - info!("TIM7 frequency is {}", TIM7::frequency()); + info!("TIM7 frequency is {}", frequency::()); const FREQUENCY: Hertz = Hertz::hz(600); - let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32; + let reload: u32 = (frequency::().0 / FREQUENCY.0) / data.len() as u32; if reload < 10 { error!("Reload value {} below threshold!", reload); } - TIM7::enable_and_reset(); - TIM7::regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); - TIM7::regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); - TIM7::regs_basic().cr1().modify(|w| { + let tim = Timer::new(tim); + tim.regs_basic().arr().modify(|w| w.set_arr(reload as u16 - 1)); + tim.regs_basic().cr2().modify(|w| w.set_mms(Mms::UPDATE)); + tim.regs_basic().cr1().modify(|w| { w.set_opm(false); w.set_cen(true); }); @@ -96,7 +96,7 @@ async fn dac_task2(mut dac: DacCh2<'static, DAC1, DMA1_CH4>) { debug!( "TIM7 Frequency {}, Target Frequency {}, Reload {}, Reload as u16 {}, Samples {}", - TIM7::frequency(), + frequency::(), FREQUENCY, reload, reload as u16, diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs index 32bfab6eb..343e09e68 100644 --- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs +++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs @@ -42,7 +42,7 @@ bind_interrupts!(struct Irqs { RNG => rng::InterruptHandler; }); -use embassy_net_adin1110::{self, Device, Runner, ADIN1110}; +use embassy_net_adin1110::{Device, Runner, ADIN1110}; use embedded_hal_bus::spi::ExclusiveDevice; use hal::gpio::Pull; use hal::i2c::Config as I2C_Config; diff --git a/examples/stm32l4/src/bin/usb_serial.rs b/examples/stm32l4/src/bin/usb_serial.rs index 9247e56a1..198504b59 100644 --- a/examples/stm32l4/src/bin/usb_serial.rs +++ b/examples/stm32l4/src/bin/usb_serial.rs @@ -4,9 +4,8 @@ use defmt::{panic, *}; use defmt_rtt as _; // global logger use embassy_executor::Spawner; -use embassy_stm32::rcc::*; -use embassy_stm32::usb_otg::{Driver, Instance}; -use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; +use embassy_stm32::usb::{Driver, Instance}; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::driver::EndpointError; use embassy_usb::Builder; @@ -14,7 +13,7 @@ use futures::future::join; use panic_probe as _; bind_interrupts!(struct Irqs { - OTG_FS => usb_otg::InterruptHandler; + OTG_FS => usb::InterruptHandler; }); #[embassy_executor::main] @@ -22,23 +21,26 @@ async fn main(_spawner: Spawner) { info!("Hello World!"); let mut config = Config::default(); - config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB - config.rcc.sys = Sysclk::PLL1_R; - config.rcc.hsi = true; - config.rcc.pll = Some(Pll { - source: PllSource::HSI, - prediv: PllPreDiv::DIV1, - mul: PllMul::MUL10, - divp: None, - divq: None, - divr: Some(PllRDiv::DIV2), // sysclk 80Mhz (16 / 1 * 10 / 2) - }); - + { + use embassy_stm32::rcc::*; + config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB + config.rcc.sys = Sysclk::PLL1_R; + config.rcc.hsi = true; + config.rcc.pll = Some(Pll { + source: PllSource::HSI, + prediv: PllPreDiv::DIV1, + mul: PllMul::MUL10, + divp: None, + divq: None, + divr: Some(PllRDiv::DIV2), // sysclk 80Mhz (16 / 1 * 10 / 2) + }); + config.rcc.mux.clk48sel = mux::Clk48sel::HSI48; + } let p = embassy_stm32::init(config); // Create the driver, from the HAL. let mut ep_out_buffer = [0u8; 256]; - let mut config = embassy_stm32::usb_otg::Config::default(); + let mut config = embassy_stm32::usb::Config::default(); config.vbus_detection = true; let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); @@ -58,7 +60,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -68,7 +69,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32l5/src/bin/usb_ethernet.rs b/examples/stm32l5/src/bin/usb_ethernet.rs index f6d8b16d0..7f73fd677 100644 --- a/examples/stm32l5/src/bin/usb_ethernet.rs +++ b/examples/stm32l5/src/bin/usb_ethernet.rs @@ -5,7 +5,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_net::tcp::TcpSocket; use embassy_net::{Stack, StackResources}; -use embassy_stm32::rcc::*; use embassy_stm32::rng::Rng; use embassy_stm32::usb::Driver; use embassy_stm32::{bind_interrupts, peripherals, rng, usb, Config}; @@ -44,17 +43,22 @@ async fn net_task(stack: &'static Stack>) -> ! { #[embassy_executor::main] async fn main(spawner: Spawner) { let mut config = Config::default(); - config.rcc.hsi = true; - config.rcc.sys = Sysclk::PLL1_R; - config.rcc.pll = Some(Pll { - // 80Mhz clock (16 / 1 * 10 / 2) - source: PllSource::HSI, - prediv: PllPreDiv::DIV1, - mul: PllMul::MUL10, - divp: None, - divq: None, - divr: Some(PllRDiv::DIV2), - }); + { + use embassy_stm32::rcc::*; + config.rcc.hsi = true; + config.rcc.sys = Sysclk::PLL1_R; + config.rcc.pll = Some(Pll { + // 80Mhz clock (16 / 1 * 10 / 2) + source: PllSource::HSI, + prediv: PllPreDiv::DIV1, + mul: PllMul::MUL10, + divp: None, + divq: None, + divr: Some(PllRDiv::DIV2), + }); + config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB + config.rcc.mux.clk48sel = mux::Clk48sel::HSI48; + } let p = embassy_stm32::init(config); // Create the driver, from the HAL. @@ -75,14 +79,12 @@ async fn main(spawner: Spawner) { config.device_protocol = 0x01; // Create embassy-usb DeviceBuilder using the driver and config. - static DEVICE_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static CONFIG_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static BOS_DESC: StaticCell<[u8; 256]> = StaticCell::new(); static CONTROL_BUF: StaticCell<[u8; 128]> = StaticCell::new(); let mut builder = Builder::new( driver, config, - &mut DEVICE_DESC.init([0; 256])[..], &mut CONFIG_DESC.init([0; 256])[..], &mut BOS_DESC.init([0; 256])[..], &mut [], // no msos descriptors diff --git a/examples/stm32l5/src/bin/usb_hid_mouse.rs b/examples/stm32l5/src/bin/usb_hid_mouse.rs index c51ed96e0..9d30205bb 100644 --- a/examples/stm32l5/src/bin/usb_hid_mouse.rs +++ b/examples/stm32l5/src/bin/usb_hid_mouse.rs @@ -4,7 +4,6 @@ use defmt::*; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_stm32::rcc::*; use embassy_stm32::usb::Driver; use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_time::Timer; @@ -21,17 +20,22 @@ bind_interrupts!(struct Irqs { #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = Config::default(); - config.rcc.hsi = true; - config.rcc.sys = Sysclk::PLL1_R; - config.rcc.pll = Some(Pll { - // 80Mhz clock (16 / 1 * 10 / 2) - source: PllSource::HSI, - prediv: PllPreDiv::DIV1, - mul: PllMul::MUL10, - divp: None, - divq: None, - divr: Some(PllRDiv::DIV2), - }); + { + use embassy_stm32::rcc::*; + config.rcc.hsi = true; + config.rcc.sys = Sysclk::PLL1_R; + config.rcc.pll = Some(Pll { + // 80Mhz clock (16 / 1 * 10 / 2) + source: PllSource::HSI, + prediv: PllPreDiv::DIV1, + mul: PllMul::MUL10, + divp: None, + divq: None, + divr: Some(PllRDiv::DIV2), + }); + config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB + config.rcc.mux.clk48sel = mux::Clk48sel::HSI48; + } let p = embassy_stm32::init(config); // Create the driver, from the HAL. @@ -47,7 +51,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -58,7 +61,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32l5/src/bin/usb_serial.rs b/examples/stm32l5/src/bin/usb_serial.rs index 87987f2ce..a64bda31b 100644 --- a/examples/stm32l5/src/bin/usb_serial.rs +++ b/examples/stm32l5/src/bin/usb_serial.rs @@ -4,7 +4,6 @@ use defmt::{panic, *}; use embassy_executor::Spawner; use embassy_futures::join::join; -use embassy_stm32::rcc::*; use embassy_stm32::usb::{Driver, Instance}; use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; @@ -19,17 +18,22 @@ bind_interrupts!(struct Irqs { #[embassy_executor::main] async fn main(_spawner: Spawner) { let mut config = Config::default(); - config.rcc.hsi = true; - config.rcc.sys = Sysclk::PLL1_R; - config.rcc.pll = Some(Pll { - // 80Mhz clock (16 / 1 * 10 / 2) - source: PllSource::HSI, - prediv: PllPreDiv::DIV1, - mul: PllMul::MUL10, - divp: None, - divq: None, - divr: Some(PllRDiv::DIV2), - }); + { + use embassy_stm32::rcc::*; + config.rcc.hsi = true; + config.rcc.sys = Sysclk::PLL1_R; + config.rcc.pll = Some(Pll { + // 80Mhz clock (16 / 1 * 10 / 2) + source: PllSource::HSI, + prediv: PllPreDiv::DIV1, + mul: PllMul::MUL10, + divp: None, + divq: None, + divr: Some(PllRDiv::DIV2), + }); + config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB + config.rcc.mux.clk48sel = mux::Clk48sel::HSI48; + } let p = embassy_stm32::init(config); info!("Hello World!"); @@ -43,7 +47,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 7]; @@ -53,7 +56,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/examples/stm32u5/src/bin/usb_serial.rs b/examples/stm32u5/src/bin/usb_serial.rs index 61851e5a2..6a313efb0 100644 --- a/examples/stm32u5/src/bin/usb_serial.rs +++ b/examples/stm32u5/src/bin/usb_serial.rs @@ -4,8 +4,8 @@ use defmt::{panic, *}; use defmt_rtt as _; // global logger use embassy_executor::Spawner; -use embassy_stm32::usb_otg::{Driver, Instance}; -use embassy_stm32::{bind_interrupts, peripherals, usb_otg, Config}; +use embassy_stm32::usb::{Driver, Instance}; +use embassy_stm32::{bind_interrupts, peripherals, usb, Config}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::driver::EndpointError; use embassy_usb::Builder; @@ -13,7 +13,7 @@ use futures::future::join; use panic_probe as _; bind_interrupts!(struct Irqs { - OTG_FS => usb_otg::InterruptHandler; + OTG_FS => usb::InterruptHandler; }); #[embassy_executor::main] @@ -35,13 +35,14 @@ async fn main(_spawner: Spawner) { config.rcc.sys = Sysclk::PLL1_R; config.rcc.voltage_range = VoltageScale::RANGE1; config.rcc.hsi48 = Some(Hsi48Config { sync_from_usb: true }); // needed for USB + config.rcc.mux.iclksel = mux::Iclksel::HSI48; // USB uses ICLK } let p = embassy_stm32::init(config); // Create the driver, from the HAL. let mut ep_out_buffer = [0u8; 256]; - let mut config = embassy_stm32::usb_otg::Config::default(); + let mut config = embassy_stm32::usb::Config::default(); config.vbus_detection = false; let driver = Driver::new_fs(p.USB_OTG_FS, Irqs, p.PA12, p.PA11, &mut ep_out_buffer, config); @@ -60,7 +61,6 @@ async fn main(_spawner: Spawner) { // Create embassy-usb DeviceBuilder using the driver and config. // It needs some buffers for building the descriptors. - let mut device_descriptor = [0; 256]; let mut config_descriptor = [0; 256]; let mut bos_descriptor = [0; 256]; let mut control_buf = [0; 64]; @@ -70,7 +70,6 @@ async fn main(_spawner: Spawner) { let mut builder = Builder::new( driver, config, - &mut device_descriptor, &mut config_descriptor, &mut bos_descriptor, &mut [], // no msos descriptors diff --git a/rust-toolchain-nightly.toml b/rust-toolchain-nightly.toml index b8a7db353..98696fd2b 100644 --- a/rust-toolchain-nightly.toml +++ b/rust-toolchain-nightly.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "nightly-2023-12-20" +channel = "nightly-2024-03-20" components = [ "rust-src", "rustfmt", "llvm-tools", "miri" ] targets = [ "thumbv7em-none-eabi", diff --git a/rust-toolchain.toml b/rust-toolchain.toml index a6fe52ee2..2f5d17069 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,5 +1,5 @@ [toolchain] -channel = "1.75" +channel = "1.77" components = [ "rust-src", "rustfmt", "llvm-tools" ] targets = [ "thumbv7em-none-eabi", diff --git a/tests/rp/src/bin/gpio_multicore.rs b/tests/rp/src/bin/gpio_multicore.rs index 8aed9b80c..e9c6f3122 100644 --- a/tests/rp/src/bin/gpio_multicore.rs +++ b/tests/rp/src/bin/gpio_multicore.rs @@ -21,10 +21,14 @@ static CHANNEL1: Channel = Channel::new(); #[cortex_m_rt::entry] fn main() -> ! { let p = embassy_rp::init(Default::default()); - spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { - let executor1 = EXECUTOR1.init(Executor::new()); - executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1)))); - }); + spawn_core1( + p.CORE1, + unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, + move || { + let executor1 = EXECUTOR1.init(Executor::new()); + executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1)))); + }, + ); let executor0 = EXECUTOR0.init(Executor::new()); executor0.run(|spawner| unwrap!(spawner.spawn(core0_task(p.PIN_0)))); } diff --git a/tests/rp/src/bin/i2c.rs b/tests/rp/src/bin/i2c.rs index 153b37999..9615007bd 100644 --- a/tests/rp/src/bin/i2c.rs +++ b/tests/rp/src/bin/i2c.rs @@ -210,10 +210,14 @@ async fn controller_task(con: &mut i2c::I2c<'static, I2C0, i2c::Async>) { config.addr = DEV_ADDR as u16; let device = i2c_slave::I2cSlave::new(p.I2C1, d_sda, d_scl, Irqs, config); - spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { - let executor1 = EXECUTOR1.init(Executor::new()); - executor1.run(|spawner| unwrap!(spawner.spawn(device_task(device)))); - }); + spawn_core1( + p.CORE1, + unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, + move || { + let executor1 = EXECUTOR1.init(Executor::new()); + executor1.run(|spawner| unwrap!(spawner.spawn(device_task(device)))); + }, + ); let c_sda = p.PIN_21; let c_scl = p.PIN_20; diff --git a/tests/rp/src/bin/multicore.rs b/tests/rp/src/bin/multicore.rs index 60d9f85ec..783ea0f27 100644 --- a/tests/rp/src/bin/multicore.rs +++ b/tests/rp/src/bin/multicore.rs @@ -19,10 +19,14 @@ static CHANNEL1: Channel = Channel::new(); #[cortex_m_rt::entry] fn main() -> ! { let p = embassy_rp::init(Default::default()); - spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { - let executor1 = EXECUTOR1.init(Executor::new()); - executor1.run(|spawner| unwrap!(spawner.spawn(core1_task()))); - }); + spawn_core1( + p.CORE1, + unsafe { &mut *core::ptr::addr_of_mut!(CORE1_STACK) }, + move || { + let executor1 = EXECUTOR1.init(Executor::new()); + executor1.run(|spawner| unwrap!(spawner.spawn(core1_task()))); + }, + ); let executor0 = EXECUTOR0.init(Executor::new()); executor0.run(|spawner| unwrap!(spawner.spawn(core0_task()))); }