From ab8f25fd78582aab68c9820e4b4dd9771a1ded65 Mon Sep 17 00:00:00 2001
From: shufps <shufps80@gmail.com>
Date: Thu, 8 Feb 2024 10:47:26 +0100
Subject: [PATCH] added support for ADC of L0s

---
 embassy-stm32/Cargo.toml             |  4 ++--
 embassy-stm32/src/adc/mod.rs         | 23 ++++++++++++-----------
 embassy-stm32/src/adc/resolution.rs  |  8 ++++----
 embassy-stm32/src/adc/sample_time.rs |  2 +-
 embassy-stm32/src/adc/v1.rs          | 21 +++++++++++++++++++++
 5 files changed, 40 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"
 sdio-host = "0.5.0"
 critical-section = "1.1"
 #stm32-metapac = { version = "15" }
-stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e702b4d564bc9e3c8a5c0141a11efdc5f7ee8f24" }
+stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d7c933984fe0cbd120b6aaa7742bd585f89fa786" }
 vcell = "0.1.3"
 bxcan = "0.7.0"
 nb = "1.0.0"
@@ -89,7 +89,7 @@ critical-section = { version = "1.1", features = ["std"] }
 proc-macro2 = "1.0.36"
 quote = "1.0.15"
 #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]}
-stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-e702b4d564bc9e3c8a5c0141a11efdc5f7ee8f24", default-features = false, features = ["metadata"]}
+stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-d7c933984fe0cbd120b6aaa7742bd585f89fa786", default-features = false, features = ["metadata"]}
 
 
 [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 @@
 #[cfg_attr(adc_f3, path = "f3.rs")]
 #[cfg_attr(adc_f3_v1_1, path = "f3_v1_1.rs")]
 #[cfg_attr(adc_v1, path = "v1.rs")]
+#[cfg_attr(adc_l0, path = "v1.rs")]
 #[cfg_attr(adc_v2, path = "v2.rs")]
 #[cfg_attr(any(adc_v3, adc_g0), path = "v3.rs")]
 #[cfg_attr(adc_v4, path = "v4.rs")]
@@ -36,15 +37,15 @@ pub struct Adc<'d, T: Instance> {
 }
 
 pub(crate) mod sealed {
-    #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
+    #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
     use embassy_sync::waitqueue::AtomicWaker;
 
-    #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
+    #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
     pub struct State {
         pub waker: AtomicWaker,
     }
 
-    #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
+    #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
     impl State {
         pub const fn new() -> Self {
             Self {
@@ -59,14 +60,14 @@ pub(crate) mod sealed {
 
     pub trait Instance: InterruptableInstance {
         fn regs() -> crate::pac::adc::Adc;
-        #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
+        #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
         fn common_regs() -> crate::pac::adccommon::AdcCommon;
-        #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
+        #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
         fn state() -> &'static State;
     }
 
     pub trait AdcPin<T: Instance> {
-        #[cfg(any(adc_v1, adc_v2))]
+        #[cfg(any(adc_v1, adc_l0, adc_v2))]
         fn set_as_analog(&mut self) {}
 
         fn channel(&self) -> u8;
@@ -78,10 +79,10 @@ pub(crate) mod sealed {
 }
 
 /// ADC instance.
-#[cfg(not(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0)))]
+#[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0)))]
 pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> {}
 /// ADC instance.
-#[cfg(any(adc_f1, adc_v1, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))]
+#[cfg(any(adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_f3, adc_f3_v1_1, adc_g0))]
 pub trait Instance: sealed::Instance + crate::Peripheral<P = Self> + crate::rcc::RccPeripheral {}
 
 /// ADC pin.
@@ -96,12 +97,12 @@ foreach_adc!(
                 crate::pac::$inst
             }
 
-            #[cfg(not(any(adc_f1, adc_v1, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
+            #[cfg(not(any(adc_f1, adc_v1, adc_l0, adc_f3_v2, adc_f3_v1_1, adc_g0)))]
             fn common_regs() -> crate::pac::adccommon::AdcCommon {
                 return crate::pac::$common_inst
             }
 
-            #[cfg(any(adc_f1, adc_f3, adc_v1, adc_f3_v1_1))]
+            #[cfg(any(adc_f1, adc_f3, adc_v1, adc_l0, adc_f3_v1_1))]
             fn state() -> &'static sealed::State {
                 static STATE: sealed::State = sealed::State::new();
                 &STATE
@@ -125,7 +126,7 @@ macro_rules! impl_adc_pin {
         impl crate::adc::AdcPin<peripherals::$inst> for crate::peripherals::$pin {}
 
         impl crate::adc::sealed::AdcPin<peripherals::$inst> for crate::peripherals::$pin {
-            #[cfg(any(adc_v1, adc_v2))]
+            #[cfg(any(adc_v1, adc_l0, adc_v2))]
             fn set_as_analog(&mut self) {
                 <Self as crate::gpio::sealed::Pin>::set_as_analog(self);
             }
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 @@
 /// ADC resolution
 #[allow(missing_docs)]
-#[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))]
+#[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 #[cfg_attr(feature = "defmt", derive(defmt::Format))]
 pub enum Resolution {
@@ -25,7 +25,7 @@ pub enum Resolution {
 
 impl Default for Resolution {
     fn default() -> Self {
-        #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))]
+        #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
         {
             Self::TwelveBit
         }
@@ -46,7 +46,7 @@ impl From<Resolution> for crate::pac::adc::vals::Res {
             Resolution::TwelveBit => crate::pac::adc::vals::Res::TWELVEBIT,
             Resolution::TenBit => crate::pac::adc::vals::Res::TENBIT,
             Resolution::EightBit => crate::pac::adc::vals::Res::EIGHTBIT,
-            #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))]
+            #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
             Resolution::SixBit => crate::pac::adc::vals::Res::SIXBIT,
         }
     }
@@ -65,7 +65,7 @@ impl Resolution {
             Resolution::TwelveBit => (1 << 12) - 1,
             Resolution::TenBit => (1 << 10) - 1,
             Resolution::EightBit => (1 << 8) - 1,
-            #[cfg(any(adc_v1, adc_v2, adc_v3, adc_g0, adc_f3, adc_f3_v1_1))]
+            #[cfg(any(adc_v1, adc_v2, adc_v3, adc_l0, adc_g0, adc_f3, adc_f3_v1_1))]
             Resolution::SixBit => (1 << 6) - 1,
         }
     }
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!(
     )
 );
 
-#[cfg(adc_g0)]
+#[cfg(any(adc_l0, adc_g0))]
 impl_sample_time!(
     "1.5",
     Cycles1_5,
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs
index 852b027df..13a7ead3e 100644
--- a/embassy-stm32/src/adc/v1.rs
+++ b/embassy-stm32/src/adc/v1.rs
@@ -6,6 +6,10 @@ use embassy_hal_internal::into_ref;
 use embedded_hal_02::blocking::delay::DelayUs;
 
 use crate::adc::{Adc, AdcPin, Instance, Resolution, SampleTime};
+
+#[cfg(adc_l0)]
+use stm32_metapac::adc::vals::Ckmode;
+
 use crate::interrupt::typelevel::Interrupt;
 use crate::peripherals::ADC;
 use crate::{interrupt, Peripheral};
@@ -30,8 +34,13 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl
     }
 }
 
+#[cfg(not(adc_l0))]
 pub struct Vbat;
+
+#[cfg(not(adc_l0))]
 impl AdcPin<ADC> for Vbat {}
+
+#[cfg(not(adc_l0))]
 impl super::sealed::AdcPin<ADC> for Vbat {
     fn channel(&self) -> u8 {
         18
@@ -72,6 +81,11 @@ impl<'d, T: Instance> Adc<'d, T> {
         // A.7.1 ADC calibration code example
         T::regs().cfgr1().modify(|reg| reg.set_dmaen(false));
         T::regs().cr().modify(|reg| reg.set_adcal(true));
+
+        #[cfg(adc_l0)]
+        while !T::regs().isr().read().eocal() {}
+
+        #[cfg(not(adc_l0))]
         while T::regs().cr().read().adcal() {}
 
         // A.7.2 ADC enable sequence code example
@@ -97,6 +111,7 @@ impl<'d, T: Instance> Adc<'d, T> {
         }
     }
 
+    #[cfg(not(adc_l0))]
     pub fn enable_vbat(&self, _delay: &mut impl DelayUs<u32>) -> Vbat {
         // SMP must be ≥ 56 ADC clock cycles when using HSI14.
         //
@@ -133,6 +148,12 @@ impl<'d, T: Instance> Adc<'d, T> {
         T::regs().cfgr1().modify(|reg| reg.set_res(resolution.into()));
     }
 
+    #[cfg(adc_l0)]
+    pub fn set_ckmode(&mut self, ckmode: Ckmode) {
+        // set ADC clock mode
+        T::regs().cfgr2().modify(|reg| reg.set_ckmode(ckmode));
+    }
+
     pub async fn read(&mut self, pin: &mut impl AdcPin<T>) -> u16 {
         let channel = pin.channel();
         pin.set_as_analog();