Merged in raiden00/nuttx_pe (pull request #772)

arch/arm/src/stm32/stm32_adc.c: refactor adc_reset. It should be easier to maintain this code if it's divided into smaller functions

Approved-by: GregoryN <gnutt@nuttx.org>
This commit is contained in:
Mateusz Szafoni 2018-12-02 18:34:02 +00:00 committed by GregoryN
parent b7fa409fc4
commit db799e857c

View File

@ -2324,102 +2324,34 @@ static int adc_bind(FAR struct adc_dev_s *dev,
}
/****************************************************************************
* Name: adc_reset
*
* Description:
* Reset the ADC device. Called early to initialize the hardware.
* This is called, before adc_setup() and on error conditions.
*
* Input Parameters:
*
* Returned Value:
*
* Name: adc_watchdog_cfg
****************************************************************************/
static void adc_reset(FAR struct adc_dev_s *dev)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
irqstate_t flags;
uint32_t clrbits;
uint32_t setbits;
#ifdef ADC_HAVE_TIMER
int ret;
#endif
ainfo("intf: %d\n", priv->intf);
flags = enter_critical_section();
#ifdef HAVE_HSI_CONTROL
/* The STM32L15XX family uses HSI as an independent clock-source
* for the ADC
*/
adc_enable_hsi(true);
#endif
#if defined(HAVE_IP_ADC_V2)
/* Turn off the ADC so we can write the RCC bits */
adc_enable(priv, false);
#endif
/* Only if this is the first initialzied ADC instance in the ADC block */
#ifdef HAVE_ADC_CMN_DATA
adccmn_lock(priv, true);
if (priv->cmn->initialized == 0)
#endif
static void adc_watchdog_cfg(FAR struct stm32_dev_s *priv)
{
/* Enable ADC reset state */
adc_rccreset(priv, true);
/* Release ADC from reset state */
adc_rccreset(priv, false);
}
#ifdef HAVE_ADC_CMN_DATA
adccmn_lock(priv, false);
#endif
#if defined(HAVE_IP_ADC_V2)
/* Set voltage regular enable to intermediate state */
adc_modifyreg(priv, STM32_ADC_CR_OFFSET, ADC_CR_ADVREGEN_MASK,
ADC_CR_ADVREGEN_INTER);
/* Enable the ADC voltage regulator */
adc_modifyreg(priv, STM32_ADC_CR_OFFSET, ADC_CR_ADVREGEN_MASK,
ADC_CR_ADVREGEN_ENABLED);
/* Wait for the ADC voltage regulator to startup */
up_udelay(10);
#if 0 /* Doesn't work */
/* Calibrate the ADC */
adc_modifyreg(priv, STM32_ADC_CR_OFFSET, ADC_CR_ADCALDIF, AD_CR_ADCAL);
/* Wait for the calibration to complete */
while ((adc_getreg(priv, STM32_ADC_CR_OFFSET) & ADC_CR_ADCAL) != 0);
#endif
uint32_t clrbits = 0;
uint32_t setbits = 0;
/* Initialize the watchdog 1 threshold register */
adc_putreg(priv, STM32_ADC_TR1_OFFSET, 0x0fff0000);
#else /* HAVE_IP_ADC_V1 */
/* Enable the analog watchdog */
clrbits = ADC_CFGR1_AWD1CH_MASK;
setbits = ADC_CFGR1_AWD1EN | ADC_CFGR1_AWD1SGL |
(priv->r_chanlist[0] << ADC_CFGR1_AWD1CH_SHIFT);
/* Modify CFGR configuration */
adc_modifyreg(priv, STM32_ADC_CFGR1_OFFSET, clrbits, setbits);
}
#else
static void adc_watchdog_cfg(FAR struct stm32_dev_s *priv)
{
uint32_t clrbits = 0;
uint32_t setbits = 0;
/* Initialize the watchdog high threshold register */
@ -2429,60 +2361,57 @@ static void adc_reset(FAR struct adc_dev_s *dev)
adc_putreg(priv, STM32_ADC_LTR_OFFSET, 0x00000000);
clrbits = ADC_CR1_AWDCH_MASK;
setbits = ADC_CR1_AWDEN | (priv->r_chanlist[0] << ADC_CR1_AWDCH_SHIFT);
/* Modify CR1 configuration */
adc_modifyreg(priv, STM32_ADC_CR1_OFFSET, clrbits, setbits);
}
#endif
/* Initialize the same sample time for each ADC.
* During sample cycles channel selection bits must remain unchanged.
*/
/****************************************************************************
* Name: adc_calibrate
****************************************************************************/
#if defined(HAVE_IP_ADC_V2)
static void adc_calibrate(FAR struct stm32_dev_s *priv)
{
#if 0 /* Doesn't work */
/* Calibrate the ADC */
adc_modifyreg(priv, STM32_ADC_CR_OFFSET, ADC_CR_ADCALDIF, AD_CR_ADCAL);
/* Wait for the calibration to complete */
while ((adc_getreg(priv, STM32_ADC_CR_OFFSET) & ADC_CR_ADCAL) != 0);
#ifdef CONFIG_STM32_ADC_CHANGE_SAMPLETIME
adc_sampletime_write((FAR struct stm32_adc_dev_s *)dev);
#else
adc_putreg(priv, STM32_ADC_SMPR1_OFFSET, ADC_SMPR1_DEFAULT);
adc_putreg(priv, STM32_ADC_SMPR2_OFFSET, ADC_SMPR2_DEFAULT);
# ifdef STM32_ADC_SMPR3_OFFSET
adc_putreg(priv, STM32_ADC_SMPR3_OFFSET, ADC_SMPR3_DEFAULT);
# endif
# ifdef STM32_ADC_SMPR0_OFFSET
adc_putreg(priv, STM32_ADC_SMPR0_OFFSET, ADC_SMPR0_DEFAULT);
UNUSED(priv);
#endif
}
#else
static void adc_calibrate(FAR struct stm32_dev_s *priv)
{
/* TODO: adc_calibrate for ADC IPv1*/
UNUSED(priv);
}
#endif
/****************************************************************************
* Name: adc_mode_cfg
****************************************************************************/
#ifdef HAVE_IP_ADC_V2
/* Enable the analog watchdog */
clrbits = ADC_CFGR1_AWD1CH_MASK;
setbits = ADC_CFGR1_AWD1EN | ADC_CFGR1_AWD1SGL |
(priv->r_chanlist[0] << ADC_CFGR1_AWD1CH_SHIFT);
# ifdef ADC_HAVE_DMA
if (priv->hasdma)
static void adc_mode_cfg(FAR struct stm32_dev_s *priv)
{
/* Set DMA mode */
if (priv->dmacfg == 0)
{
/* One Shot Mode */
clrbits |= ADC_CFGR1_DMACFG;
}
else
{
/* Circular Mode */
setbits |= ADC_CFGR1_DMACFG;
}
/* Enable DMA */
setbits |= ADC_CFGR1_DMAEN;
}
# endif
uint32_t clrbits = 0;
uint32_t setbits = 0;
/* Disable continuous mode and set align to right */
clrbits |= ADC_CFGR1_CONT | ADC_CFGR1_ALIGN;
clrbits = ADC_CFGR1_CONT | ADC_CFGR1_ALIGN;
/* Disable external trigger for regular channels */
@ -2492,24 +2421,12 @@ static void adc_reset(FAR struct adc_dev_s *dev)
/* Set CFGR configuration */
adc_modifyreg(priv, STM32_ADC_CFGR1_OFFSET, clrbits, setbits);
# ifndef CONFIG_STM32_ADC_NOIRQ
/* Enable interrupt flags, but disable overrun interrupt */
clrbits = ADC_IER_OVR;
setbits = ADC_IER_ALLINTS & ~ADC_IER_OVR;
/* Set IER configuration */
adc_modifyreg(priv, STM32_ADC_IER_OFFSET, clrbits, setbits);
# endif
#else /* HAVE_IP_ADC_V1 */
/* Enable the analog watchdog */
clrbits = ADC_CR1_AWDCH_MASK;
setbits = ADC_CR1_AWDEN | (priv->r_chanlist[0] << ADC_CR1_AWDCH_SHIFT);
}
#else
static void adc_mode_cfg(FAR struct stm32_dev_s *priv)
{
uint32_t clrbits = 0;
uint32_t setbits = 0;
#ifdef HAVE_BASIC_ADC
/* Set independent mode */
@ -2529,7 +2446,9 @@ static void adc_reset(FAR struct adc_dev_s *dev)
adc_modifyreg(priv, STM32_ADC_CR1_OFFSET, clrbits, setbits);
# ifdef CONFIG_STM32_STM32L15XX /* REVISIT: */
/* REVISIT: */
#ifdef CONFIG_STM32_STM32L15XX
/* Select the bank of channels A */
@ -2566,9 +2485,156 @@ static void adc_reset(FAR struct adc_dev_s *dev)
setbits |= ADC_CR2_EXTSEL_SWSTART | ADC_CR2_EXTTRIG; /* SW is considered as external trigger */
#endif
# ifdef ADC_HAVE_DMA
if (priv->hasdma)
/* Set CR2 configuration */
adc_modifyreg(priv, STM32_ADC_CR2_OFFSET, clrbits, setbits);
}
#endif
/****************************************************************************
* Name: adc_voltreg_cfg
****************************************************************************/
#if defined(HAVE_IP_ADC_V2)
static void adc_voltreg_cfg(FAR struct stm32_dev_s *priv)
{
/* Set ADC voltage regulator to intermediate state */
adc_modifyreg(priv, STM32_ADC_CR_OFFSET, ADC_CR_ADVREGEN_MASK,
ADC_CR_ADVREGEN_INTER);
/* Enable the ADC voltage regulator */
adc_modifyreg(priv, STM32_ADC_CR_OFFSET, ADC_CR_ADVREGEN_MASK,
ADC_CR_ADVREGEN_ENABLED);
/* Wait for the ADC voltage regulator to startup */
up_udelay(10);
}
#else
static void adc_voltreg_cfg(FAR struct stm32_dev_s *priv)
{
/* Nothing to do here */
UNUSED(priv);
}
#endif
/****************************************************************************
* Name: adc_voltreg_cfg
****************************************************************************/
static void adc_sampletime_cfg(FAR struct adc_dev_s *dev)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
/* Initialize the same sample time for each ADC.
* During sample cycles channel selection bits must remain unchanged.
*/
#ifdef CONFIG_STM32_ADC_CHANGE_SAMPLETIME
adc_sampletime_write((FAR struct stm32_adc_dev_s *)dev);
#else
adc_putreg(priv, STM32_ADC_SMPR1_OFFSET, ADC_SMPR1_DEFAULT);
adc_putreg(priv, STM32_ADC_SMPR2_OFFSET, ADC_SMPR2_DEFAULT);
# ifdef STM32_ADC_SMPR3_OFFSET
adc_putreg(priv, STM32_ADC_SMPR3_OFFSET, ADC_SMPR3_DEFAULT);
# endif
# ifdef STM32_ADC_SMPR0_OFFSET
adc_putreg(priv, STM32_ADC_SMPR0_OFFSET, ADC_SMPR0_DEFAULT);
# endif
#endif
}
/****************************************************************************
* Name: adc_common_cfg
****************************************************************************/
#if defined(HAVE_IP_ADC_V2)
static void adc_common_cfg(FAR struct stm32_dev_s *priv)
{
uint32_t clrbits = 0;
uint32_t setbits = 0;
/* REVISIT: */
clrbits = ADC_CCR_DUAL_MASK | ADC_CCR_DELAY_MASK | ADC_CCR_DMACFG |
ADC_CCR_MDMA_MASK | ADC_CCR_CKMODE_MASK | ADC_CCR_VREFEN |
ADC_CCR_TSEN | ADC_CCR_VBATEN;
setbits = ADC_CCR_DUAL_IND | ADC_CCR_DELAY(0) | ADC_CCR_MDMA_DISABLED |
ADC_CCR_CKMODE_ASYNCH;
adccmn_modifyreg(priv, STM32_ADC_CCR_OFFSET, clrbits, setbits);
}
#elif defined(HAVE_IP_ADC_V1) && !defined(HAVE_BASIC_ADC)
static void adc_common_cfg(FAR struct stm32_dev_s *priv)
{
uint32_t clrbits = 0;
uint32_t setbits = 0;
clrbits = ADC_CCR_ADCPRE_MASK | ADC_CCR_TSVREFE;
setbits = ADC_CCR_ADCPRE_DIV2;
/* REVISIT: */
#if !defined(CONFIG_STM32_STM32L15XX)
clrbits |= ADC_CCR_MULTI_MASK | ADC_CCR_DELAY_MASK | ADC_CCR_DDS |
ADC_CCR_DMA_MASK | ADC_CCR_VBATEN;
setbits |= ADC_CCR_MULTI_NONE | ADC_CCR_DMA_DISABLED;
#endif /* !defined(CONFIG_STM32_STM32L15XX) */
adccmn_modifyreg(priv, STM32_ADC_CCR_OFFSET, clrbits, setbits);
}
#else
static void adc_common_cfg(FAR struct stm32_dev_s *priv)
{
/* Do nothing here */
UNUSED(priv);
}
#endif
#ifdef ADC_HAVE_DMA
/****************************************************************************
* Name: adc_dma_cfg
****************************************************************************/
#ifdef HAVE_IP_ADC_V2
static void adc_dma_cfg(FAR struct stm32_dev_s *priv)
{
uint32_t clrbits = 0;
uint32_t setbits = 0;
/* Set DMA mode */
if (priv->dmacfg == 0)
{
/* One Shot Mode */
clrbits |= ADC_CFGR1_DMACFG;
}
else
{
/* Circular Mode */
setbits |= ADC_CFGR1_DMACFG;
}
/* Enable DMA */
setbits |= ADC_CFGR1_DMAEN;
/* Modify CFGR configuration */
adc_modifyreg(priv, STM32_ADC_CFGR1_OFFSET, clrbits, setbits);
}
#else
static void adc_dma_cfg(FAR struct stm32_dev_s *priv)
{
uint32_t clrbits = 0;
uint32_t setbits = 0;
#ifdef ADC_HAVE_DMACFG
/* Set DMA mode */
@ -2589,63 +2655,21 @@ static void adc_reset(FAR struct adc_dev_s *dev)
/* Enable DMA */
setbits |= ADC_CR2_DMA;
}
# endif
/* Set CR2 configuration */
/* Modify CR2 configuration */
adc_modifyreg(priv, STM32_ADC_CR2_OFFSET, clrbits, setbits);
#endif
/* Configuration of the channel conversions */
if (priv->cr_channels > 0)
{
adc_set_ch(dev, 0);
}
#ifdef ADC_HAVE_INJECTED
/* Configuration of the injected channel conversions after adc enabled */
if (priv->cj_channels > 0)
{
adc_inj_set_ch(dev, 0);
}
#endif
/* ADC CCR configuration
* REVISIT: simplify this
*/
/****************************************************************************
* Name: adc_dma_start
****************************************************************************/
#if defined(HAVE_IP_ADC_V2)
clrbits = ADC_CCR_DUAL_MASK | ADC_CCR_DELAY_MASK | ADC_CCR_DMACFG |
ADC_CCR_MDMA_MASK | ADC_CCR_CKMODE_MASK | ADC_CCR_VREFEN |
ADC_CCR_TSEN | ADC_CCR_VBATEN;
setbits = ADC_CCR_DUAL_IND | ADC_CCR_DELAY(0) | ADC_CCR_MDMA_DISABLED |
ADC_CCR_CKMODE_ASYNCH;
adccmn_modifyreg(priv, STM32_ADC_CCR_OFFSET, clrbits, setbits);
#elif defined(HAVE_IP_ADC_V1) && !defined(HAVE_BASIC_ADC)
clrbits = ADC_CCR_ADCPRE_MASK | ADC_CCR_TSVREFE;
setbits = ADC_CCR_ADCPRE_DIV2;
# if !defined(CONFIG_STM32_STM32L15XX)
clrbits |= ADC_CCR_MULTI_MASK | ADC_CCR_DELAY_MASK | ADC_CCR_DDS |
ADC_CCR_DMA_MASK | ADC_CCR_VBATEN;
setbits |= ADC_CCR_MULTI_NONE | ADC_CCR_DMA_DISABLED;
# endif /* !defined(CONFIG_STM32_STM32L15XX) */
adccmn_modifyreg(priv, STM32_ADC_CCR_OFFSET, clrbits, setbits);
#endif
#ifdef ADC_HAVE_DMA
/* Enable DMA */
if (priv->hasdma)
static void adc_dma_start(FAR struct adc_dev_s *dev)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
/* Stop and free DMA if it was started before */
if (priv->dma != NULL)
@ -2666,7 +2690,123 @@ static void adc_reset(FAR struct adc_dev_s *dev)
stm32_dmastart(priv->dma, adc_dmaconvcallback, dev, false);
#endif
}
#endif /* ADC_HAVE_DMA */
/****************************************************************************
* Name: adc_reset
*
* Description:
* Reset the ADC device. Called early to initialize the hardware.
* This is called, before adc_setup() and on error conditions.
*
* TODO: Separate the configuration logic from the reset logic!
* REVISIT: The ADC device should be configured in adc_setup not in adc_reset.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
static void adc_reset(FAR struct adc_dev_s *dev)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
irqstate_t flags;
#ifdef ADC_HAVE_TIMER
int ret;
#endif
ainfo("intf: %d\n", priv->intf);
flags = enter_critical_section();
#ifdef HAVE_HSI_CONTROL
/* The STM32L15XX family uses HSI as an independent clock-source
* for the ADC
*/
adc_enable_hsi(true);
#endif
#if defined(HAVE_IP_ADC_V2)
/* Turn off the ADC so we can write the RCC bits */
adc_enable(priv, false);
#endif
/* Only if this is the first initialzied ADC instance in the ADC block */
#ifdef HAVE_ADC_CMN_DATA
adccmn_lock(priv, true);
if (priv->cmn->initialized == 0)
#endif
{
/* Enable ADC reset state */
adc_rccreset(priv, true);
/* Release ADC from reset state */
adc_rccreset(priv, false);
}
#ifdef HAVE_ADC_CMN_DATA
adccmn_lock(priv, false);
#endif
/* Configure voltage regulator if present */
adc_voltreg_cfg(priv);
/* Calibrate ADC - doesnt work for now */
adc_calibrate(priv);
/* Initialize the ADC watchdog */
adc_watchdog_cfg(priv);
/* Initialize the ADC sample time */
adc_sampletime_cfg(dev);
/* Set ADC working mode */
adc_mode_cfg(priv);
/* Configuration of the channel conversions */
if (priv->cr_channels > 0)
{
adc_set_ch(dev, 0);
}
#ifdef ADC_HAVE_INJECTED
/* Configuration of the injected channel conversions after adc enabled */
if (priv->cj_channels > 0)
{
adc_inj_set_ch(dev, 0);
}
#endif
/* ADC common register configuration */
adc_common_cfg(priv);
#ifdef ADC_HAVE_DMA
/* Configure ADC DMA if enabled */
if (priv->hasdma)
{
/* Configure ADC DMA */
adc_dma_cfg(priv);
/* Start ADC DMA */
adc_dma_start(dev);
}
#endif
#ifdef HAVE_ADC_RESOLUTION
@ -2675,12 +2815,6 @@ static void adc_reset(FAR struct adc_dev_s *dev)
(void)adc_resolution_set(dev, priv->resolution);
#endif
/* Enable ADC */
adc_enable(priv, true);
/* REVISIT: events configuration should be before adc_enable ?? */
#ifdef ADC_HAVE_EXTCFG
/* Configure external event for regular group */
@ -2693,6 +2827,10 @@ static void adc_reset(FAR struct adc_dev_s *dev)
adc_jextcfg_set(dev, priv->jextcfg);
#endif
/* Enable ADC */
adc_enable(priv, true);
#ifdef ADC_HAVE_TIMER
if (priv->tbase != 0)
{