aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/build.rs11
-rw-r--r--embassy-stm32/src/adc/f3.rs126
-rw-r--r--embassy-stm32/src/adc/mod.rs59
-rw-r--r--embassy-stm32/src/adc/resolution.rs8
-rw-r--r--embassy-stm32/src/adc/sample_time.rs18
-rw-r--r--embassy-stm32/src/rcc/f3.rs93
-rw-r--r--embassy-stm32/src/rcc/mod.rs9
-rw-r--r--examples/stm32f334/src/bin/adc.rs34
8 files changed, 330 insertions, 28 deletions
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index aef0668a2..d3bfd24fb 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -309,14 +309,17 @@ fn main() {
309 // Generate RccPeripheral impls 309 // Generate RccPeripheral impls
310 310
311 // TODO: maybe get this from peripheral kind? Not sure 311 // TODO: maybe get this from peripheral kind? Not sure
312 let refcounted_peripherals = HashSet::from(["USART"]); 312 let mut refcounted_peripherals = HashSet::from(["usart"]);
313 let mut refcount_statics = HashSet::new(); 313 let mut refcount_statics = HashSet::new();
314 314
315 if chip_name.starts_with("stm32f3") {
316 refcounted_peripherals.insert("adc");
317 }
318
315 for p in METADATA.peripherals { 319 for p in METADATA.peripherals {
316 // generating RccPeripheral impl for H7 ADC3 would result in bad frequency 320 // generating RccPeripheral impl for H7 ADC3 would result in bad frequency
317 if !singletons.contains(&p.name.to_string()) 321 if !singletons.contains(&p.name.to_string())
318 || (p.name == "ADC3" && METADATA.line.starts_with("STM32H7")) 322 || (p.name == "ADC3" && METADATA.line.starts_with("STM32H7"))
319 || (p.name.starts_with("ADC") && p.registers.as_ref().map_or(false, |r| r.version == "f3"))
320 || (p.name.starts_with("ADC") && p.registers.as_ref().map_or(false, |r| r.version == "v4")) 323 || (p.name.starts_with("ADC") && p.registers.as_ref().map_or(false, |r| r.version == "v4"))
321 { 324 {
322 continue; 325 continue;
@@ -348,13 +351,13 @@ fn main() {
348 TokenStream::new() 351 TokenStream::new()
349 }; 352 };
350 353
351 let ptype = (if let Some(reg) = &p.registers { reg.kind } else { "" }).to_ascii_uppercase(); 354 let ptype = if let Some(reg) = &p.registers { reg.kind } else { "" };
352 let pname = format_ident!("{}", p.name); 355 let pname = format_ident!("{}", p.name);
353 let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase()); 356 let clk = format_ident!("{}", rcc.clock.to_ascii_lowercase());
354 let en_reg = format_ident!("{}", en.register.to_ascii_lowercase()); 357 let en_reg = format_ident!("{}", en.register.to_ascii_lowercase());
355 let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase()); 358 let set_en_field = format_ident!("set_{}", en.field.to_ascii_lowercase());
356 359
357 let (before_enable, before_disable) = if refcounted_peripherals.contains(ptype.as_str()) { 360 let (before_enable, before_disable) = if refcounted_peripherals.contains(ptype) {
358 let refcount_static = 361 let refcount_static =
359 format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase()); 362 format_ident!("{}_{}", en.register.to_ascii_uppercase(), en.field.to_ascii_uppercase());
360 363
diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs
new file mode 100644
index 000000000..458573c05
--- /dev/null
+++ b/embassy-stm32/src/adc/f3.rs
@@ -0,0 +1,126 @@
1use embassy_hal_internal::into_ref;
2use embedded_hal_02::blocking::delay::DelayUs;
3
4use crate::adc::{Adc, AdcPin, Instance, SampleTime};
5use crate::time::Hertz;
6use crate::Peripheral;
7
8pub const VDDA_CALIB_MV: u32 = 3300;
9pub const ADC_MAX: u32 = (1 << 12) - 1;
10// No calibration data for F103, voltage should be 1.2v
11pub const VREF_INT: u32 = 1200;
12
13pub struct Vref;
14impl<T: Instance> AdcPin<T> for Vref {}
15impl<T: Instance> super::sealed::AdcPin<T> for Vref {
16 fn channel(&self) -> u8 {
17 18
18 }
19}
20
21pub struct Temperature;
22impl<T: Instance> AdcPin<T> for Temperature {}
23impl<T: Instance> super::sealed::AdcPin<T> for Temperature {
24 fn channel(&self) -> u8 {
25 16
26 }
27}
28
29impl<'d, T: Instance> Adc<'d, T> {
30 pub fn new(adc: impl Peripheral<P = T> + 'd, delay: &mut impl DelayUs<u32>) -> Self {
31 use crate::pac::adc::vals;
32
33 into_ref!(adc);
34
35 T::enable();
36 T::reset();
37
38 // Enable the adc regulator
39 T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::INTERMEDIATE));
40 T::regs().cr().modify(|w| w.set_advregen(vals::Advregen::ENABLED));
41
42 // Wait for the regulator to stabilize
43 delay.delay_us(10);
44
45 assert!(!T::regs().cr().read().aden());
46
47 // Begin calibration
48 T::regs().cr().modify(|w| w.set_adcaldif(false));
49 T::regs().cr().modify(|w| w.set_adcal(true));
50
51 while T::regs().cr().read().adcal() {}
52
53 // Enable the adc
54 T::regs().cr().modify(|w| w.set_aden(true));
55
56 // Wait until the adc is ready
57 while !T::regs().isr().read().adrdy() {}
58
59 Self {
60 adc,
61 sample_time: Default::default(),
62 }
63 }
64
65 fn freq() -> Hertz {
66 <T as crate::adc::sealed::Instance>::frequency()
67 }
68
69 pub fn sample_time_for_us(&self, us: u32) -> SampleTime {
70 match us * Self::freq().0 / 1_000_000 {
71 0..=1 => SampleTime::Cycles1_5,
72 2..=4 => SampleTime::Cycles4_5,
73 5..=7 => SampleTime::Cycles7_5,
74 8..=19 => SampleTime::Cycles19_5,
75 20..=61 => SampleTime::Cycles61_5,
76 62..=181 => SampleTime::Cycles181_5,
77 _ => SampleTime::Cycles601_5,
78 }
79 }
80
81 pub fn enable_vref(&self, _delay: &mut impl DelayUs<u32>) -> Vref {
82 T::common_regs().ccr().modify(|w| w.set_vrefen(true));
83
84 Vref {}
85 }
86
87 pub fn enable_temperature(&self) -> Temperature {
88 T::common_regs().ccr().modify(|w| w.set_tsen(true));
89
90 Temperature {}
91 }
92
93 pub fn set_sample_time(&mut self, sample_time: SampleTime) {
94 self.sample_time = sample_time;
95 }
96
97 /// Perform a single conversion.
98 fn convert(&mut self) -> u16 {
99 T::regs().isr().write(|_| {});
100 T::regs().cr().modify(|w| w.set_adstart(true));
101
102 while !T::regs().isr().read().eoc() && !T::regs().isr().read().eos() {}
103 T::regs().isr().write(|_| {});
104
105 T::regs().dr().read().0 as u16
106 }
107
108 pub fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
109 // pin.set_as_analog();
110
111 Self::set_channel_sample_time(pin.channel(), self.sample_time);
112
113 // Configure the channel to sample
114 T::regs().sqr3().write(|w| w.set_sq(0, pin.channel()));
115 self.convert()
116 }
117
118 fn set_channel_sample_time(ch: u8, sample_time: SampleTime) {
119 let sample_time = sample_time.into();
120 if ch <= 9 {
121 T::regs().smpr2().modify(|reg| reg.set_smp(ch as _, sample_time));
122 } else {
123 T::regs().smpr1().modify(|reg| reg.set_smp((ch - 10) as _, sample_time));
124 }
125 }
126}
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index e57889aa6..a127445d8 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -1,23 +1,24 @@
1#![macro_use] 1#![macro_use]
2 2
3#[cfg(not(any(adc_f3, adc_f3_v2)))] 3#[cfg(not(adc_f3_v2))]
4#[cfg_attr(adc_f1, path = "f1.rs")] 4#[cfg_attr(adc_f1, path = "f1.rs")]
5#[cfg_attr(adc_f3, path = "f3.rs")]
5#[cfg_attr(adc_v1, path = "v1.rs")] 6#[cfg_attr(adc_v1, path = "v1.rs")]
6#[cfg_attr(adc_v2, path = "v2.rs")] 7#[cfg_attr(adc_v2, path = "v2.rs")]
7#[cfg_attr(any(adc_v3, adc_g0), path = "v3.rs")] 8#[cfg_attr(any(adc_v3, adc_g0), path = "v3.rs")]
8#[cfg_attr(adc_v4, path = "v4.rs")] 9#[cfg_attr(adc_v4, path = "v4.rs")]
9mod _version; 10mod _version;
10 11
11#[cfg(not(any(adc_f1, adc_f3, adc_f3_v2)))] 12#[cfg(not(any(adc_f1, adc_f3_v2)))]
12mod resolution; 13mod resolution;
13mod sample_time; 14mod sample_time;
14 15
15#[cfg(not(any(adc_f3, adc_f3_v2)))]
16#[allow(unused)] 16#[allow(unused)]
17#[cfg(not(adc_f3_v2))]
17pub use _version::*; 18pub use _version::*;
18#[cfg(not(any(adc_f1, adc_f3, adc_f3_v2)))] 19#[cfg(not(any(adc_f1, adc_f3, adc_f3_v2)))]
19pub use resolution::Resolution; 20pub use resolution::Resolution;
20#[cfg(not(any(adc_f3, adc_f3_v2)))] 21#[cfg(not(adc_f3_v2))]
21pub use sample_time::SampleTime; 22pub use sample_time::SampleTime;
22 23
23use crate::peripherals; 24use crate::peripherals;
@@ -25,15 +26,17 @@ use crate::peripherals;
25pub struct Adc<'d, T: Instance> { 26pub struct Adc<'d, T: Instance> {
26 #[allow(unused)] 27 #[allow(unused)]
27 adc: crate::PeripheralRef<'d, T>, 28 adc: crate::PeripheralRef<'d, T>,
28 #[cfg(not(any(adc_f3, adc_f3_v2)))] 29 #[cfg(not(adc_f3_v2))]
29 sample_time: SampleTime, 30 sample_time: SampleTime,
30} 31}
31 32
32pub(crate) mod sealed { 33pub(crate) mod sealed {
33 pub trait Instance { 34 pub trait Instance {
34 fn regs() -> crate::pac::adc::Adc; 35 fn regs() -> crate::pac::adc::Adc;
35 #[cfg(not(any(adc_f1, adc_v1, adc_f3, adc_f3_v2)))] 36 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2)))]
36 fn common_regs() -> crate::pac::adccommon::AdcCommon; 37 fn common_regs() -> crate::pac::adccommon::AdcCommon;
38 #[cfg(adc_f3)]
39 fn frequency() -> crate::time::Hertz;
37 } 40 }
38 41
39 pub trait AdcPin<T: Instance> { 42 pub trait AdcPin<T: Instance> {
@@ -45,22 +48,22 @@ pub(crate) mod sealed {
45 } 48 }
46} 49}
47 50
48#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v4)))] 51#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v4, adc_f3)))]
49pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {} 52pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {}
50#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v4))] 53#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v4, adc_f3))]
51pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {} 54pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {}
52 55
53pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {} 56pub trait AdcPin<T: Instance>: sealed::AdcPin<T> {}
54pub trait InternalChannel<T>: sealed::InternalChannel<T> {} 57pub trait InternalChannel<T>: sealed::InternalChannel<T> {}
55 58
56#[cfg(not(stm32h7))] 59#[cfg(not(any(stm32h7, adc_f3)))]
57foreach_peripheral!( 60foreach_peripheral!(
58 (adc, $inst:ident) => { 61 (adc, $inst:ident) => {
59 impl crate::adc::sealed::Instance for peripherals::$inst { 62 impl crate::adc::sealed::Instance for peripherals::$inst {
60 fn regs() -> crate::pac::adc::Adc { 63 fn regs() -> crate::pac::adc::Adc {
61 crate::pac::$inst 64 crate::pac::$inst
62 } 65 }
63 #[cfg(not(any(adc_f1, adc_v1, adc_f3, adc_f3_v2)))] 66 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2)))]
64 fn common_regs() -> crate::pac::adccommon::AdcCommon { 67 fn common_regs() -> crate::pac::adccommon::AdcCommon {
65 foreach_peripheral!{ 68 foreach_peripheral!{
66 (adccommon, $common_inst:ident) => { 69 (adccommon, $common_inst:ident) => {
@@ -74,7 +77,7 @@ foreach_peripheral!(
74 }; 77 };
75); 78);
76 79
77#[cfg(stm32h7)] 80#[cfg(any(stm32h7, adc_f3))]
78foreach_peripheral!( 81foreach_peripheral!(
79 (adc, ADC3) => { 82 (adc, ADC3) => {
80 impl crate::adc::sealed::Instance for peripherals::ADC3 { 83 impl crate::adc::sealed::Instance for peripherals::ADC3 {
@@ -89,16 +92,43 @@ foreach_peripheral!(
89 }; 92 };
90 } 93 }
91 } 94 }
95
96 #[cfg(adc_f3)]
97 fn frequency() -> crate::time::Hertz {
98 unsafe { crate::rcc::get_freqs() }.adc34.unwrap()
99 }
92 } 100 }
93 101
94 impl crate::adc::Instance for peripherals::ADC3 {} 102 impl crate::adc::Instance for peripherals::ADC3 {}
95 }; 103 };
104 (adc, ADC4) => {
105 impl crate::adc::sealed::Instance for peripherals::ADC4 {
106 fn regs() -> crate::pac::adc::Adc {
107 crate::pac::ADC4
108 }
109 #[cfg(not(any(adc_f1, adc_v1)))]
110 fn common_regs() -> crate::pac::adccommon::AdcCommon {
111 foreach_peripheral!{
112 (adccommon, ADC3_COMMON) => {
113 return crate::pac::ADC3_COMMON
114 };
115 }
116 }
117
118 #[cfg(adc_f3)]
119 fn frequency() -> crate::time::Hertz {
120 unsafe { crate::rcc::get_freqs() }.adc34.unwrap()
121 }
122 }
123
124 impl crate::adc::Instance for peripherals::ADC4 {}
125 };
96 (adc, $inst:ident) => { 126 (adc, $inst:ident) => {
97 impl crate::adc::sealed::Instance for peripherals::$inst { 127 impl crate::adc::sealed::Instance for peripherals::$inst {
98 fn regs() -> crate::pac::adc::Adc { 128 fn regs() -> crate::pac::adc::Adc {
99 crate::pac::$inst 129 crate::pac::$inst
100 } 130 }
101 #[cfg(all(not(adc_f1), not(adc_v1)))] 131 #[cfg(not(any(adc_f1, adc_v1)))]
102 fn common_regs() -> crate::pac::adccommon::AdcCommon { 132 fn common_regs() -> crate::pac::adccommon::AdcCommon {
103 foreach_peripheral!{ 133 foreach_peripheral!{
104 (adccommon, ADC_COMMON) => { 134 (adccommon, ADC_COMMON) => {
@@ -106,6 +136,11 @@ foreach_peripheral!(
106 }; 136 };
107 } 137 }
108 } 138 }
139
140 #[cfg(adc_f3)]
141 fn frequency() -> crate::time::Hertz {
142 unsafe { crate::rcc::get_freqs() }.adc.unwrap()
143 }
109 } 144 }
110 145
111 impl crate::adc::Instance for peripherals::$inst {} 146 impl crate::adc::Instance for peripherals::$inst {}
diff --git a/embassy-stm32/src/adc/resolution.rs b/embassy-stm32/src/adc/resolution.rs
index 67fb9b8c0..5668137b5 100644
--- a/embassy-stm32/src/adc/resolution.rs
+++ b/embassy-stm32/src/adc/resolution.rs
@@ -1,4 +1,4 @@
1#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0))] 1#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
2#[derive(Clone, Copy, Debug, Eq, PartialEq)] 2#[derive(Clone, Copy, Debug, Eq, PartialEq)]
3pub enum Resolution { 3pub enum Resolution {
4 TwelveBit, 4 TwelveBit,
@@ -19,7 +19,7 @@ pub enum Resolution {
19 19
20impl Default for Resolution { 20impl Default for Resolution {
21 fn default() -> Self { 21 fn default() -> Self {
22 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0))] 22 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
23 { 23 {
24 Self::TwelveBit 24 Self::TwelveBit
25 } 25 }
@@ -40,7 +40,7 @@ impl From<Resolution> for crate::pac::adc::vals::Res {
40 Resolution::TwelveBit => crate::pac::adc::vals::Res::TWELVEBIT, 40 Resolution::TwelveBit => crate::pac::adc::vals::Res::TWELVEBIT,
41 Resolution::TenBit => crate::pac::adc::vals::Res::TENBIT, 41 Resolution::TenBit => crate::pac::adc::vals::Res::TENBIT,
42 Resolution::EightBit => crate::pac::adc::vals::Res::EIGHTBIT, 42 Resolution::EightBit => crate::pac::adc::vals::Res::EIGHTBIT,
43 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0))] 43 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
44 Resolution::SixBit => crate::pac::adc::vals::Res::SIXBIT, 44 Resolution::SixBit => crate::pac::adc::vals::Res::SIXBIT,
45 } 45 }
46 } 46 }
@@ -56,7 +56,7 @@ impl Resolution {
56 Resolution::TwelveBit => (1 << 12) - 1, 56 Resolution::TwelveBit => (1 << 12) - 1,
57 Resolution::TenBit => (1 << 10) - 1, 57 Resolution::TenBit => (1 << 10) - 1,
58 Resolution::EightBit => (1 << 8) - 1, 58 Resolution::EightBit => (1 << 8) - 1,
59 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0))] 59 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3))]
60 Resolution::SixBit => (1 << 6) - 1, 60 Resolution::SixBit => (1 << 6) - 1,
61 } 61 }
62 } 62 }
diff --git a/embassy-stm32/src/adc/sample_time.rs b/embassy-stm32/src/adc/sample_time.rs
index 5480e7a77..6a6619299 100644
--- a/embassy-stm32/src/adc/sample_time.rs
+++ b/embassy-stm32/src/adc/sample_time.rs
@@ -1,4 +1,4 @@
1#[cfg(not(any(adc_f3, adc_f3_v2)))] 1#[cfg(not(adc_f3_v2))]
2macro_rules! impl_sample_time { 2macro_rules! impl_sample_time {
3 ($default_doc:expr, $default:ident, ($(($doc:expr, $variant:ident, $pac_variant:ident)),*)) => { 3 ($default_doc:expr, $default:ident, ($(($doc:expr, $variant:ident, $pac_variant:ident)),*)) => {
4 #[doc = concat!("ADC sample time\n\nThe default setting is ", $default_doc, " ADC clock cycles.")] 4 #[doc = concat!("ADC sample time\n\nThe default setting is ", $default_doc, " ADC clock cycles.")]
@@ -105,3 +105,19 @@ impl_sample_time!(
105 ("810.5", Cycles810_5, CYCLES810_5) 105 ("810.5", Cycles810_5, CYCLES810_5)
106 ) 106 )
107); 107);
108
109#[cfg(adc_f3)]
110impl_sample_time!(
111 "1.5",
112 Cycles1_5,
113 (
114 ("1.5", Cycles1_5, CYCLES1_5),
115 ("2.5", Cycles2_5, CYCLES2_5),
116 ("4.5", Cycles4_5, CYCLES4_5),
117 ("7.5", Cycles7_5, CYCLES7_5),
118 ("19.5", Cycles19_5, CYCLES19_5),
119 ("61.5", Cycles61_5, CYCLES61_5),
120 ("181.5", Cycles181_5, CYCLES181_5),
121 ("601.5", Cycles601_5, CYCLES601_5)
122 )
123);
diff --git a/embassy-stm32/src/rcc/f3.rs b/embassy-stm32/src/rcc/f3.rs
index 7480c0393..f8726c24a 100644
--- a/embassy-stm32/src/rcc/f3.rs
+++ b/embassy-stm32/src/rcc/f3.rs
@@ -1,5 +1,5 @@
1use crate::pac::flash::vals::Latency; 1use crate::pac::flash::vals::Latency;
2use crate::pac::rcc::vals::{Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre}; 2use crate::pac::rcc::vals::{Adcpres, Hpre, Pllmul, Pllsrc, Ppre, Prediv, Sw, Usbpre};
3use crate::pac::{FLASH, RCC}; 3use crate::pac::{FLASH, RCC};
4use crate::rcc::{set_freqs, Clocks}; 4use crate::rcc::{set_freqs, Clocks};
5use crate::time::Hertz; 5use crate::time::Hertz;
@@ -10,6 +10,46 @@ pub const HSI_FREQ: Hertz = Hertz(8_000_000);
10/// LSI speed 10/// LSI speed
11pub const LSI_FREQ: Hertz = Hertz(40_000); 11pub const LSI_FREQ: Hertz = Hertz(40_000);
12 12
13#[repr(u16)]
14#[derive(Clone, Copy)]
15pub enum ADCPrescaler {
16 Div1 = 1,
17 Div2 = 2,
18 Div4 = 4,
19 Div6 = 6,
20 Div8 = 8,
21 Div12 = 12,
22 Div16 = 16,
23 Div32 = 32,
24 Div64 = 64,
25 Div128 = 128,
26 Div256 = 256,
27}
28
29impl From<ADCPrescaler> for Adcpres {
30 fn from(value: ADCPrescaler) -> Self {
31 match value {
32 ADCPrescaler::Div1 => Adcpres::DIV1,
33 ADCPrescaler::Div2 => Adcpres::DIV2,
34 ADCPrescaler::Div4 => Adcpres::DIV4,
35 ADCPrescaler::Div6 => Adcpres::DIV6,
36 ADCPrescaler::Div8 => Adcpres::DIV8,
37 ADCPrescaler::Div12 => Adcpres::DIV12,
38 ADCPrescaler::Div16 => Adcpres::DIV16,
39 ADCPrescaler::Div32 => Adcpres::DIV32,
40 ADCPrescaler::Div64 => Adcpres::DIV64,
41 ADCPrescaler::Div128 => Adcpres::DIV128,
42 ADCPrescaler::Div256 => Adcpres::DIV256,
43 }
44 }
45}
46
47#[derive(Clone, Copy)]
48pub enum ADCClock {
49 AHB(ADCPrescaler),
50 PLL(ADCPrescaler),
51}
52
13/// Clocks configutation 53/// Clocks configutation
14#[non_exhaustive] 54#[non_exhaustive]
15#[derive(Default)] 55#[derive(Default)]
@@ -36,9 +76,18 @@ pub struct Config {
36 /// - The System clock frequency is either 48MHz or 72MHz 76 /// - The System clock frequency is either 48MHz or 72MHz
37 /// - APB1 clock has a minimum frequency of 10MHz 77 /// - APB1 clock has a minimum frequency of 10MHz
38 pub pll48: bool, 78 pub pll48: bool,
79 #[cfg(rcc_f3)]
80 /// ADC clock setup
81 /// - For AHB, a psc of 4 or less must be used
82 pub adc: Option<ADCClock>,
83 #[cfg(rcc_f3)]
84 /// ADC clock setup
85 /// - For AHB, a psc of 4 or less must be used
86 pub adc34: Option<ADCClock>,
39} 87}
40 88
41// Information required to setup the PLL clock 89// Information required to setup the PLL clock
90#[derive(Clone, Copy)]
42struct PllConfig { 91struct PllConfig {
43 pll_src: Pllsrc, 92 pll_src: Pllsrc,
44 pll_mul: Pllmul, 93 pll_mul: Pllmul,
@@ -148,6 +197,44 @@ pub(crate) unsafe fn init(config: Config) {
148 }); 197 });
149 } 198 }
150 199
200 #[cfg(rcc_f3)]
201 let adc = config.adc.map(|adc| match adc {
202 ADCClock::PLL(psc) => RCC.cfgr2().modify(|w| {
203 // Make sure that we're using the PLL
204 pll_config.unwrap();
205 w.set_adc12pres(psc.into());
206
207 Hertz(sysclk / psc as u32)
208 }),
209 ADCClock::AHB(psc) => {
210 assert!(psc as u16 <= 4);
211 assert!(!(psc as u16 == 1 && hpre_bits != Hpre::DIV1));
212
213 // To select this scheme, bits CKMODE[1:0] of the ADCx_CCR register must be
214 // different from “00”.
215 todo!();
216 }
217 });
218
219 #[cfg(rcc_f3)]
220 let adc34 = config.adc34.map(|adc| match adc {
221 ADCClock::PLL(psc) => RCC.cfgr2().modify(|w| {
222 // Make sure that we're using the PLL
223 pll_config.unwrap();
224 w.set_adc34pres(psc.into());
225
226 Hertz(sysclk / psc as u32)
227 }),
228 ADCClock::AHB(psc) => {
229 assert!(psc as u16 <= 4);
230 assert!(!(psc as u16 == 1 && hpre_bits != Hpre::DIV1));
231
232 // To select this scheme, bits CKMODE[1:0] of the ADCx_CCR register must be
233 // different from “00”.
234 todo!();
235 }
236 });
237
151 // Set prescalers 238 // Set prescalers
152 // CFGR has been written before (PLL, PLL48) don't overwrite these settings 239 // CFGR has been written before (PLL, PLL48) don't overwrite these settings
153 RCC.cfgr().modify(|w| { 240 RCC.cfgr().modify(|w| {
@@ -177,6 +264,10 @@ pub(crate) unsafe fn init(config: Config) {
177 apb1_tim: Hertz(pclk1 * timer_mul1), 264 apb1_tim: Hertz(pclk1 * timer_mul1),
178 apb2_tim: Hertz(pclk2 * timer_mul2), 265 apb2_tim: Hertz(pclk2 * timer_mul2),
179 ahb1: Hertz(hclk), 266 ahb1: Hertz(hclk),
267 #[cfg(rcc_f3)]
268 adc: adc,
269 #[cfg(rcc_f3)]
270 adc34: adc34,
180 }); 271 });
181} 272}
182 273
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index ecabe23ae..535ab6ad4 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -74,14 +74,11 @@ pub struct Clocks {
74 #[cfg(stm32f1)] 74 #[cfg(stm32f1)]
75 pub adc: Hertz, 75 pub adc: Hertz,
76 76
77 #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab))] 77 #[cfg(any(rcc_h5, rcc_h50, rcc_h7, rcc_h7ab, rcc_f3, rcc_g4))]
78 pub adc: Option<Hertz>, 78 pub adc: Option<Hertz>,
79 79
80 #[cfg(any(rcc_g4))] 80 #[cfg(any(rcc_f3, rcc_g4))]
81 pub adc12: Option<Hertz>, 81 pub adc34: Option<Hertz>,
82
83 #[cfg(any(rcc_g4))]
84 pub adc345: Option<Hertz>,
85 82
86 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] 83 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
87 /// Set only if the lsi or lse is configured, indicates stop is supported 84 /// Set only if the lsi or lse is configured, indicates stop is supported
diff --git a/examples/stm32f334/src/bin/adc.rs b/examples/stm32f334/src/bin/adc.rs
new file mode 100644
index 000000000..729497e82
--- /dev/null
+++ b/examples/stm32f334/src/bin/adc.rs
@@ -0,0 +1,34 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::info;
6use embassy_executor::Spawner;
7use embassy_stm32::adc::Adc;
8use embassy_stm32::rcc::{ADCClock, ADCPrescaler};
9use embassy_stm32::time::Hertz;
10use embassy_stm32::Config;
11use embassy_time::{Delay, Duration, Timer};
12use {defmt_rtt as _, panic_probe as _};
13
14#[embassy_executor::main]
15async fn main(_spawner: Spawner) -> ! {
16 let mut config = Config::default();
17 config.rcc.hse = Some(Hertz(8_000_000));
18 config.rcc.sysclk = Some(Hertz(16_000_000));
19 config.rcc.adc = Some(ADCClock::PLL(ADCPrescaler::Div1));
20
21 let mut p = embassy_stm32::init(config);
22
23 let mut adc = Adc::new(p.ADC1, &mut Delay);
24
25 let mut vrefint = adc.enable_vref(&mut Delay);
26
27 let _vref = adc.read(&mut vrefint);
28 let _pin = adc.read(&mut p.PA0);
29
30 loop {
31 info!("Hello World!");
32 Timer::after(Duration::from_secs(1)).await;
33 }
34}