aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/dac.rs (renamed from embassy-stm32/src/dac/v2.rs)176
-rw-r--r--embassy-stm32/src/dac/mod.rs36
-rw-r--r--embassy-stm32/src/dac/v1.rs1
-rw-r--r--examples/stm32f4/Cargo.toml1
-rw-r--r--examples/stm32f4/src/bin/dac.rs37
m---------stm32-data0
6 files changed, 136 insertions, 115 deletions
diff --git a/embassy-stm32/src/dac/v2.rs b/embassy-stm32/src/dac.rs
index 6b7f41c63..60e856c78 100644
--- a/embassy-stm32/src/dac/v2.rs
+++ b/embassy-stm32/src/dac.rs
@@ -1,8 +1,10 @@
1#![macro_use]
2
1use embassy_hal_common::{into_ref, PeripheralRef}; 3use embassy_hal_common::{into_ref, PeripheralRef};
2 4
3use crate::dac::{DacPin, Instance};
4use crate::pac::dac; 5use crate::pac::dac;
5use crate::Peripheral; 6use crate::rcc::RccPeripheral;
7use crate::{peripherals, Peripheral};
6 8
7#[derive(Debug, Copy, Clone, Eq, PartialEq)] 9#[derive(Debug, Copy, Clone, Eq, PartialEq)]
8#[cfg_attr(feature = "defmt", derive(defmt::Format))] 10#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -18,6 +20,15 @@ pub enum Channel {
18 Ch2, 20 Ch2,
19} 21}
20 22
23impl Channel {
24 fn index(&self) -> usize {
25 match self {
26 Channel::Ch1 => 0,
27 Channel::Ch2 => 1,
28 }
29 }
30}
31
21#[derive(Debug, Copy, Clone, Eq, PartialEq)] 32#[derive(Debug, Copy, Clone, Eq, PartialEq)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))] 33#[cfg_attr(feature = "defmt", derive(defmt::Format))]
23pub enum Ch1Trigger { 34pub enum Ch1Trigger {
@@ -91,14 +102,6 @@ pub struct Dac<'d, T: Instance> {
91 _peri: PeripheralRef<'d, T>, 102 _peri: PeripheralRef<'d, T>,
92} 103}
93 104
94macro_rules! enable {
95 ($enable_reg:ident, $enable_field:ident, $reset_reg:ident, $reset_field:ident) => {
96 crate::pac::RCC.$enable_reg().modify(|w| w.$enable_field(true));
97 crate::pac::RCC.$reset_reg().modify(|w| w.$reset_field(true));
98 crate::pac::RCC.$reset_reg().modify(|w| w.$reset_field(false));
99 };
100}
101
102impl<'d, T: Instance> Dac<'d, T> { 105impl<'d, T: Instance> Dac<'d, T> {
103 pub fn new_1ch(peri: impl Peripheral<P = T> + 'd, _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd) -> Self { 106 pub fn new_1ch(peri: impl Peripheral<P = T> + 'd, _ch1: impl Peripheral<P = impl DacPin<T, 1>> + 'd) -> Self {
104 into_ref!(peri); 107 into_ref!(peri);
@@ -115,31 +118,15 @@ impl<'d, T: Instance> Dac<'d, T> {
115 } 118 }
116 119
117 fn new_inner(peri: PeripheralRef<'d, T>, channels: u8) -> Self { 120 fn new_inner(peri: PeripheralRef<'d, T>, channels: u8) -> Self {
121 T::enable();
122 T::reset();
123
118 unsafe { 124 unsafe {
119 // Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock 125 T::regs().cr().modify(|reg| {
120 // configuration. 126 for ch in 0..channels {
121 critical_section::with(|_| { 127 reg.set_en(ch as usize, true);
122 #[cfg(rcc_h7)] 128 }
123 enable!(apb1lenr, set_dac12en, apb1lrstr, set_dac12rst);
124 #[cfg(rcc_h7ab)]
125 enable!(apb1lenr, set_dac1en, apb1lrstr, set_dac1rst);
126 #[cfg(stm32g0)]
127 enable!(apbenr1, set_dac1en, apbrstr1, set_dac1rst);
128 #[cfg(any(stm32l4, stm32l5))]
129 enable!(apb1enr1, set_dac1en, apb1rstr1, set_dac1rst);
130 }); 129 });
131
132 if channels >= 1 {
133 T::regs().cr().modify(|reg| {
134 reg.set_en1(true);
135 });
136 }
137
138 if channels >= 2 {
139 T::regs().cr().modify(|reg| {
140 reg.set_en2(true);
141 });
142 }
143 } 130 }
144 131
145 Self { channels, _peri: peri } 132 Self { channels, _peri: peri }
@@ -156,17 +143,10 @@ impl<'d, T: Instance> Dac<'d, T> {
156 143
157 fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> { 144 fn set_channel_enable(&mut self, ch: Channel, on: bool) -> Result<(), Error> {
158 self.check_channel_exists(ch)?; 145 self.check_channel_exists(ch)?;
159 match ch { 146 unsafe {
160 Channel::Ch1 => unsafe { 147 T::regs().cr().modify(|reg| {
161 T::regs().cr().modify(|reg| { 148 reg.set_en(ch.index(), on);
162 reg.set_en1(on); 149 })
163 })
164 },
165 Channel::Ch2 => unsafe {
166 T::regs().cr().modify(|reg| {
167 reg.set_en2(on);
168 });
169 },
170 } 150 }
171 Ok(()) 151 Ok(())
172 } 152 }
@@ -203,17 +183,10 @@ impl<'d, T: Instance> Dac<'d, T> {
203 183
204 pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> { 184 pub fn trigger(&mut self, ch: Channel) -> Result<(), Error> {
205 self.check_channel_exists(ch)?; 185 self.check_channel_exists(ch)?;
206 match ch { 186 unsafe {
207 Channel::Ch1 => unsafe { 187 T::regs().swtrigr().write(|reg| {
208 T::regs().swtrigr().write(|reg| { 188 reg.set_swtrig(ch.index(), true);
209 reg.set_swtrig1(true); 189 });
210 });
211 },
212 Channel::Ch2 => unsafe {
213 T::regs().swtrigr().write(|reg| {
214 reg.set_swtrig2(true);
215 })
216 },
217 } 190 }
218 Ok(()) 191 Ok(())
219 } 192 }
@@ -221,38 +194,85 @@ impl<'d, T: Instance> Dac<'d, T> {
221 pub fn trigger_all(&mut self) { 194 pub fn trigger_all(&mut self) {
222 unsafe { 195 unsafe {
223 T::regs().swtrigr().write(|reg| { 196 T::regs().swtrigr().write(|reg| {
224 reg.set_swtrig1(true); 197 reg.set_swtrig(Channel::Ch1.index(), true);
225 reg.set_swtrig2(true); 198 reg.set_swtrig(Channel::Ch2.index(), true);
226 }) 199 })
227 } 200 }
228 } 201 }
229 202
230 pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> { 203 pub fn set(&mut self, ch: Channel, value: Value) -> Result<(), Error> {
231 self.check_channel_exists(ch)?; 204 self.check_channel_exists(ch)?;
232 match ch { 205 match value {
233 Channel::Ch1 => match value { 206 Value::Bit8(v) => unsafe {
234 Value::Bit8(v) => unsafe { 207 T::regs().dhr8r(ch.index()).write(|reg| reg.set_dhr(v));
235 T::regs().dhr8r1().write(|reg| reg.set_dacc1dhr(v)); 208 },
236 }, 209 Value::Bit12(v, Alignment::Left) => unsafe {
237 Value::Bit12(v, Alignment::Left) => unsafe { 210 T::regs().dhr12l(ch.index()).write(|reg| reg.set_dhr(v));
238 T::regs().dhr12l1().write(|reg| reg.set_dacc1dhr(v));
239 },
240 Value::Bit12(v, Alignment::Right) => unsafe {
241 T::regs().dhr12r1().write(|reg| reg.set_dacc1dhr(v));
242 },
243 }, 211 },
244 Channel::Ch2 => match value { 212 Value::Bit12(v, Alignment::Right) => unsafe {
245 Value::Bit8(v) => unsafe { 213 T::regs().dhr12r(ch.index()).write(|reg| reg.set_dhr(v));
246 T::regs().dhr8r2().write(|reg| reg.set_dacc2dhr(v));
247 },
248 Value::Bit12(v, Alignment::Left) => unsafe {
249 T::regs().dhr12l2().write(|reg| reg.set_dacc2dhr(v));
250 },
251 Value::Bit12(v, Alignment::Right) => unsafe {
252 T::regs().dhr12r2().write(|reg| reg.set_dacc2dhr(v));
253 },
254 }, 214 },
255 } 215 }
256 Ok(()) 216 Ok(())
257 } 217 }
258} 218}
219
220pub(crate) mod sealed {
221 pub trait Instance {
222 fn regs() -> &'static crate::pac::dac::Dac;
223 }
224}
225
226pub trait Instance: sealed::Instance + RccPeripheral + 'static {}
227
228pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {}
229
230foreach_peripheral!(
231 (dac, $inst:ident) => {
232 // H7 uses single bit for both DAC1 and DAC2, this is a hack until a proper fix is implemented
233 #[cfg(rcc_h7)]
234 impl crate::rcc::sealed::RccPeripheral for peripherals::$inst {
235 fn frequency() -> crate::time::Hertz {
236 critical_section::with(|_| unsafe {
237 crate::rcc::get_freqs().apb1
238 })
239 }
240
241 fn reset() {
242 critical_section::with(|_| unsafe {
243 crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(true));
244 crate::pac::RCC.apb1lrstr().modify(|w| w.set_dac12rst(false));
245 })
246 }
247
248 fn enable() {
249 critical_section::with(|_| unsafe {
250 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true));
251 })
252 }
253
254 fn disable() {
255 critical_section::with(|_| unsafe {
256 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(false));
257 })
258 }
259 }
260
261 #[cfg(rcc_h7)]
262 impl crate::rcc::RccPeripheral for peripherals::$inst {}
263
264 impl crate::dac::sealed::Instance for peripherals::$inst {
265 fn regs() -> &'static crate::pac::dac::Dac {
266 &crate::pac::$inst
267 }
268 }
269
270 impl crate::dac::Instance for peripherals::$inst {}
271 };
272);
273
274macro_rules! impl_dac_pin {
275 ($inst:ident, $pin:ident, $ch:expr) => {
276 impl crate::dac::DacPin<peripherals::$inst, $ch> for crate::peripherals::$pin {}
277 };
278}
diff --git a/embassy-stm32/src/dac/mod.rs b/embassy-stm32/src/dac/mod.rs
deleted file mode 100644
index f1cb452c7..000000000
--- a/embassy-stm32/src/dac/mod.rs
+++ /dev/null
@@ -1,36 +0,0 @@
1#![macro_use]
2
3#[cfg_attr(dac_v1, path = "v1.rs")]
4#[cfg_attr(dac_v2, path = "v2.rs")]
5mod _version;
6pub use _version::*;
7
8use crate::peripherals;
9
10pub(crate) mod sealed {
11 pub trait Instance {
12 fn regs() -> &'static crate::pac::dac::Dac;
13 }
14}
15
16pub trait Instance: sealed::Instance + 'static {}
17
18pub trait DacPin<T: Instance, const C: u8>: crate::gpio::Pin + 'static {}
19
20foreach_peripheral!(
21 (dac, $inst:ident) => {
22 impl crate::dac::sealed::Instance for peripherals::$inst {
23 fn regs() -> &'static crate::pac::dac::Dac {
24 &crate::pac::$inst
25 }
26 }
27
28 impl crate::dac::Instance for peripherals::$inst {}
29 };
30);
31
32macro_rules! impl_dac_pin {
33 ($inst:ident, $pin:ident, $ch:expr) => {
34 impl crate::dac::DacPin<peripherals::$inst, $ch> for crate::peripherals::$pin {}
35 };
36}
diff --git a/embassy-stm32/src/dac/v1.rs b/embassy-stm32/src/dac/v1.rs
deleted file mode 100644
index 8b1378917..000000000
--- a/embassy-stm32/src/dac/v1.rs
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml
index 37464b1e0..3c58320dd 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
21heapless = { version = "0.7.5", default-features = false } 21heapless = { version = "0.7.5", default-features = false }
22nb = "1.0.0" 22nb = "1.0.0"
23embedded-storage = "0.3.0" 23embedded-storage = "0.3.0"
24micromath = "2.0.0"
24 25
25usb-device = "0.2" 26usb-device = "0.2"
26usbd-serial = "0.1.1" 27usbd-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 000000000..392f5bf4d
--- /dev/null
+++ b/examples/stm32f4/src/bin/dac.rs
@@ -0,0 +1,37 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::executor::Spawner;
7use embassy_stm32::dac::{Channel, Dac, Value};
8use embassy_stm32::Peripherals;
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner, p: Peripherals) -> ! {
13 info!("Hello World, dude!");
14
15 let mut dac = Dac::new_1ch(p.DAC, p.PA4);
16
17 loop {
18 for v in 0..=255 {
19 unwrap!(dac.set(Channel::Ch1, Value::Bit8(to_sine_wave(v))));
20 unwrap!(dac.trigger(Channel::Ch1));
21 }
22 }
23}
24
25use micromath::F32Ext;
26
27fn to_sine_wave(v: u8) -> u8 {
28 if v >= 128 {
29 // top half
30 let r = 3.14 * ((v - 128) as f32 / 128.0);
31 (r.sin() * 128.0 + 127.0) as u8
32 } else {
33 // bottom half
34 let r = 3.14 + 3.14 * (v as f32 / 128.0);
35 (r.sin() * 128.0 + 127.0) as u8
36 }
37}
diff --git a/stm32-data b/stm32-data
Subproject b13ba26f6f9b7049097e39ccc7e5e246ac023d1 Subproject 758c9e74625c68bc23d66ced8bfeb5643c63cec