diff --git a/arch/arm/src/stm32/stm32f33xxx_adc.c b/arch/arm/src/stm32/stm32f33xxx_adc.c index b75641c27af..3369b2da562 100644 --- a/arch/arm/src/stm32/stm32f33xxx_adc.c +++ b/arch/arm/src/stm32/stm32f33xxx_adc.c @@ -121,9 +121,10 @@ /* RCC reset ****************************************************************/ -#define STM32_RCC_RSTR STM32_RCC_AHBRSTR -#define RCC_RSTR_ADC1RST RCC_AHBRSTR_ADC12RST -#define RCC_RSTR_ADC2RST RCC_AHBRSTR_ADC12RST +#define STM32_RCC_RSTR STM32_RCC_AHBRSTR +#define STM32_RCC_ENR STM32_RCC_AHBENR +#define RCC_RSTR_ADC12RST RCC_AHBRSTR_ADC12RST +#define RCC_RSTR_ADC12EN RCC_AHBENR_ADC12EN /* ADC interrupts ***********************************************************/ @@ -376,6 +377,14 @@ * Private Types ****************************************************************************/ +/* Data common to all ADC instances */ + +struct adc_cmn_s +{ + uint8_t initialized; /* How many ADC instances are currently in use */ + /* TODO: dual ADC mode */ +}; + /* This structure describes the state of one ADC block */ struct stm32_dev_s @@ -386,6 +395,7 @@ struct stm32_dev_s FAR const struct adc_callback_s *cb; uint8_t irq; /* Interrupt generated by this ADC block */ #endif + struct adc_cmn_s *cmn; /* Common ADC data */ uint8_t rnchannels; /* Number of regular channels */ uint8_t cr_channels; /* Number of configured regular channels */ #ifdef ADC_HAVE_INJECTED @@ -552,6 +562,13 @@ static const struct stm32_adc_ops_s g_adc_lowerops = }; #endif +/* Common ADC12 data */ + +struct adc_cmn_s g_adc12_cmn = +{ + .initialized = 0 +}; + /* ADC1 state */ #ifdef CONFIG_STM32_ADC1 @@ -563,6 +580,7 @@ static struct stm32_dev_s g_adcpriv1 = .irq = STM32_IRQ_ADC12, .isr = adc12_interrupt, #endif + .cmn = &g_adc12_cmn, .intf = 1, .resolution = ADC1_RESOLUTION, .base = STM32_ADC1_BASE, @@ -605,6 +623,7 @@ static struct stm32_dev_s g_adcpriv2 = .irq = STM32_IRQ_ADC12, .isr = adc12_interrupt, #endif + .cmn = &g_adc12_cmn, .intf = 2, .resolution = ADC2_RESOLUTION, .base = STM32_ADC2_BASE, @@ -1304,7 +1323,10 @@ static void adc_inj_startconv(FAR struct stm32_dev_s *priv, bool enable) static void adc_rccreset(FAR struct stm32_dev_s *priv, bool reset) { - uint32_t adcbit; + uint32_t rstbit; + uint32_t enbit; + uint32_t rst_reg; + uint32_t en_reg; /* Pick the appropriate bit in the APB2 reset register. * For the STM32 F1, there is an individual bit to reset each ADC, @@ -1314,18 +1336,21 @@ static void adc_rccreset(FAR struct stm32_dev_s *priv, bool reset) switch (priv->intf) { -#ifdef CONFIG_STM32_ADC1 +#if defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2) case 1: - adcbit = RCC_RSTR_ADC1RST; - break; -#endif -#ifdef CONFIG_STM32_ADC2 case 2: - adcbit = RCC_RSTR_ADC2RST; - break; + { + rstbit = RCC_RSTR_ADC12RST; + enbit = RCC_RSTR_ADC12EN; + rst_reg = RCC_RSTR_ADC12RST; + en_reg = RCC_RSTR_ADC12EN; + break; + } #endif default: - return; + { + return; + } } /* Set or clear the selected bit in the APB2 reset register. @@ -1337,13 +1362,13 @@ static void adc_rccreset(FAR struct stm32_dev_s *priv, bool reset) { /* Enable ADC reset state */ - modifyreg32(STM32_RCC_RSTR, 0, adcbit); + modifyreg32(rst_reg, 0, rstbit); } else { /* Release ADC from reset state */ - modifyreg32(STM32_RCC_RSTR, adcbit, 0); + modifyreg32(en_reg, enbit, 1); } } @@ -1507,13 +1532,18 @@ static void adc_reset(FAR struct adc_dev_s *dev) adc_enable(priv, false); - /* Enable ADC reset state */ + /* Only if this is the first instance */ - adc_rccreset(priv, true); + if (priv->cmn->initialized <= 0) + { + /* Enable ADC reset state */ - /* Release ADC from reset state */ + adc_rccreset(priv, true); - adc_rccreset(priv, false); + /* Release ADC from reset state */ + + adc_rccreset(priv, false); + } /* Set voltage regular enable to intermediate state */ @@ -1812,9 +1842,16 @@ static void adc_shutdown(FAR struct adc_dev_s *dev) irq_detach(priv->irq); #endif - /* Disable and reset the ADC module */ + if (priv->cmn->initialized <= 1) + { + /* Disable and reset the ADC module only when last instance */ - adc_rccreset(priv, true); + adc_rccreset(priv, true); + + /* Decrease instances counter */ + } + + priv->cmn->initialized -= 1; } /**************************************************************************** @@ -1939,7 +1976,7 @@ static int adc_set_ch(FAR struct adc_dev_s *dev, uint8_t ch) static int adc_inj_set_ch(FAR struct adc_dev_s *dev, uint8_t ch) { FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv; - uint32_t regval; + uint32_t regval = 0; int i; /* Configure JEXTSEL */ @@ -2259,6 +2296,8 @@ errout: * Description: * Initialize the ADC. * + * TODO: describe injected channels configuration. + * * The logic is, save rnchannels : # of channels (conversions) in ADC_SQR1_L * Then, take the chanlist array and store it in the SQR Regs, * chanlist[0] -> ADC_SQR3_SQ1 @@ -2313,7 +2352,7 @@ struct adc_dev_s *stm32_adcinitialize(int intf, FAR const uint8_t *chanlist, cr_channels = channels - ADC2_INJECTED_CHAN; #ifdef ADC_HAVE_INJECTED cj_channels = ADC2_INJECTED_CHAN; - j_chanlist = chanlist + cr_channels; + j_chanlist = (FAR uint8_t *)chanlist + cr_channels; #endif break; } @@ -2356,6 +2395,10 @@ struct adc_dev_s *stm32_adcinitialize(int intf, FAR const uint8_t *chanlist, ainfo("intf: %d cr_channels: %d\n", intf, priv->cr_channels); #endif + /* Increase instances counter */ + + priv->cmn->initialized += 1; + return dev; }