stabilizer/hardware/
cpu_temp_sensor.rs

1//! STM32 Temperature Sensor Driver
2//!
3//! # Description
4//! This file provides an API for measuring the internal STM32 temperature sensor. This temperature
5//! sensor measures the silicon junction temperature (Tj) and is connected via an internal ADC.
6use stm32h7xx_hal::{
7    self as hal,
8    signature::{TS_CAL_110, TS_CAL_30},
9};
10
11use super::shared_adc::{AdcChannel, AdcError};
12
13/// Helper utility to convert raw codes into temperature measurements.
14struct Calibration {
15    slope: f32,
16    offset: f32,
17}
18
19impl Calibration {
20    /// Construct the calibration utility.
21    pub fn new() -> Self {
22        let ts_cal2 = TS_CAL_110::read();
23        let ts_cal1 = TS_CAL_30::read();
24        let slope = (110. - 30.) / (ts_cal2 as f32 - ts_cal1 as f32);
25        let offset = 30. - slope * ts_cal1 as f32;
26        Self { slope, offset }
27    }
28
29    /// Convert a raw ADC sample to a temperature in degrees Celsius.
30    pub fn sample_to_temperature(&self, sample: u32) -> f32 {
31        // We use a 2.048V reference, but calibration data was taken at 3.3V.
32        let sample_3v3 = sample as f32 * 2.048 / 3.3;
33
34        self.slope * sample_3v3 + self.offset
35    }
36}
37
38/// A driver to access the CPU temeprature sensor.
39pub struct CpuTempSensor {
40    sensor: AdcChannel<'static, hal::stm32::ADC3, hal::adc::Temperature>,
41    calibration: Calibration,
42}
43
44impl CpuTempSensor {
45    /// Construct the temperature sensor.
46    ///
47    /// # Args
48    /// * `sensor` - The ADC channel of the integrated temperature sensor.
49    pub fn new(
50        sensor: AdcChannel<'static, hal::stm32::ADC3, hal::adc::Temperature>,
51    ) -> Self {
52        Self {
53            sensor,
54            calibration: Calibration::new(),
55        }
56    }
57
58    /// Get the temperature of the CPU in degrees Celsius.
59    pub fn get_temperature(&mut self) -> Result<f32, AdcError> {
60        self.sensor
61            .read_raw()
62            .map(|raw| self.calibration.sample_to_temperature(raw))
63    }
64}