aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/Cargo.toml4
-rw-r--r--embassy-stm32/src/adc/mod.rs23
-rw-r--r--embassy-stm32/src/adc/resolution.rs8
-rw-r--r--embassy-stm32/src/adc/sample_time.rs2
-rw-r--r--embassy-stm32/src/adc/v1.rs23
-rw-r--r--examples/stm32l0/src/bin/adc.rs40
6 files changed, 82 insertions, 18 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 8f0fc1c59..61d70b732 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -68,7 +68,7 @@ rand_core = "0.6.3"
68sdio-host = "0.5.0" 68sdio-host = "0.5.0"
69critical-section = "1.1" 69critical-section = "1.1"
70#stm32-metapac = { version = "15" } 70#stm32-metapac = { version = "15" }
71stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e702b4d564bc9e3c8a5c0141a11efdc5f7ee8f24" } 71stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d7c933984fe0cbd120b6aaa7742bd585f89fa786" }
72vcell = "0.1.3" 72vcell = "0.1.3"
73bxcan = "0.7.0" 73bxcan = "0.7.0"
74nb = "1.0.0" 74nb = "1.0.0"
@@ -89,7 +89,7 @@ critical-section = { version = "1.1", features = ["std"] }
89proc-macro2 = "1.0.36" 89proc-macro2 = "1.0.36"
90quote = "1.0.15" 90quote = "1.0.15"
91#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} 91#stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
92stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e702b4d564bc9e3c8a5c0141a11efdc5f7ee8f24", default-features = false, features = ["metadata"]} 92stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d7c933984fe0cbd120b6aaa7742bd585f89fa786", default-features = false, features = ["metadata"]}
93 93
94 94
95[features] 95[features]
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs
index d21c3053f..51b4b5fcc 100644
--- a/embassy-stm32/src/adc/mod.rs
+++ b/embassy-stm32/src/adc/mod.rs
@@ -8,6 +8,7 @@
8#[cfg_attr(adc_f3, path = "f3.rs")] 8#[cfg_attr(adc_f3, path = "f3.rs")]
9#[cfg_attr(adc_f3_v1_1, path = "f3_v1_1.rs")] 9#[cfg_attr(adc_f3_v1_1, path = "f3_v1_1.rs")]
10#[cfg_attr(adc_v1, path = "v1.rs")] 10#[cfg_attr(adc_v1, path = "v1.rs")]
11#[cfg_attr(adc_l0, path = "v1.rs")]
11#[cfg_attr(adc_v2, path = "v2.rs")] 12#[cfg_attr(adc_v2, path = "v2.rs")]
12#[cfg_attr(any(adc_v3, adc_g0), path = "v3.rs")] 13#[cfg_attr(any(adc_v3, adc_g0), path = "v3.rs")]
13#[cfg_attr(adc_v4, path = "v4.rs")] 14#[cfg_attr(adc_v4, path = "v4.rs")]
@@ -36,15 +37,15 @@ pub struct Adc<'d, T: Instance> {
36} 37}
37 38
38pub(crate) mod sealed { 39pub(crate) mod sealed {
39 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))] 40 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
40 use embassy_sync::waitqueue::AtomicWaker; 41 use embassy_sync::waitqueue::AtomicWaker;
41 42
42 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))] 43 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
43 pub struct State { 44 pub struct State {
44 pub waker: AtomicWaker, 45 pub waker: AtomicWaker,
45 } 46 }
46 47
47 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))] 48 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
48 impl State { 49 impl State {
49 pub const fn new() -> Self { 50 pub const fn new() -> Self {
50 Self { 51 Self {
@@ -59,14 +60,14 @@ pub(crate) mod sealed {
59 60
60 pub trait Instance: InterruptableInstance { 61 pub trait Instance: InterruptableInstance {
61 fn regs() -> crate::pac::adc::Adc; 62 fn regs() -> crate::pac::adc::Adc;
62 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_f3_v1_1, adc_g0)))] 63 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
63 fn common_regs() -> crate::pac::adccommon::AdcCommon; 64 fn common_regs() -> crate::pac::adccommon::AdcCommon;
64 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))] 65 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
65 fn state() -> &'static State; 66 fn state() -> &'static State;
66 } 67 }
67 68
68 pub trait AdcPin<T: Instance> { 69 pub trait AdcPin<T: Instance> {
69 #[cfg(any(adc_v1, adc_v2))] 70 #[cfg(any(adc_v1, adc_l0, adc_v2))]
70 fn set_as_analog(&mut self) {} 71 fn set_as_analog(&mut self) {}
71 72
72 fn channel(&self) -> u8; 73 fn channel(&self) -> u8;
@@ -78,10 +79,10 @@ pub(crate) mod sealed {
78} 79}
79 80
80/// ADC instance. 81/// ADC instance.
81#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0)))] 82#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0)))]
82pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {} 83pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {}
83/// ADC instance. 84/// ADC instance.
84#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))] 85#[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))]
85pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {} 86pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {}
86 87
87/// ADC pin. 88/// ADC pin.
@@ -96,12 +97,12 @@ foreach_adc!(
96 crate::pac::$inst 97 crate::pac::$inst
97 } 98 }
98 99
99 #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_f3_v1_1, adc_g0)))] 100 #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
100 fn common_regs() -> crate::pac::adccommon::AdcCommon { 101 fn common_regs() -> crate::pac::adccommon::AdcCommon {
101 return crate::pac::$common_inst 102 return crate::pac::$common_inst
102 } 103 }
103 104
104 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))] 105 #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
105 fn state() -> &'static sealed::State { 106 fn state() -> &'static sealed::State {
106 static STATE: sealed::State = sealed::State::new(); 107 static STATE: sealed::State = sealed::State::new();
107 &STATE 108 &STATE
@@ -125,7 +126,7 @@ macro_rules! impl_adc_pin {
125 impl crate::adc::AdcPin<peripherals::$inst> for crate::peripherals::$pin {} 126 impl crate::adc::AdcPin<peripherals::$inst> for crate::peripherals::$pin {}
126 127
127 impl crate::adc::sealed::AdcPin<peripherals::$inst> for crate::peripherals::$pin { 128 impl crate::adc::sealed::AdcPin<peripherals::$inst> for crate::peripherals::$pin {
128 #[cfg(any(adc_v1, adc_v2))] 129 #[cfg(any(adc_v1, adc_l0, adc_v2))]
129 fn set_as_analog(&mut self) { 130 fn set_as_analog(&mut self) {
130 <Self as crate::gpio::sealed::Pin>::set_as_analog(self); 131 <Self as crate::gpio::sealed::Pin>::set_as_analog(self);
131 } 132 }
diff --git a/embassy-stm32/src/adc/resolution.rs b/embassy-stm32/src/adc/resolution.rs
index 9513e1df7..0e6c45c65 100644
--- a/embassy-stm32/src/adc/resolution.rs
+++ b/embassy-stm32/src/adc/resolution.rs
@@ -1,6 +1,6 @@
1/// ADC resolution 1/// ADC resolution
2#[allow(missing_docs)] 2#[allow(missing_docs)]
3#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))] 3#[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
4#[derive(Clone, Copy, Debug, Eq, PartialEq)] 4#[derive(Clone, Copy, Debug, Eq, PartialEq)]
5#[cfg_attr(feature = "defmt", derive(defmt::Format))] 5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6pub enum Resolution { 6pub enum Resolution {
@@ -25,7 +25,7 @@ pub enum Resolution {
25 25
26impl Default for Resolution { 26impl Default for Resolution {
27 fn default() -> Self { 27 fn default() -> Self {
28 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))] 28 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
29 { 29 {
30 Self::TwelveBit 30 Self::TwelveBit
31 } 31 }
@@ -46,7 +46,7 @@ impl From<Resolution> for crate::pac::adc::vals::Res {
46 Resolution::TwelveBit => crate::pac::adc::vals::Res::TWELVEBIT, 46 Resolution::TwelveBit => crate::pac::adc::vals::Res::TWELVEBIT,
47 Resolution::TenBit => crate::pac::adc::vals::Res::TENBIT, 47 Resolution::TenBit => crate::pac::adc::vals::Res::TENBIT,
48 Resolution::EightBit => crate::pac::adc::vals::Res::EIGHTBIT, 48 Resolution::EightBit => crate::pac::adc::vals::Res::EIGHTBIT,
49 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))] 49 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
50 Resolution::SixBit => crate::pac::adc::vals::Res::SIXBIT, 50 Resolution::SixBit => crate::pac::adc::vals::Res::SIXBIT,
51 } 51 }
52 } 52 }
@@ -65,7 +65,7 @@ impl Resolution {
65 Resolution::TwelveBit => (1 << 12) - 1, 65 Resolution::TwelveBit => (1 << 12) - 1,
66 Resolution::TenBit => (1 << 10) - 1, 66 Resolution::TenBit => (1 << 10) - 1,
67 Resolution::EightBit => (1 << 8) - 1, 67 Resolution::EightBit => (1 << 8) - 1,
68 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))] 68 #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
69 Resolution::SixBit => (1 << 6) - 1, 69 Resolution::SixBit => (1 << 6) - 1,
70 } 70 }
71 } 71 }
diff --git a/embassy-stm32/src/adc/sample_time.rs b/embassy-stm32/src/adc/sample_time.rs
index 5a06f1a5a..f4b22b462 100644
--- a/embassy-stm32/src/adc/sample_time.rs
+++ b/embassy-stm32/src/adc/sample_time.rs
@@ -83,7 +83,7 @@ impl_sample_time!(
83 ) 83 )
84); 84);
85 85
86#[cfg(adc_g0)] 86#[cfg(any(adc_l0, adc_g0))]
87impl_sample_time!( 87impl_sample_time!(
88 "1.5", 88 "1.5",
89 Cycles1_5, 89 Cycles1_5,
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index 852b027df..37115dfab 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -4,6 +4,8 @@ use core::task::Poll;
4 4
5use embassy_hal_internal::into_ref; 5use embassy_hal_internal::into_ref;
6use embedded_hal_02::blocking::delay::DelayUs; 6use embedded_hal_02::blocking::delay::DelayUs;
7#[cfg(adc_l0)]
8use stm32_metapac::adc::vals::Ckmode;
7 9
8use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime}; 10use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
9use crate::interrupt::typelevel::Interrupt; 11use crate::interrupt::typelevel::Interrupt;
@@ -30,8 +32,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
30 } 32 }
31} 33}
32 34
35#[cfg(not(adc_l0))]
33pub struct Vbat; 36pub struct Vbat;
37
38#[cfg(not(adc_l0))]
34impl AdcPin<ADC> for Vbat {} 39impl AdcPin<ADC> for Vbat {}
40
41#[cfg(not(adc_l0))]
35impl super::sealed::AdcPin<ADC> for Vbat { 42impl super::sealed::AdcPin<ADC> for Vbat {
36 fn channel(&self) -> u8 { 43 fn channel(&self) -> u8 {
37 18 44 18
@@ -69,9 +76,18 @@ impl<'d, T: Instance> Adc<'d, T> {
69 // tstab = 14 * 1/fadc 76 // tstab = 14 * 1/fadc
70 delay.delay_us(1); 77 delay.delay_us(1);
71 78
79 // set default PCKL/2 on L0s because HSI is disabled in the default clock config
80 #[cfg(adc_l0)]
81 T::regs().cfgr2().modify(|reg| reg.set_ckmode(Ckmode::PCLK_DIV2));
82
72 // A.7.1 ADC calibration code example 83 // A.7.1 ADC calibration code example
73 T::regs().cfgr1().modify(|reg| reg.set_dmaen(false)); 84 T::regs().cfgr1().modify(|reg| reg.set_dmaen(false));
74 T::regs().cr().modify(|reg| reg.set_adcal(true)); 85 T::regs().cr().modify(|reg| reg.set_adcal(true));
86
87 #[cfg(adc_l0)]
88 while !T::regs().isr().read().eocal() {}
89
90 #[cfg(not(adc_l0))]
75 while T::regs().cr().read().adcal() {} 91 while T::regs().cr().read().adcal() {}
76 92
77 // A.7.2 ADC enable sequence code example 93 // A.7.2 ADC enable sequence code example
@@ -97,6 +113,7 @@ impl<'d, T: Instance> Adc<'d, T> {
97 } 113 }
98 } 114 }
99 115
116 #[cfg(not(adc_l0))]
100 pub fn enable_vbat(&self, _delay: &mut impl DelayUs<u32>) -> Vbat { 117 pub fn enable_vbat(&self, _delay: &mut impl DelayUs<u32>) -> Vbat {
101 // SMP must be ≥ 56 ADC clock cycles when using HSI14. 118 // SMP must be ≥ 56 ADC clock cycles when using HSI14.
102 // 119 //
@@ -133,6 +150,12 @@ impl<'d, T: Instance> Adc<'d, T> {
133 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into())); 150 T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
134 } 151 }
135 152
153 #[cfg(adc_l0)]
154 pub fn set_ckmode(&mut self, ckmode: Ckmode) {
155 // set ADC clock mode
156 T::regs().cfgr2().modify(|reg| reg.set_ckmode(ckmode));
157 }
158
136 pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 { 159 pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
137 let channel = pin.channel(); 160 let channel = pin.channel();
138 pin.set_as_analog(); 161 pin.set_as_analog();
diff --git a/examples/stm32l0/src/bin/adc.rs b/examples/stm32l0/src/bin/adc.rs
new file mode 100644
index 000000000..adeaa208a
--- /dev/null
+++ b/examples/stm32l0/src/bin/adc.rs
@@ -0,0 +1,40 @@
1#![no_std]
2#![no_main]
3
4use defmt::*;
5use embassy_executor::Spawner;
6use embassy_stm32::adc::{Adc, SampleTime};
7use embassy_stm32::peripherals::ADC;
8use embassy_stm32::{adc, bind_interrupts};
9use embassy_time::{Delay, Timer};
10use {defmt_rtt as _, panic_probe as _};
11
12bind_interrupts!(struct Irqs {
13 ADC1_COMP => adc::InterruptHandler<ADC>;
14});
15
16#[embassy_executor::main]
17async fn main(_spawner: Spawner) {
18 let p = embassy_stm32::init(Default::default());
19 info!("Hello World!");
20
21 let mut adc = Adc::new(p.ADC, Irqs, &mut Delay);
22 adc.set_sample_time(SampleTime::Cycles79_5);
23 let mut pin = p.PA1;
24
25 let mut vrefint = adc.enable_vref(&mut Delay);
26 let vrefint_sample = adc.read(&mut vrefint).await;
27 let convert_to_millivolts = |sample| {
28 // From https://www.st.com/resource/en/datasheet/stm32l051c6.pdf
29 // 6.3.3 Embedded internal reference voltage
30 const VREFINT_MV: u32 = 1224; // mV
31
32 (u32::from(sample) * VREFINT_MV / u32::from(vrefint_sample)) as u16
33 };
34
35 loop {
36 let v = adc.read(&mut pin).await;
37 info!("--> {} - {} mV", v, convert_to_millivolts(v));
38 Timer::after_millis(100).await;
39 }
40}