aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-08-08 11:37:41 +0000
committerGitHub <[email protected]>2022-08-08 11:37:41 +0000
commitb7b4c84067e0e85fa641a540458438297176f2e4 (patch)
tree73a659ae11498729a252cddc4e48b57e4ed6176a
parentb400e6aa75f8b629a948c891447e2aab49f57a42 (diff)
parented74bcb8d8b3414dc041ee0cbdf544a6604a5f25 (diff)
Merge #892
892: Merge v1, v2 DAC and update register definitions r=Dirbaio a=chemicstry This merges v1 (unimplemented) and v2 DAC implementations, because they share most of the code except for some exotic stuff, which is not yet implemented for neither of the versions. This should allow using DAC on all chips that have v1 peripheral. ~Currently blocked on https://github.com/embassy-rs/stm32-data/pull/153~ Co-authored-by: chemicstry <[email protected]>
-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