From 5f01e56728c3a06f1d2298dea6dde000a43acc83 Mon Sep 17 00:00:00 2001 From: chemicstry Date: Thu, 4 Aug 2022 03:02:57 +0300 Subject: [PATCH 1/5] Merge v1, v2 DAC and update register definitions --- embassy-stm32/src/{dac/v2.rs => dac.rs} | 145 +++++++++++++----------- embassy-stm32/src/dac/mod.rs | 36 ------ embassy-stm32/src/dac/v1.rs | 1 - examples/stm32f1/Cargo.toml | 3 +- examples/stm32f1/src/bin/dac.rs | 37 ++++++ stm32-data | 2 +- 6 files changed, 119 insertions(+), 105 deletions(-) rename embassy-stm32/src/{dac/v2.rs => dac.rs} (66%) delete mode 100644 embassy-stm32/src/dac/mod.rs delete mode 100644 embassy-stm32/src/dac/v1.rs create mode 100644 examples/stm32f1/src/bin/dac.rs diff --git a/embassy-stm32/src/dac/v2.rs b/embassy-stm32/src/dac.rs similarity index 66% rename from embassy-stm32/src/dac/v2.rs rename to embassy-stm32/src/dac.rs index 6b7f41c6..c0369d97 100644 --- a/embassy-stm32/src/dac/v2.rs +++ b/embassy-stm32/src/dac.rs @@ -1,8 +1,10 @@ +#![macro_use] + +use cfg_if::cfg_if; use embassy_hal_common::{into_ref, PeripheralRef}; -use crate::dac::{DacPin, Instance}; use crate::pac::dac; -use crate::Peripheral; +use crate::{peripherals, Peripheral}; #[derive(Debug, Copy, Clone, Eq, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -18,6 +20,15 @@ pub enum Channel { Ch2, } +impl Channel { + fn index(&self) -> usize { + match self { + Channel::Ch1 => 0, + Channel::Ch2 => 1, + } + } +} + #[derive(Debug, Copy, Clone, Eq, PartialEq)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum Ch1Trigger { @@ -119,27 +130,28 @@ impl<'d, T: Instance> Dac<'d, T> { // Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock // configuration. critical_section::with(|_| { - #[cfg(rcc_h7)] - enable!(apb1lenr, set_dac12en, apb1lrstr, set_dac12rst); - #[cfg(rcc_h7ab)] - enable!(apb1lenr, set_dac1en, apb1lrstr, set_dac1rst); - #[cfg(stm32g0)] - enable!(apbenr1, set_dac1en, apbrstr1, set_dac1rst); - #[cfg(any(stm32l4, stm32l5))] - enable!(apb1enr1, set_dac1en, apb1rstr1, set_dac1rst); + cfg_if! { + if #[cfg(rcc_f1)] { + enable!(apb1enr, set_dacen, apb1rstr, set_dacrst); + } else if #[cfg(rcc_h7)] { + enable!(apb1lenr, set_dac12en, apb1lrstr, set_dac12rst); + } else if #[cfg(rcc_h7ab)] { + enable!(apb1lenr, set_dac1en, apb1lrstr, set_dac1rst); + } else if #[cfg(stm32g0)] { + enable!(apbenr1, set_dac1en, apbrstr1, set_dac1rst); + } else if #[cfg(any(stm32l4, stm32l5))] { + enable!(apb1enr1, set_dac1en, apb1rstr1, set_dac1rst); + } else { + unimplemented!("DAC enable/reset is not yet implemented for this chip"); + } + } }); - if channels >= 1 { - T::regs().cr().modify(|reg| { - reg.set_en1(true); - }); - } - - if channels >= 2 { - T::regs().cr().modify(|reg| { - reg.set_en2(true); - }); - } + T::regs().cr().modify(|reg| { + for ch in 0..channels { + reg.set_en(ch as usize, true); + } + }); } Self { channels, _peri: peri } @@ -156,17 +168,10 @@ impl<'d, T: Instance> Dac<'d, T> { fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { self.check_channel_exists(ch)?; - match ch { - Channel::Ch1 => unsafe { - T::regs().cr().modify(|reg| { - reg.set_en1(on); - }) - }, - Channel::Ch2 => unsafe { - T::regs().cr().modify(|reg| { - reg.set_en2(on); - }); - }, + unsafe { + T::regs().cr().modify(|reg| { + reg.set_en(ch.index(), on); + }) } Ok(()) } @@ -203,17 +208,10 @@ impl<'d, T: Instance> Dac<'d, T> { pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> { self.check_channel_exists(ch)?; - match ch { - Channel::Ch1 => unsafe { - T::regs().swtrigr().write(|reg| { - reg.set_swtrig1(true); - }); - }, - Channel::Ch2 => unsafe { - T::regs().swtrigr().write(|reg| { - reg.set_swtrig2(true); - }) - }, + unsafe { + T::regs().swtrigr().write(|reg| { + reg.set_swtrig(ch.index(), true); + }); } Ok(()) } @@ -221,38 +219,53 @@ impl<'d, T: Instance> Dac<'d, T> { pub fn trigger_all(&mut self) { unsafe { T::regs().swtrigr().write(|reg| { - reg.set_swtrig1(true); - reg.set_swtrig2(true); + reg.set_swtrig(Channel::Ch1.index(), true); + reg.set_swtrig(Channel::Ch2.index(), true); }) } } pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> { self.check_channel_exists(ch)?; - match ch { - Channel::Ch1 => match value { - Value::Bit8(v) => unsafe { - T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v)); - }, - Value::Bit12(v, Alignment::Left) => unsafe { - T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v)); - }, - Value::Bit12(v, Alignment::Right) => unsafe { - T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v)); - }, + match value { + Value::Bit8(v) => unsafe { + T::regs().dhr8r(ch.index()).write(|reg| reg.set_dhr(v)); }, - Channel::Ch2 => match value { - Value::Bit8(v) => unsafe { - T::regs().dhr8r2().write(|reg| reg.set_dacc2dhr(v)); - }, - Value::Bit12(v, Alignment::Left) => unsafe { - T::regs().dhr12l2().write(|reg| reg.set_dacc2dhr(v)); - }, - Value::Bit12(v, Alignment::Right) => unsafe { - T::regs().dhr12r2().write(|reg| reg.set_dacc2dhr(v)); - }, + Value::Bit12(v, Alignment::Left) => unsafe { + T::regs().dhr12l(ch.index()).write(|reg| reg.set_dhr(v)); + }, + Value::Bit12(v, Alignment::Right) => unsafe { + T::regs().dhr12r(ch.index()).write(|reg| reg.set_dhr(v)); }, } Ok(()) } } + +pub(crate) mod sealed { + pub trait Instance { + fn regs() -> &'static crate::pac::dac::Dac; + } +} + +pub trait Instance: sealed::Instance + 'static {} + +pub trait DacPin: crate::gpio::Pin + 'static {} + +foreach_peripheral!( + (dac, $inst:ident) => { + impl crate::dac::sealed::Instance for peripherals::$inst { + fn regs() -> &'static crate::pac::dac::Dac { + &crate::pac::$inst + } + } + + impl crate::dac::Instance for peripherals::$inst {} + }; +); + +macro_rules! impl_dac_pin { + ($inst:ident, $pin:ident, $ch:expr) => { + impl crate::dac::DacPin for crate::peripherals::$pin {} + }; +} diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs deleted file mode 100644 index f1cb452c..00000000 --- a/embassy-stm32/src/dac/mod.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![macro_use] - -#[cfg_attr(dac_v1, path = "v1.rs")] -#[cfg_attr(dac_v2, path = "v2.rs")] -mod _version; -pub use _version::*; - -use crate::peripherals; - -pub(crate) mod sealed { - pub trait Instance { - fn regs() -> &'static crate::pac::dac::Dac; - } -} - -pub trait Instance: sealed::Instance + 'static {} - -pub trait DacPin: crate::gpio::Pin + 'static {} - -foreach_peripheral!( - (dac, $inst:ident) => { - impl crate::dac::sealed::Instance for peripherals::$inst { - fn regs() -> &'static crate::pac::dac::Dac { - &crate::pac::$inst - } - } - - impl crate::dac::Instance for peripherals::$inst {} - }; -); - -macro_rules! impl_dac_pin { - ($inst:ident, $pin:ident, $ch:expr) => { - impl crate::dac::DacPin for crate::peripherals::$pin {} - }; -} diff --git a/embassy-stm32/src/dac/v1.rs b/embassy-stm32/src/dac/v1.rs deleted file mode 100644 index 8b137891..00000000 --- a/embassy-stm32/src/dac/v1.rs +++ /dev/null @@ -1 +0,0 @@ - diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 9ce553b6..638f1eff 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -6,7 +6,7 @@ version = "0.1.0" [dependencies] embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "defmt-timestamp-uptime", "time-tick-32768hz"] } -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103rc", "unstable-pac", "memory-x", "time-driver-any"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] } @@ -20,6 +20,7 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } nb = "1.0.0" +micromath = "2.0.0" [profile.dev] opt-level = "s" diff --git a/examples/stm32f1/src/bin/dac.rs b/examples/stm32f1/src/bin/dac.rs new file mode 100644 index 00000000..392f5bf4 --- /dev/null +++ b/examples/stm32f1/src/bin/dac.rs @@ -0,0 +1,37 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::executor::Spawner; +use embassy_stm32::dac::{Channel, Dac, Value}; +use embassy_stm32::Peripherals; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner, p: Peripherals) -> ! { + info!("Hello World, dude!"); + + let mut dac = Dac::new_1ch(p.DAC, p.PA4); + + loop { + for v in 0..=255 { + unwrap!(dac.set(Channel::Ch1, Value::Bit8(to_sine_wave(v)))); + unwrap!(dac.trigger(Channel::Ch1)); + } + } +} + +use micromath::F32Ext; + +fn to_sine_wave(v: u8) -> u8 { + if v >= 128 { + // top half + let r = 3.14 * ((v - 128) as f32 / 128.0); + (r.sin() * 128.0 + 127.0) as u8 + } else { + // bottom half + let r = 3.14 + 3.14 * (v as f32 / 128.0); + (r.sin() * 128.0 + 127.0) as u8 + } +} diff --git a/stm32-data b/stm32-data index b13ba26f..ac5e65f0 160000 --- a/stm32-data +++ b/stm32-data @@ -1 +1 @@ -Subproject commit b13ba26f6f9b7049097e39ccc7e5e246ac023d15 +Subproject commit ac5e65f02a48a443b160e08e8db4bbd7c7787ab4 From d990740dd5f04980006196c5a416416679d7b457 Mon Sep 17 00:00:00 2001 From: chemicstry Date: Thu, 4 Aug 2022 03:07:42 +0300 Subject: [PATCH 2/5] Restore F1 example chip --- examples/stm32f1/Cargo.toml | 2 +- examples/stm32f1/src/bin/dac.rs | 37 --------------------------------- 2 files changed, 1 insertion(+), 38 deletions(-) delete mode 100644 examples/stm32f1/src/bin/dac.rs diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 638f1eff..6e77497a 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -6,7 +6,7 @@ version = "0.1.0" [dependencies] embassy-util = { version = "0.1.0", path = "../../embassy-util", features = ["defmt"] } embassy-executor = { version = "0.1.0", path = "../../embassy-executor", features = ["defmt", "defmt-timestamp-uptime", "time-tick-32768hz"] } -embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103rc", "unstable-pac", "memory-x", "time-driver-any"] } +embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["nightly", "defmt", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-any"] } embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } embassy-usb-serial = { version = "0.1.0", path = "../../embassy-usb-serial", features = ["defmt"] } diff --git a/examples/stm32f1/src/bin/dac.rs b/examples/stm32f1/src/bin/dac.rs deleted file mode 100644 index 392f5bf4..00000000 --- a/examples/stm32f1/src/bin/dac.rs +++ /dev/null @@ -1,37 +0,0 @@ -#![no_std] -#![no_main] -#![feature(type_alias_impl_trait)] - -use defmt::*; -use embassy_executor::executor::Spawner; -use embassy_stm32::dac::{Channel, Dac, Value}; -use embassy_stm32::Peripherals; -use {defmt_rtt as _, panic_probe as _}; - -#[embassy_executor::main] -async fn main(_spawner: Spawner, p: Peripherals) -> ! { - info!("Hello World, dude!"); - - let mut dac = Dac::new_1ch(p.DAC, p.PA4); - - loop { - for v in 0..=255 { - unwrap!(dac.set(Channel::Ch1, Value::Bit8(to_sine_wave(v)))); - unwrap!(dac.trigger(Channel::Ch1)); - } - } -} - -use micromath::F32Ext; - -fn to_sine_wave(v: u8) -> u8 { - if v >= 128 { - // top half - let r = 3.14 * ((v - 128) as f32 / 128.0); - (r.sin() * 128.0 + 127.0) as u8 - } else { - // bottom half - let r = 3.14 + 3.14 * (v as f32 / 128.0); - (r.sin() * 128.0 + 127.0) as u8 - } -} From 206b7fd8edd6503ddf728d9c232ad395896990e4 Mon Sep 17 00:00:00 2001 From: chemicstry Date: Thu, 4 Aug 2022 03:31:47 +0300 Subject: [PATCH 3/5] Use RccPeripheral for DAC and add a hackfix for H7 --- embassy-stm32/src/dac.rs | 67 ++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/embassy-stm32/src/dac.rs b/embassy-stm32/src/dac.rs index c0369d97..60e856c7 100644 --- a/embassy-stm32/src/dac.rs +++ b/embassy-stm32/src/dac.rs @@ -1,9 +1,9 @@ #![macro_use] -use cfg_if::cfg_if; use embassy_hal_common::{into_ref, PeripheralRef}; use crate::pac::dac; +use crate::rcc::RccPeripheral; use crate::{peripherals, Peripheral}; #[derive(Debug, Copy, Clone, Eq, PartialEq)] @@ -102,14 +102,6 @@ pub struct Dac<'d, T: Instance> { _peri: PeripheralRef<'d, T>, } -macro_rules! enable { - ($enable_reg:ident, $enable_field:ident, $reset_reg:ident, $reset_field:ident) => { - crate::pac::RCC.$enable_reg().modify(|w| w.$enable_field(true)); - crate::pac::RCC.$reset_reg().modify(|w| w.$reset_field(true)); - crate::pac::RCC.$reset_reg().modify(|w| w.$reset_field(false)); - }; -} - impl<'d, T: Instance> Dac<'d, T> { pub fn new_1ch(peri: impl Peripheral

+ 'd, _ch1: impl Peripheral

> + 'd) -> Self { into_ref!(peri); @@ -126,27 +118,10 @@ impl<'d, T: Instance> Dac<'d, T> { } fn new_inner(peri: PeripheralRef<'d, T>, channels: u8) -> Self { - unsafe { - // Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock - // configuration. - critical_section::with(|_| { - cfg_if! { - if #[cfg(rcc_f1)] { - enable!(apb1enr, set_dacen, apb1rstr, set_dacrst); - } else if #[cfg(rcc_h7)] { - enable!(apb1lenr, set_dac12en, apb1lrstr, set_dac12rst); - } else if #[cfg(rcc_h7ab)] { - enable!(apb1lenr, set_dac1en, apb1lrstr, set_dac1rst); - } else if #[cfg(stm32g0)] { - enable!(apbenr1, set_dac1en, apbrstr1, set_dac1rst); - } else if #[cfg(any(stm32l4, stm32l5))] { - enable!(apb1enr1, set_dac1en, apb1rstr1, set_dac1rst); - } else { - unimplemented!("DAC enable/reset is not yet implemented for this chip"); - } - } - }); + T::enable(); + T::reset(); + unsafe { T::regs().cr().modify(|reg| { for ch in 0..channels { reg.set_en(ch as usize, true); @@ -248,12 +223,44 @@ pub(crate) mod sealed { } } -pub trait Instance: sealed::Instance + 'static {} +pub trait Instance: sealed::Instance + RccPeripheral + 'static {} pub trait DacPin: crate::gpio::Pin + 'static {} foreach_peripheral!( (dac, $inst:ident) => { + // H7 uses single bit for both DAC1 and DAC2, this is a hack until a proper fix is implemented + #[cfg(rcc_h7)] + impl crate::rcc::sealed::RccPeripheral for peripherals::$inst { + fn frequency() -> crate::time::Hertz { + critical_section::with(|_| unsafe { + crate::rcc::get_freqs().apb1 + }) + } + + fn reset() { + critical_section::with(|_| unsafe { + crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true)); + crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false)); + }) + } + + fn enable() { + critical_section::with(|_| unsafe { + crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true)); + }) + } + + fn disable() { + critical_section::with(|_| unsafe { + crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false)); + }) + } + } + + #[cfg(rcc_h7)] + impl crate::rcc::RccPeripheral for peripherals::$inst {} + impl crate::dac::sealed::Instance for peripherals::$inst { fn regs() -> &'static crate::pac::dac::Dac { &crate::pac::$inst From 8a25906eff30951e68969c67aabc16ac55826c39 Mon Sep 17 00:00:00 2001 From: chemicstry Date: Thu, 4 Aug 2022 03:31:59 +0300 Subject: [PATCH 4/5] Add DACv1 example for F4 --- examples/stm32f1/Cargo.toml | 1 - examples/stm32f4/Cargo.toml | 1 + examples/stm32f4/src/bin/dac.rs | 37 +++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 examples/stm32f4/src/bin/dac.rs diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml index 6e77497a..9ce553b6 100644 --- a/examples/stm32f1/Cargo.toml +++ b/examples/stm32f1/Cargo.toml @@ -20,7 +20,6 @@ panic-probe = { version = "0.3", features = ["print-defmt"] } futures = { version = "0.3.17", default-features = false, features = ["async-await"] } heapless = { version = "0.7.5", default-features = false } nb = "1.0.0" -micromath = "2.0.0" [profile.dev] opt-level = "s" diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml index 37464b1e..3c58320d 100644 --- a/examples/stm32f4/Cargo.toml +++ b/examples/stm32f4/Cargo.toml @@ -21,6 +21,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa heapless = { version = "0.7.5", default-features = false } nb = "1.0.0" embedded-storage = "0.3.0" +micromath = "2.0.0" usb-device = "0.2" usbd-serial = "0.1.1" diff --git a/examples/stm32f4/src/bin/dac.rs b/examples/stm32f4/src/bin/dac.rs new file mode 100644 index 00000000..392f5bf4 --- /dev/null +++ b/examples/stm32f4/src/bin/dac.rs @@ -0,0 +1,37 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::executor::Spawner; +use embassy_stm32::dac::{Channel, Dac, Value}; +use embassy_stm32::Peripherals; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner, p: Peripherals) -> ! { + info!("Hello World, dude!"); + + let mut dac = Dac::new_1ch(p.DAC, p.PA4); + + loop { + for v in 0..=255 { + unwrap!(dac.set(Channel::Ch1, Value::Bit8(to_sine_wave(v)))); + unwrap!(dac.trigger(Channel::Ch1)); + } + } +} + +use micromath::F32Ext; + +fn to_sine_wave(v: u8) -> u8 { + if v >= 128 { + // top half + let r = 3.14 * ((v - 128) as f32 / 128.0); + (r.sin() * 128.0 + 127.0) as u8 + } else { + // bottom half + let r = 3.14 + 3.14 * (v as f32 / 128.0); + (r.sin() * 128.0 + 127.0) as u8 + } +} From ed74bcb8d8b3414dc041ee0cbdf544a6604a5f25 Mon Sep 17 00:00:00 2001 From: chemicstry Date: Mon, 8 Aug 2022 13:14:13 +0300 Subject: [PATCH 5/5] Update stm32-data --- stm32-data | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stm32-data b/stm32-data index ac5e65f0..758c9e74 160000 --- a/stm32-data +++ b/stm32-data @@ -1 +1 @@ -Subproject commit ac5e65f02a48a443b160e08e8db4bbd7c7787ab4 +Subproject commit 758c9e74625c68bc23d66ced8bfeb5643c63cec9