aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2025-07-10 14:09:57 +0000
committerGitHub <[email protected]>2025-07-10 14:09:57 +0000
commit7f1f2377022757a50fb8d23197baef6b576bffb3 (patch)
tree5eecb39139333feca4ff203f5b959c6eaaf2dd2b
parentdbc4b2bce43ef4ed83458036d1df52f9f79a791d (diff)
parent423870d1f73e8b3110ae1ecc76989b112cb2da2b (diff)
Merge pull request #4390 from diondokter/g4-temperature-fix
[STM32G4] Introduce traits for special ADC channels
-rw-r--r--embassy-stm32/src/adc/g4.rs119
1 files changed, 94 insertions, 25 deletions
diff --git a/embassy-stm32/src/adc/g4.rs b/embassy-stm32/src/adc/g4.rs
index 1fce3085a..cb3e342d8 100644
--- a/embassy-stm32/src/adc/g4.rs
+++ b/embassy-stm32/src/adc/g4.rs
@@ -24,44 +24,31 @@ const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(60);
24#[cfg(stm32h7)] 24#[cfg(stm32h7)]
25const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); 25const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50);
26 26
27#[cfg(stm32g4)]
28const VREF_CHANNEL: u8 = 18;
29#[cfg(stm32g4)]
30const TEMP_CHANNEL: u8 = 16;
31
32#[cfg(stm32h7)]
33const VREF_CHANNEL: u8 = 19;
34#[cfg(stm32h7)]
35const TEMP_CHANNEL: u8 = 18;
36
37// TODO this should be 14 for H7a/b/35
38const VBAT_CHANNEL: u8 = 17;
39
40// 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 27// 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
41/// Internal voltage reference channel. 28/// Internal voltage reference channel.
42pub struct VrefInt; 29pub struct VrefInt;
43impl<T: Instance> AdcChannel<T> for VrefInt {} 30impl<T: Instance + VrefChannel> AdcChannel<T> for VrefInt {}
44impl<T: Instance> super::SealedAdcChannel<T> for VrefInt { 31impl<T: Instance + VrefChannel> super::SealedAdcChannel<T> for VrefInt {
45 fn channel(&self) -> u8 { 32 fn channel(&self) -> u8 {
46 VREF_CHANNEL 33 T::CHANNEL
47 } 34 }
48} 35}
49 36
50/// Internal temperature channel. 37/// Internal temperature channel.
51pub struct Temperature; 38pub struct Temperature;
52impl<T: Instance> AdcChannel<T> for Temperature {} 39impl<T: Instance + TemperatureChannel> AdcChannel<T> for Temperature {}
53impl<T: Instance> super::SealedAdcChannel<T> for Temperature { 40impl<T: Instance + TemperatureChannel> super::SealedAdcChannel<T> for Temperature {
54 fn channel(&self) -> u8 { 41 fn channel(&self) -> u8 {
55 TEMP_CHANNEL 42 T::CHANNEL
56 } 43 }
57} 44}
58 45
59/// Internal battery voltage channel. 46/// Internal battery voltage channel.
60pub struct Vbat; 47pub struct Vbat;
61impl<T: Instance> AdcChannel<T> for Vbat {} 48impl<T: Instance + VBatChannel> AdcChannel<T> for Vbat {}
62impl<T: Instance> super::SealedAdcChannel<T> for Vbat { 49impl<T: Instance + VBatChannel> super::SealedAdcChannel<T> for Vbat {
63 fn channel(&self) -> u8 { 50 fn channel(&self) -> u8 {
64 VBAT_CHANNEL 51 T::CHANNEL
65 } 52 }
66} 53}
67 54
@@ -234,7 +221,10 @@ impl<'d, T: Instance> Adc<'d, T> {
234 } 221 }
235 222
236 /// Enable reading the voltage reference internal channel. 223 /// Enable reading the voltage reference internal channel.
237 pub fn enable_vrefint(&self) -> VrefInt { 224 pub fn enable_vrefint(&self) -> VrefInt
225 where
226 T: VrefChannel,
227 {
238 T::common_regs().ccr().modify(|reg| { 228 T::common_regs().ccr().modify(|reg| {
239 reg.set_vrefen(true); 229 reg.set_vrefen(true);
240 }); 230 });
@@ -243,7 +233,10 @@ impl<'d, T: Instance> Adc<'d, T> {
243 } 233 }
244 234
245 /// Enable reading the temperature internal channel. 235 /// Enable reading the temperature internal channel.
246 pub fn enable_temperature(&self) -> Temperature { 236 pub fn enable_temperature(&self) -> Temperature
237 where
238 T: TemperatureChannel,
239 {
247 T::common_regs().ccr().modify(|reg| { 240 T::common_regs().ccr().modify(|reg| {
248 reg.set_vsenseen(true); 241 reg.set_vsenseen(true);
249 }); 242 });
@@ -252,7 +245,10 @@ impl<'d, T: Instance> Adc<'d, T> {
252 } 245 }
253 246
254 /// Enable reading the vbat internal channel. 247 /// Enable reading the vbat internal channel.
255 pub fn enable_vbat(&self) -> Vbat { 248 pub fn enable_vbat(&self) -> Vbat
249 where
250 T: VBatChannel,
251 {
256 T::common_regs().ccr().modify(|reg| { 252 T::common_regs().ccr().modify(|reg| {
257 reg.set_vbaten(true); 253 reg.set_vbaten(true);
258 }); 254 });
@@ -519,3 +515,76 @@ impl<'d, T: Instance> Adc<'d, T> {
519 } 515 }
520 } 516 }
521} 517}
518
519/// Implemented for ADCs that have a Temperature channel
520pub trait TemperatureChannel {
521 const CHANNEL: u8;
522}
523/// Implemented for ADCs that have a Vref channel
524pub trait VrefChannel {
525 const CHANNEL: u8;
526}
527/// Implemented for ADCs that have a VBat channel
528pub trait VBatChannel {
529 const CHANNEL: u8;
530}
531
532#[cfg(stm32g4)]
533mod g4 {
534 pub use super::*;
535
536 impl TemperatureChannel for crate::peripherals::ADC1 {
537 const CHANNEL: u8 = 16;
538 }
539
540 impl VrefChannel for crate::peripherals::ADC1 {
541 const CHANNEL: u8 = 18;
542 }
543
544 impl VBatChannel for crate::peripherals::ADC1 {
545 const CHANNEL: u8 = 17;
546 }
547
548 impl VrefChannel for crate::peripherals::ADC3 {
549 const CHANNEL: u8 = 18;
550 }
551
552 impl VBatChannel for crate::peripherals::ADC3 {
553 const CHANNEL: u8 = 17;
554 }
555
556 #[cfg(not(stm32g4x1))]
557 impl VrefChannel for crate::peripherals::ADC4 {
558 const CHANNEL: u8 = 18;
559 }
560
561 #[cfg(not(stm32g4x1))]
562 impl TemperatureChannel for crate::peripherals::ADC5 {
563 const CHANNEL: u8 = 4;
564 }
565
566 #[cfg(not(stm32g4x1))]
567 impl VrefChannel for crate::peripherals::ADC5 {
568 const CHANNEL: u8 = 18;
569 }
570
571 #[cfg(not(stm32g4x1))]
572 impl VBatChannel for crate::peripherals::ADC5 {
573 const CHANNEL: u8 = 17;
574 }
575}
576
577// TODO this should look at each ADC individually and impl the correct channels
578#[cfg(stm32h7)]
579mod h7 {
580 impl<T: Instance> TemperatureChannel for T {
581 const CHANNEL: u8 = 18;
582 }
583 impl<T: Instance> VrefChannel for T {
584 const CHANNEL: u8 = 19;
585 }
586 impl<T: Instance> VBatChannel for T {
587 // TODO this should be 14 for H7a/b/35
588 const CHANNEL: u8 = 17;
589 }
590}