mirror of
https://github.com/embassy-rs/embassy.git
synced 2024-11-21 22:32:29 +00:00
Merge pull request #2730 from embassy-rs/stm32-sealed
stm32: use private_bounds for sealed traits.
This commit is contained in:
commit
1171e11655
1
ci.sh
1
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 \
|
||||
|
@ -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
|
||||
}
|
||||
@ -1486,7 +1486,7 @@ fn main() {
|
||||
#[crate::interrupt]
|
||||
unsafe fn #irq () {
|
||||
#(
|
||||
<crate::peripherals::#channels as crate::dma::sealed::ChannelInterrupt>::on_irq();
|
||||
<crate::peripherals::#channels as crate::dma::ChannelInterrupt>::on_irq();
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
|
||||
|
||||
pub struct Vref;
|
||||
impl<T: Instance> AdcPin<T> for Vref {}
|
||||
impl<T: Instance> super::sealed::AdcPin<T> for Vref {
|
||||
impl<T: Instance> super::SealedAdcPin<T> for Vref {
|
||||
fn channel(&self) -> u8 {
|
||||
17
|
||||
}
|
||||
@ -41,7 +41,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for Vref {
|
||||
|
||||
pub struct Temperature;
|
||||
impl<T: Instance> AdcPin<T> for Temperature {}
|
||||
impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
|
||||
impl<T: Instance> super::SealedAdcPin<T> for Temperature {
|
||||
fn channel(&self) -> u8 {
|
||||
16
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
|
||||
|
||||
pub struct Vref;
|
||||
impl<T: Instance> AdcPin<T> for Vref {}
|
||||
impl<T: Instance> super::sealed::AdcPin<T> for Vref {
|
||||
impl<T: Instance> super::SealedAdcPin<T> for Vref {
|
||||
fn channel(&self) -> u8 {
|
||||
18
|
||||
}
|
||||
@ -48,7 +48,7 @@ impl Vref {
|
||||
|
||||
pub struct Temperature;
|
||||
impl<T: Instance> AdcPin<T> for Temperature {}
|
||||
impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
|
||||
impl<T: Instance> super::SealedAdcPin<T> for Temperature {
|
||||
fn channel(&self) -> u8 {
|
||||
16
|
||||
}
|
||||
@ -102,7 +102,7 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||
}
|
||||
|
||||
fn freq() -> Hertz {
|
||||
<T as crate::rcc::sealed::RccPeripheral>::frequency()
|
||||
<T as crate::rcc::SealedRccPeripheral>::frequency()
|
||||
}
|
||||
|
||||
pub fn sample_time_for_us(&self, us: u32) -> SampleTime {
|
||||
|
@ -65,7 +65,7 @@ fn update_vref<T: Instance>(op: i8) {
|
||||
|
||||
pub struct Vref<T: Instance>(core::marker::PhantomData<T>);
|
||||
impl<T: Instance> AdcPin<T> for Vref<T> {}
|
||||
impl<T: Instance> super::sealed::AdcPin<T> for Vref<T> {
|
||||
impl<T: Instance> super::SealedAdcPin<T> for Vref<T> {
|
||||
fn channel(&self) -> u8 {
|
||||
17
|
||||
}
|
||||
@ -124,7 +124,7 @@ impl<T: Instance> Drop for Vref<T> {
|
||||
|
||||
pub struct Temperature<T: Instance>(core::marker::PhantomData<T>);
|
||||
impl<T: Instance> AdcPin<T> for Temperature<T> {}
|
||||
impl<T: Instance> super::sealed::AdcPin<T> for Temperature<T> {
|
||||
impl<T: Instance> super::SealedAdcPin<T> for Temperature<T> {
|
||||
fn channel(&self) -> u8 {
|
||||
16
|
||||
}
|
||||
|
@ -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<T: Instance> {
|
||||
#[cfg(any(adc_v1, adc_l0, adc_v2))]
|
||||
fn set_as_analog(&mut self) {}
|
||||
|
||||
pub trait AdcPin<T: Instance> {
|
||||
#[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<T> {
|
||||
fn channel(&self) -> u8;
|
||||
}
|
||||
trait SealedInternalChannel<T> {
|
||||
#[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<P = Self> {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + crate::Peripheral<P = Self> {
|
||||
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<P = Self> + crate::rcc::RccPeripheral {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {
|
||||
type Interrupt: crate::interrupt::typelevel::Interrupt;
|
||||
}
|
||||
|
||||
/// ADC pin.
|
||||
pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait AdcPin<T: Instance>: SealedAdcPin<T> {}
|
||||
/// ADC internal channel.
|
||||
pub trait InternalChannel<T>: sealed::InternalChannel<T> {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait InternalChannel<T>: SealedInternalChannel<T> {}
|
||||
|
||||
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<peripherals::$inst> for crate::peripherals::$pin {}
|
||||
|
||||
impl crate::adc::sealed::AdcPin<peripherals::$inst> for crate::peripherals::$pin {
|
||||
impl crate::adc::SealedAdcPin<peripherals::$inst> for crate::peripherals::$pin {
|
||||
#[cfg(any(adc_v1, adc_l0, adc_v2))]
|
||||
fn set_as_analog(&mut self) {
|
||||
<Self as crate::gpio::sealed::Pin>::set_as_analog(self);
|
||||
<Self as crate::gpio::SealedPin>::set_as_analog(self);
|
||||
}
|
||||
|
||||
fn channel(&self) -> u8 {
|
||||
|
@ -39,7 +39,7 @@ pub struct Vbat;
|
||||
impl AdcPin<ADC> for Vbat {}
|
||||
|
||||
#[cfg(not(adc_l0))]
|
||||
impl super::sealed::AdcPin<ADC> for Vbat {
|
||||
impl super::SealedAdcPin<ADC> for Vbat {
|
||||
fn channel(&self) -> u8 {
|
||||
18
|
||||
}
|
||||
@ -47,7 +47,7 @@ impl super::sealed::AdcPin<ADC> for Vbat {
|
||||
|
||||
pub struct Vref;
|
||||
impl AdcPin<ADC> for Vref {}
|
||||
impl super::sealed::AdcPin<ADC> for Vref {
|
||||
impl super::SealedAdcPin<ADC> for Vref {
|
||||
fn channel(&self) -> u8 {
|
||||
17
|
||||
}
|
||||
@ -55,7 +55,7 @@ impl super::sealed::AdcPin<ADC> for Vref {
|
||||
|
||||
pub struct Temperature;
|
||||
impl AdcPin<ADC> for Temperature {}
|
||||
impl super::sealed::AdcPin<ADC> for Temperature {
|
||||
impl super::SealedAdcPin<ADC> for Temperature {
|
||||
fn channel(&self) -> u8 {
|
||||
16
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ pub const ADC_POWERUP_TIME_US: u32 = 3;
|
||||
|
||||
pub struct VrefInt;
|
||||
impl AdcPin<ADC1> for VrefInt {}
|
||||
impl super::sealed::AdcPin<ADC1> for VrefInt {
|
||||
impl super::SealedAdcPin<ADC1> for VrefInt {
|
||||
fn channel(&self) -> u8 {
|
||||
17
|
||||
}
|
||||
@ -31,7 +31,7 @@ impl VrefInt {
|
||||
|
||||
pub struct Temperature;
|
||||
impl AdcPin<ADC1> for Temperature {}
|
||||
impl super::sealed::AdcPin<ADC1> for Temperature {
|
||||
impl super::SealedAdcPin<ADC1> 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<ADC1> for Vbat {}
|
||||
impl super::sealed::AdcPin<ADC1> for Vbat {
|
||||
impl super::SealedAdcPin<ADC1> for Vbat {
|
||||
fn channel(&self) -> u8 {
|
||||
18
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ pub const VREF_CALIB_MV: u32 = 3000;
|
||||
|
||||
pub struct VrefInt;
|
||||
impl<T: Instance> AdcPin<T> for VrefInt {}
|
||||
impl<T: Instance> super::sealed::AdcPin<T> for VrefInt {
|
||||
impl<T: Instance> super::SealedAdcPin<T> for VrefInt {
|
||||
fn channel(&self) -> u8 {
|
||||
cfg_if! {
|
||||
if #[cfg(adc_g0)] {
|
||||
@ -29,7 +29,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for VrefInt {
|
||||
|
||||
pub struct Temperature;
|
||||
impl<T: Instance> AdcPin<T> for Temperature {}
|
||||
impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
|
||||
impl<T: Instance> super::SealedAdcPin<T> for Temperature {
|
||||
fn channel(&self) -> u8 {
|
||||
cfg_if! {
|
||||
if #[cfg(adc_g0)] {
|
||||
@ -46,7 +46,7 @@ impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
|
||||
|
||||
pub struct Vbat;
|
||||
impl<T: Instance> AdcPin<T> for Vbat {}
|
||||
impl<T: Instance> super::sealed::AdcPin<T> for Vbat {
|
||||
impl<T: Instance> super::SealedAdcPin<T> 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<T: Instance> AdcPin<T> for VddCore {}
|
||||
impl<T: Instance> super::sealed::AdcPin<T> for VddCore {
|
||||
impl<T: Instance> super::SealedAdcPin<T> for VddCore {
|
||||
fn channel(&self) -> u8 {
|
||||
6
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ const VBAT_CHANNEL: u8 = 17;
|
||||
/// Internal voltage reference channel.
|
||||
pub struct VrefInt;
|
||||
impl<T: Instance> InternalChannel<T> for VrefInt {}
|
||||
impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt {
|
||||
impl<T: Instance> super::SealedInternalChannel<T> for VrefInt {
|
||||
fn channel(&self) -> u8 {
|
||||
VREF_CHANNEL
|
||||
}
|
||||
@ -44,7 +44,7 @@ impl<T: Instance> super::sealed::InternalChannel<T> for VrefInt {
|
||||
/// Internal temperature channel.
|
||||
pub struct Temperature;
|
||||
impl<T: Instance> InternalChannel<T> for Temperature {}
|
||||
impl<T: Instance> super::sealed::InternalChannel<T> for Temperature {
|
||||
impl<T: Instance> super::SealedInternalChannel<T> for Temperature {
|
||||
fn channel(&self) -> u8 {
|
||||
TEMP_CHANNEL
|
||||
}
|
||||
@ -53,7 +53,7 @@ impl<T: Instance> super::sealed::InternalChannel<T> for Temperature {
|
||||
/// Internal battery voltage channel.
|
||||
pub struct Vbat;
|
||||
impl<T: Instance> InternalChannel<T> for Vbat {}
|
||||
impl<T: Instance> super::sealed::InternalChannel<T> for Vbat {
|
||||
impl<T: Instance> super::SealedInternalChannel<T> for Vbat {
|
||||
fn channel(&self) -> u8 {
|
||||
VBAT_CHANNEL
|
||||
}
|
||||
@ -276,7 +276,7 @@ impl<'d, T: Instance> Adc<'d, T> {
|
||||
pub fn read<P>(&mut self, pin: &mut P) -> u16
|
||||
where
|
||||
P: AdcPin<T>,
|
||||
P: crate::gpio::sealed::Pin,
|
||||
P: crate::gpio::Pin,
|
||||
{
|
||||
pin.set_as_analog();
|
||||
|
||||
|
@ -7,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;
|
||||
@ -485,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<CriticalSectionRawMutex, Envelope, 32>,
|
||||
}
|
||||
|
||||
use super::Envelope;
|
||||
|
||||
pub struct State {
|
||||
pub tx_waker: AtomicWaker,
|
||||
pub err_waker: AtomicWaker,
|
||||
pub rx_queue: Channel<CriticalSectionRawMutex, Envelope, 32>,
|
||||
}
|
||||
|
||||
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.
|
||||
@ -533,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
|
||||
}
|
||||
}
|
||||
|
@ -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 <http://www.bittiming.can-wiki.info/> 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 {
|
||||
|
@ -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<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> 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<T: Instance> interrupt::typelevel::Handler<T::IT0Interrupt> 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<T: Instance>(&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::<T, _>() {
|
||||
let _ = buf.rx_sender.try_send(result);
|
||||
}
|
||||
}
|
||||
RxMode::FdBuffered(buf) => {
|
||||
if let Some(result) = self.read::<T, _>() {
|
||||
let _ = buf.rx_sender.try_send(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read<T: Instance, F: CanHeader>(&self) -> Option<Result<(F, Timestamp), BusError>> {
|
||||
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<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> {
|
||||
poll_fn(|cx| {
|
||||
T::state().err_waker.register(cx.waker());
|
||||
self.register(cx.waker());
|
||||
match self.read::<T, _>() {
|
||||
Some(result) => Poll::Ready(result),
|
||||
None => Poll::Pending,
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> {
|
||||
self.read_async::<T, _>().await
|
||||
}
|
||||
|
||||
pub async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> {
|
||||
self.read_async::<T, _>().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<T: Instance, F: embedded_can::Frame + CanHeader>(&self, frame: &F) -> Option<F> {
|
||||
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<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> {
|
||||
self.write_generic::<T, _>(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<T: Instance>(&self, frame: &FdFrame) -> Option<FdFrame> {
|
||||
self.write_generic::<T, _>(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<T: Instance>(&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::<T, _>() {
|
||||
let _ = buf.rx_sender.try_send(result);
|
||||
}
|
||||
}
|
||||
RxMode::FdBuffered(buf) => {
|
||||
if let Some(result) = self.read::<T, _>() {
|
||||
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<T: Instance, F: CanHeader>(&self) -> Option<Result<(F, Timestamp), BusError>> {
|
||||
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<T: Instance, F: CanHeader>(&self) -> Result<(F, Timestamp), BusError> {
|
||||
poll_fn(|cx| {
|
||||
T::state().err_waker.register(cx.waker());
|
||||
self.register(cx.waker());
|
||||
match self.read::<T, _>() {
|
||||
Some(result) => Poll::Ready(result),
|
||||
None => Poll::Pending,
|
||||
}
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
async fn read_classic<T: Instance>(&self) -> Result<(ClassicFrame, Timestamp), BusError> {
|
||||
self.read_async::<T, _>().await
|
||||
}
|
||||
|
||||
async fn read_fd<T: Instance>(&self) -> Result<(FdFrame, Timestamp), BusError> {
|
||||
self.read_async::<T, _>().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<T: Instance, F: embedded_can::Frame + CanHeader>(&self, frame: &F) -> Option<F> {
|
||||
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<T: Instance>(&self, frame: &ClassicFrame) -> Option<ClassicFrame> {
|
||||
self.write_generic::<T, _>(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<T: Instance>(&self, frame: &FdFrame) -> Option<FdFrame> {
|
||||
self.write_generic::<T, _>(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 sealed::State {
|
||||
static mut STATE: sealed::State = sealed::State::new();
|
||||
unsafe fn mut_state() -> &'static mut State {
|
||||
static mut STATE: State = State::new();
|
||||
&mut *core::ptr::addr_of_mut!(STATE)
|
||||
}
|
||||
fn state() -> &'static sealed::State {
|
||||
fn state() -> &'static State {
|
||||
unsafe { peripherals::$inst::mut_state() }
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + Peripheral<P = Self> + 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
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ impl<'d, T: Instance, const N: u8, DMA> DacChannel<'d, T, N, DMA> {
|
||||
pub fn new(
|
||||
_peri: impl Peripheral<P = T> + 'd,
|
||||
dma: impl Peripheral<P = DMA> + 'd,
|
||||
pin: impl Peripheral<P = impl DacPin<T, N> + crate::gpio::sealed::Pin> + 'd,
|
||||
pin: impl Peripheral<P = impl DacPin<T, N> + 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<P = T> + 'd,
|
||||
dma_ch1: impl Peripheral<P = DMACh1> + 'd,
|
||||
dma_ch2: impl Peripheral<P = DMACh2> + 'd,
|
||||
pin_ch1: impl Peripheral<P = impl DacPin<T, 1> + crate::gpio::sealed::Pin> + 'd,
|
||||
pin_ch2: impl Peripheral<P = impl DacPin<T, 2> + crate::gpio::sealed::Pin> + 'd,
|
||||
pin_ch1: impl Peripheral<P = impl DacPin<T, 1> + crate::gpio::Pin> + 'd,
|
||||
pin_ch2: impl Peripheral<P = impl DacPin<T, 2> + 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<T: Instance, const C: u8>: 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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -39,18 +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 {
|
||||
#[cfg_attr(not(feature = "rt"), allow(unused))]
|
||||
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<P = Self> + Into<AnyChannel> + 'static {
|
||||
#[allow(private_bounds)]
|
||||
pub trait Channel: SealedChannel + Peripheral<P = Self> + Into<AnyChannel> + 'static {
|
||||
/// Type-erase (degrade) this pin into an `AnyChannel`.
|
||||
///
|
||||
/// This converts DMA channel singletons (`DMA1_CH3`, `DMA2_CH1`, ...), which
|
||||
@ -64,12 +64,12 @@ pub trait Channel: sealed::Channel + Peripheral<P = Self> + Into<AnyChannel> + '
|
||||
|
||||
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();
|
||||
}
|
||||
@ -97,7 +97,7 @@ impl AnyChannel {
|
||||
}
|
||||
}
|
||||
|
||||
impl sealed::Channel for AnyChannel {
|
||||
impl SealedChannel for AnyChannel {
|
||||
fn id(&self) -> u8 {
|
||||
self.id
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -177,16 +177,15 @@ pub unsafe trait PHY {
|
||||
fn poll_link<S: StationManagement>(&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
|
||||
}
|
||||
|
@ -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 = <T as RccPeripheral>::frequency();
|
||||
let hclk = <T as SealedRccPeripheral>::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<T: Instance> {
|
||||
|
||||
unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
|
||||
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<T: Instance> StationManagement for EthernetStationManagement<T> {
|
||||
}
|
||||
|
||||
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<T: Instance> StationManagement for EthernetStationManagement<T> {
|
||||
|
||||
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));
|
||||
|
@ -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 = <T as RccPeripheral>::frequency();
|
||||
let hclk = <T as SealedRccPeripheral>::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<T: Instance> {
|
||||
|
||||
unsafe impl<T: Instance> StationManagement for EthernetStationManagement<T> {
|
||||
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<T: Instance> StationManagement for EthernetStationManagement<T> {
|
||||
}
|
||||
|
||||
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<T: Instance> StationManagement for EthernetStationManagement<T> {
|
||||
|
||||
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));
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
<T as crate::rcc::sealed::RccPeripheral>::frequency().0
|
||||
<T as crate::rcc::SealedRccPeripheral>::frequency().0
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,7 +68,7 @@ where
|
||||
}
|
||||
|
||||
fn source_clock_hz(&self) -> u32 {
|
||||
<T as crate::rcc::sealed::RccPeripheral>::frequency().0
|
||||
<T as crate::rcc::SealedRccPeripheral>::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 {}
|
||||
|
@ -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<OutputType> for sealed::AFType {
|
||||
impl From<OutputType> 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<P = Self> + Into<AnyPin> + sealed::Pin + Sized + 'static {
|
||||
#[allow(private_bounds)]
|
||||
pub trait Pin: Peripheral<P = Self> + Into<AnyPin> + 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)]
|
||||
<crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable_and_reset_with_cs(_cs);
|
||||
<crate::peripherals::AFIO as crate::rcc::SealedRccPeripheral>::enable_and_reset_with_cs(_cs);
|
||||
|
||||
crate::_generated::init_gpio();
|
||||
|
||||
@ -1061,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::*;
|
||||
}
|
||||
|
@ -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<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + Peripheral<P = Self> + 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
|
||||
}
|
||||
|
@ -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<T: Instance> {
|
||||
phantom: PhantomData<T>,
|
||||
}
|
||||
|
||||
mod sealed {
|
||||
use super::Instance;
|
||||
|
||||
pub trait AdvancedChannel<T: Instance> {
|
||||
fn raw() -> usize;
|
||||
}
|
||||
trait SealedAdvancedChannel<T: Instance> {
|
||||
fn raw() -> usize;
|
||||
}
|
||||
|
||||
/// Advanced channel instance trait.
|
||||
pub trait AdvancedChannel<T: Instance>: sealed::AdvancedChannel<T> {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait AdvancedChannel<T: Instance>: SealedAdvancedChannel<T> {}
|
||||
|
||||
/// HRTIM PWM pin.
|
||||
pub struct PwmPin<'d, T, C> {
|
||||
@ -113,7 +108,7 @@ macro_rules! advanced_channel_impl {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Instance> sealed::AdvancedChannel<T> for $channel<T> {
|
||||
impl<T: Instance> SealedAdvancedChannel<T> for $channel<T> {
|
||||
fn raw() -> usize {
|
||||
$ch_num
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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<T: Instance> interrupt::typelevel::Handler<T::ErrorInterrupt> 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
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -158,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]
|
||||
|
@ -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<P = impl NonInvertingPin<T> + crate::gpio::sealed::Pin>,
|
||||
out_pin: impl Peripheral<P = impl OutputPin<T> + crate::gpio::sealed::Pin> + 'd,
|
||||
in_pin: impl Peripheral<P = impl NonInvertingPin<T> + crate::gpio::Pin>,
|
||||
out_pin: impl Peripheral<P = impl OutputPin<T> + 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<P = impl NonInvertingPin<T> + crate::gpio::sealed::Pin>,
|
||||
pin: impl Peripheral<P = impl NonInvertingPin<T> + 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<T: Instance> {
|
||||
fn channel(&self) -> u8;
|
||||
}
|
||||
|
||||
pub trait InvertingPin<T: Instance> {
|
||||
fn channel(&self) -> u8;
|
||||
}
|
||||
|
||||
pub trait OutputPin<T: Instance> {}
|
||||
pub(crate) trait SealedInstance {
|
||||
fn regs() -> crate::pac::opamp::Opamp;
|
||||
}
|
||||
|
||||
pub(crate) trait SealedNonInvertingPin<T: Instance> {
|
||||
fn channel(&self) -> u8;
|
||||
}
|
||||
|
||||
pub(crate) trait SealedInvertingPin<T: Instance> {
|
||||
#[allow(unused)]
|
||||
fn channel(&self) -> u8;
|
||||
}
|
||||
|
||||
pub(crate) trait SealedOutputPin<T: Instance> {}
|
||||
|
||||
/// Opamp instance trait.
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + 'static {}
|
||||
/// Non-inverting pin trait.
|
||||
pub trait NonInvertingPin<T: Instance>: sealed::NonInvertingPin<T> {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait NonInvertingPin<T: Instance>: SealedNonInvertingPin<T> {}
|
||||
/// Inverting pin trait.
|
||||
pub trait InvertingPin<T: Instance>: sealed::InvertingPin<T> {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait InvertingPin<T: Instance>: SealedInvertingPin<T> {}
|
||||
/// Output pin trait.
|
||||
pub trait OutputPin<T: Instance>: sealed::OutputPin<T> {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait OutputPin<T: Instance>: SealedOutputPin<T> {}
|
||||
|
||||
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<crate::peripherals::$adc>
|
||||
impl<'d> crate::adc::SealedAdcPin<crate::peripherals::$adc>
|
||||
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<crate::peripherals::$adc>
|
||||
impl<'d> crate::adc::SealedAdcPin<crate::peripherals::$adc>
|
||||
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<peripherals::$inst> for crate::peripherals::$pin {}
|
||||
impl crate::opamp::sealed::NonInvertingPin<peripherals::$inst> for crate::peripherals::$pin {
|
||||
impl crate::opamp::SealedNonInvertingPin<peripherals::$inst> 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<peripherals::$inst> for crate::peripherals::$pin {}
|
||||
impl crate::opamp::sealed::OutputPin<peripherals::$inst> for crate::peripherals::$pin {}
|
||||
impl crate::opamp::SealedOutputPin<peripherals::$inst> for crate::peripherals::$pin {}
|
||||
};
|
||||
}
|
||||
|
@ -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<P = Self> + sealed::Instance + RccPeripheral {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: Peripheral<P = Self> + 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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
});
|
||||
|
@ -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<T: RccPeripheral>() -> Hertz {
|
||||
T::frequency()
|
||||
}
|
||||
|
@ -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<P = Self> + crate::rcc::RccPeripheral + 'static + Send {
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + Peripheral<P = Self> + 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
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ 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 {
|
||||
|
@ -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<P = RTC>, rtc_config: RtcConfig) -> Self {
|
||||
#[cfg(not(any(stm32l0, stm32f3, stm32l1, stm32f0, stm32f2)))]
|
||||
<RTC as crate::rcc::sealed::RccPeripheral>::enable_and_reset();
|
||||
<RTC as crate::rcc::SealedRccPeripheral>::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));
|
||||
|
||||
<RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
|
||||
<RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend();
|
||||
});
|
||||
}
|
||||
|
||||
@ -449,8 +448,8 @@ impl Rtc {
|
||||
use crate::interrupt::typelevel::Interrupt;
|
||||
use crate::pac::EXTI;
|
||||
|
||||
<RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::unpend();
|
||||
unsafe { <RTC as crate::rtc::sealed::Instance>::WakeupInterrupt::enable() };
|
||||
<RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend();
|
||||
unsafe { <RTC as crate::rtc::SealedInstance>::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<u32>;
|
||||
|
||||
/// 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<u32>;
|
||||
|
||||
/// 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);
|
||||
}
|
||||
|
@ -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))]
|
||||
|
@ -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))]
|
||||
|
@ -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};
|
||||
@ -1041,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<P = Self> + sealed::Instance + RccPeripheral {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: Peripheral<P = Self> + SealedInstance + RccPeripheral {}
|
||||
|
||||
pin_trait!(SckPin, Instance, SubBlockInstance);
|
||||
pin_trait!(FsPin, Instance, SubBlockInstance);
|
||||
pin_trait!(SdPin, Instance, SubBlockInstance);
|
||||
@ -1087,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;
|
||||
}
|
||||
|
||||
|
@ -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,19 +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;
|
||||
}
|
||||
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);
|
||||
@ -1457,9 +1454,7 @@ impl<T: Instance> SdmmcDma<T> 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
|
||||
}
|
||||
@ -1470,6 +1465,8 @@ foreach_peripheral!(
|
||||
}
|
||||
}
|
||||
|
||||
impl Instance for peripherals::$inst {}
|
||||
impl Instance for peripherals::$inst {
|
||||
type Interrupt = crate::interrupt::typelevel::$inst;
|
||||
}
|
||||
};
|
||||
);
|
||||
|
@ -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 = <peripherals::SUBGHZSPI as crate::rcc::sealed::RccPeripheral>::frequency().0;
|
||||
let pclk3_freq = <peripherals::SUBGHZSPI as crate::rcc::SealedRccPeripheral>::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(<u8 as sealed::Word>::CONFIG)
|
||||
w.set_dff(<u8 as SealedWord>::CONFIG)
|
||||
});
|
||||
}
|
||||
#[cfg(spi_v2)]
|
||||
{
|
||||
T::REGS.cr2().modify(|w| {
|
||||
let (ds, frxth) = <u8 as sealed::Word>::CONFIG;
|
||||
let (ds, frxth) = <u8 as SealedWord>::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(<u8 as sealed::Word>::CONFIG);
|
||||
w.set_dsize(<u8 as SealedWord>::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: <u8 as sealed::Word>::CONFIG,
|
||||
current_word_size: <u8 as SealedWord>::CONFIG,
|
||||
}
|
||||
}
|
||||
|
||||
@ -975,24 +974,21 @@ impl<'d, T: Instance, Tx: TxDma<T>, Rx: RxDma<T>, 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<P = Self> + sealed::Instance + RccPeripheral {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: Peripheral<P = Self> + 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;
|
||||
}
|
||||
|
||||
|
@ -8,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:
|
||||
@ -207,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.
|
||||
//
|
||||
@ -271,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();
|
||||
|
||||
<T as RccPeripheral>::enable_and_reset_with_cs(cs);
|
||||
<T as SealedRccPeripheral>::enable_and_reset_with_cs(cs);
|
||||
|
||||
let timer_freq = T::frequency();
|
||||
|
||||
@ -308,9 +312,9 @@ impl RtcDriver {
|
||||
|
||||
#[cfg(any(time_driver_tim1, time_driver_tim8, time_driver_tim20))]
|
||||
{
|
||||
<T as AdvancedControlInstance>::CaptureCompareInterrupt::unpend();
|
||||
<T as AdvancedInstance1Channel>::CaptureCompareInterrupt::unpend();
|
||||
unsafe {
|
||||
<T as AdvancedControlInstance>::CaptureCompareInterrupt::enable();
|
||||
<T as AdvancedInstance1Channel>::CaptureCompareInterrupt::enable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,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| {
|
||||
@ -349,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;
|
||||
@ -413,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
|
||||
@ -439,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 {
|
||||
@ -496,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(())
|
||||
}
|
||||
@ -506,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;
|
||||
@ -515,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);
|
||||
@ -553,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);
|
||||
|
@ -5,11 +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.
|
||||
@ -22,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<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
|
||||
into_ref!(pin);
|
||||
@ -47,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(
|
||||
@ -71,11 +75,7 @@ impl<'d, T: ComplementaryCaptureCompare16bitInstance> ComplementaryPwm<'d, T> {
|
||||
}
|
||||
|
||||
fn new_inner(tim: impl Peripheral<P = T> + '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);
|
||||
@ -122,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.
|
||||
@ -130,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.
|
||||
@ -148,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;
|
||||
@ -168,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<P>(&mut self, period: P)
|
||||
|
638
embassy-stm32/src/timer/low_level.rs
Normal file
638
embassy-stm32/src/timer/low_level.rs
Normal file
@ -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<InputTISelection> 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<CountingMode> 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_CNT<TIMx_CCRx
|
||||
/// else inactive. In downcounting, channel is inactive (OCxREF=0) as long as
|
||||
/// TIMx_CNT>TIMx_CCRx else active (OCxREF=1).
|
||||
PwmMode1,
|
||||
/// PWM mode 2 - In upcounting, channel is inactive as long as
|
||||
/// TIMx_CNT<TIMx_CCRx else active. In downcounting, channel is active as long as
|
||||
/// TIMx_CNT>TIMx_CCRx else inactive.
|
||||
PwmMode2,
|
||||
// TODO: there's more modes here depending on the chip family.
|
||||
}
|
||||
|
||||
impl From<OutputCompareMode> 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<OutputPolarity> 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<P = T> + '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));
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -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<P = impl $pin_trait<T>> + '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<P = T> + 'd, _ch1: QeiPin<'d, T, Ch1>, _ch2: QeiPin<'d, T, Ch2>) -> Self {
|
||||
Self::new_inner(tim)
|
||||
}
|
||||
|
||||
fn new_inner(tim: impl Peripheral<P = T> + '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()
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,10 @@ 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;
|
||||
|
||||
/// Channel 1 marker type.
|
||||
@ -29,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<P = impl $pin_trait<T>> + 'd, output_type: OutputType) -> Self {
|
||||
into_ref!(pin);
|
||||
@ -54,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<P = T> + 'd,
|
||||
@ -73,15 +73,11 @@ impl<'d, T: CaptureCompare16bitInstance> SimplePwm<'d, T> {
|
||||
}
|
||||
|
||||
fn new_inner(tim: impl Peripheral<P = T> + '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]
|
||||
@ -126,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)
|
||||
}
|
||||
@ -141,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)
|
||||
}
|
||||
|
||||
@ -165,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
|
||||
@ -201,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
|
||||
@ -227,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<P = impl super::$dma_ch<T>>, 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);
|
||||
@ -279,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
|
||||
@ -314,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);
|
||||
|
@ -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<T: Instance> interrupt::typelevel::Handler<T::Interrupt> 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;
|
||||
}
|
||||
};
|
||||
);
|
||||
|
||||
|
@ -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<P = Self> + sealed::BasicInstance + 'static + Send {}
|
||||
#[allow(private_bounds)]
|
||||
pub trait BasicInstance: Peripheral<P = Self> + 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
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ mod _version;
|
||||
pub use _version::*;
|
||||
|
||||
use crate::interrupt::typelevel::Interrupt;
|
||||
use crate::rcc::sealed::RccPeripheral;
|
||||
use crate::rcc::SealedRccPeripheral;
|
||||
|
||||
/// clock, power initialization stuff that's common for USB and OTG.
|
||||
fn common_init<T: Instance>() {
|
||||
@ -65,5 +65,5 @@ fn common_init<T: Instance>() {
|
||||
T::Interrupt::unpend();
|
||||
unsafe { T::Interrupt::enable() };
|
||||
|
||||
<T as RccPeripheral>::enable_and_reset();
|
||||
<T as SealedRccPeripheral>::enable_and_reset();
|
||||
}
|
||||
|
@ -11,11 +11,11 @@ use embassy_usb_driver::{
|
||||
};
|
||||
use futures::future::poll_fn;
|
||||
|
||||
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.
|
||||
@ -809,7 +809,7 @@ impl<'d, T: Instance> Bus<'d, T> {
|
||||
fn disable(&mut self) {
|
||||
T::Interrupt::disable();
|
||||
|
||||
<T as RccPeripheral>::disable();
|
||||
<T as SealedRccPeripheral>::disable();
|
||||
|
||||
#[cfg(stm32l4)]
|
||||
crate::pac::PWR.cr2().modify(|w| w.set_usv(false));
|
||||
@ -1436,19 +1436,18 @@ fn quirk_setup_late_cnak(r: crate::pac::otg::Otg) -> bool {
|
||||
// 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;
|
||||
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<{ super::MAX_EP_COUNT }>;
|
||||
}
|
||||
fn regs() -> crate::pac::otg::Otg;
|
||||
fn state() -> &'static super::State<{ MAX_EP_COUNT }>;
|
||||
}
|
||||
|
||||
/// USB instance trait.
|
||||
pub trait Instance: sealed::Instance + RccPeripheral + 'static {
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + RccPeripheral + 'static {
|
||||
/// Interrupt for this USB instance.
|
||||
type Interrupt: interrupt::typelevel::Interrupt;
|
||||
}
|
||||
@ -1473,7 +1472,7 @@ pin_trait!(UlpiD7Pin, Instance);
|
||||
|
||||
foreach_interrupt!(
|
||||
(USB_OTG_FS, otg, $block:ident, GLOBAL, $irq:ident) => {
|
||||
impl sealed::Instance for crate::peripherals::USB_OTG_FS {
|
||||
impl SealedInstance for crate::peripherals::USB_OTG_FS {
|
||||
const HIGH_SPEED: bool = false;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
@ -1538,7 +1537,7 @@ foreach_interrupt!(
|
||||
};
|
||||
|
||||
(USB_OTG_HS, otg, $block:ident, GLOBAL, $irq:ident) => {
|
||||
impl sealed::Instance for crate::peripherals::USB_OTG_HS {
|
||||
impl SealedInstance for crate::peripherals::USB_OTG_HS {
|
||||
const HIGH_SPEED: bool = true;
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
|
@ -15,7 +15,7 @@ use embassy_usb_driver::{
|
||||
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.
|
||||
@ -277,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.
|
||||
@ -1037,14 +1037,13 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod sealed {
|
||||
pub trait Instance {
|
||||
fn regs() -> crate::pac::usb::Usb;
|
||||
}
|
||||
trait SealedInstance {
|
||||
fn regs() -> crate::pac::usb::Usb;
|
||||
}
|
||||
|
||||
/// USB instance trait.
|
||||
pub trait Instance: sealed::Instance + RccPeripheral + 'static {
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + RccPeripheral + 'static {
|
||||
/// Interrupt for this USB instance.
|
||||
type Interrupt: interrupt::typelevel::Interrupt;
|
||||
}
|
||||
@ -1055,7 +1054,7 @@ pin_trait!(DmPin, Instance);
|
||||
|
||||
foreach_interrupt!(
|
||||
($inst:ident, usb, $block:ident, LP, $irq:ident) => {
|
||||
impl sealed::Instance for crate::peripherals::$inst {
|
||||
impl SealedInstance for crate::peripherals::$inst {
|
||||
fn regs() -> crate::pac::usb::Usb {
|
||||
crate::pac::$inst
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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::<TIM6>());
|
||||
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::<TIM6>().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::<TIM6>(),
|
||||
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::<TIM6>());
|
||||
|
||||
const FREQUENCY: Hertz = Hertz::hz(600);
|
||||
let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32;
|
||||
let reload: u32 = (frequency::<TIM7>().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::<TIM7>(),
|
||||
FREQUENCY,
|
||||
reload,
|
||||
reload as u16,
|
||||
|
@ -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<P = T> + 'd,
|
||||
ch1: impl Peripheral<P = impl Channel1Pin<T>> + 'd,
|
||||
@ -69,25 +73,33 @@ impl<'d, T: CaptureCompare32bitInstance> SimplePwm32<'d, T> {
|
||||
ch4: impl Peripheral<P = impl Channel4Pin<T>> + '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) {
|
||||
<T as embassy_stm32::timer::low_level::GeneralPurpose32bitInstance>::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)
|
||||
}
|
||||
}
|
||||
|
@ -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::<TIM6>());
|
||||
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::<TIM6>().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::<TIM6>(),
|
||||
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::<TIM7>());
|
||||
|
||||
const FREQUENCY: Hertz = Hertz::hz(600);
|
||||
let reload: u32 = (TIM7::frequency().0 / FREQUENCY.0) / data.len() as u32;
|
||||
let reload: u32 = (frequency::<TIM7>().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::<TIM7>(),
|
||||
FREQUENCY,
|
||||
reload,
|
||||
reload as u16,
|
||||
|
Loading…
Reference in New Issue
Block a user