From ce91fb2bfc846570ef543a09396c428d70675245 Mon Sep 17 00:00:00 2001 From: Tyler Gilbert Date: Fri, 29 Sep 2023 20:57:59 -0500 Subject: [PATCH 01/16] Issue #1974 add SAI driver --- embassy-stm32/Cargo.toml | 4 +-- embassy-stm32/build.rs | 11 ++++++++ embassy-stm32/src/lib.rs | 2 ++ embassy-stm32/src/rcc/f4.rs | 54 ++++++++++++++++++++++++++++++++----- 4 files changed, 63 insertions(+), 8 deletions(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 150014af..612a54f2 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -58,7 +58,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7" } +stm32-metapac = "12" vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" @@ -77,7 +77,7 @@ critical-section = { version = "1.1", features = ["std"] } [build-dependencies] proc-macro2 = "1.0.36" quote = "1.0.15" -stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-2b87e34c661e19ff6dc603fabfe7fe99ab7261f7", default-features = false, features = ["metadata"]} +stm32-metapac = { path = "../../stm32-data-generated/stm32-metapac", default-features = false, features = ["metadata"]} [features] default = ["rt"] diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 6c364f7b..1b86dad7 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs @@ -425,6 +425,15 @@ fn main() { (("lpuart", "RTS"), quote!(crate::usart::RtsPin)), (("lpuart", "CK"), quote!(crate::usart::CkPin)), (("lpuart", "DE"), quote!(crate::usart::DePin)), + (("sai", "SCK_A"), quote!(crate::sai::SckAPin)), + (("sai", "SCK_B"), quote!(crate::sai::SckBPin)), + (("sai", "FS_A"), quote!(crate::sai::FsAPin)), + (("sai", "FS_B"), quote!(crate::sai::FsBPin)), + (("sai", "SD_A"), quote!(crate::sai::SdAPin)), + (("sai", "SD_B"), quote!(crate::sai::SdBPin)), + (("sai", "MCLK_A"), quote!(crate::sai::MclkAPin)), + (("sai", "MCLK_B"), quote!(crate::sai::MclkBPin)), + (("sai", "WS"), quote!(crate::sai::WsPin)), (("spi", "SCK"), quote!(crate::spi::SckPin)), (("spi", "MOSI"), quote!(crate::spi::MosiPin)), (("spi", "MISO"), quote!(crate::spi::MisoPin)), @@ -708,6 +717,8 @@ fn main() { (("usart", "TX"), quote!(crate::usart::TxDma)), (("lpuart", "RX"), quote!(crate::usart::RxDma)), (("lpuart", "TX"), quote!(crate::usart::TxDma)), + (("sai", "A"), quote!(crate::sai::DmaA)), + (("sai", "B"), quote!(crate::sai::DmaB)), (("spi", "RX"), quote!(crate::spi::RxDma)), (("spi", "TX"), quote!(crate::spi::TxDma)), (("i2c", "RX"), quote!(crate::i2c::RxDma)), diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs index 8c87ea7d..b5a12859 100644 --- a/embassy-stm32/src/lib.rs +++ b/embassy-stm32/src/lib.rs @@ -55,6 +55,8 @@ pub mod qspi; pub mod rng; #[cfg(all(rtc, not(rtc_v1)))] pub mod rtc; +#[cfg(sai)] +pub mod sai; #[cfg(sdmmc)] pub mod sdmmc; #[cfg(spi)] diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index ee9cb289..72bdbd5d 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -33,6 +33,9 @@ pub struct Config { #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] pub plli2s: Option, + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] + pub pllsai: Option, + pub pll48: bool, pub rtc: Option, } @@ -48,11 +51,9 @@ fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { None } -#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] -fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { +fn calculate_sai_i2s_pll_values(vco_in: u32, max_div: u32, target: Option, ) -> Option<(u32, u32, u32)> { let min_div = 2; - let max_div = 7; - let target = match plli2s { + let target = match target { Some(target) => target, None => return None, }; @@ -76,15 +77,41 @@ fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { }) .min_by_key(|(_, _, _, error)| *error)?; + Some((n, outdiv, output)) +} + +#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] +fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { + let (n, outdiv, output) = calculate_sai_i2s_pll_values(vco_in, 7, plli2s)?; + RCC.plli2scfgr().modify(|w| { w.set_plli2sn(n as u16); w.set_plli2sr(outdiv as u8); + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] + w.set_plli2sq(outdiv as u8); //set sai divider same as i2s }); Some(output) } -fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Option, pll48clk: bool) -> PllResults { +#[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))] +fn setup_sai_pll(vco_in: u32, pllsai: Option) -> Option { + None +} + +#[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] +fn setup_sai_pll(vco_in: u32, pllsai: Option) -> Option { + let (n, outdiv, output) = calculate_sai_i2s_pll_values(vco_in, 15, pllsai)?; + + RCC.pllsaicfgr().modify(|w| { + w.set_pllsain(n as u16); + w.set_pllsaiq(outdiv as u8); + }); + + Some(output) +} + +fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Option, pllsai: Option, pll48clk: bool) -> PllResults { use crate::pac::rcc::vals::{Pllp, Pllsrc}; let sysclk = pllsysclk.unwrap_or(pllsrcclk); @@ -96,6 +123,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Opti pllsysclk: None, pll48clk: None, plli2sclk: None, + pllsaiclk: None, }; } // Input divisor from PLL source clock, must result to frequency in @@ -146,6 +174,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Opti w.set_pllp(Pllp::from_bits(pllp as u8)); w.set_pllq(pllq as u8); w.set_pllsrc(Pllsrc::from_bits(use_hse as u8)); + w.set_pllr(0); }); let real_pllsysclk = vco_in * plln / sysclk_div; @@ -155,6 +184,7 @@ fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Opti pllsysclk: Some(real_pllsysclk), pll48clk: if pll48clk { Some(real_pll48clk) } else { None }, plli2sclk: setup_i2s_pll(vco_in, plli2s), + pllsaiclk: setup_sai_pll(vco_in, pllsai), } } @@ -344,6 +374,10 @@ pub(crate) unsafe fn init(config: Config) { config.plli2s.map(|i2s| i2s.0), #[cfg(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] None, + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] + config.pllsai.map(|sai| sai.0), + #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))] + None, config.pll48, ); @@ -441,6 +475,12 @@ pub(crate) unsafe fn init(config: Config) { while !RCC.cr().read().plli2srdy() {} } + #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] + if plls.pllsaiclk.is_some() { + RCC.cr().modify(|w| w.set_pllsaion(true)); + while !RCC.cr().read().pllsairdy() {} + } + RCC.cfgr().modify(|w| { w.set_ppre2(Ppre::from_bits(ppre2_bits)); w.set_ppre1(Ppre::from_bits(ppre1_bits)); @@ -496,7 +536,7 @@ pub(crate) unsafe fn init(config: Config) { plli2s: plls.plli2sclk.map(Hertz), #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] - pllsai: None, + pllsai: plls.pllsaiclk.map(Hertz), rtc: rtc, }); @@ -508,6 +548,8 @@ struct PllResults { pll48clk: Option, #[allow(dead_code)] plli2sclk: Option, + #[allow(dead_code)] + pllsaiclk: Option, } mod max { From a35d149cb151d53fd95b5073cef927116b34fe0d Mon Sep 17 00:00:00 2001 From: Tyler Date: Fri, 29 Sep 2023 21:07:09 -0500 Subject: [PATCH 02/16] Revert metapac change in Cargo.toml --- embassy-stm32/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index b3b3cd81..1ef92430 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml @@ -59,7 +59,7 @@ sdio-host = "0.5.0" embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } critical-section = "1.1" atomic-polyfill = "1.0.1" -stm32-metapac = "12" +stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-735cab337aad6161f3d6bcf3e49cd1f034bc3130" } vcell = "0.1.3" bxcan = "0.7.0" nb = "1.0.0" From 92df87781d6a0f0e85753d3d58c6594846bb2f0b Mon Sep 17 00:00:00 2001 From: Tyler Gilbert Date: Fri, 29 Sep 2023 21:08:07 -0500 Subject: [PATCH 03/16] Issue 1974 add sai/mod file --- embassy-stm32/src/sai/mod.rs | 888 +++++++++++++++++++++++++++++++++++ 1 file changed, 888 insertions(+) create mode 100644 embassy-stm32/src/sai/mod.rs diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs new file mode 100644 index 00000000..1fcee226 --- /dev/null +++ b/embassy-stm32/src/sai/mod.rs @@ -0,0 +1,888 @@ +#![macro_use] + +use embassy_embedded_hal::SetConfig; +use embassy_hal_internal::{into_ref, PeripheralRef}; + +use crate::dma::{Channel, ReadableRingBuffer, TransferOptions, WritableRingBuffer}; +use crate::gpio::sealed::{AFType, Pin as _}; +use crate::gpio::AnyPin; +use crate::pac::sai::{vals, Sai as Regs}; +use crate::rcc::RccPeripheral; +use crate::time::Hertz; +use crate::{peripherals, Peripheral}; + +pub use crate::dma::word; + +#[derive(Debug)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Error { + NotATransmitter, + NotAReceiver, +} + +#[derive(Copy, Clone)] +pub enum SyncBlock { + None, + Sai1BlockA, + Sai1BlockB, + Sai2BlockA, + Sai2BlockB, +} + +#[derive(Copy, Clone)] +pub enum SyncIn { + None, + ChannelZero, + ChannelOne, +} + +#[derive(Copy, Clone)] +pub enum Mode { + Master, + Slave, +} + +#[derive(Copy, Clone)] +enum TxRx { + Transmiter, + Receiver, +} + +impl Mode { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + const fn mode(&self, tx_rx: TxRx) -> vals::Mode { + match tx_rx { + TxRx::Transmiter => match self { + Mode::Master => vals::Mode::MASTERTX, + Mode::Slave => vals::Mode::SLAVETX, + }, + TxRx::Receiver => match self { + Mode::Master => vals::Mode::MASTERRX, + Mode::Slave => vals::Mode::SLAVERX, + }, + } + } +} + +#[derive(Copy, Clone)] +pub enum SlotSize { + DataSize, + /// 16 bit data length on 16 bit wide channel + Channel16, + /// 16 bit data length on 32 bit wide channel + Channel32, +} + +impl SlotSize { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn slotsz(&self) -> vals::Slotsz { + match self { + SlotSize::DataSize => vals::Slotsz::DATASIZE, + SlotSize::Channel16 => vals::Slotsz::BIT16, + SlotSize::Channel32 => vals::Slotsz::BIT32, + } + } +} + +#[derive(Copy, Clone)] +pub enum DataSize { + Data8, + Data10, + Data16, + Data20, + Data24, + Data32, +} + +impl DataSize { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn ds(&self) -> vals::Ds { + match self { + DataSize::Data8 => vals::Ds::BIT8, + DataSize::Data10 => vals::Ds::BIT10, + DataSize::Data16 => vals::Ds::BIT16, + DataSize::Data20 => vals::Ds::BIT20, + DataSize::Data24 => vals::Ds::BIT24, + DataSize::Data32 => vals::Ds::BIT32, + } + } +} + +#[derive(Copy, Clone)] +pub enum FifoThreshold { + Empty, + Quarter, + Half, + ThreeQuarters, + Full, +} + +impl FifoThreshold { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn fth(&self) -> vals::Fth { + match self { + FifoThreshold::Empty => vals::Fth::EMPTY, + FifoThreshold::Quarter => vals::Fth::QUARTER1, + FifoThreshold::Half => vals::Fth::QUARTER2, + FifoThreshold::ThreeQuarters => vals::Fth::QUARTER3, + FifoThreshold::Full => vals::Fth::FULL, + } + } +} + +#[derive(Copy, Clone)] +pub enum FifoLevel { + Empty, + FirstQuarter, + SecondQuarter, + ThirdQuarter, + FourthQuarter, + Full, +} + +#[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] +impl From for FifoLevel { + fn from(flvl: vals::Flvl) -> Self { + match flvl { + vals::Flvl::EMPTY => FifoLevel::Empty, + vals::Flvl::QUARTER1 => FifoLevel::FirstQuarter, + vals::Flvl::QUARTER2 => FifoLevel::SecondQuarter, + vals::Flvl::QUARTER3 => FifoLevel::ThirdQuarter, + vals::Flvl::QUARTER4 => FifoLevel::FourthQuarter, + vals::Flvl::FULL => FifoLevel::Full, + _ => FifoLevel::Empty, + } + } +} + +#[derive(Copy, Clone)] +pub enum MuteDetection { + NoMute, + Mute, +} + +#[derive(Copy, Clone)] +pub enum MuteValue { + Zero, + LastValue, +} + +impl MuteValue { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn muteval(&self) -> vals::Muteval { + match self { + MuteValue::Zero => vals::Muteval::SENDZERO, + MuteValue::LastValue => vals::Muteval::SENDLAST, + } + } +} + +#[derive(Copy, Clone)] +pub enum OverUnderStatus { + NoError, + OverUnderRunDetected, +} + +#[derive(Copy, Clone)] +pub enum Protocol { + Free, + Spdif, + Ac97, +} + +impl Protocol { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn prtcfg(&self) -> vals::Prtcfg { + match self { + Protocol::Free => vals::Prtcfg::FREE, + Protocol::Spdif => vals::Prtcfg::SPDIF, + Protocol::Ac97 => vals::Prtcfg::AC97, + } + } +} + +#[derive(Copy, Clone)] +pub enum SyncEnable { + Asynchronous, + /// Syncs with the other A/B sub-block within the SAI unit + Internal, + /// Syncs with a sub-block in the other SAI unit - use set_sync_output() and set_sync_input() + External, +} + +impl SyncEnable { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn syncen(&self) -> vals::Syncen { + match self { + SyncEnable::Asynchronous => vals::Syncen::ASYNCHRONOUS, + SyncEnable::Internal => vals::Syncen::INTERNAL, + SyncEnable::External => vals::Syncen::EXTERNAL, + } + } +} + +#[derive(Copy, Clone, PartialEq)] +pub enum StereoMono { + Stereo, + Mono, +} + +impl StereoMono { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn mono(&self) -> vals::Mono { + match self { + StereoMono::Stereo => vals::Mono::STEREO, + StereoMono::Mono => vals::Mono::MONO, + } + } +} + +#[derive(Copy, Clone)] +pub enum BitOrder { + LsbFirst, + MsbFirst, +} + +impl BitOrder { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn lsbfirst(&self) -> vals::Lsbfirst { + match self { + BitOrder::LsbFirst => vals::Lsbfirst::LSBFIRST, + BitOrder::MsbFirst => vals::Lsbfirst::MSBFIRST, + } + } +} + +#[derive(Copy, Clone)] +pub enum FrameSyncOffset { + /// This is used in modes other than standard I2S phillips mode + OnFirstBit, + /// This is used in standard I2S phillips mode + BeforeFirstBit, +} + +impl FrameSyncOffset { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn fsoff(&self) -> vals::Fsoff { + match self { + FrameSyncOffset::OnFirstBit => vals::Fsoff::ONFIRST, + FrameSyncOffset::BeforeFirstBit => vals::Fsoff::BEFOREFIRST, + } + } +} + +#[derive(Copy, Clone)] +pub enum FrameSyncPolarity { + ActiveLow, + ActiveHigh, +} + +impl FrameSyncPolarity { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn fspol(&self) -> vals::Fspol { + match self { + FrameSyncPolarity::ActiveLow => vals::Fspol::FALLINGEDGE, + FrameSyncPolarity::ActiveHigh => vals::Fspol::RISINGEDGE, + } + } +} + +#[derive(Copy, Clone)] +pub enum FrameSyncDefinition { + StartOfFrame, + ChannelIdentification, +} + +impl FrameSyncDefinition { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn fsdef(&self) -> bool { + match self { + FrameSyncDefinition::StartOfFrame => false, + FrameSyncDefinition::ChannelIdentification => true, + } + } +} + +#[derive(Copy, Clone)] +pub enum ClockStrobe { + Falling, + Rising, +} + +impl ClockStrobe { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn ckstr(&self) -> vals::Ckstr { + match self { + ClockStrobe::Falling => vals::Ckstr::FALLINGEDGE, + ClockStrobe::Rising => vals::Ckstr::RISINGEDGE, + } + } +} + +#[derive(Copy, Clone)] +pub enum ComplementFormat { + OnesComplement, + TwosComplement, +} + +impl ComplementFormat { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn cpl(&self) -> vals::Cpl { + match self { + ComplementFormat::OnesComplement => vals::Cpl::ONESCOMPLEMENT, + ComplementFormat::TwosComplement => vals::Cpl::TWOSCOMPLEMENT, + } + } +} + +#[derive(Copy, Clone)] +pub enum Companding { + None, + MuLaw, + ALaw, +} + +impl Companding { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn comp(&self) -> vals::Comp { + match self { + Companding::None => vals::Comp::NOCOMPANDING, + Companding::MuLaw => vals::Comp::MULAW, + Companding::ALaw => vals::Comp::ALAW, + } + } +} + +#[derive(Copy, Clone)] +pub enum OutputDrive { + OnStart, + Immediately, +} + +impl OutputDrive { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn outdriv(&self) -> vals::Outdriv { + match self { + OutputDrive::OnStart => vals::Outdriv::ONSTART, + OutputDrive::Immediately => vals::Outdriv::IMMEDIATELY, + } + } +} + +#[derive(Copy, Clone, PartialEq)] +pub enum MasterClockDivider { + MasterClockDisabled, + Div1, + Div2, + Div4, + Div6, + Div8, + Div10, + Div12, + Div14, + Div16, + Div18, + Div20, + Div22, + Div24, + Div26, + Div28, + Div30, +} + +impl MasterClockDivider { + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + pub const fn mckdiv(&self) -> u8 { + match self { + MasterClockDivider::MasterClockDisabled => 0, + MasterClockDivider::Div1 => 0, + MasterClockDivider::Div2 => 1, + MasterClockDivider::Div4 => 2, + MasterClockDivider::Div6 => 3, + MasterClockDivider::Div8 => 4, + MasterClockDivider::Div10 => 5, + MasterClockDivider::Div12 => 6, + MasterClockDivider::Div14 => 7, + MasterClockDivider::Div16 => 8, + MasterClockDivider::Div18 => 9, + MasterClockDivider::Div20 => 10, + MasterClockDivider::Div22 => 11, + MasterClockDivider::Div24 => 12, + MasterClockDivider::Div26 => 13, + MasterClockDivider::Div28 => 14, + MasterClockDivider::Div30 => 15, + } + } +} + +/// [`SAI`] configuration. +#[non_exhaustive] +#[derive(Copy, Clone)] +pub struct Config { + pub mode: Mode, + pub sync_enable: SyncEnable, + pub is_sync_output: bool, + pub protocol: Protocol, + pub slot_size: SlotSize, + pub slot_count: word::U4, + pub slot_enable: u16, + pub first_bit_offset: word::U5, + pub data_size: DataSize, + pub stereo_mono: StereoMono, + pub bit_order: BitOrder, + pub frame_sync_offset: FrameSyncOffset, + pub frame_sync_polarity: FrameSyncPolarity, + pub frame_sync_active_level_length: word::U7, + pub frame_sync_definition: FrameSyncDefinition, + pub frame_length: u8, + pub clock_strobe: ClockStrobe, + pub output_drive: OutputDrive, + pub master_clock_divider: MasterClockDivider, + pub is_high_impedenane_on_inactive_slot: bool, + pub fifo_threshold: FifoThreshold, + pub companding: Companding, + pub complement_format: ComplementFormat, + pub mute_value: MuteValue, + pub mute_detection_counter: word::U5, +} + +impl Default for Config { + fn default() -> Self { + Self { + mode: Mode::Master, + is_sync_output: false, + sync_enable: SyncEnable::Asynchronous, + protocol: Protocol::Free, + slot_size: SlotSize::DataSize, + slot_count: word::U4(2), + first_bit_offset: word::U5(0), + slot_enable: 0b11, + data_size: DataSize::Data16, + stereo_mono: StereoMono::Stereo, + bit_order: BitOrder::LsbFirst, + frame_sync_offset: FrameSyncOffset::BeforeFirstBit, + frame_sync_polarity: FrameSyncPolarity::ActiveLow, + frame_sync_active_level_length: word::U7(16), + frame_sync_definition: FrameSyncDefinition::ChannelIdentification, + frame_length: 32, + master_clock_divider: MasterClockDivider::MasterClockDisabled, + clock_strobe: ClockStrobe::Rising, + output_drive: OutputDrive::Immediately, + is_high_impedenane_on_inactive_slot: false, + fifo_threshold: FifoThreshold::ThreeQuarters, + companding: Companding::None, + complement_format: ComplementFormat::TwosComplement, + mute_value: MuteValue::Zero, + mute_detection_counter: word::U5(4), + } + } +} + +impl Config { + pub fn new_i2s() -> Self { + return Default::default(); + } + + pub fn new_msb_first() -> Self { + Self { + bit_order: BitOrder::MsbFirst, + frame_sync_offset: FrameSyncOffset::OnFirstBit, + ..Default::default() + } + } +} + +#[derive(Copy, Clone)] +pub enum SubBlock { + A = 0, + B = 1, +} + +enum RingBuffer<'d, C: Channel, W: word::Word> { + Writable(WritableRingBuffer<'d, C, W>), + Readable(ReadableRingBuffer<'d, C, W>), +} + +#[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] +fn wdr(w: crate::pac::sai::Sai, sub_block: SubBlock) -> *mut W { + let ch = w.ch(sub_block as usize); + ch.dr().as_ptr() as _ +} + +pub struct Sai<'d, T: Instance, C: Channel, W: word::Word> { + _peri: PeripheralRef<'d, T>, + sd: Option>, + fs: Option>, + sck: Option>, + mclk: Option>, + ring_buffer: RingBuffer<'d, C, W>, + sub_block: SubBlock, +} + +impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { + fn get_transmitter_af_types(mode: Mode) -> (AFType, AFType) { + match mode { + Mode::Master => (AFType::OutputPushPull, AFType::OutputPushPull), + Mode::Slave => (AFType::OutputPushPull, AFType::Input), + } + } + + pub fn new_asynchronous_transmitter_with_mclk_a( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + sd: impl Peripheral

> + 'd, + fs: impl Peripheral

> + 'd, + mclk: impl Peripheral

> + 'd, + dma: impl Peripheral

+ 'd, + dma_buf: &'d mut [W], + mut config: Config, + ) -> Self + where + C: Channel + DmaA, + { + into_ref!(mclk); + + mclk.set_as_af(mclk.af_num(), AFType::OutputPushPull); + mclk.set_speed(crate::gpio::Speed::VeryHigh); + + if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { + config.master_clock_divider = MasterClockDivider::Div1; + } + + Self::new_asynchronous_transmitter_a(peri, sck, sd, fs, dma, dma_buf, config) + } + + pub fn new_asynchronous_transmitter_a( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + sd: impl Peripheral

> + 'd, + fs: impl Peripheral

> + 'd, + dma: impl Peripheral

+ 'd, + dma_buf: &'d mut [W], + config: Config, + ) -> Self + where + C: Channel + DmaA, + { + into_ref!(peri, dma, sck, sd, fs); + + let (sd_af_type, ck_af_type) = Self::get_transmitter_af_types(config.mode); + sd.set_as_af(sd.af_num(), sd_af_type); + sd.set_speed(crate::gpio::Speed::VeryHigh); + + sck.set_as_af(sck.af_num(), ck_af_type); + sck.set_speed(crate::gpio::Speed::VeryHigh); + fs.set_as_af(fs.af_num(), ck_af_type); + fs.set_speed(crate::gpio::Speed::VeryHigh); + + let request = dma.request(); + let opts = TransferOptions { + half_transfer_ir: true, + circular: true, + ..Default::default() + }; + + let sub_block = SubBlock::A; + + Self::new_inner( + peri, + sub_block, + Some(sck.map_into()), + None, + Some(sd.map_into()), + Some(fs.map_into()), + RingBuffer::Writable(unsafe { + WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts) + }), + config, + ) + } + + pub fn new_asynchronous_transmitter_with_mclk_b( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + sd: impl Peripheral

> + 'd, + fs: impl Peripheral

> + 'd, + mclk: impl Peripheral

> + 'd, + dma: impl Peripheral

+ 'd, + dma_buf: &'d mut [W], + mut config: Config, + ) -> Self + where + C: Channel + DmaB, + { + into_ref!(mclk); + + mclk.set_as_af(mclk.af_num(), AFType::OutputPushPull); + mclk.set_speed(crate::gpio::Speed::VeryHigh); + + if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { + config.master_clock_divider = MasterClockDivider::Div1; + } + + Self::new_asynchronous_transmitter_b(peri, sck, sd, fs, dma, dma_buf, config) + } + + pub fn new_asynchronous_transmitter_b( + peri: impl Peripheral

+ 'd, + sck: impl Peripheral

> + 'd, + sd: impl Peripheral

> + 'd, + fs: impl Peripheral

> + 'd, + dma: impl Peripheral

+ 'd, + dma_buf: &'d mut [W], + config: Config, + ) -> Self + where + C: Channel + DmaB, + { + into_ref!(dma, peri, sck, sd, fs); + + let (sd_af_type, ck_af_type) = Self::get_transmitter_af_types(config.mode); + + sd.set_as_af(sd.af_num(), sd_af_type); + sd.set_speed(crate::gpio::Speed::VeryHigh); + + sck.set_as_af(sck.af_num(), ck_af_type); + sck.set_speed(crate::gpio::Speed::VeryHigh); + fs.set_as_af(fs.af_num(), ck_af_type); + fs.set_speed(crate::gpio::Speed::VeryHigh); + + let request = dma.request(); + let opts = TransferOptions { + half_transfer_ir: true, + ..Default::default() + }; + + let sub_block = SubBlock::B; + + Self::new_inner( + peri, + sub_block, + Some(sck.map_into()), + None, + Some(sd.map_into()), + Some(fs.map_into()), + RingBuffer::Writable(unsafe { + WritableRingBuffer::new_write(dma, request, wdr(T::REGS, sub_block), dma_buf, opts) + }), + config, + ) + } + + pub fn start(self: &mut Self) { + match self.ring_buffer { + RingBuffer::Writable(ref mut rb) => { + rb.start(); + } + RingBuffer::Readable(ref mut rb) => { + rb.start(); + } + } + } + + fn is_transmitter(ring_buffer: &RingBuffer) -> bool { + match ring_buffer { + RingBuffer::Writable(_) => true, + _ => false, + } + } + + fn new_inner( + peri: impl Peripheral

+ 'd, + sub_block: SubBlock, + sck: Option>, + mclk: Option>, + sd: Option>, + fs: Option>, + ring_buffer: RingBuffer<'d, C, W>, + config: Config, + ) -> Self { + T::enable(); + T::reset(); + + #[cfg(any(sai_v4))] + { + /// Not totally clear from the datasheet if this is right + /// This is only used if using SyncEnable::External + let value: u8 = if T::REGS.as_ptr() == stm32_metapac::SAI1.as_ptr() { + 1 //this is SAI1, so sync with SAI2 + } else { + 0 //this is SAI2, so sync with SAI1 + }; + T::REGS.gcr().modify(|w| { + w.set_syncin(value); + }); + + if config.is_sync_output { + let syncout: u8 = match sub_block { + SubBlock::A => 0b01, + SubBlock::B => 0b10, + }; + T::REGS.gcr().modify(|w| { + w.set_syncout(syncout); + }); + } + } + + #[cfg(any(sai_v1, sai_v2, sai_v3, sai_v4))] + { + let ch = T::REGS.ch(sub_block as usize); + ch.cr1().modify(|w| { + w.set_mode(config.mode.mode(if Self::is_transmitter(&ring_buffer) { + TxRx::Transmiter + } else { + TxRx::Receiver + })); + w.set_prtcfg(config.protocol.prtcfg()); + w.set_ds(config.data_size.ds()); + w.set_lsbfirst(config.bit_order.lsbfirst()); + w.set_ckstr(config.clock_strobe.ckstr()); + w.set_syncen(config.sync_enable.syncen()); + w.set_mono(config.stereo_mono.mono()); + w.set_outdriv(config.output_drive.outdriv()); + w.set_mckdiv(config.master_clock_divider.mckdiv()); + w.set_nodiv( + if config.master_clock_divider == MasterClockDivider::MasterClockDisabled { + vals::Nodiv::NODIV + } else { + vals::Nodiv::MASTERCLOCK + }, + ); + w.set_dmaen(true); + }); + + ch.cr2().modify(|w| { + w.set_fth(config.fifo_threshold.fth()); + w.set_comp(config.companding.comp()); + w.set_cpl(config.complement_format.cpl()); + w.set_muteval(config.mute_value.muteval()); + w.set_mutecnt(config.mute_detection_counter.0 as u8); + w.set_tris(config.is_high_impedenane_on_inactive_slot); + }); + + ch.frcr().modify(|w| { + w.set_fsoff(config.frame_sync_offset.fsoff()); + w.set_fspol(config.frame_sync_polarity.fspol()); + w.set_fsdef(config.frame_sync_definition.fsdef()); + w.set_fsall(config.frame_sync_active_level_length.0 as u8); + w.set_frl(config.frame_length - 1); + }); + + ch.slotr().modify(|w| { + w.set_nbslot(config.slot_count.0 as u8 - 1); + w.set_slotsz(config.slot_size.slotsz()); + w.set_fboff(config.first_bit_offset.0 as u8); + w.set_sloten(vals::Sloten(config.slot_enable as u16)); + }); + + ch.cr1().modify(|w| w.set_saien(true)); + } + + Self { + _peri: peri.into_ref(), + sub_block, + sck, + mclk, + sd, + fs, + ring_buffer, + } + } + + fn flush(&mut self) { + let ch = T::REGS.ch(self.sub_block as usize); + ch.cr1().modify(|w| w.set_saien(false)); + #[cfg(any(sai_v1, sai_v2))] + { + ch.cr2().modify(|w| w.set_fflush(vals::Fflush::FLUSH)); + } + #[cfg(any(sai_v3, sai_v4))] + { + ch.cr2().modify(|w| w.set_fflush(true)); + } + ch.cr1().modify(|w| w.set_saien(true)); + } + + fn set_mute(&mut self, value: bool) { + let ch = T::REGS.ch(self.sub_block as usize); + ch.cr2().modify(|w| w.set_mute(value)); + } + + /// Reconfigures it with the supplied config. + pub fn reconfigure(&mut self, config: Config) {} + + pub fn get_current_config(&self) -> Config { + Config::default() + } + + pub async fn write(&mut self, data: &[W]) -> Result<(), Error> { + match &mut self.ring_buffer { + RingBuffer::Writable(buffer) => { + buffer.write_exact(data).await; + Ok(()) + } + _ => return Err(Error::NotATransmitter), + } + } + + pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> { + match &mut self.ring_buffer { + RingBuffer::Readable(buffer) => { + buffer.read_exact(data).await; + Ok(()) + } + _ => Err(Error::NotAReceiver), + } + } +} + +impl<'d, T: Instance, C: Channel, W: word::Word> Drop for Sai<'d, T, C, W> { + fn drop(&mut self) { + let ch = T::REGS.ch(self.sub_block as usize); + ch.cr1().modify(|w| w.set_saien(false)); + self.fs.as_ref().map(|x| x.set_as_disconnected()); + self.sd.as_ref().map(|x| x.set_as_disconnected()); + self.sck.as_ref().map(|x| x.set_as_disconnected()); + self.mclk.as_ref().map(|x| x.set_as_disconnected()); + } +} + +pub(crate) mod sealed { + use super::*; + + pub trait Instance { + const REGS: Regs; + } +} + +pub trait Word: word::Word {} + +pub trait Instance: Peripheral

+ sealed::Instance + RccPeripheral {} +pin_trait!(SckAPin, Instance); +pin_trait!(SckBPin, Instance); +pin_trait!(FsAPin, Instance); +pin_trait!(FsBPin, Instance); +pin_trait!(SdAPin, Instance); +pin_trait!(SdBPin, Instance); +pin_trait!(MclkAPin, Instance); +pin_trait!(MclkBPin, Instance); + +dma_trait!(DmaA, Instance); +dma_trait!(DmaB, Instance); + +foreach_peripheral!( + (sai, $inst:ident) => { + impl sealed::Instance for peripherals::$inst { + const REGS: Regs = crate::pac::$inst; + } + + impl Instance for peripherals::$inst {} + }; +); + +impl<'d, T: Instance, C: Channel, W: word::Word> SetConfig for Sai<'d, T, C, W> { + type Config = Config; + fn set_config(&mut self, config: &Self::Config) { + self.reconfigure(*config); + } +} From 5c8c1b21462cae078ede1025a54b2c96b233d118 Mon Sep 17 00:00:00 2001 From: Tyler Gilbert Date: Fri, 29 Sep 2023 21:16:20 -0500 Subject: [PATCH 04/16] #Issue 1974 fix warnings --- embassy-stm32/src/rcc/f4.rs | 3 ++- embassy-stm32/src/sai/mod.rs | 15 +++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 2c027ebe..17834784 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -52,6 +52,7 @@ fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { None } +#[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] fn calculate_sai_i2s_pll_values(vco_in: u32, max_div: u32, target: Option, ) -> Option<(u32, u32, u32)> { let min_div = 2; let target = match target { @@ -96,7 +97,7 @@ fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { } #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))] -fn setup_sai_pll(vco_in: u32, pllsai: Option) -> Option { +fn setup_sai_pll(vco_in: u32, _pllsai: Option) -> Option { None } diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index 1fcee226..aa996a99 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -8,7 +8,6 @@ use crate::gpio::sealed::{AFType, Pin as _}; use crate::gpio::AnyPin; use crate::pac::sai::{vals, Sai as Regs}; use crate::rcc::RccPeripheral; -use crate::time::Hertz; use crate::{peripherals, Peripheral}; pub use crate::dma::word; @@ -702,8 +701,8 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { #[cfg(any(sai_v4))] { - /// Not totally clear from the datasheet if this is right - /// This is only used if using SyncEnable::External + // Not totally clear from the datasheet if this is right + // This is only used if using SyncEnable::External let value: u8 = if T::REGS.as_ptr() == stm32_metapac::SAI1.as_ptr() { 1 //this is SAI1, so sync with SAI2 } else { @@ -789,7 +788,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { } } - fn flush(&mut self) { + pub fn flush(&mut self) { let ch = T::REGS.ch(self.sub_block as usize); ch.cr1().modify(|w| w.set_saien(false)); #[cfg(any(sai_v1, sai_v2))] @@ -803,13 +802,13 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { ch.cr1().modify(|w| w.set_saien(true)); } - fn set_mute(&mut self, value: bool) { + pub fn set_mute(&mut self, value: bool) { let ch = T::REGS.ch(self.sub_block as usize); ch.cr2().modify(|w| w.set_mute(value)); } /// Reconfigures it with the supplied config. - pub fn reconfigure(&mut self, config: Config) {} + pub fn reconfigure(&mut self, _config: Config) {} pub fn get_current_config(&self) -> Config { Config::default() @@ -818,7 +817,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { pub async fn write(&mut self, data: &[W]) -> Result<(), Error> { match &mut self.ring_buffer { RingBuffer::Writable(buffer) => { - buffer.write_exact(data).await; + buffer.write_exact(data).await?; Ok(()) } _ => return Err(Error::NotATransmitter), @@ -828,7 +827,7 @@ impl<'d, T: Instance, C: Channel, W: word::Word> Sai<'d, T, C, W> { pub async fn read(&mut self, data: &mut [W]) -> Result<(), Error> { match &mut self.ring_buffer { RingBuffer::Readable(buffer) => { - buffer.read_exact(data).await; + buffer.read_exact(data).await?; Ok(()) } _ => Err(Error::NotAReceiver), From 6cdee93934f55c06c6bb6cee94f5f70ec1384220 Mon Sep 17 00:00:00 2001 From: Tyler Gilbert Date: Fri, 29 Sep 2023 21:27:15 -0500 Subject: [PATCH 05/16] #Issue 1974 fix more warnings treated as errors --- embassy-stm32/src/rcc/f4.rs | 2 +- embassy-stm32/src/sai/mod.rs | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 17834784..2f851cfa 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -97,7 +97,7 @@ fn setup_i2s_pll(vco_in: u32, plli2s: Option) -> Option { } #[cfg(not(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479)))] -fn setup_sai_pll(vco_in: u32, _pllsai: Option) -> Option { +fn setup_sai_pll(_vco_in: u32, _pllsai: Option) -> Option { None } diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index aa996a99..d2949e9a 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -3,7 +3,7 @@ use embassy_embedded_hal::SetConfig; use embassy_hal_internal::{into_ref, PeripheralRef}; -use crate::dma::{Channel, ReadableRingBuffer, TransferOptions, WritableRingBuffer}; +use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, TransferOptions, WritableRingBuffer}; use crate::gpio::sealed::{AFType, Pin as _}; use crate::gpio::AnyPin; use crate::pac::sai::{vals, Sai as Regs}; @@ -17,6 +17,13 @@ pub use crate::dma::word; pub enum Error { NotATransmitter, NotAReceiver, + OverrunError, +} + +impl From for Error { + fn from(_: ringbuffer::OverrunError) -> Self { + Self::OverrunError + } } #[derive(Copy, Clone)] @@ -499,6 +506,7 @@ pub enum SubBlock { enum RingBuffer<'d, C: Channel, W: word::Word> { Writable(WritableRingBuffer<'d, C, W>), + #[allow(dead_code)] // remove this after implementing new_* functions for receiver Readable(ReadableRingBuffer<'d, C, W>), } From 4a632e08b720b18062396d2d4f999f0acf80355a Mon Sep 17 00:00:00 2001 From: Tyler Gilbert Date: Fri, 29 Sep 2023 21:46:19 -0500 Subject: [PATCH 06/16] #Issue 1974 fix extra whitespace --- embassy-stm32/src/rcc/f4.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 2f851cfa..6315dc77 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -48,9 +48,7 @@ fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { // Not currently implemented, but will be in the future #[cfg(any(stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] -fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { - None -} +fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { None } #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] fn calculate_sai_i2s_pll_values(vco_in: u32, max_div: u32, target: Option, ) -> Option<(u32, u32, u32)> { From 1be5f193c39379ce63e743bdb50d52ae223c9985 Mon Sep 17 00:00:00 2001 From: Tyler Gilbert Date: Fri, 29 Sep 2023 21:53:01 -0500 Subject: [PATCH 07/16] #Issue 1974 more whitespace fixes --- embassy-stm32/src/rcc/f4.rs | 15 ++++++++++++--- embassy-stm32/src/sai/mod.rs | 3 +-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/embassy-stm32/src/rcc/f4.rs b/embassy-stm32/src/rcc/f4.rs index 6315dc77..ebf78d0e 100644 --- a/embassy-stm32/src/rcc/f4.rs +++ b/embassy-stm32/src/rcc/f4.rs @@ -48,10 +48,12 @@ fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { // Not currently implemented, but will be in the future #[cfg(any(stm32f411, stm32f412, stm32f413, stm32f423, stm32f446))] -fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { None } +fn setup_i2s_pll(_vco_in: u32, _plli2s: Option) -> Option { + None +} #[cfg(not(any(stm32f410, stm32f411, stm32f412, stm32f413, stm32f423, stm32f446)))] -fn calculate_sai_i2s_pll_values(vco_in: u32, max_div: u32, target: Option, ) -> Option<(u32, u32, u32)> { +fn calculate_sai_i2s_pll_values(vco_in: u32, max_div: u32, target: Option) -> Option<(u32, u32, u32)> { let min_div = 2; let target = match target { Some(target) => target, @@ -111,7 +113,14 @@ fn setup_sai_pll(vco_in: u32, pllsai: Option) -> Option { Some(output) } -fn setup_pll(pllsrcclk: u32, use_hse: bool, pllsysclk: Option, plli2s: Option, pllsai: Option, pll48clk: bool) -> PllResults { +fn setup_pll( + pllsrcclk: u32, + use_hse: bool, + pllsysclk: Option, + plli2s: Option, + pllsai: Option, + pll48clk: bool, +) -> PllResults { use crate::pac::rcc::vals::{Pllp, Pllsrc}; let sysclk = pllsysclk.unwrap_or(pllsrcclk); diff --git a/embassy-stm32/src/sai/mod.rs b/embassy-stm32/src/sai/mod.rs index d2949e9a..4ffa6e9c 100644 --- a/embassy-stm32/src/sai/mod.rs +++ b/embassy-stm32/src/sai/mod.rs @@ -3,6 +3,7 @@ use embassy_embedded_hal::SetConfig; use embassy_hal_internal::{into_ref, PeripheralRef}; +pub use crate::dma::word; use crate::dma::{ringbuffer, Channel, ReadableRingBuffer, TransferOptions, WritableRingBuffer}; use crate::gpio::sealed::{AFType, Pin as _}; use crate::gpio::AnyPin; @@ -10,8 +11,6 @@ use crate::pac::sai::{vals, Sai as Regs}; use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; -pub use crate::dma::word; - #[derive(Debug)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Error { From 8da987cfbb6b2f3d6bdbe11e60e0f0db8f030b1b Mon Sep 17 00:00:00 2001 From: brian horakh Date: Sat, 30 Sep 2023 05:34:22 +0000 Subject: [PATCH 08/16] typo --- examples/wasm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/wasm/README.md b/examples/wasm/README.md index b7fee2dc..3b037ea0 100644 --- a/examples/wasm/README.md +++ b/examples/wasm/README.md @@ -23,4 +23,4 @@ To run the example, start a webserver server the local folder: python -m http.server ``` -Then, open a browser at https://127.0.0.1:8000 and watch the ticker print entries to the window. +Then, open a browser at http://127.0.0.1:8000 and watch the ticker print entries to the window. From 08175f191a302b44a0201be1741dc3613ee2f819 Mon Sep 17 00:00:00 2001 From: brian horakh Date: Sat, 30 Sep 2023 05:42:59 +0000 Subject: [PATCH 09/16] bump wasm-pack version --- examples/wasm/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/wasm/README.md b/examples/wasm/README.md index 3b037ea0..3d300d9a 100644 --- a/examples/wasm/README.md +++ b/examples/wasm/README.md @@ -3,7 +3,7 @@ Examples use a CLI tool named `wasm-pack` to build this example: ``` -cargo install wasm-pack --version 0.9.1 +cargo install wasm-pack --version 0.12.1 ``` ## Building From 55a0a15be21804814e97a065ba413f5474f5f3d2 Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Sat, 30 Sep 2023 11:19:09 -0400 Subject: [PATCH 10/16] Fix trait inconsistency between sealed traits and implementations --- embassy-stm32/src/timer/mod.rs | 96 +--------------------------------- 1 file changed, 1 insertion(+), 95 deletions(-) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 1d642ed3..5beca1e4 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -94,25 +94,7 @@ pub(crate) mod sealed { fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); } - pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance { - fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf); - - fn clear_input_interrupt(&mut self, channel: Channel); - - fn enable_input_interrupt(&mut self, channel: Channel, enable: bool); - - fn set_input_capture_prescaler(&mut self, channel: Channel, val: u8); - - fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection); - - fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode); - - fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); - - fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity); - - fn enable_channel(&mut self, channel: Channel, enable: bool); - + pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance + CaptureCompare16bitInstance { fn set_compare_value(&mut self, channel: Channel, value: u32); fn get_capture_value(&mut self, channel: Channel) -> u32; @@ -228,7 +210,6 @@ pub trait CaptureCompare32bitInstance: sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static { } - pin_trait!(Channel1Pin, CaptureCompare16bitInstance); pin_trait!(Channel1ComplementaryPin, CaptureCompare16bitInstance); pin_trait!(Channel2Pin, CaptureCompare16bitInstance); @@ -475,81 +456,6 @@ foreach_interrupt! { impl GeneralPurpose32bitInstance for crate::peripherals::$inst {} impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { - fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) { - use sealed::GeneralPurpose32bitInstance; - let raw_channel = channel.raw(); - Self::regs_gp32() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_icf(raw_channel % 2, icf)); - } - - fn clear_input_interrupt(&mut self, channel: Channel) { - use sealed::GeneralPurpose32bitInstance; - Self::regs_gp32() - .sr() - .modify(|r| r.set_ccif(channel.raw(), false)); - } - fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) { - use sealed::GeneralPurpose32bitInstance; - Self::regs_gp32() - .dier() - .modify(|r| r.set_ccie(channel.raw(), enable)); - } - fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) { - use crate::timer::sealed::GeneralPurpose32bitInstance; - let raw_channel = channel.raw(); - Self::regs_gp32() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_icpsc(raw_channel % 2, factor)); - } - - fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { - use crate::timer::sealed::GeneralPurpose32bitInstance; - let raw_channel = channel.raw(); - Self::regs_gp32() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); - } - - fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { - use crate::timer::sealed::GeneralPurpose32bitInstance; - Self::regs_gp32().ccer().modify(|r| match mode { - InputCaptureMode::Rising => { - r.set_ccnp(channel.raw(), false); - r.set_ccp(channel.raw(), false); - } - InputCaptureMode::Falling => { - r.set_ccnp(channel.raw(), false); - r.set_ccp(channel.raw(), true); - } - InputCaptureMode::BothEdges => { - r.set_ccnp(channel.raw(), true); - r.set_ccp(channel.raw(), true); - } - }); - } - fn set_output_compare_mode( - &mut self, - channel: Channel, - mode: OutputCompareMode, - ) { - use crate::timer::sealed::GeneralPurpose32bitInstance; - let raw_channel = channel.raw(); - Self::regs_gp32().ccmr_output(raw_channel / 2).modify(|w| w.set_ocm(raw_channel % 2, mode.into())); - } - - fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { - use crate::timer::sealed::GeneralPurpose32bitInstance; - Self::regs_gp32() - .ccer() - .modify(|w| w.set_ccp(channel.raw(), polarity.into())); - } - - fn enable_channel(&mut self, channel: Channel, enable: bool) { - use crate::timer::sealed::GeneralPurpose32bitInstance; - Self::regs_gp32().ccer().modify(|w| w.set_cce(channel.raw(), enable)); - } - fn set_compare_value(&mut self, channel: Channel, value: u32) { use crate::timer::sealed::GeneralPurpose32bitInstance; Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); From 61dc36b1f28d38b55d2fe65f4de3fba7e8036b99 Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Sat, 30 Sep 2023 11:36:32 -0400 Subject: [PATCH 11/16] Fix small formatting issue --- embassy-stm32/src/timer/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 5beca1e4..4402e1cf 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -210,6 +210,7 @@ pub trait CaptureCompare32bitInstance: sealed::CaptureCompare32bitInstance + CaptureCompare16bitInstance + GeneralPurpose32bitInstance + 'static { } + pin_trait!(Channel1Pin, CaptureCompare16bitInstance); pin_trait!(Channel1ComplementaryPin, CaptureCompare16bitInstance); pin_trait!(Channel2Pin, CaptureCompare16bitInstance); From 74eb51981091e2e8fab4f8d251353f7b8c2f7584 Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Sat, 30 Sep 2023 12:14:20 -0400 Subject: [PATCH 12/16] Move trait impls out of macros --- embassy-stm32/src/timer/mod.rs | 489 ++++++++++----------------------- 1 file changed, 143 insertions(+), 346 deletions(-) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 4402e1cf..04919659 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -22,27 +22,67 @@ pub(crate) mod sealed { fn regs() -> crate::pac::timer::TimBasic; - fn start(&mut self); + fn start(&mut self) { + Self::regs().cr1().modify(|r| r.set_cen(true)); + } - fn stop(&mut self); + fn stop(&mut self) { + Self::regs().cr1().modify(|r| r.set_cen(false)); + } - fn reset(&mut self); + fn reset(&mut self) { + Self::regs().cnt().write(|r| r.set_cnt(0)); + } - fn set_frequency(&mut self, frequency: Hertz); + fn set_frequency(&mut self, frequency: Hertz) { + let f = frequency.0; + let timer_f = Self::frequency().0; + assert!(f > 0); + let pclk_ticks_per_timer_period = timer_f / f; + let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into()); + let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into()); - fn clear_update_interrupt(&mut self) -> bool; + let regs = Self::regs(); + regs.psc().write(|r| r.set_psc(psc)); + regs.arr().write(|r| r.set_arr(arr)); - fn enable_update_interrupt(&mut self, enable: bool); + 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)); + } - fn set_autoreload_preload(&mut self, enable: vals::Arpe); + fn clear_update_interrupt(&mut self) -> bool { + let regs = Self::regs(); + let sr = regs.sr().read(); + if sr.uif() { + regs.sr().modify(|r| { + r.set_uif(false); + }); + true + } else { + false + } + } + + fn enable_update_interrupt(&mut self, enable: bool) { + Self::regs().dier().write(|r| r.set_uie(enable)); + } + + fn set_autoreload_preload(&mut self, enable: vals::Arpe) { + Self::regs().cr1().modify(|r| r.set_arpe(enable)); + } } pub trait GeneralPurpose16bitInstance: Basic16bitInstance { fn regs_gp16() -> crate::pac::timer::TimGp16; - fn set_count_direction(&mut self, direction: vals::Dir); + fn set_count_direction(&mut self, direction: vals::Dir) { + Self::regs_gp16().cr1().modify(|r| r.set_dir(direction)); + } - fn set_clock_division(&mut self, ckd: vals::Ckd); + fn set_clock_division(&mut self, ckd: vals::Ckd) { + Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd)); + } } pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { @@ -56,50 +96,115 @@ pub(crate) mod sealed { } pub trait CaptureCompare16bitInstance: GeneralPurpose16bitInstance { - fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf); + fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) { + let raw_channel = channel.raw(); + Self::regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icf(raw_channel % 2, icf)); + } - fn clear_input_interrupt(&mut self, channel: Channel); + fn clear_input_interrupt(&mut self, channel: Channel) { + Self::regs_gp16().sr().modify(|r| r.set_ccif(channel.raw(), false)); + } - fn enable_input_interrupt(&mut self, channel: Channel, enable: bool); + fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) { + Self::regs_gp16().dier().modify(|r| r.set_ccie(channel.raw(), enable)); + } + fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) { + let raw_channel = channel.raw(); + Self::regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_icpsc(raw_channel % 2, factor)); + } - fn set_input_capture_prescaler(&mut self, channel: Channel, val: u8); + fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { + let raw_channel = channel.raw(); + Self::regs_gp16() + .ccmr_input(raw_channel / 2) + .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); + } + fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { + Self::regs_gp16().ccer().modify(|r| match mode { + InputCaptureMode::Rising => { + r.set_ccnp(channel.raw(), false); + r.set_ccp(channel.raw(), false); + } + InputCaptureMode::Falling => { + r.set_ccnp(channel.raw(), false); + r.set_ccp(channel.raw(), true); + } + InputCaptureMode::BothEdges => { + r.set_ccnp(channel.raw(), true); + r.set_ccp(channel.raw(), true); + } + }); + } + fn enable_outputs(&mut self, _enable: bool) {} - fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection); + fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) { + let r = Self::regs_gp16(); + let raw_channel: usize = channel.raw(); + r.ccmr_output(raw_channel / 2) + .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); + } - fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode); + fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { + Self::regs_gp16() + .ccer() + .modify(|w| w.set_ccp(channel.raw(), polarity.into())); + } - /// Global output enable. Does not do anything on non-advanced timers. - fn enable_outputs(&mut self, enable: bool); + fn enable_channel(&mut self, channel: Channel, enable: bool) { + Self::regs_gp16().ccer().modify(|w| w.set_cce(channel.raw(), enable)); + } - fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode); + fn set_compare_value(&mut self, channel: Channel, value: u16) { + Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); + } - fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity); + fn get_capture_value(&mut self, channel: Channel) -> u16 { + Self::regs_gp16().ccr(channel.raw()).read().ccr() + } - fn enable_channel(&mut self, channel: Channel, enable: bool); - - fn set_compare_value(&mut self, channel: Channel, value: u16); - - fn get_capture_value(&mut self, channel: Channel) -> u16; - - fn get_max_compare_value(&self) -> u16; + fn get_max_compare_value(&self) -> u16 { + Self::regs_gp16().arr().read().arr() + } } - pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance { - fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity); + pub trait ComplementaryCaptureCompare16bitInstance: CaptureCompare16bitInstance + AdvancedControlInstance { + fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { + Self::regs_advanced() + .ccer() + .modify(|w| w.set_ccnp(channel.raw(), polarity.into())); + } - fn set_dead_time_clock_division(&mut self, value: vals::Ckd); + fn set_dead_time_clock_division(&mut self, value: vals::Ckd) { + Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); + } - fn set_dead_time_value(&mut self, value: u8); + fn set_dead_time_value(&mut self, value: u8) { + Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); + } - fn enable_complementary_channel(&mut self, channel: Channel, enable: bool); + fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { + Self::regs_advanced() + .ccer() + .modify(|w| w.set_ccne(channel.raw(), enable)); + } } pub trait CaptureCompare32bitInstance: GeneralPurpose32bitInstance + CaptureCompare16bitInstance { - fn set_compare_value(&mut self, channel: Channel, value: u32); + fn set_compare_value(&mut self, channel: Channel, value: u32) { + Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); + } - fn get_capture_value(&mut self, channel: Channel) -> u32; + fn get_capture_value(&mut self, channel: Channel) -> u32 { + Self::regs_gp32().ccr(channel.raw()).read().ccr() + } - fn get_max_compare_value(&self) -> u32; + fn get_max_compare_value(&self) -> u32 { + Self::regs_gp32().arr().read().arr() as u32 + } } } @@ -236,57 +341,6 @@ macro_rules! impl_basic_16bit_timer { fn regs() -> crate::pac::timer::TimBasic { unsafe { crate::pac::timer::TimBasic::from_ptr(crate::pac::$inst.as_ptr()) } } - - fn start(&mut self) { - Self::regs().cr1().modify(|r| r.set_cen(true)); - } - - fn stop(&mut self) { - Self::regs().cr1().modify(|r| r.set_cen(false)); - } - - fn reset(&mut self) { - Self::regs().cnt().write(|r| r.set_cnt(0)); - } - - fn set_frequency(&mut self, frequency: Hertz) { - use core::convert::TryInto; - let f = frequency.0; - let timer_f = Self::frequency().0; - assert!(f > 0); - let pclk_ticks_per_timer_period = timer_f / f; - let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 16)).try_into()); - let arr: u16 = unwrap!((pclk_ticks_per_timer_period / (u32::from(psc) + 1)).try_into()); - - let regs = Self::regs(); - regs.psc().write(|r| r.set_psc(psc)); - regs.arr().write(|r| r.set_arr(arr)); - - regs.cr1().modify(|r| r.set_urs(vals::Urs::COUNTERONLY)); - regs.egr().write(|r| r.set_ug(true)); - regs.cr1().modify(|r| r.set_urs(vals::Urs::ANYEVENT)); - } - - fn clear_update_interrupt(&mut self) -> bool { - let regs = Self::regs(); - let sr = regs.sr().read(); - if sr.uif() { - regs.sr().modify(|r| { - r.set_uif(false); - }); - true - } else { - false - } - } - - fn enable_update_interrupt(&mut self, enable: bool) { - Self::regs().dier().write(|r| r.set_uie(enable)); - } - - fn set_autoreload_preload(&mut self, enable: vals::Arpe) { - Self::regs().cr1().modify(|r| r.set_arpe(enable)); - } } }; } @@ -323,99 +377,7 @@ macro_rules! impl_32bit_timer { #[allow(unused)] macro_rules! impl_compare_capable_16bit { ($inst:ident) => { - impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { - fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) { - use sealed::GeneralPurpose16bitInstance; - let raw_channel = channel.raw(); - Self::regs_gp16() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_icf(raw_channel % 2, icf)); - } - - fn clear_input_interrupt(&mut self, channel: Channel) { - use sealed::GeneralPurpose16bitInstance; - Self::regs_gp16() - .sr() - .modify(|r| r.set_ccif(channel.raw(), false)); - } - - fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) { - use sealed::GeneralPurpose16bitInstance; - Self::regs_gp16() - .dier() - .modify(|r| r.set_ccie(channel.raw(), enable)); - } - fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) { - use sealed::GeneralPurpose16bitInstance; - let raw_channel = channel.raw(); - Self::regs_gp16() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_icpsc(raw_channel % 2, factor)); - } - - fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { - use sealed::GeneralPurpose16bitInstance; - let raw_channel = channel.raw(); - Self::regs_gp16() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); - } - fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { - use sealed::GeneralPurpose16bitInstance; - Self::regs_gp16().ccer().modify(|r| match mode { - InputCaptureMode::Rising => { - r.set_ccnp(channel.raw(), false); - r.set_ccp(channel.raw(), false); - } - InputCaptureMode::Falling => { - r.set_ccnp(channel.raw(), false); - r.set_ccp(channel.raw(), true); - } - InputCaptureMode::BothEdges => { - r.set_ccnp(channel.raw(), true); - r.set_ccp(channel.raw(), true); - } - }); - } - fn enable_outputs(&mut self, _enable: bool) {} - - fn set_output_compare_mode(&mut self, channel: Channel, mode: OutputCompareMode) { - use sealed::GeneralPurpose16bitInstance; - let r = Self::regs_gp16(); - let raw_channel: usize = channel.raw(); - r.ccmr_output(raw_channel / 2) - .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); - } - - fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { - use sealed::GeneralPurpose16bitInstance; - Self::regs_gp16() - .ccer() - .modify(|w| w.set_ccp(channel.raw(), polarity.into())); - } - - fn enable_channel(&mut self, channel: Channel, enable: bool) { - use sealed::GeneralPurpose16bitInstance; - Self::regs_gp16() - .ccer() - .modify(|w| w.set_cce(channel.raw(), enable)); - } - - fn set_compare_value(&mut self, channel: Channel, value: u16) { - use sealed::GeneralPurpose16bitInstance; - Self::regs_gp16().ccr(channel.raw()).modify(|w| w.set_ccr(value)); - } - - fn get_capture_value(&mut self, channel: Channel) -> u16 { - use sealed::GeneralPurpose16bitInstance; - Self::regs_gp16().ccr(channel.raw()).read().ccr() - } - - fn get_max_compare_value(&self) -> u16 { - use sealed::GeneralPurpose16bitInstance; - Self::regs_gp16().arr().read().arr() - } - } + impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {} }; } @@ -435,14 +397,6 @@ foreach_interrupt! { fn regs_gp16() -> crate::pac::timer::TimGp16 { crate::pac::$inst } - - fn set_count_direction(&mut self, direction: vals::Dir) { - Self::regs_gp16().cr1().modify(|r| r.set_dir(direction)); - } - - fn set_clock_division(&mut self, ckd: vals::Ckd) { - Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd)); - } } }; @@ -455,36 +409,12 @@ foreach_interrupt! { impl CaptureCompare32bitInstance for crate::peripherals::$inst {} impl GeneralPurpose16bitInstance for crate::peripherals::$inst {} impl GeneralPurpose32bitInstance for crate::peripherals::$inst {} - - impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst { - fn set_compare_value(&mut self, channel: Channel, value: u32) { - use crate::timer::sealed::GeneralPurpose32bitInstance; - Self::regs_gp32().ccr(channel.raw()).modify(|w| w.set_ccr(value)); - } - - fn get_capture_value(&mut self, channel: Channel) -> u32 { - use crate::timer::sealed::GeneralPurpose32bitInstance; - Self::regs_gp32().ccr(channel.raw()).read().ccr() - } - - fn get_max_compare_value(&self) -> u32 { - use crate::timer::sealed::GeneralPurpose32bitInstance; - Self::regs_gp32().arr().read().arr() as u32 - } - } + impl sealed::CaptureCompare32bitInstance for crate::peripherals::$inst {} impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { fn regs_gp16() -> crate::pac::timer::TimGp16 { unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } } - - fn set_count_direction(&mut self, direction: vals::Dir) { - Self::regs_gp16().cr1().modify(|r| r.set_dir(direction)); - } - - fn set_clock_division(&mut self, ckd: vals::Ckd) { - Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd)); - } } }; @@ -496,19 +426,12 @@ foreach_interrupt! { impl CaptureCompare16bitInstance for crate::peripherals::$inst {} impl ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} impl AdvancedControlInstance for crate::peripherals::$inst {} - + impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst {} + impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst {} impl sealed::GeneralPurpose16bitInstance for crate::peripherals::$inst { fn regs_gp16() -> crate::pac::timer::TimGp16 { unsafe { crate::pac::timer::TimGp16::from_ptr(crate::pac::$inst.as_ptr()) } } - - fn set_count_direction(&mut self, direction: vals::Dir) { - Self::regs_gp16().cr1().modify(|r| r.set_dir(direction)); - } - - fn set_clock_division(&mut self, ckd: vals::Ckd) { - Self::regs_gp16().cr1().modify(|r| r.set_ckd(ckd)); - } } impl sealed::AdvancedControlInstance for crate::peripherals::$inst { @@ -517,133 +440,7 @@ foreach_interrupt! { } } - impl sealed::CaptureCompare16bitInstance for crate::peripherals::$inst { - fn set_input_capture_filter(&mut self, channel: Channel, icf: vals::Icf) { - use crate::timer::sealed::AdvancedControlInstance; - let raw_channel = channel.raw(); - Self::regs_advanced() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_icf(raw_channel % 2, icf)); - } - fn clear_input_interrupt(&mut self, channel: Channel) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced() - .sr() - .modify(|r| r.set_ccif(channel.raw(), false)); - } - fn enable_input_interrupt(&mut self, channel: Channel, enable: bool) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced() - .dier() - .modify(|r| r.set_ccie(channel.raw(), enable)); - } - fn set_input_capture_prescaler(&mut self, channel: Channel, factor: u8) { - use crate::timer::sealed::AdvancedControlInstance; - let raw_channel = channel.raw(); - Self::regs_advanced() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_icpsc(raw_channel % 2, factor)); - } - fn set_input_ti_selection(&mut self, channel: Channel, tisel: InputTISelection) { - use crate::timer::sealed::AdvancedControlInstance; - let raw_channel = channel.raw(); - Self::regs_advanced() - .ccmr_input(raw_channel / 2) - .modify(|r| r.set_ccs(raw_channel % 2, tisel.into())); - } - fn set_input_capture_mode(&mut self, channel: Channel, mode: InputCaptureMode) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced().ccer().modify(|r| match mode { - InputCaptureMode::Rising => { - r.set_ccnp(channel.raw(), false); - r.set_ccp(channel.raw(), false); - } - InputCaptureMode::Falling => { - r.set_ccnp(channel.raw(), false); - r.set_ccp(channel.raw(), true); - } - InputCaptureMode::BothEdges => { - r.set_ccnp(channel.raw(), true); - r.set_ccp(channel.raw(), true); - } - }); - } - fn enable_outputs(&mut self, enable: bool) { - use crate::timer::sealed::AdvancedControlInstance; - let r = Self::regs_advanced(); - r.bdtr().modify(|w| w.set_moe(enable)); - } - - fn set_output_compare_mode( - &mut self, - channel: Channel, - mode: OutputCompareMode, - ) { - use crate::timer::sealed::AdvancedControlInstance; - let r = Self::regs_advanced(); - let raw_channel: usize = channel.raw(); - r.ccmr_output(raw_channel / 2) - .modify(|w| w.set_ocm(raw_channel % 2, mode.into())); - } - - fn set_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced() - .ccer() - .modify(|w| w.set_ccp(channel.raw(), polarity.into())); - } - - fn enable_channel(&mut self, channel: Channel, enable: bool) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced() - .ccer() - .modify(|w| w.set_cce(channel.raw(), enable)); - } - - fn get_capture_value(&mut self, channel: Channel) -> u16 { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced().ccr(channel.raw()).read().ccr() - } - - fn set_compare_value(&mut self, channel: Channel, value: u16) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced() - .ccr(channel.raw()) - .modify(|w| w.set_ccr(value)); - } - - fn get_max_compare_value(&self) -> u16 { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced().arr().read().arr() - } - } - - impl sealed::ComplementaryCaptureCompare16bitInstance for crate::peripherals::$inst { - fn set_complementary_output_polarity(&mut self, channel: Channel, polarity: OutputPolarity) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced() - .ccer() - .modify(|w| w.set_ccnp(channel.raw(), polarity.into())); - } - - fn set_dead_time_clock_division(&mut self, value: vals::Ckd) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced().cr1().modify(|w| w.set_ckd(value)); - } - - fn set_dead_time_value(&mut self, value: u8) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced().bdtr().modify(|w| w.set_dtg(value)); - } - - fn enable_complementary_channel(&mut self, channel: Channel, enable: bool) { - use crate::timer::sealed::AdvancedControlInstance; - Self::regs_advanced() - .ccer() - .modify(|w| w.set_ccne(channel.raw(), enable)); - } - } }; From dc4c27aeadcd58d04c29c4c43c87b95f6960268e Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Sat, 30 Sep 2023 12:16:47 -0400 Subject: [PATCH 13/16] Move one more method out of macros --- embassy-stm32/src/timer/mod.rs | 36 ++++++++++++++++------------------ 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 04919659..8cd47aed 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -88,7 +88,23 @@ pub(crate) mod sealed { pub trait GeneralPurpose32bitInstance: GeneralPurpose16bitInstance { fn regs_gp32() -> crate::pac::timer::TimGp32; - fn set_frequency(&mut self, frequency: Hertz); + fn set_frequency(&mut self, frequency: Hertz) { + use core::convert::TryInto; + let f = frequency.0; + assert!(f > 0); + let timer_f = Self::frequency().0; + let pclk_ticks_per_timer_period = (timer_f / f) as u64; + let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); + let arr: u32 = unwrap!(((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into())); + + let regs = Self::regs_gp32(); + regs.psc().write(|r| r.set_psc(psc)); + regs.arr().write(|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)); + } } pub trait AdvancedControlInstance: GeneralPurpose16bitInstance { @@ -352,24 +368,6 @@ macro_rules! impl_32bit_timer { fn regs_gp32() -> crate::pac::timer::TimGp32 { crate::pac::$inst } - - fn set_frequency(&mut self, frequency: Hertz) { - use core::convert::TryInto; - let f = frequency.0; - assert!(f > 0); - let timer_f = Self::frequency().0; - let pclk_ticks_per_timer_period = (timer_f / f) as u64; - let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); - let arr: u32 = unwrap!(((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into())); - - let regs = Self::regs_gp32(); - regs.psc().write(|r| r.set_psc(psc)); - regs.arr().write(|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)); - } } }; } From 3c3fb0a529ac1fabbfef0e3c84d27d21c9fc1058 Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Sat, 30 Sep 2023 12:19:29 -0400 Subject: [PATCH 14/16] Remove unused imports --- embassy-stm32/src/timer/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 8cd47aed..953c8343 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -5,7 +5,6 @@ pub mod simple_pwm; use stm32_metapac::timer::vals; use crate::interrupt; -use crate::rcc::sealed::RccPeripheral as __RccPeri; use crate::rcc::RccPeripheral; use crate::time::Hertz; @@ -89,7 +88,6 @@ pub(crate) mod sealed { fn regs_gp32() -> crate::pac::timer::TimGp32; fn set_frequency(&mut self, frequency: Hertz) { - use core::convert::TryInto; let f = frequency.0; assert!(f > 0); let timer_f = Self::frequency().0; From 9b8bdad40337944ad275691a4eb6a54736c7bd55 Mon Sep 17 00:00:00 2001 From: Daniel Berlin Date: Sat, 30 Sep 2023 12:22:52 -0400 Subject: [PATCH 15/16] Fix clippy error exposed by moving out of macros --- embassy-stm32/src/timer/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index 953c8343..c62f4a15 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -217,7 +217,7 @@ pub(crate) mod sealed { } fn get_max_compare_value(&self) -> u32 { - Self::regs_gp32().arr().read().arr() as u32 + Self::regs_gp32().arr().read().arr() } } } From 4999de6f82e78c129dddf3d97fc1282b6c7d0e66 Mon Sep 17 00:00:00 2001 From: xoviat Date: Sat, 30 Sep 2023 12:53:17 -0500 Subject: [PATCH 16/16] rustfmt --- embassy-stm32/src/timer/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/embassy-stm32/src/timer/mod.rs b/embassy-stm32/src/timer/mod.rs index c62f4a15..d88fbcfd 100644 --- a/embassy-stm32/src/timer/mod.rs +++ b/embassy-stm32/src/timer/mod.rs @@ -93,7 +93,7 @@ pub(crate) mod sealed { let timer_f = Self::frequency().0; let pclk_ticks_per_timer_period = (timer_f / f) as u64; let psc: u16 = unwrap!(((pclk_ticks_per_timer_period - 1) / (1 << 32)).try_into()); - let arr: u32 = unwrap!(((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into())); + let arr: u32 = unwrap!((pclk_ticks_per_timer_period / (psc as u64 + 1)).try_into()); let regs = Self::regs_gp32(); regs.psc().write(|r| r.set_psc(psc));