aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-09-06 16:32:12 +0000
committerGitHub <[email protected]>2023-09-06 16:32:12 +0000
commitaf7c93abba768057f1d3299c7b4f4aa4501b3e56 (patch)
treeef6a688c53d3742f37171d4cb9b1aa4ba2d430d3
parenta05afc54262e180fbbbe5b9369246c5275a5c4a3 (diff)
parentc356585a5918f1c66f5fc0e12edd82094dacd5c9 (diff)
Merge pull request #1864 from oll3/feat/stm32wl-adc
ADC support for STM32WLx
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/src/adc/mod.rs4
-rw-r--r--embassy-stm32/src/adc/v3.rs41
-rw-r--r--embassy-stm32/src/rcc/wl.rs29
4 files changed, 61 insertions, 17 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 306945962..ded58aee3 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -58,7 +58,7 @@ sdio-host = "0.5.0"
58embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true } 58embedded-sdmmc = { git = "https://github.com/embassy-rs/embedded-sdmmc-rs", rev = "a4f293d3a6f72158385f79c98634cb8a14d0d2fc", optional = true }
59critical-section = "1.1" 59critical-section = "1.1"
60atomic-polyfill = "1.0.1" 60atomic-polyfill = "1.0.1"
61stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7e2310f49fa123fbc3225b91be73522b212703f0" } 61stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-eaa4987e523408dfb31c1b76765dd345d2761373" }
62vcell = "0.1.3" 62vcell = "0.1.3"
63bxcan = "0.7.0" 63bxcan = "0.7.0"
64nb = "1.0.0" 64nb = "1.0.0"
@@ -77,7 +77,7 @@ critical-section = { version = "1.1", features = ["std"] }
77[build-dependencies] 77[build-dependencies]
78proc-macro2 = "1.0.36" 78proc-macro2 = "1.0.36"
79quote = "1.0.15" 79quote = "1.0.15"
80stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-7e2310f49fa123fbc3225b91be73522b212703f0", default-features = false, features = ["metadata"]} 80stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-eaa4987e523408dfb31c1b76765dd345d2761373", default-features = false, features = ["metadata"]}
81 81
82[features] 82[features]
83default = ["rt"] 83default = ["rt"]
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index 0eeadfa93..013debca8 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -33,7 +33,7 @@ pub struct Adc<'d, T: Instance> {
33pub(crate) mod sealed { 33pub(crate) mod sealed {
34 pub trait Instance { 34 pub trait Instance {
35 fn regs() -> crate::pac::adc::Adc; 35 fn regs() -> crate::pac::adc::Adc;
36 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2)))] 36 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_g0)))]
37 fn common_regs() -> crate::pac::adccommon::AdcCommon; 37 fn common_regs() -> crate::pac::adccommon::AdcCommon;
38 #[cfg(adc_f3)] 38 #[cfg(adc_f3)]
39 fn frequency() -> crate::time::Hertz; 39 fn frequency() -> crate::time::Hertz;
@@ -63,7 +63,7 @@ foreach_peripheral!(
63 fn regs() -> crate::pac::adc::Adc { 63 fn regs() -> crate::pac::adc::Adc {
64 crate::pac::$inst 64 crate::pac::$inst
65 } 65 }
66 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2)))] 66 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_g0)))]
67 fn common_regs() -> crate::pac::adccommon::AdcCommon { 67 fn common_regs() -> crate::pac::adccommon::AdcCommon {
68 foreach_peripheral!{ 68 foreach_peripheral!{
69 (adccommon, $common_inst:ident) => { 69 (adccommon, $common_inst:ident) => {
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index 821cc7f6a..011ecc281 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -13,7 +13,7 @@ pub const VREF_CALIB_MV: u32 = 3000;
13/// configuration. 13/// configuration.
14fn enable() { 14fn enable() {
15 critical_section::with(|_| { 15 critical_section::with(|_| {
16 #[cfg(stm32h7)] 16 #[cfg(any(stm32h7, stm32wl))]
17 crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true)); 17 crate::pac::RCC.apb2enr().modify(|w| w.set_adcen(true));
18 #[cfg(stm32g0)] 18 #[cfg(stm32g0)]
19 crate::pac::RCC.apbenr2().modify(|w| w.set_adcen(true)); 19 crate::pac::RCC.apbenr2().modify(|w| w.set_adcen(true));
@@ -26,9 +26,9 @@ pub struct VrefInt;
26impl<T: Instance> AdcPin<T> for VrefInt {} 26impl<T: Instance> AdcPin<T> for VrefInt {}
27impl<T: Instance> super::sealed::AdcPin<T> for VrefInt { 27impl<T: Instance> super::sealed::AdcPin<T> for VrefInt {
28 fn channel(&self) -> u8 { 28 fn channel(&self) -> u8 {
29 #[cfg(not(stm32g0))] 29 #[cfg(not(adc_g0))]
30 let val = 0; 30 let val = 0;
31 #[cfg(stm32g0)] 31 #[cfg(adc_g0)]
32 let val = 13; 32 let val = 13;
33 val 33 val
34 } 34 }
@@ -38,9 +38,9 @@ pub struct Temperature;
38impl<T: Instance> AdcPin<T> for Temperature {} 38impl<T: Instance> AdcPin<T> for Temperature {}
39impl<T: Instance> super::sealed::AdcPin<T> for Temperature { 39impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
40 fn channel(&self) -> u8 { 40 fn channel(&self) -> u8 {
41 #[cfg(not(stm32g0))] 41 #[cfg(not(adc_g0))]
42 let val = 17; 42 let val = 17;
43 #[cfg(stm32g0)] 43 #[cfg(adc_g0)]
44 let val = 12; 44 let val = 12;
45 val 45 val
46 } 46 }
@@ -50,9 +50,9 @@ pub struct Vbat;
50impl<T: Instance> AdcPin<T> for Vbat {} 50impl<T: Instance> AdcPin<T> for Vbat {}
51impl<T: Instance> super::sealed::AdcPin<T> for Vbat { 51impl<T: Instance> super::sealed::AdcPin<T> for Vbat {
52 fn channel(&self) -> u8 { 52 fn channel(&self) -> u8 {
53 #[cfg(not(stm32g0))] 53 #[cfg(not(adc_g0))]
54 let val = 18; 54 let val = 18;
55 #[cfg(stm32g0)] 55 #[cfg(adc_g0)]
56 let val = 14; 56 let val = 14;
57 val 57 val
58 } 58 }
@@ -92,9 +92,14 @@ impl<'d, T: Instance> Adc<'d, T> {
92 } 92 }
93 93
94 pub fn enable_vrefint(&self, delay: &mut impl DelayUs<u32>) -> VrefInt { 94 pub fn enable_vrefint(&self, delay: &mut impl DelayUs<u32>) -> VrefInt {
95 #[cfg(not(adc_g0))]
95 T::common_regs().ccr().modify(|reg| { 96 T::common_regs().ccr().modify(|reg| {
96 reg.set_vrefen(true); 97 reg.set_vrefen(true);
97 }); 98 });
99 #[cfg(adc_g0)]
100 T::regs().ccr().modify(|reg| {
101 reg.set_vrefen(true);
102 });
98 103
99 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us 104 // "Table 24. Embedded internal voltage reference" states that it takes a maximum of 12 us
100 // to stabilize the internal voltage reference, we wait a little more. 105 // to stabilize the internal voltage reference, we wait a little more.
@@ -106,17 +111,27 @@ impl<'d, T: Instance> Adc<'d, T> {
106 } 111 }
107 112
108 pub fn enable_temperature(&self) -> Temperature { 113 pub fn enable_temperature(&self) -> Temperature {
114 #[cfg(not(adc_g0))]
109 T::common_regs().ccr().modify(|reg| { 115 T::common_regs().ccr().modify(|reg| {
110 reg.set_ch17sel(true); 116 reg.set_ch17sel(true);
111 }); 117 });
118 #[cfg(adc_g0)]
119 T::regs().ccr().modify(|reg| {
120 reg.set_tsen(true);
121 });
112 122
113 Temperature {} 123 Temperature {}
114 } 124 }
115 125
116 pub fn enable_vbat(&self) -> Vbat { 126 pub fn enable_vbat(&self) -> Vbat {
127 #[cfg(not(adc_g0))]
117 T::common_regs().ccr().modify(|reg| { 128 T::common_regs().ccr().modify(|reg| {
118 reg.set_ch18sel(true); 129 reg.set_ch18sel(true);
119 }); 130 });
131 #[cfg(adc_g0)]
132 T::regs().ccr().modify(|reg| {
133 reg.set_vbaten(true);
134 });
120 135
121 Vbat {} 136 Vbat {}
122 } 137 }
@@ -126,9 +141,9 @@ impl<'d, T: Instance> Adc<'d, T> {
126 } 141 }
127 142
128 pub fn set_resolution(&mut self, resolution: Resolution) { 143 pub fn set_resolution(&mut self, resolution: Resolution) {
129 #[cfg(not(stm32g0))] 144 #[cfg(not(adc_g0))]
130 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into())); 145 T::regs().cfgr().modify(|reg| reg.set_res(resolution.into()));
131 #[cfg(stm32g0)] 146 #[cfg(adc_g0)]
132 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); 147 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
133 } 148 }
134 149
@@ -182,9 +197,9 @@ impl<'d, T: Instance> Adc<'d, T> {
182 Self::set_channel_sample_time(pin.channel(), self.sample_time); 197 Self::set_channel_sample_time(pin.channel(), self.sample_time);
183 198
184 // Select channel 199 // Select channel
185 #[cfg(not(stm32g0))] 200 #[cfg(not(adc_g0))]
186 T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel())); 201 T::regs().sqr1().write(|reg| reg.set_sq(0, pin.channel()));
187 #[cfg(stm32g0)] 202 #[cfg(adc_g0)]
188 T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel())); 203 T::regs().chselr().write(|reg| reg.set_chsel(1 << pin.channel()));
189 204
190 // Some models are affected by an erratum: 205 // Some models are affected by an erratum:
@@ -203,12 +218,12 @@ impl<'d, T: Instance> Adc<'d, T> {
203 val 218 val
204 } 219 }
205 220
206 #[cfg(stm32g0)] 221 #[cfg(adc_g0)]
207 fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) { 222 fn set_channel_sample_time(_ch: u8, sample_time: SampleTime) {
208 T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into())); 223 T::regs().smpr().modify(|reg| reg.set_smp1(sample_time.into()));
209 } 224 }
210 225
211 #[cfg(not(stm32g0))] 226 #[cfg(not(adc_g0))]
212 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) { 227 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
213 let sample_time = sample_time.into(); 228 let sample_time = sample_time.into();
214 T::regs() 229 T::regs()
diff --git a/embassy-stm32/src/rcc/wl.rs b/embassy-stm32/src/rcc/wl.rs
index e33690d10..47be00ad8 100644
--- a/embassy-stm32/src/rcc/wl.rs
+++ b/embassy-stm32/src/rcc/wl.rs
@@ -1,4 +1,5 @@
1pub use super::bus::{AHBPrescaler, APBPrescaler, VoltageScale}; 1pub use super::bus::{AHBPrescaler, APBPrescaler, VoltageScale};
2use crate::pac::rcc::vals::Adcsel;
2use crate::pac::{FLASH, PWR, RCC}; 3use crate::pac::{FLASH, PWR, RCC};
3use crate::rcc::bd::{BackupDomain, RtcClockSource}; 4use crate::rcc::bd::{BackupDomain, RtcClockSource};
4use crate::rcc::{set_freqs, Clocks}; 5use crate::rcc::{set_freqs, Clocks};
@@ -106,6 +107,29 @@ impl Into<u8> for MSIRange {
106 } 107 }
107} 108}
108 109
110#[derive(Clone, Copy)]
111pub enum AdcClockSource {
112 HSI16,
113 PLLPCLK,
114 SYSCLK,
115}
116
117impl AdcClockSource {
118 pub fn adcsel(&self) -> Adcsel {
119 match self {
120 AdcClockSource::HSI16 => Adcsel::HSI16,
121 AdcClockSource::PLLPCLK => Adcsel::PLLPCLK,
122 AdcClockSource::SYSCLK => Adcsel::SYSCLK,
123 }
124 }
125}
126
127impl Default for AdcClockSource {
128 fn default() -> Self {
129 Self::HSI16
130 }
131}
132
109/// Clocks configutation 133/// Clocks configutation
110pub struct Config { 134pub struct Config {
111 pub mux: ClockSrc, 135 pub mux: ClockSrc,
@@ -116,6 +140,7 @@ pub struct Config {
116 pub enable_lsi: bool, 140 pub enable_lsi: bool,
117 pub enable_rtc_apb: bool, 141 pub enable_rtc_apb: bool,
118 pub rtc_mux: RtcClockSource, 142 pub rtc_mux: RtcClockSource,
143 pub adc_clock_source: AdcClockSource,
119} 144}
120 145
121impl Default for Config { 146impl Default for Config {
@@ -130,6 +155,7 @@ impl Default for Config {
130 enable_lsi: false, 155 enable_lsi: false,
131 enable_rtc_apb: false, 156 enable_rtc_apb: false,
132 rtc_mux: RtcClockSource::LSI, 157 rtc_mux: RtcClockSource::LSI,
158 adc_clock_source: AdcClockSource::default(),
133 } 159 }
134 } 160 }
135} 161}
@@ -299,6 +325,9 @@ pub(crate) unsafe fn init(config: Config) {
299 w.set_ppre2(config.apb2_pre.into()); 325 w.set_ppre2(config.apb2_pre.into());
300 }); 326 });
301 327
328 // ADC clock MUX
329 RCC.ccipr().modify(|w| w.set_adcsel(config.adc_clock_source.adcsel()));
330
302 // TODO: switch voltage range 331 // TODO: switch voltage range
303 332
304 if config.enable_lsi { 333 if config.enable_lsi {