This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new b1df6b149b8 arch/arm/src/common/stm32: add a low-level ADC calibration
operation
b1df6b149b8 is described below
commit b1df6b149b8ab3a88020411fd7f8cd2541cf9988
Author: Daniel P. Carvalho <[email protected]>
AuthorDate: Sun Oct 25 12:33:36 2026 -0300
arch/arm/src/common/stm32: add a low-level ADC calibration operation
The ADC is only calibrated when it is opened, so a device that stays
open while the temperature changes a lot keeps the old calibration
factor. Add a calibrate operation to the low-level ADC operations of
the ADC IPv2 (STM32G4 and F3) so the board can run it again.
The ADC is disabled for the calibration and enabled again if it was
enabled before. The operation returns -EBUSY while a conversion is
running, the caller has to stop it first.
Assisted-by: Claude Code:claude-sonnet-5-5
Signed-off-by: Daniel P. Carvalho <[email protected]>
---
arch/arm/src/common/stm32/stm32_adc_m3m4_v1v2.c | 54 ++++++++++++++++++++++++-
arch/arm/src/common/stm32/stm32_adc_m3m4_v1v2.h | 8 ++++
2 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/arch/arm/src/common/stm32/stm32_adc_m3m4_v1v2.c
b/arch/arm/src/common/stm32/stm32_adc_m3m4_v1v2.c
index 2246438925e..61688e281a6 100644
--- a/arch/arm/src/common/stm32/stm32_adc_m3m4_v1v2.c
+++ b/arch/arm/src/common/stm32/stm32_adc_m3m4_v1v2.c
@@ -672,6 +672,9 @@ static void adc_sampletime_write(struct stm32_adc_dev_s
*dev);
static void adc_llops_dumpregs(struct stm32_adc_dev_s *dev);
static int adc_llops_multicfg(struct stm32_adc_dev_s *dev, uint8_t mode);
static void adc_llops_enable(struct stm32_adc_dev_s *dev, bool enable);
+# ifdef HAVE_IP_ADC_V2
+static int adc_llops_calibrate(struct stm32_adc_dev_s *dev);
+# endif
#endif
/****************************************************************************
@@ -727,7 +730,10 @@ static const struct stm32_adc_ops_s g_adc_llops =
# endif
.dump_regs = adc_llops_dumpregs,
.multi_cfg = adc_llops_multicfg,
- .enable = adc_llops_enable
+ .enable = adc_llops_enable,
+# ifdef HAVE_IP_ADC_V2
+ .calibrate = adc_llops_calibrate
+# endif
};
#endif
@@ -4984,6 +4990,52 @@ static void adc_llops_enable(struct stm32_adc_dev_s
*dev, bool enable)
adc_enable(priv, enable);
}
+/****************************************************************************
+ * Name: adc_llops_calibrate
+ *
+ * Description:
+ * Run the calibration again, for example after a large temperature
+ * change. The ADC is disabled for the calibration and enabled again if
+ * it was enabled before.
+ *
+ * Returned Value:
+ * OK on success, -EBUSY if a conversion is in progress.
+ *
+ ****************************************************************************/
+
+# ifdef HAVE_IP_ADC_V2
+static int adc_llops_calibrate(struct stm32_adc_dev_s *dev)
+{
+ struct stm32_dev_s *priv = (struct stm32_dev_s *)dev;
+ irqstate_t flags;
+ uint32_t regval;
+ bool enabled;
+
+ flags = enter_critical_section();
+
+ regval = adc_getreg(priv, STM32_ADC_CR_OFFSET);
+ if ((regval & (ADC_CR_ADSTART | ADC_CR_JADSTART)) != 0)
+ {
+ leave_critical_section(flags);
+ return -EBUSY;
+ }
+
+ enabled = (regval & ADC_CR_ADEN) != 0;
+
+ adc_enable(priv, false);
+ adc_voltreg_cfg(priv);
+ adc_calibrate(priv);
+
+ if (enabled)
+ {
+ adc_enable(priv, true);
+ }
+
+ leave_critical_section(flags);
+ return OK;
+}
+# endif
+
#endif /* CONFIG_STM32_ADC_LL_OPS */
/****************************************************************************
diff --git a/arch/arm/src/common/stm32/stm32_adc_m3m4_v1v2.h
b/arch/arm/src/common/stm32/stm32_adc_m3m4_v1v2.h
index 3d6e01da79a..e07428bcfeb 100644
--- a/arch/arm/src/common/stm32/stm32_adc_m3m4_v1v2.h
+++ b/arch/arm/src/common/stm32/stm32_adc_m3m4_v1v2.h
@@ -2296,6 +2296,14 @@ struct stm32_adc_ops_s
/* Enable/disable ADC */
void (*enable)(struct stm32_adc_dev_s *dev, bool enable);
+
+#ifdef HAVE_IP_ADC_V2
+ /* Recalibrate the ADC (ADCAL). Returns -EBUSY while a conversion is
+ * running; the caller has to stop it first.
+ */
+
+ int (*calibrate)(struct stm32_adc_dev_s *dev);
+#endif
};
#endif /* CONFIG_STM32_ADC_LL_OPS */