diff --git a/os/hal/platforms/STM32F37x/adc_lld.c b/os/hal/platforms/STM32F37x/adc_lld.c index 582f84d8f..6d119044b 100644 --- a/os/hal/platforms/STM32F37x/adc_lld.c +++ b/os/hal/platforms/STM32F37x/adc_lld.c @@ -77,12 +77,70 @@ ADCDriver SDADCD3; /* Driver local variables and types. */ /*===========================================================================*/ -static const ADCConfig adc_lld_default_config = {0}; +static const ADCConfig adc_lld_default_config = { +#if STM32_ADC_USE_SDADC + 0, + { + 0, + 0, + 0 + } +#else /* !STM32_ADC_USE_SDADC */ + 0 +#endif /* !STM32_ADC_USE_SDADC */ +}; /*===========================================================================*/ /* Driver local functions. */ /*===========================================================================*/ +/** + * @brief Stops, reconfigures and restarts an ADC/SDADC. + * + * @param[in] adcp pointer to the @p ADCDriver object + */ +static void adc_lld_reconfig(ADCDriver *adcp) { + +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC + if (adcp->adc != NULL) +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_ADC + { + /* ADC initial setup, starting the analog part here in order to reduce + the latency when starting a conversion.*/ + uint32_t cr2 = adcp->adc->CR2 & ADC_CR2_TSVREFE; + adcp->adc->CR2 = cr2; + adcp->adc->CR1 = 0; + adcp->adc->CR2 = cr2 | ADC_CR2_ADON; + + } +#endif /* STM32_ADC_USE_ADC */ +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC + else if (adcp->sdadc != NULL) +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_SDADC + { + /* SDADC initial setup, starting the analog part here in order to reduce + the latency when starting a conversion.*/ + adcp->sdadc->CR2 = 0; + adcp->sdadc->CR1 = (adcp->config->cr1 | SDADC_ENFORCED_CR1_FLAGS) & + ~SDADC_FORBIDDEN_CR1_FLAGS; + adcp->sdadc->CONF0R = (adcp->sdadc->CONF0R & SDADC_CONFR_OFFSET_MASK) | + adcp->config->confxr[0]; + adcp->sdadc->CONF1R = (adcp->sdadc->CONF1R & SDADC_CONFR_OFFSET_MASK) | + adcp->config->confxr[1]; + adcp->sdadc->CONF2R = (adcp->sdadc->CONF2R & SDADC_CONFR_OFFSET_MASK) | + adcp->config->confxr[2]; + adcp->sdadc->CR2 = SDADC_CR2_ADON; + } +#endif /* STM32_ADC_USE_SDADC */ +#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC +else { + chDbgAssert(FALSE, "adc_lld_start(), #5", "invalid state"); + } +#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ +} + /** * @brief ADC DMA ISR service routine. * @@ -115,12 +173,14 @@ static void adc_lld_serve_dma_interrupt(ADCDriver *adcp, uint32_t flags) { } } -#if STM32_ADC_USE_ADC +#if STM32_ADC_USE_ADC || defined(__DOXYGEN__) /** * @brief ADC ISR service routine. * * @param[in] adcp pointer to the @p ADCDriver object * @param[in] sr content of the ISR register + * + * @notapi */ static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t sr) { @@ -135,12 +195,14 @@ static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t sr) { } #endif /* STM32_ADC_USE_ADC */ -#if STM32_ADC_USE_SDADC +#if STM32_ADC_USE_SDADC || defined(__DOXYGEN__) /** * @brief ADC ISR service routine. * * @param[in] adcp pointer to the @p ADCDriver object * @param[in] isr content of the ISR register + * + * @notapi */ static void sdadc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) { @@ -346,12 +408,6 @@ void adc_lld_start(ADCDriver *adcp) { chDbgAssert(!b, "adc_lld_start(), #1", "stream already allocated"); dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); rccEnableADC1(FALSE); - - /* ADC initial setup, starting the analog part here in order to reduce - the latency when starting a conversion.*/ - adcp->adc->CR1 = 0; - adcp->adc->CR2 = 0; - adcp->adc->CR2 = ADC_CR2_ADON; } #endif /* STM32_ADC_USE_ADC1 */ @@ -406,6 +462,8 @@ void adc_lld_start(ADCDriver *adcp) { } #endif /* STM32_ADC_USE_SDADC3 */ } + + adc_lld_reconfig(adcp); } /** @@ -531,9 +589,6 @@ void adc_lld_start_conversion(ADCDriver *adcp) { /* SDADC setup.*/ adcp->sdadc->JCHGR = grpp->u.sdadc.jchgr; - adcp->sdadc->CONF0R = grpp->u.sdadc.confxr[0]; - adcp->sdadc->CONF1R = grpp->u.sdadc.confxr[1]; - adcp->sdadc->CONF2R = grpp->u.sdadc.confxr[2]; adcp->sdadc->CONFCHR1 = grpp->u.sdadc.confchr[0]; adcp->sdadc->CONFCHR2 = grpp->u.sdadc.confchr[1]; @@ -564,32 +619,9 @@ void adc_lld_stop_conversion(ADCDriver *adcp) { /* Disabling the associated DMA stream.*/ dmaStreamDisable(adcp->dmastp); -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC - if (adcp->adc != NULL) -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_ADC - { - uint32_t cr2 = adcp->adc->CR2 & ADC_CR2_TSVREFE; - adcp->adc->CR2 = cr2; - adcp->adc->CR1 = 0; - adcp->adc->CR2 = cr2 | ADC_CR2_ADON; - } -#endif /* STM32_ADC_USE_ADC */ -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC - else if (adcp->sdadc != NULL) -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_SDADC - { - adcp->sdadc->CR1 = 0; - adcp->sdadc->CR2 = 0; - adcp->sdadc->CR2 = ADC_CR2_ADON; - } -#endif /* STM32_ADC_USE_SDADC */ -#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC - else { - chDbgAssert(FALSE, "adc_lld_stop_conversion(), #1", "invalid state"); - } -#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ + /* Stopping and restarting the whole ADC, apparently the only way to stop + a conversion.*/ + adc_lld_reconfig(adcp); } /** diff --git a/os/hal/platforms/STM32F37x/adc_lld.h b/os/hal/platforms/STM32F37x/adc_lld.h index 6d4fcb504..4e8c4645c 100644 --- a/os/hal/platforms/STM32F37x/adc_lld.h +++ b/os/hal/platforms/STM32F37x/adc_lld.h @@ -468,10 +468,6 @@ typedef struct { * @brief SDADC JCHGR register initialization data. */ uint32_t jchgr; - /** - * @brief SDADC CONFxR registers initialization data. - */ - uint32_t confxr[3]; /** * @brief SDADC CONFCHxR registers initialization data. */ @@ -491,6 +487,10 @@ typedef struct { * @brief SDADC CR1 register initialization data. */ uint32_t cr1; + /** + * @brief SDADC CONFxR registers initialization data. + */ + uint32_t confxr[3]; #else /* !STM32_ADC_USE_SDADC */ uint32_t dummy; #endif /* !STM32_ADC_USE_SDADC */ @@ -669,18 +669,6 @@ struct ADCDriver { #define SDADC_CONFR_COMMON_VDDSD (2U << 30) /** @} */ -#define SDADC_CONF1R_OFFSET1 ((uint32_t)0x00000FFF) /*!< 12-bit calibration offset for configuration 1 */ -#define SDADC_CONF1R_GAIN1 ((uint32_t)0x00700000) /*!< Gain setting for configuration 1 */ -#define SDADC_CONF1R_GAIN1_0 ((uint32_t)0x00100000) /*!< Gain setting for configuration 1 Bit 0 */ -#define SDADC_CONF1R_GAIN1_1 ((uint32_t)0x00200000) /*!< Gain setting for configuration 1 Bit 1 */ -#define SDADC_CONF1R_GAIN1_2 ((uint32_t)0x00400000) /*!< Gain setting for configuration 1 Bit 2 */ -#define SDADC_CONF1R_SE1 ((uint32_t)0x0C000000) /*!< Single ended mode for configuration 1 */ -#define SDADC_CONF1R_SE1_0 ((uint32_t)0x04000000) /*!< Single ended mode for configuration 1 Bit 0 */ -#define SDADC_CONF1R_SE1_1 ((uint32_t)0x08000000) /*!< Single ended mode for configuration 1 Bit 1 */ -#define SDADC_CONF1R_COMMON1 ((uint32_t)0xC0000000) /*!< Common mode for configuration 1 */ -#define SDADC_CONF1R_COMMON1_0 ((uint32_t)0x40000000) /*!< Common mode for configuration 1 Bit 0 */ -#define SDADC_CONF1R_COMMON1_1 ((uint32_t)0x40000000) /*!< Common mode for configuration 1 Bit 1 */ - /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ diff --git a/testhal/STM32F37x/SDADC/main.c b/testhal/STM32F37x/SDADC/main.c index 4b3e69df4..eb4790873 100644 --- a/testhal/STM32F37x/SDADC/main.c +++ b/testhal/STM32F37x/SDADC/main.c @@ -24,8 +24,8 @@ #define ADC_GRP1_NUM_CHANNELS 1 #define ADC_GRP1_BUF_DEPTH 8 -#define ADC_GRP2_NUM_CHANNELS 8 -#define ADC_GRP2_BUF_DEPTH 16 +#define ADC_GRP2_NUM_CHANNELS 1 +#define ADC_GRP2_BUF_DEPTH 32 static adcsample_t samples1[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH]; static adcsample_t samples2[ADC_GRP2_NUM_CHANNELS * ADC_GRP2_BUF_DEPTH]; @@ -51,6 +51,18 @@ static void adcerrorcallback(ADCDriver *adcp, adcerror_t err) { (void)err; } +/* + * SDADC configuration. + */ +static const ADCConfig sdadc_config = { + 0, + { + SDADC_CONFR_GAIN_1X | SDADC_CONFR_SE_ZERO_VOLT | SDADC_CONFR_COMMON_VSSSD, + 0, + 0 + } +}; + /* * ADC conversion group. * Mode: Linear buffer, 8 samples of 1 channel, SW triggered. @@ -64,11 +76,6 @@ static const ADCConversionGroup adcgrpcfg1 = { .u.sdadc = { SDADC_CR2_JSWSTART, /* CR2 */ SDADC_JCHGR_CH(5), /* JCHGR */ - { /* CONFxR[3]*/ - SDADC_CONFR_GAIN_1X | SDADC_CONFR_SE_DIFF | SDADC_CONFR_COMMON_VSSSD, - 0, - 0 - }, { /* CONFCHR[2]*/ SDADC_CONFCHR1_CH5(0), 0 @@ -76,36 +83,25 @@ static const ADCConversionGroup adcgrpcfg1 = { } }; -#if 0 /* * ADC conversion group. - * Mode: Continuous, 16 samples of 8 channels, SW triggered. - * Channels: IN7, IN8, IN7, IN8, IN7, IN8, Sensor, VBat/2. + * Mode: Continuous, 32 samples of 1 channel, SW triggered. + * Channels: ADC_IN5P. */ static const ADCConversionGroup adcgrpcfg2 = { TRUE, ADC_GRP2_NUM_CHANNELS, adccallback, adcerrorcallback, - 0, /* CFGR */ - ADC_TR(0, 4095), /* TR1 */ - ADC_CCR_TSEN | ADC_CCR_VBATEN, /* CCR */ - { /* SMPR[2] */ - ADC_SMPR1_SMP_AN7(ADC_SMPR_SMP_19P5) - | ADC_SMPR1_SMP_AN8(ADC_SMPR_SMP_19P5), - ADC_SMPR2_SMP_AN16(ADC_SMPR_SMP_61P5) - | ADC_SMPR2_SMP_AN17(ADC_SMPR_SMP_61P5), - }, - { /* SQR[4] */ - ADC_SQR1_SQ1_N(ADC_CHANNEL_IN7) | ADC_SQR1_SQ2_N(ADC_CHANNEL_IN8) | - ADC_SQR1_SQ3_N(ADC_CHANNEL_IN7) | ADC_SQR1_SQ4_N(ADC_CHANNEL_IN8), - ADC_SQR2_SQ5_N(ADC_CHANNEL_IN7) | ADC_SQR2_SQ6_N(ADC_CHANNEL_IN8) | - ADC_SQR2_SQ7_N(ADC_CHANNEL_IN16) | ADC_SQR2_SQ8_N(ADC_CHANNEL_IN17), - 0, - 0 + .u.sdadc = { + SDADC_CR2_JSWSTART, /* CR2 */ + SDADC_JCHGR_CH(5), /* JCHGR */ + { /* CONFCHR[2]*/ + SDADC_CONFCHR1_CH5(0), + 0 + } } }; -#endif /* * Red LEDs blinker thread, times are in milliseconds. @@ -147,26 +143,25 @@ int main(void) { /* * Activates the SDADC1 driver. */ - adcStart(&SDADCD1, NULL); + adcStart(&SDADCD1, &sdadc_config); adcSTM32Calibrate(&SDADCD1); /* * Linear conversion. */ adcConvert(&SDADCD1, &adcgrpcfg1, samples1, ADC_GRP1_BUF_DEPTH); - chThdSleepMilliseconds(1000); /* * Starts an ADC continuous conversion. */ -// adcStartConversion(&SDADC1, &adcgrpcfg2, samples2, ADC_GRP2_BUF_DEPTH); + adcStartConversion(&SDADCD1, &adcgrpcfg2, samples2, ADC_GRP2_BUF_DEPTH); /* * Normal main() thread activity, in this demo it does nothing. */ while (TRUE) { if (palReadPad(GPIOA, GPIOA_WKUP_BUTTON)) { -// adcStopConversion(&SDADCD1); + adcStopConversion(&SDADCD1); } chThdSleepMilliseconds(500); }