diff options
| author | xoviat <[email protected]> | 2025-11-10 12:37:38 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2025-11-10 12:37:38 -0600 |
| commit | c90e4b3135283070bddc6a8e64df3139909ac8ce (patch) | |
| tree | 21fdadcff4c71e90f5ede1475547e739c06345ae | |
| parent | 12b59dc610fb659a4d51ccc364865a7e154379d6 (diff) | |
adc: use common vref scheme
| -rw-r--r-- | embassy-stm32/src/adc/c0.rs | 32 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/f1.rs | 24 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/f3.rs | 26 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/g4.rs | 85 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/mod.rs | 41 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/v1.rs | 40 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/v2.rs | 47 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/v3.rs | 101 | ||||
| -rw-r--r-- | embassy-stm32/src/adc/v4.rs | 61 |
9 files changed, 195 insertions, 262 deletions
diff --git a/embassy-stm32/src/adc/c0.rs b/embassy-stm32/src/adc/c0.rs index 70302ef96..1869993a5 100644 --- a/embassy-stm32/src/adc/c0.rs +++ b/embassy-stm32/src/adc/c0.rs | |||
| @@ -19,33 +19,17 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(25); | |||
| 19 | 19 | ||
| 20 | const TIME_ADC_VOLTAGE_REGUALTOR_STARTUP_US: u32 = 20; | 20 | const TIME_ADC_VOLTAGE_REGUALTOR_STARTUP_US: u32 = 20; |
| 21 | 21 | ||
| 22 | const TEMP_CHANNEL: u8 = 9; | ||
| 23 | const VREF_CHANNEL: u8 = 10; | ||
| 24 | |||
| 25 | const NUM_HW_CHANNELS: u8 = 22; | 22 | const NUM_HW_CHANNELS: u8 = 22; |
| 26 | const CHSELR_SQ_SIZE: usize = 8; | 23 | const CHSELR_SQ_SIZE: usize = 8; |
| 27 | const CHSELR_SQ_MAX_CHANNEL: u8 = 14; | 24 | const CHSELR_SQ_MAX_CHANNEL: u8 = 14; |
| 28 | const CHSELR_SQ_SEQUENCE_END_MARKER: u8 = 0b1111; | 25 | const CHSELR_SQ_SEQUENCE_END_MARKER: u8 = 0b1111; |
| 29 | 26 | ||
| 30 | // NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, | 27 | impl<T: Instance> super::VrefConverter for T { |
| 31 | // this currently cannot be modeled with stm32-data, | 28 | const CHANNEL: u8 = 10; |
| 32 | // so these are available from the software on all ADCs. | ||
| 33 | /// Internal voltage reference channel. | ||
| 34 | pub struct VrefInt; | ||
| 35 | impl<T: Instance> AdcChannel<T> for VrefInt {} | ||
| 36 | impl<T: Instance> SealedAdcChannel<T> for VrefInt { | ||
| 37 | fn channel(&self) -> u8 { | ||
| 38 | VREF_CHANNEL | ||
| 39 | } | ||
| 40 | } | 29 | } |
| 41 | 30 | ||
| 42 | /// Internal temperature channel. | 31 | impl<T: Instance> super::TemperatureConverter for T { |
| 43 | pub struct Temperature; | 32 | const CHANNEL: u8 = 9; |
| 44 | impl<T: Instance> AdcChannel<T> for Temperature {} | ||
| 45 | impl<T: Instance> SealedAdcChannel<T> for Temperature { | ||
| 46 | fn channel(&self) -> u8 { | ||
| 47 | TEMP_CHANNEL | ||
| 48 | } | ||
| 49 | } | 33 | } |
| 50 | 34 | ||
| 51 | #[derive(Copy, Clone, Debug)] | 35 | #[derive(Copy, Clone, Debug)] |
| @@ -232,22 +216,22 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 232 | } | 216 | } |
| 233 | 217 | ||
| 234 | /// Enable reading the voltage reference internal channel. | 218 | /// Enable reading the voltage reference internal channel. |
| 235 | pub fn enable_vrefint(&self) -> VrefInt { | 219 | pub fn enable_vrefint(&self) -> super::VrefInt { |
| 236 | T::common_regs().ccr().modify(|reg| { | 220 | T::common_regs().ccr().modify(|reg| { |
| 237 | reg.set_vrefen(true); | 221 | reg.set_vrefen(true); |
| 238 | }); | 222 | }); |
| 239 | 223 | ||
| 240 | VrefInt {} | 224 | super::VrefInt {} |
| 241 | } | 225 | } |
| 242 | 226 | ||
| 243 | /// Enable reading the temperature internal channel. | 227 | /// Enable reading the temperature internal channel. |
| 244 | pub fn enable_temperature(&self) -> Temperature { | 228 | pub fn enable_temperature(&self) -> super::Temperature { |
| 245 | debug!("Ensure that sample time is set to more than temperature sensor T_start from the datasheet!"); | 229 | debug!("Ensure that sample time is set to more than temperature sensor T_start from the datasheet!"); |
| 246 | T::common_regs().ccr().modify(|reg| { | 230 | T::common_regs().ccr().modify(|reg| { |
| 247 | reg.set_tsen(true); | 231 | reg.set_tsen(true); |
| 248 | }); | 232 | }); |
| 249 | 233 | ||
| 250 | Temperature {} | 234 | super::Temperature {} |
| 251 | } | 235 | } |
| 252 | 236 | ||
| 253 | /// Set the ADC sample time. | 237 | /// Set the ADC sample time. |
diff --git a/embassy-stm32/src/adc/f1.rs b/embassy-stm32/src/adc/f1.rs index 32e330d76..835cc8c63 100644 --- a/embassy-stm32/src/adc/f1.rs +++ b/embassy-stm32/src/adc/f1.rs | |||
| @@ -28,20 +28,12 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 28 | } | 28 | } |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | pub struct Vref; | 31 | impl<T: Instance> super::VrefConverter for T { |
| 32 | impl<T: Instance> AdcChannel<T> for Vref {} | 32 | const CHANNEL: u8 = 17; |
| 33 | impl<T: Instance> super::SealedAdcChannel<T> for Vref { | ||
| 34 | fn channel(&self) -> u8 { | ||
| 35 | 17 | ||
| 36 | } | ||
| 37 | } | 33 | } |
| 38 | 34 | ||
| 39 | pub struct Temperature; | 35 | impl<T: Instance> super::TemperatureConverter for T { |
| 40 | impl<T: Instance> AdcChannel<T> for Temperature {} | 36 | const CHANNEL: u8 = 16; |
| 41 | impl<T: Instance> super::SealedAdcChannel<T> for Temperature { | ||
| 42 | fn channel(&self) -> u8 { | ||
| 43 | 16 | ||
| 44 | } | ||
| 45 | } | 37 | } |
| 46 | 38 | ||
| 47 | impl<'d, T: Instance> Adc<'d, T> { | 39 | impl<'d, T: Instance> Adc<'d, T> { |
| @@ -91,18 +83,18 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 91 | } | 83 | } |
| 92 | } | 84 | } |
| 93 | 85 | ||
| 94 | pub fn enable_vref(&self) -> Vref { | 86 | pub fn enable_vref(&self) -> super::VrefInt { |
| 95 | T::regs().cr2().modify(|reg| { | 87 | T::regs().cr2().modify(|reg| { |
| 96 | reg.set_tsvrefe(true); | 88 | reg.set_tsvrefe(true); |
| 97 | }); | 89 | }); |
| 98 | Vref {} | 90 | super::VrefInt {} |
| 99 | } | 91 | } |
| 100 | 92 | ||
| 101 | pub fn enable_temperature(&self) -> Temperature { | 93 | pub fn enable_temperature(&self) -> super::Temperature { |
| 102 | T::regs().cr2().modify(|reg| { | 94 | T::regs().cr2().modify(|reg| { |
| 103 | reg.set_tsvrefe(true); | 95 | reg.set_tsvrefe(true); |
| 104 | }); | 96 | }); |
| 105 | Temperature {} | 97 | super::Temperature {} |
| 106 | } | 98 | } |
| 107 | 99 | ||
| 108 | /// Perform a single conversion. | 100 | /// Perform a single conversion. |
diff --git a/embassy-stm32/src/adc/f3.rs b/embassy-stm32/src/adc/f3.rs index cf31aa81b..da185e875 100644 --- a/embassy-stm32/src/adc/f3.rs +++ b/embassy-stm32/src/adc/f3.rs | |||
| @@ -29,27 +29,19 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 29 | } | 29 | } |
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | pub struct Vref; | 32 | impl<T: Instance> super::VrefConverter for T { |
| 33 | impl<T: Instance> AdcChannel<T> for Vref {} | 33 | const CHANNEL: u8 = 18; |
| 34 | impl<T: Instance> super::SealedAdcChannel<T> for Vref { | ||
| 35 | fn channel(&self) -> u8 { | ||
| 36 | 18 | ||
| 37 | } | ||
| 38 | } | 34 | } |
| 39 | 35 | ||
| 40 | impl Vref { | 36 | impl super::VrefInt { |
| 41 | /// The value that vref would be if vdda was at 3300mv | 37 | /// The value that vref would be if vdda was at 3300mv |
| 42 | pub fn value(&self) -> u16 { | 38 | pub fn value(&self) -> u16 { |
| 43 | crate::pac::VREFINTCAL.data().read() | 39 | crate::pac::VREFINTCAL.data().read() |
| 44 | } | 40 | } |
| 45 | } | 41 | } |
| 46 | 42 | ||
| 47 | pub struct Temperature; | 43 | impl<T: Instance> super::TemperatureConverter for T { |
| 48 | impl<T: Instance> AdcChannel<T> for Temperature {} | 44 | const CHANNEL: u8 = 16; |
| 49 | impl<T: Instance> super::SealedAdcChannel<T> for Temperature { | ||
| 50 | fn channel(&self) -> u8 { | ||
| 51 | 16 | ||
| 52 | } | ||
| 53 | } | 45 | } |
| 54 | 46 | ||
| 55 | impl<'d, T: Instance> Adc<'d, T> { | 47 | impl<'d, T: Instance> Adc<'d, T> { |
| @@ -109,16 +101,16 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 109 | } | 101 | } |
| 110 | } | 102 | } |
| 111 | 103 | ||
| 112 | pub fn enable_vref(&self) -> Vref { | 104 | pub fn enable_vref(&self) -> super::VrefInt { |
| 113 | T::common_regs().ccr().modify(|w| w.set_vrefen(true)); | 105 | T::common_regs().ccr().modify(|w| w.set_vrefen(true)); |
| 114 | 106 | ||
| 115 | Vref {} | 107 | super::VrefInt {} |
| 116 | } | 108 | } |
| 117 | 109 | ||
| 118 | pub fn enable_temperature(&self) -> Temperature { | 110 | pub fn enable_temperature(&self) -> super::Temperature { |
| 119 | T::common_regs().ccr().modify(|w| w.set_tsen(true)); | 111 | T::common_regs().ccr().modify(|w| w.set_tsen(true)); |
| 120 | 112 | ||
| 121 | Temperature {} | 113 | super::Temperature {} |
| 122 | } | 114 | } |
| 123 | 115 | ||
| 124 | /// Perform a single conversion. | 116 | /// Perform a single conversion. |
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs index 5066aeec0..2138a82b4 100644 --- a/embassy-stm32/src/adc/g4.rs +++ b/embassy-stm32/src/adc/g4.rs | |||
| @@ -35,34 +35,6 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60); | |||
| 35 | #[cfg(stm32h7)] | 35 | #[cfg(stm32h7)] |
| 36 | const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); | 36 | const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); |
| 37 | 37 | ||
| 38 | // NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs | ||
| 39 | /// Internal voltage reference channel. | ||
| 40 | pub struct VrefInt; | ||
| 41 | impl<T: Instance + VrefChannel> AdcChannel<T> for VrefInt {} | ||
| 42 | impl<T: Instance + VrefChannel> super::SealedAdcChannel<T> for VrefInt { | ||
| 43 | fn channel(&self) -> u8 { | ||
| 44 | T::CHANNEL | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | /// Internal temperature channel. | ||
| 49 | pub struct Temperature; | ||
| 50 | impl<T: Instance + TemperatureChannel> AdcChannel<T> for Temperature {} | ||
| 51 | impl<T: Instance + TemperatureChannel> super::SealedAdcChannel<T> for Temperature { | ||
| 52 | fn channel(&self) -> u8 { | ||
| 53 | T::CHANNEL | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | /// Internal battery voltage channel. | ||
| 58 | pub struct Vbat; | ||
| 59 | impl<T: Instance + VBatChannel> AdcChannel<T> for Vbat {} | ||
| 60 | impl<T: Instance + VBatChannel> super::SealedAdcChannel<T> for Vbat { | ||
| 61 | fn channel(&self) -> u8 { | ||
| 62 | T::CHANNEL | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | // NOTE (unused): The prescaler enum closely copies the hardware capabilities, | 38 | // NOTE (unused): The prescaler enum closely copies the hardware capabilities, |
| 67 | // but high prescaling doesn't make a lot of sense in the current implementation and is ommited. | 39 | // but high prescaling doesn't make a lot of sense in the current implementation and is ommited. |
| 68 | #[allow(unused)] | 40 | #[allow(unused)] |
| @@ -250,39 +222,39 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 250 | } | 222 | } |
| 251 | 223 | ||
| 252 | /// Enable reading the voltage reference internal channel. | 224 | /// Enable reading the voltage reference internal channel. |
| 253 | pub fn enable_vrefint(&self) -> VrefInt | 225 | pub fn enable_vrefint(&self) -> super::VrefInt |
| 254 | where | 226 | where |
| 255 | T: VrefChannel, | 227 | T: super::VrefConverter, |
| 256 | { | 228 | { |
| 257 | T::common_regs().ccr().modify(|reg| { | 229 | T::common_regs().ccr().modify(|reg| { |
| 258 | reg.set_vrefen(true); | 230 | reg.set_vrefen(true); |
| 259 | }); | 231 | }); |
| 260 | 232 | ||
| 261 | VrefInt {} | 233 | super::VrefInt {} |
| 262 | } | 234 | } |
| 263 | 235 | ||
| 264 | /// Enable reading the temperature internal channel. | 236 | /// Enable reading the temperature internal channel. |
| 265 | pub fn enable_temperature(&self) -> Temperature | 237 | pub fn enable_temperature(&self) -> super::Temperature |
| 266 | where | 238 | where |
| 267 | T: TemperatureChannel, | 239 | T: super::TemperatureConverter, |
| 268 | { | 240 | { |
| 269 | T::common_regs().ccr().modify(|reg| { | 241 | T::common_regs().ccr().modify(|reg| { |
| 270 | reg.set_vsenseen(true); | 242 | reg.set_vsenseen(true); |
| 271 | }); | 243 | }); |
| 272 | 244 | ||
| 273 | Temperature {} | 245 | super::Temperature {} |
| 274 | } | 246 | } |
| 275 | 247 | ||
| 276 | /// Enable reading the vbat internal channel. | 248 | /// Enable reading the vbat internal channel. |
| 277 | pub fn enable_vbat(&self) -> Vbat | 249 | pub fn enable_vbat(&self) -> super::Vbat |
| 278 | where | 250 | where |
| 279 | T: VBatChannel, | 251 | T: super::VBatConverter, |
| 280 | { | 252 | { |
| 281 | T::common_regs().ccr().modify(|reg| { | 253 | T::common_regs().ccr().modify(|reg| { |
| 282 | reg.set_vbaten(true); | 254 | reg.set_vbaten(true); |
| 283 | }); | 255 | }); |
| 284 | 256 | ||
| 285 | Vbat {} | 257 | super::Vbat {} |
| 286 | } | 258 | } |
| 287 | 259 | ||
| 288 | /// Enable differential channel. | 260 | /// Enable differential channel. |
| @@ -850,62 +822,49 @@ impl<T: Instance, const N: usize> InjectedAdc<T, N> { | |||
| 850 | } | 822 | } |
| 851 | } | 823 | } |
| 852 | 824 | ||
| 853 | /// Implemented for ADCs that have a Temperature channel | ||
| 854 | pub trait TemperatureChannel { | ||
| 855 | const CHANNEL: u8; | ||
| 856 | } | ||
| 857 | /// Implemented for ADCs that have a Vref channel | ||
| 858 | pub trait VrefChannel { | ||
| 859 | const CHANNEL: u8; | ||
| 860 | } | ||
| 861 | /// Implemented for ADCs that have a VBat channel | ||
| 862 | pub trait VBatChannel { | ||
| 863 | const CHANNEL: u8; | ||
| 864 | } | ||
| 865 | |||
| 866 | #[cfg(stm32g4)] | 825 | #[cfg(stm32g4)] |
| 867 | mod g4 { | 826 | mod g4 { |
| 868 | pub use super::*; | 827 | use crate::adc::{TemperatureConverter, VBatConverter, VrefConverter}; |
| 869 | 828 | ||
| 870 | impl TemperatureChannel for crate::peripherals::ADC1 { | 829 | impl TemperatureConverter for crate::peripherals::ADC1 { |
| 871 | const CHANNEL: u8 = 16; | 830 | const CHANNEL: u8 = 16; |
| 872 | } | 831 | } |
| 873 | 832 | ||
| 874 | impl VrefChannel for crate::peripherals::ADC1 { | 833 | impl VrefConverter for crate::peripherals::ADC1 { |
| 875 | const CHANNEL: u8 = 18; | 834 | const CHANNEL: u8 = 18; |
| 876 | } | 835 | } |
| 877 | 836 | ||
| 878 | impl VBatChannel for crate::peripherals::ADC1 { | 837 | impl VBatConverter for crate::peripherals::ADC1 { |
| 879 | const CHANNEL: u8 = 17; | 838 | const CHANNEL: u8 = 17; |
| 880 | } | 839 | } |
| 881 | 840 | ||
| 882 | #[cfg(peri_adc3_common)] | 841 | #[cfg(peri_adc3_common)] |
| 883 | impl VrefChannel for crate::peripherals::ADC3 { | 842 | impl VrefConverter for crate::peripherals::ADC3 { |
| 884 | const CHANNEL: u8 = 18; | 843 | const CHANNEL: u8 = 18; |
| 885 | } | 844 | } |
| 886 | 845 | ||
| 887 | #[cfg(peri_adc3_common)] | 846 | #[cfg(peri_adc3_common)] |
| 888 | impl VBatChannel for crate::peripherals::ADC3 { | 847 | impl VBatConverter for crate::peripherals::ADC3 { |
| 889 | const CHANNEL: u8 = 17; | 848 | const CHANNEL: u8 = 17; |
| 890 | } | 849 | } |
| 891 | 850 | ||
| 892 | #[cfg(not(stm32g4x1))] | 851 | #[cfg(not(stm32g4x1))] |
| 893 | impl VrefChannel for crate::peripherals::ADC4 { | 852 | impl VrefConverter for crate::peripherals::ADC4 { |
| 894 | const CHANNEL: u8 = 18; | 853 | const CHANNEL: u8 = 18; |
| 895 | } | 854 | } |
| 896 | 855 | ||
| 897 | #[cfg(not(stm32g4x1))] | 856 | #[cfg(not(stm32g4x1))] |
| 898 | impl TemperatureChannel for crate::peripherals::ADC5 { | 857 | impl TemperatureConverter for crate::peripherals::ADC5 { |
| 899 | const CHANNEL: u8 = 4; | 858 | const CHANNEL: u8 = 4; |
| 900 | } | 859 | } |
| 901 | 860 | ||
| 902 | #[cfg(not(stm32g4x1))] | 861 | #[cfg(not(stm32g4x1))] |
| 903 | impl VrefChannel for crate::peripherals::ADC5 { | 862 | impl VrefConverter for crate::peripherals::ADC5 { |
| 904 | const CHANNEL: u8 = 18; | 863 | const CHANNEL: u8 = 18; |
| 905 | } | 864 | } |
| 906 | 865 | ||
| 907 | #[cfg(not(stm32g4x1))] | 866 | #[cfg(not(stm32g4x1))] |
| 908 | impl VBatChannel for crate::peripherals::ADC5 { | 867 | impl VBatConverter for crate::peripherals::ADC5 { |
| 909 | const CHANNEL: u8 = 17; | 868 | const CHANNEL: u8 = 17; |
| 910 | } | 869 | } |
| 911 | } | 870 | } |
| @@ -913,13 +872,13 @@ mod g4 { | |||
| 913 | // TODO this should look at each ADC individually and impl the correct channels | 872 | // TODO this should look at each ADC individually and impl the correct channels |
| 914 | #[cfg(stm32h7)] | 873 | #[cfg(stm32h7)] |
| 915 | mod h7 { | 874 | mod h7 { |
| 916 | impl<T: Instance> TemperatureChannel for T { | 875 | impl<T: Instance> TemperatureConverter for T { |
| 917 | const CHANNEL: u8 = 18; | 876 | const CHANNEL: u8 = 18; |
| 918 | } | 877 | } |
| 919 | impl<T: Instance> VrefChannel for T { | 878 | impl<T: Instance> VrefConverter for T { |
| 920 | const CHANNEL: u8 = 19; | 879 | const CHANNEL: u8 = 19; |
| 921 | } | 880 | } |
| 922 | impl<T: Instance> VBatChannel for T { | 881 | impl<T: Instance> VBatConverter for T { |
| 923 | // TODO this should be 14 for H7a/b/35 | 882 | // TODO this should be 14 for H7a/b/35 |
| 924 | const CHANNEL: u8 = 17; | 883 | const CHANNEL: u8 = 17; |
| 925 | } | 884 | } |
diff --git a/embassy-stm32/src/adc/mod.rs b/embassy-stm32/src/adc/mod.rs index a6b796fb9..a5ca6277f 100644 --- a/embassy-stm32/src/adc/mod.rs +++ b/embassy-stm32/src/adc/mod.rs | |||
| @@ -100,6 +100,47 @@ pub(crate) fn blocking_delay_us(us: u32) { | |||
| 100 | } | 100 | } |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | /// Implemented for ADCs that have a Temperature channel | ||
| 104 | pub trait TemperatureConverter { | ||
| 105 | const CHANNEL: u8; | ||
| 106 | } | ||
| 107 | /// Implemented for ADCs that have a Vref channel | ||
| 108 | pub trait VrefConverter { | ||
| 109 | const CHANNEL: u8; | ||
| 110 | } | ||
| 111 | /// Implemented for ADCs that have a VBat channel | ||
| 112 | pub trait VBatConverter { | ||
| 113 | const CHANNEL: u8; | ||
| 114 | } | ||
| 115 | |||
| 116 | // NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs | ||
| 117 | /// Internal voltage reference channel. | ||
| 118 | pub struct VrefInt; | ||
| 119 | impl<T: Instance + VrefConverter> AdcChannel<T> for VrefInt {} | ||
| 120 | impl<T: Instance + VrefConverter> SealedAdcChannel<T> for VrefInt { | ||
| 121 | fn channel(&self) -> u8 { | ||
| 122 | T::CHANNEL | ||
| 123 | } | ||
| 124 | } | ||
| 125 | |||
| 126 | /// Internal temperature channel. | ||
| 127 | pub struct Temperature; | ||
| 128 | impl<T: Instance + TemperatureConverter> AdcChannel<T> for Temperature {} | ||
| 129 | impl<T: Instance + TemperatureConverter> SealedAdcChannel<T> for Temperature { | ||
| 130 | fn channel(&self) -> u8 { | ||
| 131 | T::CHANNEL | ||
| 132 | } | ||
| 133 | } | ||
| 134 | |||
| 135 | /// Internal battery voltage channel. | ||
| 136 | pub struct Vbat; | ||
| 137 | impl<T: Instance + VBatConverter> AdcChannel<T> for Vbat {} | ||
| 138 | impl<T: Instance + VBatConverter> SealedAdcChannel<T> for Vbat { | ||
| 139 | fn channel(&self) -> u8 { | ||
| 140 | T::CHANNEL | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 103 | /// ADC instance. | 144 | /// ADC instance. |
| 104 | #[cfg(not(any( | 145 | #[cfg(not(any( |
| 105 | adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, | 146 | adc_f1, adc_v1, adc_l0, adc_v2, adc_v3, adc_v4, adc_g4, adc_f3v1, adc_f3v2, adc_g0, adc_u0, adc_h5, adc_h7rs, |
diff --git a/embassy-stm32/src/adc/v1.rs b/embassy-stm32/src/adc/v1.rs index 3838cc12a..97557ee8a 100644 --- a/embassy-stm32/src/adc/v1.rs +++ b/embassy-stm32/src/adc/v1.rs | |||
| @@ -5,10 +5,11 @@ use core::task::Poll; | |||
| 5 | #[cfg(adc_l0)] | 5 | #[cfg(adc_l0)] |
| 6 | use stm32_metapac::adc::vals::Ckmode; | 6 | use stm32_metapac::adc::vals::Ckmode; |
| 7 | 7 | ||
| 8 | use super::blocking_delay_us; | 8 | #[cfg(not(adc_l0))] |
| 9 | use super::Vbat; | ||
| 10 | use super::{Temperature, VrefInt, blocking_delay_us}; | ||
| 9 | use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime}; | 11 | use crate::adc::{Adc, AdcChannel, Instance, Resolution, SampleTime}; |
| 10 | use crate::interrupt::typelevel::Interrupt; | 12 | use crate::interrupt::typelevel::Interrupt; |
| 11 | use crate::peripherals::ADC1; | ||
| 12 | use crate::{Peri, interrupt, rcc}; | 13 | use crate::{Peri, interrupt, rcc}; |
| 13 | 14 | ||
| 14 | mod watchdog_v1; | 15 | mod watchdog_v1; |
| @@ -42,32 +43,23 @@ impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandl | |||
| 42 | } | 43 | } |
| 43 | 44 | ||
| 44 | #[cfg(not(adc_l0))] | 45 | #[cfg(not(adc_l0))] |
| 45 | pub struct Vbat; | 46 | impl super::VBatConverter for crate::peripherals::ADC1 { |
| 46 | 47 | const CHANNEL: u8 = 18; | |
| 47 | #[cfg(not(adc_l0))] | 48 | } |
| 48 | impl AdcChannel<ADC1> for Vbat {} | ||
| 49 | 49 | ||
| 50 | #[cfg(not(adc_l0))] | 50 | #[cfg(not(adc_l0))] |
| 51 | impl super::SealedAdcChannel<ADC1> for Vbat { | 51 | impl super::VrefConverter for crate::peripherals::ADC1 { |
| 52 | fn channel(&self) -> u8 { | 52 | const CHANNEL: u8 = 17; |
| 53 | 18 | ||
| 54 | } | ||
| 55 | } | 53 | } |
| 56 | 54 | ||
| 57 | pub struct Vref; | 55 | #[cfg(adc_l0)] |
| 58 | impl AdcChannel<ADC1> for Vref {} | 56 | impl super::VrefConverter for crate::peripherals::ADC1 { |
| 59 | impl super::SealedAdcChannel<ADC1> for Vref { | 57 | const CHANNEL: u8 = 18; |
| 60 | fn channel(&self) -> u8 { | ||
| 61 | 17 | ||
| 62 | } | ||
| 63 | } | 58 | } |
| 64 | 59 | ||
| 65 | pub struct Temperature; | 60 | #[cfg(not(adc_l0))] |
| 66 | impl AdcChannel<ADC1> for Temperature {} | 61 | impl super::TemperatureConverter for crate::peripherals::ADC1 { |
| 67 | impl super::SealedAdcChannel<ADC1> for Temperature { | 62 | const CHANNEL: u8 = 16; |
| 68 | fn channel(&self) -> u8 { | ||
| 69 | if cfg!(adc_l0) { 18 } else { 16 } | ||
| 70 | } | ||
| 71 | } | 63 | } |
| 72 | 64 | ||
| 73 | impl<'d, T: Instance> Adc<'d, T> { | 65 | impl<'d, T: Instance> Adc<'d, T> { |
| @@ -127,12 +119,12 @@ impl<'d, T: Instance> Adc<'d, T> { | |||
| 127 | Vbat | 119 | Vbat |
| 128 | } | 120 | } |
| 129 | 121 | ||
| 130 | pub fn enable_vref(&self) -> Vref { | 122 | pub fn enable_vref(&self) -> VrefInt { |
| 131 | // Table 28. Embedded internal reference voltage | 123 | // Table 28. Embedded internal reference voltage |
| 132 | // tstart = 10μs | 124 | // tstart = 10μs |
| 133 | T::regs().ccr().modify(|reg| reg.set_vrefen(true)); | 125 | T::regs().ccr().modify(|reg| reg.set_vrefen(true)); |
| 134 | blocking_delay_us(10); | 126 | blocking_delay_us(10); |
| 135 | Vref | 127 | VrefInt |
| 136 | } | 128 | } |
| 137 | 129 | ||
| 138 | pub fn enable_temperature(&self) -> Temperature { | 130 | pub fn enable_temperature(&self) -> Temperature { |
diff --git a/embassy-stm32/src/adc/v2.rs b/embassy-stm32/src/adc/v2.rs index 67721770a..af5d486d9 100644 --- a/embassy-stm32/src/adc/v2.rs +++ b/embassy-stm32/src/adc/v2.rs | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | use core::mem; | 1 | use core::mem; |
| 2 | use core::sync::atomic::{Ordering, compiler_fence}; | 2 | use core::sync::atomic::{Ordering, compiler_fence}; |
| 3 | 3 | ||
| 4 | use super::blocking_delay_us; | 4 | use super::{Temperature, Vbat, VrefInt, blocking_delay_us}; |
| 5 | use crate::adc::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel}; | 5 | use crate::adc::{Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel}; |
| 6 | use crate::pac::adc::vals; | 6 | use crate::pac::adc::vals; |
| 7 | use crate::peripherals::ADC1; | ||
| 8 | use crate::time::Hertz; | 7 | use crate::time::Hertz; |
| 9 | use crate::{Peri, rcc}; | 8 | use crate::{Peri, rcc}; |
| 10 | 9 | ||
| @@ -23,12 +22,22 @@ pub const VREF_DEFAULT_MV: u32 = 3300; | |||
| 23 | /// VREF voltage used for factory calibration of VREFINTCAL register. | 22 | /// VREF voltage used for factory calibration of VREFINTCAL register. |
| 24 | pub const VREF_CALIB_MV: u32 = 3300; | 23 | pub const VREF_CALIB_MV: u32 = 3300; |
| 25 | 24 | ||
| 26 | pub struct VrefInt; | 25 | impl super::VrefConverter for crate::peripherals::ADC1 { |
| 27 | impl AdcChannel<ADC1> for VrefInt {} | 26 | const CHANNEL: u8 = 17; |
| 28 | impl super::SealedAdcChannel<ADC1> for VrefInt { | 27 | } |
| 29 | fn channel(&self) -> u8 { | 28 | |
| 30 | 17 | 29 | #[cfg(any(stm32f2, stm32f40x, stm32f41x))] |
| 31 | } | 30 | impl super::TemperatureConverter for crate::peripherals::ADC1 { |
| 31 | const CHANNEL: u8 = 16; | ||
| 32 | } | ||
| 33 | |||
| 34 | #[cfg(not(any(stm32f2, stm32f40x, stm32f41x)))] | ||
| 35 | impl super::TemperatureConverter for crate::peripherals::ADC1 { | ||
| 36 | const CHANNEL: u8 = 18; | ||
| 37 | } | ||
| 38 | |||
| 39 | impl super::VBatConverter for crate::peripherals::ADC1 { | ||
| 40 | const CHANNEL: u8 = 18; | ||
| 32 | } | 41 | } |
| 33 | 42 | ||
| 34 | impl VrefInt { | 43 | impl VrefInt { |
| @@ -38,20 +47,6 @@ impl VrefInt { | |||
| 38 | } | 47 | } |
| 39 | } | 48 | } |
| 40 | 49 | ||
| 41 | pub struct Temperature; | ||
| 42 | impl AdcChannel<ADC1> for Temperature {} | ||
| 43 | impl super::SealedAdcChannel<ADC1> for Temperature { | ||
| 44 | fn channel(&self) -> u8 { | ||
| 45 | cfg_if::cfg_if! { | ||
| 46 | if #[cfg(any(stm32f2, stm32f40x, stm32f41x))] { | ||
| 47 | 16 | ||
| 48 | } else { | ||
| 49 | 18 | ||
| 50 | } | ||
| 51 | } | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | impl Temperature { | 50 | impl Temperature { |
| 56 | /// Time needed for temperature sensor readings to stabilize | 51 | /// Time needed for temperature sensor readings to stabilize |
| 57 | pub fn start_time_us() -> u32 { | 52 | pub fn start_time_us() -> u32 { |
| @@ -59,14 +54,6 @@ impl Temperature { | |||
| 59 | } | 54 | } |
| 60 | } | 55 | } |
| 61 | 56 | ||
| 62 | pub struct Vbat; | ||
| 63 | impl AdcChannel<ADC1> for Vbat {} | ||
| 64 | impl super::SealedAdcChannel<ADC1> for Vbat { | ||
| 65 | fn channel(&self) -> u8 { | ||
| 66 | 18 | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | enum Prescaler { | 57 | enum Prescaler { |
| 71 | Div2, | 58 | Div2, |
| 72 | Div4, | 59 | Div4, |
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs index bbbaf73c8..0822fbb69 100644 --- a/embassy-stm32/src/adc/v3.rs +++ b/embassy-stm32/src/adc/v3.rs | |||
| @@ -9,8 +9,11 @@ use pac::adc::vals::{OversamplingRatio, OversamplingShift, Rovsm, Trovs}; | |||
| 9 | #[cfg(adc_g0)] | 9 | #[cfg(adc_g0)] |
| 10 | pub use pac::adc::vals::{Ovsr, Ovss, Presc}; | 10 | pub use pac::adc::vals::{Ovsr, Ovss, Presc}; |
| 11 | 11 | ||
| 12 | #[allow(unused_imports)] | ||
| 13 | use super::SealedAdcChannel; | ||
| 12 | use super::{ | 14 | use super::{ |
| 13 | Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, blocking_delay_us, | 15 | Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, Temperature, Vbat, VrefInt, |
| 16 | blocking_delay_us, | ||
| 14 | }; | 17 | }; |
| 15 | 18 | ||
| 16 | #[cfg(any(adc_v3, adc_g0, adc_u0))] | 19 | #[cfg(any(adc_v3, adc_g0, adc_u0))] |
| @@ -32,61 +35,55 @@ pub const VREF_CALIB_MV: u32 = 3000; | |||
| 32 | // TODO: Use [#![feature(variant_count)]](https://github.com/rust-lang/rust/issues/73662) when stable | 35 | // TODO: Use [#![feature(variant_count)]](https://github.com/rust-lang/rust/issues/73662) when stable |
| 33 | const SAMPLE_TIMES_CAPACITY: usize = 2; | 36 | const SAMPLE_TIMES_CAPACITY: usize = 2; |
| 34 | 37 | ||
| 35 | pub struct VrefInt; | 38 | #[cfg(adc_g0)] |
| 36 | impl<T: Instance> AdcChannel<T> for VrefInt {} | 39 | impl<T: Instance> super::VrefConverter for T { |
| 37 | impl<T: Instance> SealedAdcChannel<T> for VrefInt { | 40 | const CHANNEL: u8 = 13; |
| 38 | fn channel(&self) -> u8 { | 41 | } |
| 39 | cfg_if! { | 42 | #[cfg(any(adc_h5, adc_h7rs))] |
| 40 | if #[cfg(adc_g0)] { | 43 | impl<T: Instance> super::VrefConverter for T { |
| 41 | let val = 13; | 44 | const CHANNEL: u8 = 17; |
| 42 | } else if #[cfg(any(adc_h5, adc_h7rs))] { | 45 | } |
| 43 | let val = 17; | 46 | #[cfg(adc_u0)] |
| 44 | } else if #[cfg(adc_u0)] { | 47 | impl<T: Instance> super::VrefConverter for T { |
| 45 | let val = 12; | 48 | const CHANNEL: u8 = 12; |
| 46 | } else { | 49 | } |
| 47 | let val = 0; | 50 | #[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))] |
| 48 | } | 51 | impl<T: Instance> super::VrefConverter for T { |
| 49 | } | 52 | const CHANNEL: u8 = 0; |
| 50 | val | ||
| 51 | } | ||
| 52 | } | 53 | } |
| 53 | 54 | ||
| 54 | pub struct Temperature; | 55 | #[cfg(adc_g0)] |
| 55 | impl<T: Instance> AdcChannel<T> for Temperature {} | 56 | impl<T: Instance> super::TemperatureConverter for T { |
| 56 | impl<T: Instance> SealedAdcChannel<T> for Temperature { | 57 | const CHANNEL: u8 = 12; |
| 57 | fn channel(&self) -> u8 { | 58 | } |
| 58 | cfg_if! { | 59 | #[cfg(any(adc_h5, adc_h7rs))] |
| 59 | if #[cfg(adc_g0)] { | 60 | impl<T: Instance> super::TemperatureConverter for T { |
| 60 | let val = 12; | 61 | const CHANNEL: u8 = 16; |
| 61 | } else if #[cfg(any(adc_h5, adc_h7rs))] { | 62 | } |
| 62 | let val = 16; | 63 | #[cfg(adc_u0)] |
| 63 | } else if #[cfg(adc_u0)] { | 64 | impl<T: Instance> super::TemperatureConverter for T { |
| 64 | let val = 11; | 65 | const CHANNEL: u8 = 11; |
| 65 | } else { | 66 | } |
| 66 | let val = 17; | 67 | #[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))] |
| 67 | } | 68 | impl<T: Instance> super::TemperatureConverter for T { |
| 68 | } | 69 | const CHANNEL: u8 = 17; |
| 69 | val | ||
| 70 | } | ||
| 71 | } | 70 | } |
| 72 | 71 | ||
| 73 | pub struct Vbat; | 72 | #[cfg(adc_g0)] |
| 74 | impl<T: Instance> AdcChannel<T> for Vbat {} | 73 | impl<T: Instance> super::VBatConverter for T { |
| 75 | impl<T: Instance> SealedAdcChannel<T> for Vbat { | 74 | const CHANNEL: u8 = 14; |
| 76 | fn channel(&self) -> u8 { | 75 | } |
| 77 | cfg_if! { | 76 | #[cfg(any(adc_h5, adc_h7rs))] |
| 78 | if #[cfg(adc_g0)] { | 77 | impl<T: Instance> super::VBatConverter for T { |
| 79 | let val = 14; | 78 | const CHANNEL: u8 = 2; |
| 80 | } else if #[cfg(any(adc_h5, adc_h7rs))] { | 79 | } |
| 81 | let val = 2; | 80 | #[cfg(adc_u0)] |
| 82 | } else if #[cfg(any(adc_h5, adc_h7rs))] { | 81 | impl<T: Instance> super::VBatConverter for T { |
| 83 | let val = 13; | 82 | const CHANNEL: u8 = 13; |
| 84 | } else { | 83 | } |
| 85 | let val = 18; | 84 | #[cfg(not(any(adc_g0, adc_h5, adc_h7rs, adc_u0)))] |
| 86 | } | 85 | impl<T: Instance> super::VBatConverter for T { |
| 87 | } | 86 | const CHANNEL: u8 = 18; |
| 88 | val | ||
| 89 | } | ||
| 90 | } | 87 | } |
| 91 | 88 | ||
| 92 | cfg_if! { | 89 | cfg_if! { |
diff --git a/embassy-stm32/src/adc/v4.rs b/embassy-stm32/src/adc/v4.rs index cc3f8b34e..2f7baf3bf 100644 --- a/embassy-stm32/src/adc/v4.rs +++ b/embassy-stm32/src/adc/v4.rs | |||
| @@ -5,7 +5,8 @@ use pac::adc::vals::{Adstp, Difsel, Dmngt, Exten, Pcsel}; | |||
| 5 | use pac::adccommon::vals::Presc; | 5 | use pac::adccommon::vals::Presc; |
| 6 | 6 | ||
| 7 | use super::{ | 7 | use super::{ |
| 8 | Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, blocking_delay_us, | 8 | Adc, AdcChannel, AnyAdcChannel, Instance, Resolution, RxDma, SampleTime, SealedAdcChannel, Temperature, Vbat, |
| 9 | VrefInt, blocking_delay_us, | ||
| 9 | }; | 10 | }; |
| 10 | use crate::dma::Transfer; | 11 | use crate::dma::Transfer; |
| 11 | use crate::time::Hertz; | 12 | use crate::time::Hertz; |
| @@ -25,52 +26,40 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); | |||
| 25 | const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55); | 26 | const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(55); |
| 26 | 27 | ||
| 27 | #[cfg(stm32g4)] | 28 | #[cfg(stm32g4)] |
| 28 | const VREF_CHANNEL: u8 = 18; | 29 | impl<T: Instance> super::VrefConverter for T { |
| 30 | const CHANNEL: u8 = 18; | ||
| 31 | } | ||
| 29 | #[cfg(stm32g4)] | 32 | #[cfg(stm32g4)] |
| 30 | const TEMP_CHANNEL: u8 = 16; | 33 | impl<T: Instance> super::TemperatureConverter for T { |
| 34 | const CHANNEL: u8 = 16; | ||
| 35 | } | ||
| 31 | 36 | ||
| 32 | #[cfg(stm32h7)] | 37 | #[cfg(stm32h7)] |
| 33 | const VREF_CHANNEL: u8 = 19; | 38 | impl<T: Instance> super::VrefConverter for T { |
| 39 | const CHANNEL: u8 = 19; | ||
| 40 | } | ||
| 34 | #[cfg(stm32h7)] | 41 | #[cfg(stm32h7)] |
| 35 | const TEMP_CHANNEL: u8 = 18; | 42 | impl<T: Instance> super::TemperatureConverter for T { |
| 43 | const CHANNEL: u8 = 18; | ||
| 44 | } | ||
| 36 | 45 | ||
| 37 | // TODO this should be 14 for H7a/b/35 | 46 | // TODO this should be 14 for H7a/b/35 |
| 38 | #[cfg(not(stm32u5))] | 47 | #[cfg(not(stm32u5))] |
| 39 | const VBAT_CHANNEL: u8 = 17; | 48 | impl<T: Instance> super::VBatConverter for T { |
| 49 | const CHANNEL: u8 = 17; | ||
| 50 | } | ||
| 40 | 51 | ||
| 41 | #[cfg(stm32u5)] | 52 | #[cfg(stm32u5)] |
| 42 | const VREF_CHANNEL: u8 = 0; | 53 | impl<T: Instance> super::VrefConverter for T { |
| 43 | #[cfg(stm32u5)] | 54 | const CHANNEL: u8 = 0; |
| 44 | const TEMP_CHANNEL: u8 = 19; | ||
| 45 | #[cfg(stm32u5)] | ||
| 46 | const VBAT_CHANNEL: u8 = 18; | ||
| 47 | |||
| 48 | // NOTE: Vrefint/Temperature/Vbat are not available on all ADCs, this currently cannot be modeled with stm32-data, so these are available from the software on all ADCs | ||
| 49 | /// Internal voltage reference channel. | ||
| 50 | pub struct VrefInt; | ||
| 51 | impl<T: Instance> AdcChannel<T> for VrefInt {} | ||
| 52 | impl<T: Instance> SealedAdcChannel<T> for VrefInt { | ||
| 53 | fn channel(&self) -> u8 { | ||
| 54 | VREF_CHANNEL | ||
| 55 | } | ||
| 56 | } | 55 | } |
| 57 | 56 | #[cfg(stm32u5)] | |
| 58 | /// Internal temperature channel. | 57 | impl<T: Instance> super::TemperatureConverter for T { |
| 59 | pub struct Temperature; | 58 | const CHANNEL: u8 = 19; |
| 60 | impl<T: Instance> AdcChannel<T> for Temperature {} | ||
| 61 | impl<T: Instance> SealedAdcChannel<T> for Temperature { | ||
| 62 | fn channel(&self) -> u8 { | ||
| 63 | TEMP_CHANNEL | ||
| 64 | } | ||
| 65 | } | 59 | } |
| 66 | 60 | #[cfg(stm32u5)] | |
| 67 | /// Internal battery voltage channel. | 61 | impl<T: Instance> super::VBatConverter for T { |
| 68 | pub struct Vbat; | 62 | const CHANNEL: u8 = 18; |
| 69 | impl<T: Instance> AdcChannel<T> for Vbat {} | ||
| 70 | impl<T: Instance> SealedAdcChannel<T> for Vbat { | ||
| 71 | fn channel(&self) -> u8 { | ||
| 72 | VBAT_CHANNEL | ||
| 73 | } | ||
| 74 | } | 63 | } |
| 75 | 64 | ||
| 76 | // NOTE (unused): The prescaler enum closely copies the hardware capabilities, | 65 | // NOTE (unused): The prescaler enum closely copies the hardware capabilities, |
