aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-09-29 06:58:33 +0200
committerGitHub <[email protected]>2021-09-29 06:58:33 +0200
commitd9e2d176256ef4959c1ba60893ea361363d480d3 (patch)
treede6fcb6723eb424fdcd364f4e2e20535ade78a6c
parentb6f84efd90b3c2751e6fe03183229d1a7d456091 (diff)
parent006bbea51afeeb01fac8c7adb3ae0ff549d4ecf0 (diff)
Merge pull request #380 from bgamari/stm32g0-adc
Fix STM32G0 ADC
-rw-r--r--embassy-stm32/src/adc/g0.rs1
-rw-r--r--embassy-stm32/src/adc/mod.rs5
-rw-r--r--embassy-stm32/src/adc/v3.rs250
-rw-r--r--embassy-stm32/src/dac/v2.rs15
-rw-r--r--embassy-stm32/src/rcc/g0/mod.rs57
5 files changed, 251 insertions, 77 deletions
diff --git a/embassy-stm32/src/adc/g0.rs b/embassy-stm32/src/adc/g0.rs
deleted file mode 100644
index 8b1378917..000000000
--- a/embassy-stm32/src/adc/g0.rs
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index 9955502a6..f292d0208 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -1,7 +1,7 @@
1#![macro_use] 1#![macro_use]
2 2
3#[cfg_attr(adc_v3, path = "v3.rs")] 3#[cfg_attr(adc_v3, path = "v3.rs")]
4#[cfg_attr(adc_g0, path = "g0.rs")] 4#[cfg_attr(adc_g0, path = "v3.rs")]
5mod _version; 5mod _version;
6 6
7#[allow(unused)] 7#[allow(unused)]
@@ -72,6 +72,9 @@ macro_rules! impl_pin {
72} 72}
73 73
74crate::pac::peripheral_pins!( 74crate::pac::peripheral_pins!(
75 ($inst:ident, adc, ADC, $pin:ident, IN0) => {
76 impl_pin!($inst, $pin, 0);
77 };
75 ($inst:ident, adc, ADC, $pin:ident, IN1) => { 78 ($inst:ident, adc, ADC, $pin:ident, IN1) => {
76 impl_pin!($inst, $pin, 1); 79 impl_pin!($inst, $pin, 1);
77 }; 80 };
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 2781fc4dc..ddf06deae 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -6,6 +6,17 @@ use embedded_hal::blocking::delay::DelayUs;
6 6
7pub const VDDA_CALIB_MV: u32 = 3000; 7pub const VDDA_CALIB_MV: u32 = 3000;
8 8
9/// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent ADC clock
10/// configuration.
11unsafe fn enable() {
12 #[cfg(rcc_h7)]
13 crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true));
14 #[cfg(rcc_g0)]
15 crate::pac::RCC.apbenr2().modify(|w| w.set_adcen(true));
16 #[cfg(rcc_l4)]
17 crate::pac::RCC.ahb2enr().modify(|w| w.set_adcen(true));
18}
19
9pub enum Resolution { 20pub enum Resolution {
10 TwelveBit, 21 TwelveBit,
11 TenBit, 22 TenBit,
@@ -43,7 +54,11 @@ pub struct Vref;
43impl<T: Instance> AdcPin<T> for Vref {} 54impl<T: Instance> AdcPin<T> for Vref {}
44impl<T: Instance> super::sealed::AdcPin<T> for Vref { 55impl<T: Instance> super::sealed::AdcPin<T> for Vref {
45 fn channel(&self) -> u8 { 56 fn channel(&self) -> u8 {
46 0 57 #[cfg(not(rcc_g0))]
58 let val = 0;
59 #[cfg(rcc_g0)]
60 let val = 13;
61 val
47 } 62 }
48} 63}
49 64
@@ -51,7 +66,11 @@ pub struct Temperature;
51impl<T: Instance> AdcPin<T> for Temperature {} 66impl<T: Instance> AdcPin<T> for Temperature {}
52impl<T: Instance> super::sealed::AdcPin<T> for Temperature { 67impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
53 fn channel(&self) -> u8 { 68 fn channel(&self) -> u8 {
54 17 69 #[cfg(not(rcc_g0))]
70 let val = 17;
71 #[cfg(rcc_g0)]
72 let val = 12;
73 val
55 } 74 }
56} 75}
57 76
@@ -59,61 +78,124 @@ pub struct Vbat;
59impl<T: Instance> AdcPin<T> for Vbat {} 78impl<T: Instance> AdcPin<T> for Vbat {}
60impl<T: Instance> super::sealed::AdcPin<T> for Vbat { 79impl<T: Instance> super::sealed::AdcPin<T> for Vbat {
61 fn channel(&self) -> u8 { 80 fn channel(&self) -> u8 {
62 18 81 #[cfg(not(rcc_g0))]
82 let val = 18;
83 #[cfg(rcc_g0)]
84 let val = 14;
85 val
63 } 86 }
64} 87}
65 88
66/// ADC sample time 89#[cfg(not(adc_g0))]
67/// 90mod sample_time {
68/// The default setting is 2.5 ADC clock cycles. 91 /// ADC sample time
69#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] 92 ///
70pub enum SampleTime { 93 /// The default setting is 2.5 ADC clock cycles.
71 /// 2.5 ADC clock cycles 94 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
72 Cycles2_5 = 0b000, 95 pub enum SampleTime {
96 /// 2.5 ADC clock cycles
97 Cycles2_5 = 0b000,
73 98
74 /// 6.5 ADC clock cycles 99 /// 6.5 ADC clock cycles
75 Cycles6_5 = 0b001, 100 Cycles6_5 = 0b001,
76 101
77 /// 12.5 ADC clock cycles 102 /// 12.5 ADC clock cycles
78 Cycles12_5 = 0b010, 103 Cycles12_5 = 0b010,
79 104
80 /// 24.5 ADC clock cycles 105 /// 24.5 ADC clock cycles
81 Cycles24_5 = 0b011, 106 Cycles24_5 = 0b011,
82 107
83 /// 47.5 ADC clock cycles 108 /// 47.5 ADC clock cycles
84 Cycles47_5 = 0b100, 109 Cycles47_5 = 0b100,
85 110
86 /// 92.5 ADC clock cycles 111 /// 92.5 ADC clock cycles
87 Cycles92_5 = 0b101, 112 Cycles92_5 = 0b101,
88 113
89 /// 247.5 ADC clock cycles 114 /// 247.5 ADC clock cycles
90 Cycles247_5 = 0b110, 115 Cycles247_5 = 0b110,
91 116
92 /// 640.5 ADC clock cycles 117 /// 640.5 ADC clock cycles
93 Cycles640_5 = 0b111, 118 Cycles640_5 = 0b111,
94} 119 }
95 120
96impl SampleTime { 121 impl SampleTime {
97 fn sample_time(&self) -> crate::pac::adc::vals::SampleTime { 122 pub(crate) fn sample_time(&self) -> crate::pac::adc::vals::SampleTime {
98 match self { 123 match self {
99 SampleTime::Cycles2_5 => crate::pac::adc::vals::SampleTime::CYCLES2_5, 124 SampleTime::Cycles2_5 => crate::pac::adc::vals::SampleTime::CYCLES2_5,
100 SampleTime::Cycles6_5 => crate::pac::adc::vals::SampleTime::CYCLES6_5, 125 SampleTime::Cycles6_5 => crate::pac::adc::vals::SampleTime::CYCLES6_5,
101 SampleTime::Cycles12_5 => crate::pac::adc::vals::SampleTime::CYCLES12_5, 126 SampleTime::Cycles12_5 => crate::pac::adc::vals::SampleTime::CYCLES12_5,
102 SampleTime::Cycles24_5 => crate::pac::adc::vals::SampleTime::CYCLES24_5, 127 SampleTime::Cycles24_5 => crate::pac::adc::vals::SampleTime::CYCLES24_5,
103 SampleTime::Cycles47_5 => crate::pac::adc::vals::SampleTime::CYCLES47_5, 128 SampleTime::Cycles47_5 => crate::pac::adc::vals::SampleTime::CYCLES47_5,
104 SampleTime::Cycles92_5 => crate::pac::adc::vals::SampleTime::CYCLES92_5, 129 SampleTime::Cycles92_5 => crate::pac::adc::vals::SampleTime::CYCLES92_5,
105 SampleTime::Cycles247_5 => crate::pac::adc::vals::SampleTime::CYCLES247_5, 130 SampleTime::Cycles247_5 => crate::pac::adc::vals::SampleTime::CYCLES247_5,
106 SampleTime::Cycles640_5 => crate::pac::adc::vals::SampleTime::CYCLES640_5, 131 SampleTime::Cycles640_5 => crate::pac::adc::vals::SampleTime::CYCLES640_5,
132 }
133 }
134 }
135
136 impl Default for SampleTime {
137 fn default() -> Self {
138 Self::Cycles2_5
107 } 139 }
108 } 140 }
109} 141}
110 142
111impl Default for SampleTime { 143#[cfg(adc_g0)]
112 fn default() -> Self { 144mod sample_time {
113 Self::Cycles2_5 145 /// ADC sample time
146 ///
147 /// The default setting is 1.5 ADC clock cycles.
148 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
149 pub enum SampleTime {
150 /// 1.5 ADC clock cycles
151 Cycles1_5 = 0b000,
152
153 /// 3.5 ADC clock cycles
154 Cycles3_5 = 0b001,
155
156 /// 7.5 ADC clock cycles
157 Cycles7_5 = 0b010,
158
159 /// 12.5 ADC clock cycles
160 Cycles12_5 = 0b011,
161
162 /// 19.5 ADC clock cycles
163 Cycles19_5 = 0b100,
164
165 /// 39.5 ADC clock cycles
166 Cycles39_5 = 0b101,
167
168 /// 79.5 ADC clock cycles
169 Cycles79_5 = 0b110,
170
171 /// 160.5 ADC clock cycles
172 Cycles160_5 = 0b111,
173 }
174
175 impl SampleTime {
176 pub(crate) fn sample_time(&self) -> crate::pac::adc::vals::SampleTime {
177 match self {
178 SampleTime::Cycles1_5 => crate::pac::adc::vals::SampleTime::CYCLES1_5,
179 SampleTime::Cycles3_5 => crate::pac::adc::vals::SampleTime::CYCLES3_5,
180 SampleTime::Cycles7_5 => crate::pac::adc::vals::SampleTime::CYCLES7_5,
181 SampleTime::Cycles12_5 => crate::pac::adc::vals::SampleTime::CYCLES12_5,
182 SampleTime::Cycles19_5 => crate::pac::adc::vals::SampleTime::CYCLES19_5,
183 SampleTime::Cycles39_5 => crate::pac::adc::vals::SampleTime::CYCLES39_5,
184 SampleTime::Cycles79_5 => crate::pac::adc::vals::SampleTime::CYCLES79_5,
185 SampleTime::Cycles160_5 => crate::pac::adc::vals::SampleTime::CYCLES160_5,
186 }
187 }
188 }
189
190 impl Default for SampleTime {
191 fn default() -> Self {
192 Self::Cycles1_5
193 }
114 } 194 }
115} 195}
116 196
197pub use sample_time::SampleTime;
198
117pub struct Adc<'d, T: Instance> { 199pub struct Adc<'d, T: Instance> {
118 sample_time: SampleTime, 200 sample_time: SampleTime,
119 calibrated_vdda: u32, 201 calibrated_vdda: u32,
@@ -125,15 +207,26 @@ impl<'d, T: Instance> Adc<'d, T> {
125 pub fn new(_peri: impl Unborrow<Target = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self { 207 pub fn new(_peri: impl Unborrow<Target = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self {
126 unborrow!(_peri); 208 unborrow!(_peri);
127 unsafe { 209 unsafe {
210 enable();
128 T::regs().cr().modify(|reg| { 211 T::regs().cr().modify(|reg| {
212 #[cfg(not(adc_g0))]
129 reg.set_deeppwd(false); 213 reg.set_deeppwd(false);
130 reg.set_advregen(true); 214 reg.set_advregen(true);
131 }); 215 });
216
217 #[cfg(adc_g0)]
218 T::regs().cfgr1().modify(|reg| {
219 reg.set_chselrmod(true);
220 });
132 } 221 }
133 222
134 delay.delay_us(20); 223 delay.delay_us(20);
135 224
136 unsafe { 225 unsafe {
226 T::regs().cr().modify(|reg| {
227 reg.set_adcal(true);
228 });
229
137 while T::regs().cr().read().adcal() { 230 while T::regs().cr().read().adcal() {
138 // spin 231 // spin
139 } 232 }
@@ -229,6 +322,27 @@ impl<'d, T: Instance> Adc<'d, T> {
229 } 322 }
230 */ 323 */
231 324
325 /// Perform a single conversion.
326 fn convert(&mut self) -> u16 {
327 unsafe {
328 T::regs().isr().modify(|reg| {
329 reg.set_eos(true);
330 reg.set_eoc(true);
331 });
332
333 // Start conversion
334 T::regs().cr().modify(|reg| {
335 reg.set_adstart(true);
336 });
337
338 while !T::regs().isr().read().eos() {
339 // spin
340 }
341
342 T::regs().dr().read().0 as u16
343 }
344 }
345
232 pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 { 346 pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
233 unsafe { 347 unsafe {
234 // Make sure bits are off 348 // Make sure bits are off
@@ -249,48 +363,36 @@ impl<'d, T: Instance> Adc<'d, T> {
249 } 363 }
250 364
251 // Configure ADC 365 // Configure ADC
366 #[cfg(not(rcc_g0))]
252 T::regs() 367 T::regs()
253 .cfgr() 368 .cfgr()
254 .modify(|reg| reg.set_res(self.resolution.res())); 369 .modify(|reg| reg.set_res(self.resolution.res()));
370 #[cfg(rcc_g0)]
371 T::regs()
372 .cfgr1()
373 .modify(|reg| reg.set_res(self.resolution.res()));
255 374
256 // Configure channel 375 // Configure channel
257 Self::set_channel_sample_time(pin.channel(), self.sample_time); 376 Self::set_channel_sample_time(pin.channel(), self.sample_time);
258 377
259 // Select channel 378 // Select channel
379 #[cfg(not(rcc_g0))]
260 T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel())); 380 T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel()));
381 #[cfg(rcc_g0)]
382 T::regs()
383 .chselr()
384 .write(|reg| reg.set_chsel(pin.channel() as u32));
261 385
262 // Start conversion 386 // Some models are affected by an erratum:
263 T::regs().isr().modify(|reg| { 387 // If we perform conversions slower than 1 kHz, the first read ADC value can be
264 reg.set_eos(true); 388 // corrupted, so we discard it and measure again.
265 reg.set_eoc(true); 389 //
266 }); 390 // STM32L471xx: Section 2.7.3
267 T::regs().cr().modify(|reg| { 391 // STM32G4: Section 2.7.3
268 reg.set_adstart(true); 392 #[cfg(any(rcc_l4, rcc_g4))]
269 }); 393 let _ = self.convert();
270
271 while !T::regs().isr().read().eos() {
272 // spin
273 }
274
275 // Read ADC value first time and discard it, as per errata sheet.
276 // The errata states that if we do conversions slower than 1 kHz, the
277 // first read ADC value can be corrupted, so we discard it and measure again.
278
279 let _ = T::regs().dr().read();
280
281 T::regs().isr().modify(|reg| {
282 reg.set_eos(true);
283 reg.set_eoc(true);
284 });
285 T::regs().cr().modify(|reg| {
286 reg.set_adstart(true);
287 });
288
289 while !T::regs().isr().read().eos() {
290 // spin
291 }
292 394
293 let val = T::regs().dr().read().0 as u16; 395 let val = self.convert();
294 396
295 T::regs().cr().modify(|reg| reg.set_addis(true)); 397 T::regs().cr().modify(|reg| reg.set_addis(true));
296 398
@@ -298,6 +400,14 @@ impl<'d, T: Instance> Adc<'d, T> {
298 } 400 }
299 } 401 }
300 402
403 #[cfg(rcc_g0)]
404 unsafe fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) {
405 T::regs()
406 .smpr()
407 .modify(|reg| reg.set_smp1(sample_time.sample_time()));
408 }
409
410 #[cfg(not(rcc_g0))]
301 unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { 411 unsafe fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
302 if ch <= 9 { 412 if ch <= 9 {
303 T::regs() 413 T::regs()
diff --git a/embassy-stm32/src/dac/v2.rs b/embassy-stm32/src/dac/v2.rs
index f46145b8d..55a881d89 100644
--- a/embassy-stm32/src/dac/v2.rs
+++ b/embassy-stm32/src/dac/v2.rs
@@ -5,6 +5,17 @@ use core::marker::PhantomData;
5use embassy::util::Unborrow; 5use embassy::util::Unborrow;
6use embassy_hal_common::unborrow; 6use embassy_hal_common::unborrow;
7 7
8/// Sadly we cannot use `RccPeripheral::enable` since devices are quite inconsistent DAC clock
9/// configuration.
10unsafe fn enable() {
11 #[cfg(rcc_h7)]
12 crate::pac::RCC.apb1lenr().modify(|w| w.set_dac12en(true));
13 #[cfg(rcc_g0)]
14 crate::pac::RCC.apbenr1().modify(|w| w.set_dac1en(true));
15 #[cfg(rcc_l4)]
16 crate::pac::RCC.apb1enr1().modify(|w| w.set_dac1en(true));
17}
18
8#[derive(Debug)] 19#[derive(Debug)]
9#[cfg_attr(feature = "defmt", derive(defmt::Format))] 20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
10pub enum Error { 21pub enum Error {
@@ -91,6 +102,10 @@ impl<'d, T: Instance> Dac<'d, T> {
91 ) -> Self { 102 ) -> Self {
92 unborrow!(ch1, ch2); 103 unborrow!(ch1, ch2);
93 104
105 unsafe {
106 enable();
107 }
108
94 let ch1 = ch1.degrade_optional(); 109 let ch1 = ch1.degrade_optional();
95 if ch1.is_some() { 110 if ch1.is_some() {
96 unsafe { 111 unsafe {
diff --git a/embassy-stm32/src/rcc/g0/mod.rs b/embassy-stm32/src/rcc/g0/mod.rs
index 863db709d..c0b5b14e3 100644
--- a/embassy-stm32/src/rcc/g0/mod.rs
+++ b/embassy-stm32/src/rcc/g0/mod.rs
@@ -18,10 +18,37 @@ pub const LSI_FREQ: u32 = 32_000;
18#[derive(Clone, Copy)] 18#[derive(Clone, Copy)]
19pub enum ClockSrc { 19pub enum ClockSrc {
20 HSE(Hertz), 20 HSE(Hertz),
21 HSI16, 21 HSI16(HSI16Prescaler),
22 LSI, 22 LSI,
23} 23}
24 24
25#[derive(Clone, Copy)]
26pub enum HSI16Prescaler {
27 NotDivided,
28 Div2,
29 Div4,
30 Div8,
31 Div16,
32 Div32,
33 Div64,
34 Div128,
35}
36
37impl Into<u8> for HSI16Prescaler {
38 fn into(self) -> u8 {
39 match self {
40 HSI16Prescaler::NotDivided => 0x00,
41 HSI16Prescaler::Div2 => 0x01,
42 HSI16Prescaler::Div4 => 0x02,
43 HSI16Prescaler::Div8 => 0x03,
44 HSI16Prescaler::Div16 => 0x04,
45 HSI16Prescaler::Div32 => 0x05,
46 HSI16Prescaler::Div64 => 0x06,
47 HSI16Prescaler::Div128 => 0x07,
48 }
49 }
50}
51
25impl Into<u8> for APBPrescaler { 52impl Into<u8> for APBPrescaler {
26 fn into(self) -> u8 { 53 fn into(self) -> u8 {
27 match self { 54 match self {
@@ -55,15 +82,17 @@ pub struct Config {
55 mux: ClockSrc, 82 mux: ClockSrc,
56 ahb_pre: AHBPrescaler, 83 ahb_pre: AHBPrescaler,
57 apb_pre: APBPrescaler, 84 apb_pre: APBPrescaler,
85 low_power_run: bool,
58} 86}
59 87
60impl Default for Config { 88impl Default for Config {
61 #[inline] 89 #[inline]
62 fn default() -> Config { 90 fn default() -> Config {
63 Config { 91 Config {
64 mux: ClockSrc::HSI16, 92 mux: ClockSrc::HSI16(HSI16Prescaler::NotDivided),
65 ahb_pre: AHBPrescaler::NotDivided, 93 ahb_pre: AHBPrescaler::NotDivided,
66 apb_pre: APBPrescaler::NotDivided, 94 apb_pre: APBPrescaler::NotDivided,
95 low_power_run: false,
67 } 96 }
68 } 97 }
69} 98}
@@ -86,6 +115,12 @@ impl Config {
86 self.apb_pre = pre; 115 self.apb_pre = pre;
87 self 116 self
88 } 117 }
118
119 #[inline]
120 pub fn low_power_run(mut self, on: bool) -> Self {
121 self.low_power_run = on;
122 self
123 }
89} 124}
90 125
91/// RCC peripheral 126/// RCC peripheral
@@ -119,14 +154,18 @@ impl RccExt for RCC {
119 fn freeze(self, cfgr: Config) -> Clocks { 154 fn freeze(self, cfgr: Config) -> Clocks {
120 let rcc = pac::RCC; 155 let rcc = pac::RCC;
121 let (sys_clk, sw) = match cfgr.mux { 156 let (sys_clk, sw) = match cfgr.mux {
122 ClockSrc::HSI16 => { 157 ClockSrc::HSI16(div) => {
123 // Enable HSI16 158 // Enable HSI16
159 let div: u8 = div.into();
124 unsafe { 160 unsafe {
125 rcc.cr().write(|w| w.set_hsion(true)); 161 rcc.cr().write(|w| {
162 w.set_hsidiv(div);
163 w.set_hsion(true)
164 });
126 while !rcc.cr().read().hsirdy() {} 165 while !rcc.cr().read().hsirdy() {}
127 } 166 }
128 167
129 (HSI_FREQ, 0x00) 168 (HSI_FREQ >> div, 0x00)
130 } 169 }
131 ClockSrc::HSE(freq) => { 170 ClockSrc::HSE(freq) => {
132 // Enable HSE 171 // Enable HSE
@@ -174,6 +213,14 @@ impl RccExt for RCC {
174 } 213 }
175 }; 214 };
176 215
216 let pwr = pac::PWR;
217 if cfgr.low_power_run {
218 assert!(sys_clk.hz() <= 2_000_000.hz());
219 unsafe {
220 pwr.cr1().modify(|w| w.set_lpr(true));
221 }
222 }
223
177 Clocks { 224 Clocks {
178 sys: sys_clk.hz(), 225 sys: sys_clk.hz(),
179 ahb: ahb_freq.hz(), 226 ahb: ahb_freq.hz(),