Merged in raiden00/nuttx (pull request #607)

stm32f33xxx_adc.c: fix bug in RCC reset logic that resets ADC1 configuration when both ADC1 and ADC2 are in use

Approved-by: Gregory Nutt <gnutt@nuttx.org>
This commit is contained in:
Mateusz Szafoni
2018-03-02 20:00:52 +00:00
committed by Gregory Nutt
parent bff4e8e5b0
commit 160931ba72
+65 -22
View File
@@ -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;
}