diff options
| author | Dario Nieuwenhuis <[email protected]> | 2025-07-10 14:09:57 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-07-10 14:09:57 +0000 |
| commit | 7f1f2377022757a50fb8d23197baef6b576bffb3 (patch) | |
| tree | 5eecb39139333feca4ff203f5b959c6eaaf2dd2b | |
| parent | dbc4b2bce43ef4ed83458036d1df52f9f79a791d (diff) | |
| parent | 423870d1f73e8b3110ae1ecc76989b112cb2da2b (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.rs | 119 |
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)] |
| 25 | const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); | 25 | const MAX_ADC_CLK_FREQ: Hertz = Hertz::mhz(50); |
| 26 | 26 | ||
| 27 | #[cfg(stm32g4)] | ||
| 28 | const VREF_CHANNEL: u8 = 18; | ||
| 29 | #[cfg(stm32g4)] | ||
| 30 | const TEMP_CHANNEL: u8 = 16; | ||
| 31 | |||
| 32 | #[cfg(stm32h7)] | ||
| 33 | const VREF_CHANNEL: u8 = 19; | ||
| 34 | #[cfg(stm32h7)] | ||
| 35 | const TEMP_CHANNEL: u8 = 18; | ||
| 36 | |||
| 37 | // TODO this should be 14 for H7a/b/35 | ||
| 38 | const 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. |
| 42 | pub struct VrefInt; | 29 | pub struct VrefInt; |
| 43 | impl<T: Instance> AdcChannel<T> for VrefInt {} | 30 | impl<T: Instance + VrefChannel> AdcChannel<T> for VrefInt {} |
| 44 | impl<T: Instance> super::SealedAdcChannel<T> for VrefInt { | 31 | impl<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. |
| 51 | pub struct Temperature; | 38 | pub struct Temperature; |
| 52 | impl<T: Instance> AdcChannel<T> for Temperature {} | 39 | impl<T: Instance + TemperatureChannel> AdcChannel<T> for Temperature {} |
| 53 | impl<T: Instance> super::SealedAdcChannel<T> for Temperature { | 40 | impl<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. |
| 60 | pub struct Vbat; | 47 | pub struct Vbat; |
| 61 | impl<T: Instance> AdcChannel<T> for Vbat {} | 48 | impl<T: Instance + VBatChannel> AdcChannel<T> for Vbat {} |
| 62 | impl<T: Instance> super::SealedAdcChannel<T> for Vbat { | 49 | impl<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 | ||
| 520 | pub trait TemperatureChannel { | ||
| 521 | const CHANNEL: u8; | ||
| 522 | } | ||
| 523 | /// Implemented for ADCs that have a Vref channel | ||
| 524 | pub trait VrefChannel { | ||
| 525 | const CHANNEL: u8; | ||
| 526 | } | ||
| 527 | /// Implemented for ADCs that have a VBat channel | ||
| 528 | pub trait VBatChannel { | ||
| 529 | const CHANNEL: u8; | ||
| 530 | } | ||
| 531 | |||
| 532 | #[cfg(stm32g4)] | ||
| 533 | mod 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)] | ||
| 579 | mod 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 | } | ||
