From 0ce94e9566399fdded1a9df6b9f3da92d597d3f1 Mon Sep 17 00:00:00 2001 From: David Gu Date: Tue, 31 Dec 2024 15:58:27 -0600 Subject: [PATCH 1/5] feat: add basic support for temperature sensor (tsens) for esp32c6 --- esp-hal/CHANGELOG.md | 1 + esp-hal/src/lib.rs | 3 + esp-hal/src/soc/esp32c6/peripherals.rs | 1 + esp-hal/src/system.rs | 27 ++++++ esp-hal/src/tsens.rs | 113 +++++++++++++++++++++++++ esp-metadata/devices/esp32c6.toml | 1 + examples/src/bin/temperature_sensor.rs | 24 ++++++ 7 files changed, 170 insertions(+) create mode 100644 esp-hal/src/tsens.rs create mode 100644 examples/src/bin/temperature_sensor.rs diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 36a6e86aed5..5ae405bd84f 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -54,6 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `AnyPin::steal(pin_number)` (#2854) - `adc::{AdcCalSource, Attenuation, Resolution}` now implement `Hash` and `defmt::Format` (#2840) - `rtc_cntl::{RtcFastClock, RtcSlowClock, RtcCalSel}` now implement `PartialEq`, `Eq`, `Hash` and `defmt::Format` (#2840) +- Added `tsens::TemperatureSensor` peripheral for ESP32C6 ### Changed diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index 53beb9cac49..0cc4d989ae7 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -194,6 +194,9 @@ pub mod debugger; pub mod sync; pub mod time; +#[cfg(tsens)] +pub mod tsens; + // can't use instability on inline module definitions, see https://github.com/rust-lang/rust/issues/54727 #[doc(hidden)] macro_rules! unstable_module { diff --git a/esp-hal/src/soc/esp32c6/peripherals.rs b/esp-hal/src/soc/esp32c6/peripherals.rs index 666e7a252a6..6ae4c7c535d 100644 --- a/esp-hal/src/soc/esp32c6/peripherals.rs +++ b/esp-hal/src/soc/esp32c6/peripherals.rs @@ -80,6 +80,7 @@ crate::peripherals! { TIMG0 <= TIMG0, TIMG1 <= TIMG1, TRACE0 <= TRACE, + TSENS <= virtual, TWAI0 <= TWAI0, TWAI1 <= TWAI1, UART0 <= UART0, diff --git a/esp-hal/src/system.rs b/esp-hal/src/system.rs index b8762146270..c821a60a3da 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -132,6 +132,9 @@ pub enum Peripheral { /// Systimer peripheral. #[cfg(systimer)] Systimer, + /// Temperature sensor peripheral. + #[cfg(tsens)] + Tsens, } impl Peripheral { @@ -610,6 +613,11 @@ impl PeripheralClockControl { perip_rst_en0.modify(|_, w| w.systimer_rst().set_bit()); perip_rst_en0.modify(|_, w| w.systimer_rst().clear_bit()); } + #[cfg(tsens)] + Peripheral::Tsens => { + perip_rst_en0.modify(|_, w| w.tsens_rst().set_bit()); + perip_rst_en0.modify(|_, w| w.tsens_rst().clear_bit()); + } }); } } @@ -778,6 +786,16 @@ impl PeripheralClockControl { .systimer_conf() .modify(|_, w| w.systimer_clk_en().bit(enable)); } + #[cfg(tsens)] + Peripheral::Tsens => { + system + .tsens_clk_conf() + .modify(|_, w| w.tsens_clk_en().bit(enable)); + + system + .tsens_clk_conf() + .modify(|_, w| w.tsens_clk_sel().bit(enable)); + } } } @@ -977,6 +995,15 @@ impl PeripheralClockControl { .systimer_conf() .modify(|_, w| w.systimer_rst_en().clear_bit()); } + #[cfg(tsens)] + Peripheral::Tsens => { + system + .tsens_clk_conf() + .modify(|_, w| w.tsens_rst_en().set_bit()); + system + .tsens_clk_conf() + .modify(|_, w| w.tsens_rst_en().clear_bit()); + } } } } diff --git a/esp-hal/src/tsens.rs b/esp-hal/src/tsens.rs new file mode 100644 index 00000000000..49feb3e9d1c --- /dev/null +++ b/esp-hal/src/tsens.rs @@ -0,0 +1,113 @@ +//! # Temperature Sensor (tsens) +//! +//! ## Overview +//! +//! The Temperature Sensor peripheral is used to measure the internal +//! temperature inside the chip. The voltage is internally converted via an ADC +//! into a digital value, and has a measuring range of –40 °C to 125 °C. +//! The temperature value depends on factors like microcontroller clock +//! frequency or I/O load. Generally, the chip’s internal temperature is higher +//! than the operating ambient temperature. +//! +//! ## Configuration +//! +//! Currently, it does not support any configuration, but some future +//! configuration options are listed below in the Implementation State list of +//! pending items +//! +//! ## Examples +//! +//! The following example will measure the internal chip temperature every +//! second, and print it +//! +//! ```rust, no_run +#![doc = crate::before_snippet!()] +//! # use esp_hal::tsens::TemperatureSensor; +//! # use esp_hal::delay::Delay; +//! +//! let tsens = TemperatureSensor::new(peripherals.TSENS); +//! let delay = Delay::new(); +//! +//! loop { +//! let temp = tsens.get_celsius(); +//! println!("Temperature: {:.2}°C", temp); +//! delay.delay_millis(1_000); +//! } +//! # } +//! ``` +//! +//! ## Implementation State +//! +//! - Source clock selection is not supported +//! - Temperature calibration range is not supported +//! - Interrupts are not supported + +use crate::{ + peripheral::{Peripheral, PeripheralRef}, + peripherals::TSENS, + system::{GenericPeripheralGuard, PeripheralClockControl}, +}; + +/// Temperature sensor driver +// #[derive(Clone, Copy)] +pub struct TemperatureSensor<'d> { + _peripheral: PeripheralRef<'d, TSENS>, + _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Tsens as u8 }>, +} + +impl<'d> TemperatureSensor<'d> { + /// Create a new temperature sensor instance + pub fn new(peripheral: impl Peripheral

+ 'd) -> Self { + crate::into_ref!(peripheral); + + let guard = GenericPeripheralGuard::new(); + + // We need to enable ApbSarAdc clock before trying to write on the tsens_ctrl + // register + PeripheralClockControl::enable(crate::system::Peripheral::ApbSarAdc); + + let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; + + // Power Up + apb_saradc.tsens_ctrl().write(|w| w.pu().set_bit()); + + Self { + _guard: guard, + _peripheral: peripheral, + } + } + + /// Disable the temperature sensor + pub fn disable(&self) { + let abp_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; + abp_saradc.tsens_ctrl().write(|w| w.pu().clear_bit()); + + PeripheralClockControl::disable(crate::system::Peripheral::Tsens); + } + + /// Get the temperature in Celsius + #[inline] + pub fn get_celsius(&self) -> f32 { + let abp_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; + + let measurement = abp_saradc.tsens_ctrl().read().out().bits(); + + // TODO Address multiple temperature ranges and offsets + let offset = -1f32; + (measurement as f32) * 0.4386 - offset * 27.88 - 20.52 + } + + /// Get the temperature in Fahrenheit + #[inline] + pub fn get_fahrenheit(&self) -> f32 { + let celsius = self.get_celsius(); + (celsius * 1.8) + 32.0 + } + + /// Get the temperature in Kelvin + #[inline] + pub fn get_kelvin(&self) -> f32 { + let celsius = self.get_celsius(); + celsius + 273.15 + } +} diff --git a/esp-metadata/devices/esp32c6.toml b/esp-metadata/devices/esp32c6.toml index 6b59d5e02ea..1b02a16c138 100644 --- a/esp-metadata/devices/esp32c6.toml +++ b/esp-metadata/devices/esp32c6.toml @@ -83,6 +83,7 @@ symbols = [ "wifi6", "ieee802154", "lp_core", + "tsens", # ROM capabilities "rom_crc_le", diff --git a/examples/src/bin/temperature_sensor.rs b/examples/src/bin/temperature_sensor.rs new file mode 100644 index 00000000000..a6e0beadefa --- /dev/null +++ b/examples/src/bin/temperature_sensor.rs @@ -0,0 +1,24 @@ +//! This example uses the internal temperature sensor to measure the chip's temperature +//! + +//% CHIPS: esp32c6 + +#![no_std] +#![no_main] + +use esp_backtrace as _; +use esp_hal::{delay::Delay, entry, tsens::TemperatureSensor}; +use esp_println::println; + +#[entry] +fn main() -> ! { + let peripherals = esp_hal::init(esp_hal::Config::default()); + + let temperature_sensor = TemperatureSensor::new(peripherals.TSENS); + let delay = Delay::new(); + loop { + let temp = temperature_sensor.get_celsius(); + println!("Temperature: {:.2}°C", temp); + delay.delay_millis(1_000); + } +} From 5a0668764dced0f0d2174f3b12f99459788b17be Mon Sep 17 00:00:00 2001 From: David Gu Date: Wed, 1 Jan 2025 11:35:04 -0600 Subject: [PATCH 2/5] feat: add basic support for temperature sensor (tsens) for esp32c3 --- esp-hal/CHANGELOG.md | 2 +- esp-hal/src/soc/esp32c3/peripherals.rs | 1 + esp-hal/src/system.rs | 11 ++++++++++- esp-hal/src/tsens.rs | 4 ++++ esp-metadata/devices/esp32c3.toml | 1 + examples/src/bin/temperature_sensor.rs | 3 ++- 6 files changed, 19 insertions(+), 3 deletions(-) diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 5ae405bd84f..57b33169e6e 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -54,7 +54,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added `AnyPin::steal(pin_number)` (#2854) - `adc::{AdcCalSource, Attenuation, Resolution}` now implement `Hash` and `defmt::Format` (#2840) - `rtc_cntl::{RtcFastClock, RtcSlowClock, RtcCalSel}` now implement `PartialEq`, `Eq`, `Hash` and `defmt::Format` (#2840) -- Added `tsens::TemperatureSensor` peripheral for ESP32C6 +- Added `tsens::TemperatureSensor` peripheral for ESP32C6 and ESP32C3 (#2875) ### Changed diff --git a/esp-hal/src/soc/esp32c3/peripherals.rs b/esp-hal/src/soc/esp32c3/peripherals.rs index 00e6548a294..10180d39077 100644 --- a/esp-hal/src/soc/esp32c3/peripherals.rs +++ b/esp-hal/src/soc/esp32c3/peripherals.rs @@ -52,6 +52,7 @@ crate::peripherals! { SW_INTERRUPT <= virtual, TIMG0 <= TIMG0, TIMG1 <= TIMG1, + TSENS <= virtual, TWAI0 <= TWAI0, UART0 <= UART0, UART1 <= UART1, diff --git a/esp-hal/src/system.rs b/esp-hal/src/system.rs index c821a60a3da..38c2459cc9d 100755 --- a/esp-hal/src/system.rs +++ b/esp-hal/src/system.rs @@ -401,6 +401,10 @@ impl PeripheralClockControl { Peripheral::Systimer => { perip_clk_en0.modify(|_, w| w.systimer_clk_en().bit(enable)); } + #[cfg(tsens)] + Peripheral::Tsens => { + perip_clk_en1.modify(|_, w| w.tsens_clk_en().bit(enable)); + } } } @@ -613,11 +617,16 @@ impl PeripheralClockControl { perip_rst_en0.modify(|_, w| w.systimer_rst().set_bit()); perip_rst_en0.modify(|_, w| w.systimer_rst().clear_bit()); } - #[cfg(tsens)] + #[cfg(all(tsens, esp32c6))] Peripheral::Tsens => { perip_rst_en0.modify(|_, w| w.tsens_rst().set_bit()); perip_rst_en0.modify(|_, w| w.tsens_rst().clear_bit()); } + #[cfg(all(tsens, esp32c3))] + Peripheral::Tsens => { + perip_rst_en1.modify(|_, w| w.tsens_rst().set_bit()); + perip_rst_en1.modify(|_, w| w.tsens_rst().clear_bit()); + } }); } } diff --git a/esp-hal/src/tsens.rs b/esp-hal/src/tsens.rs index 49feb3e9d1c..ca5414a7215 100644 --- a/esp-hal/src/tsens.rs +++ b/esp-hal/src/tsens.rs @@ -71,6 +71,10 @@ impl<'d> TemperatureSensor<'d> { // Power Up apb_saradc.tsens_ctrl().write(|w| w.pu().set_bit()); + // Default to XTAL_CLK source, as it works out of the box on both esp32c6 and + // esp32c3 + apb_saradc.tsens_ctrl2().write(|w| w.clk_sel().set_bit()); + Self { _guard: guard, _peripheral: peripheral, diff --git a/esp-metadata/devices/esp32c3.toml b/esp-metadata/devices/esp32c3.toml index 08a62907cb3..2b43f5cad1d 100644 --- a/esp-metadata/devices/esp32c3.toml +++ b/esp-metadata/devices/esp32c3.toml @@ -52,6 +52,7 @@ symbols = [ "phy", "bt", "wifi", + "tsens", # ROM capabilities "rom_crc_le", diff --git a/examples/src/bin/temperature_sensor.rs b/examples/src/bin/temperature_sensor.rs index a6e0beadefa..63d066b2c79 100644 --- a/examples/src/bin/temperature_sensor.rs +++ b/examples/src/bin/temperature_sensor.rs @@ -1,7 +1,7 @@ //! This example uses the internal temperature sensor to measure the chip's temperature //! -//% CHIPS: esp32c6 +//% CHIPS: esp32c6 esp32c3 #![no_std] #![no_main] @@ -12,6 +12,7 @@ use esp_println::println; #[entry] fn main() -> ! { + esp_println::logger::init_logger_from_env(); let peripherals = esp_hal::init(esp_hal::Config::default()); let temperature_sensor = TemperatureSensor::new(peripherals.TSENS); From 59f2b7e52f18f9315bf914990a884d321ecae37e Mon Sep 17 00:00:00 2001 From: David Gu Date: Wed, 1 Jan 2025 19:20:40 -0600 Subject: [PATCH 3/5] feat: add configurable clock source for temperature sensor --- esp-hal/src/tsens.rs | 75 ++++++++++++++++++-------- examples/src/bin/temperature_sensor.rs | 12 ++++- 2 files changed, 62 insertions(+), 25 deletions(-) diff --git a/esp-hal/src/tsens.rs b/esp-hal/src/tsens.rs index ca5414a7215..e75f9d9fa40 100644 --- a/esp-hal/src/tsens.rs +++ b/esp-hal/src/tsens.rs @@ -9,11 +9,12 @@ //! frequency or I/O load. Generally, the chip’s internal temperature is higher //! than the operating ambient temperature. //! +//! It is recommended to wait a few hundred microseconds after turning it on +//! before measuring, in order to allow the sensor to stabilize. +//! //! ## Configuration //! -//! Currently, it does not support any configuration, but some future -//! configuration options are listed below in the Implementation State list of -//! pending items +//! The temperature sensor can be configured with different clock sources. //! //! ## Examples //! @@ -22,14 +23,17 @@ //! //! ```rust, no_run #![doc = crate::before_snippet!()] -//! # use esp_hal::tsens::TemperatureSensor; +//! # use esp_hal::tsens::{TemperatureSensor, Config}; //! # use esp_hal::delay::Delay; //! -//! let tsens = TemperatureSensor::new(peripherals.TSENS); +//! let temperature_sensor = TemperatureSensor::new( +//! peripherals.TSENS, +//! Config::default() +//! ).unwrap(); //! let delay = Delay::new(); //! //! loop { -//! let temp = tsens.get_celsius(); +//! let temp = temperature_sensor.get_celsius(); //! println!("Temperature: {:.2}°C", temp); //! delay.delay_millis(1_000); //! } @@ -38,7 +42,6 @@ //! //! ## Implementation State //! -//! - Source clock selection is not supported //! - Temperature calibration range is not supported //! - Interrupts are not supported @@ -48,45 +51,71 @@ use crate::{ system::{GenericPeripheralGuard, PeripheralClockControl}, }; +/// Clock source for the temperature sensor +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum ClockSource { + /// Use RC_FAST clock source + RcFast, + /// Use XTAL clock source + #[default] + Xtal, +} + +/// Temperature sensor configuration +#[derive(Debug, Clone, Default, PartialEq, Eq, Copy, procmacros::BuilderLite)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct Config { + clock_source: ClockSource, +} + +/// Temperature sensor configuration error +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ConfigError {} + /// Temperature sensor driver -// #[derive(Clone, Copy)] pub struct TemperatureSensor<'d> { _peripheral: PeripheralRef<'d, TSENS>, _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Tsens as u8 }>, } impl<'d> TemperatureSensor<'d> { - /// Create a new temperature sensor instance - pub fn new(peripheral: impl Peripheral

+ 'd) -> Self { + /// Create a new temperature sensor instance with configuration + pub fn new( + peripheral: impl Peripheral

+ 'd, + config: Config, + ) -> Result { crate::into_ref!(peripheral); - let guard = GenericPeripheralGuard::new(); // We need to enable ApbSarAdc clock before trying to write on the tsens_ctrl // register PeripheralClockControl::enable(crate::system::Peripheral::ApbSarAdc); - let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; // Power Up apb_saradc.tsens_ctrl().write(|w| w.pu().set_bit()); - // Default to XTAL_CLK source, as it works out of the box on both esp32c6 and - // esp32c3 - apb_saradc.tsens_ctrl2().write(|w| w.clk_sel().set_bit()); - - Self { + let mut tsens = Self { _guard: guard, _peripheral: peripheral, - } + }; + tsens.apply_config(&config)?; + + Ok(tsens) } - /// Disable the temperature sensor - pub fn disable(&self) { - let abp_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; - abp_saradc.tsens_ctrl().write(|w| w.pu().clear_bit()); + /// Change the temperature sensor configuration + pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> { + let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; + + // Set clock source + apb_saradc.tsens_ctrl2().write(|w| { + w.clk_sel() + .bit(matches!(config.clock_source, ClockSource::Xtal)) + }); - PeripheralClockControl::disable(crate::system::Peripheral::Tsens); + Ok(()) } /// Get the temperature in Celsius diff --git a/examples/src/bin/temperature_sensor.rs b/examples/src/bin/temperature_sensor.rs index 63d066b2c79..d016bd15ced 100644 --- a/examples/src/bin/temperature_sensor.rs +++ b/examples/src/bin/temperature_sensor.rs @@ -7,7 +7,11 @@ #![no_main] use esp_backtrace as _; -use esp_hal::{delay::Delay, entry, tsens::TemperatureSensor}; +use esp_hal::{ + delay::Delay, + entry, + tsens::{Config, TemperatureSensor}, +}; use esp_println::println; #[entry] @@ -15,8 +19,12 @@ fn main() -> ! { esp_println::logger::init_logger_from_env(); let peripherals = esp_hal::init(esp_hal::Config::default()); - let temperature_sensor = TemperatureSensor::new(peripherals.TSENS); + let temperature_sensor = TemperatureSensor::new(peripherals.TSENS, Config::default()).unwrap(); let delay = Delay::new(); + + // Wait for the sensor to stabilize + delay.delay_micros(200); + loop { let temp = temperature_sensor.get_celsius(); println!("Temperature: {:.2}°C", temp); From 1410db7ac25ce51dea921bf8744d44c8ba68a2c8 Mon Sep 17 00:00:00 2001 From: David Gu Date: Fri, 3 Jan 2025 17:14:21 -0600 Subject: [PATCH 4/5] feat: add Temperature struct to avoid enforcing usage of floats - Also add misc derives to multiple structs - Add power_up / power_down methods to TemperatureSensor - Enable ApbSarAdc via PeripheralGuard --- esp-hal/src/tsens.rs | 115 ++++++++++++------ .../src/bin/temperature_sensor.rs | 8 +- 2 files changed, 83 insertions(+), 40 deletions(-) rename {examples => qa-test}/src/bin/temperature_sensor.rs (81%) diff --git a/esp-hal/src/tsens.rs b/esp-hal/src/tsens.rs index e75f9d9fa40..6fe5cfc4623 100644 --- a/esp-hal/src/tsens.rs +++ b/esp-hal/src/tsens.rs @@ -31,10 +31,10 @@ //! Config::default() //! ).unwrap(); //! let delay = Delay::new(); -//! +//! delay.delay_micros(200); //! loop { -//! let temp = temperature_sensor.get_celsius(); -//! println!("Temperature: {:.2}°C", temp); +//! let temp = temperature_sensor.get_temperature(); +//! println!("Temperature: {:.2}°C", temp.to_celcius()); //! delay.delay_millis(1_000); //! } //! # } @@ -48,11 +48,11 @@ use crate::{ peripheral::{Peripheral, PeripheralRef}, peripherals::TSENS, - system::{GenericPeripheralGuard, PeripheralClockControl}, + system::GenericPeripheralGuard, }; /// Clock source for the temperature sensor -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Copy, Hash)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum ClockSource { /// Use RC_FAST clock source @@ -63,48 +63,104 @@ pub enum ClockSource { } /// Temperature sensor configuration -#[derive(Debug, Clone, Default, PartialEq, Eq, Copy, procmacros::BuilderLite)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Copy, Hash, procmacros::BuilderLite)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] +#[non_exhaustive] pub struct Config { clock_source: ClockSource, } /// Temperature sensor configuration error -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Copy, Hash)] +#[non_exhaustive] pub enum ConfigError {} +/// Temperature value +/// This struct stores the raw ADC value, and can be used to calculate the +/// temperature in Celsius using the formula: +/// `(raw_value * 0.4386) - (offset * 27.88) - 20.52` +#[derive(Debug)] +pub struct Temperature { + /// Raw ADC value + pub raw_value: u8, + + /// Offset value - depends on the temperature range configured + pub offset: i8, +} + +impl Temperature { + /// Create a new temperature value + #[inline] + pub fn new(raw_value: u8, offset: i8) -> Self { + Self { raw_value, offset } + } + + /// Get the temperature in Celsius + #[inline] + pub fn to_celsius(&self) -> f32 { + (self.raw_value as f32) * 0.4386 - (self.offset as f32) * 27.88 - 20.52 + } + + /// Get the temperature in Fahrenheit + #[inline] + pub fn to_fahrenheit(&self) -> f32 { + let celsius = self.to_celsius(); + (celsius * 1.8) + 32.0 + } + + /// Get the temperature in Kelvin + #[inline] + pub fn to_kelvin(&self) -> f32 { + let celsius = self.to_celsius(); + celsius + 273.15 + } +} + /// Temperature sensor driver +#[derive(Debug)] pub struct TemperatureSensor<'d> { _peripheral: PeripheralRef<'d, TSENS>, - _guard: GenericPeripheralGuard<{ crate::system::Peripheral::Tsens as u8 }>, + _tsens_guard: GenericPeripheralGuard<{ crate::system::Peripheral::Tsens as u8 }>, + _abp_saradc_guard: GenericPeripheralGuard<{ crate::system::Peripheral::ApbSarAdc as u8 }>, } impl<'d> TemperatureSensor<'d> { /// Create a new temperature sensor instance with configuration + /// The sensor will be automatically powered up pub fn new( peripheral: impl Peripheral

+ 'd, config: Config, ) -> Result { crate::into_ref!(peripheral); - let guard = GenericPeripheralGuard::new(); - - // We need to enable ApbSarAdc clock before trying to write on the tsens_ctrl - // register - PeripheralClockControl::enable(crate::system::Peripheral::ApbSarAdc); - let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; - - // Power Up - apb_saradc.tsens_ctrl().write(|w| w.pu().set_bit()); + // NOTE: We need enable ApbSarAdc before enabling Tsens + let apb_saradc_guard = GenericPeripheralGuard::new(); + let tsens_guard = GenericPeripheralGuard::new(); let mut tsens = Self { - _guard: guard, _peripheral: peripheral, + _tsens_guard: tsens_guard, + _abp_saradc_guard: apb_saradc_guard, }; tsens.apply_config(&config)?; + tsens.power_up(); + Ok(tsens) } + /// Power up the temperature sensor + pub fn power_up(&self) { + debug!("Power up"); + let abp_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; + abp_saradc.tsens_ctrl().modify(|_, w| w.pu().set_bit()); + } + + /// Power down the temperature sensor - useful if you want to save power + pub fn power_down(&self) { + let abp_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; + abp_saradc.tsens_ctrl().modify(|_, w| w.pu().clear_bit()); + } + /// Change the temperature sensor configuration pub fn apply_config(&mut self, config: &Config) -> Result<(), ConfigError> { let apb_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; @@ -118,29 +174,16 @@ impl<'d> TemperatureSensor<'d> { Ok(()) } - /// Get the temperature in Celsius + /// Get the raw temperature value #[inline] - pub fn get_celsius(&self) -> f32 { + pub fn get_temperature(&self) -> Temperature { let abp_saradc = unsafe { &*crate::peripherals::APB_SARADC::PTR }; - let measurement = abp_saradc.tsens_ctrl().read().out().bits(); + let raw_value = abp_saradc.tsens_ctrl().read().out().bits(); // TODO Address multiple temperature ranges and offsets - let offset = -1f32; - (measurement as f32) * 0.4386 - offset * 27.88 - 20.52 - } - - /// Get the temperature in Fahrenheit - #[inline] - pub fn get_fahrenheit(&self) -> f32 { - let celsius = self.get_celsius(); - (celsius * 1.8) + 32.0 - } + let offset = -1i8; - /// Get the temperature in Kelvin - #[inline] - pub fn get_kelvin(&self) -> f32 { - let celsius = self.get_celsius(); - celsius + 273.15 + Temperature::new(raw_value, offset) } } diff --git a/examples/src/bin/temperature_sensor.rs b/qa-test/src/bin/temperature_sensor.rs similarity index 81% rename from examples/src/bin/temperature_sensor.rs rename to qa-test/src/bin/temperature_sensor.rs index d016bd15ced..8158af8d075 100644 --- a/examples/src/bin/temperature_sensor.rs +++ b/qa-test/src/bin/temperature_sensor.rs @@ -1,5 +1,5 @@ -//! This example uses the internal temperature sensor to measure the chip's temperature -//! +//! This example uses the internal temperature sensor to measure the chip's +//! temperature //% CHIPS: esp32c6 esp32c3 @@ -26,8 +26,8 @@ fn main() -> ! { delay.delay_micros(200); loop { - let temp = temperature_sensor.get_celsius(); - println!("Temperature: {:.2}°C", temp); + let temp = temperature_sensor.get_temperature(); + println!("Temperature: {:.2}°C", temp.to_celsius()); delay.delay_millis(1_000); } } From ad3e44b2ed6b80ba67432bd036282f1df953dc00 Mon Sep 17 00:00:00 2001 From: David Gu Date: Mon, 6 Jan 2025 13:11:14 -0600 Subject: [PATCH 5/5] fix: move tsens module to unstable module list --- esp-hal/src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/esp-hal/src/lib.rs b/esp-hal/src/lib.rs index 0cc4d989ae7..1230738192e 100644 --- a/esp-hal/src/lib.rs +++ b/esp-hal/src/lib.rs @@ -194,9 +194,6 @@ pub mod debugger; pub mod sync; pub mod time; -#[cfg(tsens)] -pub mod tsens; - // can't use instability on inline module definitions, see https://github.com/rust-lang/rust/issues/54727 #[doc(hidden)] macro_rules! unstable_module { @@ -270,6 +267,8 @@ unstable_module! { pub mod touch; #[cfg(trace0)] pub mod trace; + #[cfg(tsens)] + pub mod tsens; #[cfg(any(twai0, twai1))] pub mod twai; #[cfg(usb_device)]