From d20524c6ad613a968b265b3831a7a8e677f09312 Mon Sep 17 00:00:00 2001 From: Javier Cardona Date: Tue, 23 Jan 2024 16:14:18 +0000 Subject: [PATCH] Implement ADC self-calibration (#233) * Implement ADC self-calibration Implement the ACD self-calibration procedure, which is defined in the RM377 reference manual as follows: The ADC has a calibration feature. During the procedure, the ADC calculates a calibration factor which is internally applied to the ADC until the next ADC power-off. The application must not use the ADC during calibration and must wait until it is complete. Calibration should be performed before starting A/D convers * Wait for hardware to clear ADCAL after calibration The reference manual says that software should wait until ADCAL = 0. Do that instead of being paranoid and eventually timing out if this does not happen. --------- Co-authored-by: Javier Cardona --- src/adc.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/adc.rs b/src/adc.rs index 98366bf..f4dadcb 100755 --- a/src/adc.rs +++ b/src/adc.rs @@ -123,6 +123,23 @@ impl Adc { self.precision = precision; } + /// Trigger internal ADC calibration + /// + /// This process is documented in Reference Manual RM377, section 13.3.3 + /// Calibration (ADCAL) + pub fn calibrate(&mut self) -> Result<(), Error> { + if self._state != Ready + || self.rb.cr.read().aden().bit_is_set() + || self.rb.cfgr1.read().dmaen().bit_is_set() + { + return Err(Error::InvalidAdcState); + } + + self.rb.cr.modify(|_, w| w.adcal().set_bit()); + while self.rb.cr.read().adcal().bit_is_set() {} + Ok(()) + } + /// Starts a continuous conversion process /// /// The `channel` argument specifies which channel should be converted. @@ -321,6 +338,7 @@ where } /// Indicates that the ADC peripheral is ready +#[derive(PartialEq)] pub struct Ready; /// Indicates that the ADC peripheral is performing conversions @@ -615,6 +633,9 @@ pub enum Error { /// just keeps writing more values. It does mean that some values in the /// buffer were overwritten though. BufferOverrun, + + /// Invalid ADC state for requested operation + InvalidAdcState, } macro_rules! int_adc {