mirror of
https://github.com/apache/nuttx.git
synced 2026-06-02 17:48:54 +08:00
stm32h7_adc: Dynamically set clock prescaler and BOOST setting.
The ADC peripheral can only support up to
50MHz on rev V silicon and 36MHz on Y silicon.
The existing driver always used no prescaler
and kept boost setting at 0.
This commit is contained in:
committed by
Xiang Xiao
parent
d31214aa25
commit
962ac35170
@@ -243,18 +243,20 @@
|
|||||||
#define ADC_CR_ADSTP (1 << 4) /* Bit 4: ADC stop of regular conversion command */
|
#define ADC_CR_ADSTP (1 << 4) /* Bit 4: ADC stop of regular conversion command */
|
||||||
#define ADC_CR_JADSTP (1 << 5) /* Bit 5: ADC stop of injected conversion command */
|
#define ADC_CR_JADSTP (1 << 5) /* Bit 5: ADC stop of injected conversion command */
|
||||||
/* Bits 6-7: Reserved */
|
/* Bits 6-7: Reserved */
|
||||||
#if defined(ADC_DEVICE_VERSION_V)
|
|
||||||
# define ADC_CR_BOOST_SHIFT (8) /* Bits 8-9: ADC Boost mode control */
|
/* On rev V silicon, the BOOST setting is 2 bits. On Y silicon it's a
|
||||||
# define ADC_CR_BOOST_MASK (3 << ADC_CR_BOOST_SHIFT)
|
* single bit.
|
||||||
# define ADC_CR_BOOST_6p25_MHZ (0 << ADC_CR_BOOST_SHIFT)
|
*/
|
||||||
# define ADC_CR_BOOST_12p5_MHZ (1 << ADC_CR_BOOST_SHIFT)
|
|
||||||
# define ADC_CR_BOOST_25_MHZ (2 << ADC_CR_BOOST_SHIFT)
|
#define ADC_CR_BOOST_SHIFT (8) /* Bits 8-9: ADC Boost mode control */
|
||||||
# define ADC_CR_BOOST_50_MHZ (3 << ADC_CR_BOOST_SHIFT)
|
#define ADC_CR_BOOST_MASK (3 << ADC_CR_BOOST_SHIFT)
|
||||||
/* Bits 10-15: Reserved */
|
# define ADC_CR_BOOST_6p25_MHZ (0 << ADC_CR_BOOST_SHIFT)
|
||||||
#else
|
# define ADC_CR_BOOST_12p5_MHZ (1 << ADC_CR_BOOST_SHIFT)
|
||||||
# define ADC_CR_BOOST (1 << 8) /* Bit 8: ADC Boost mode control */
|
# define ADC_CR_BOOST_25_MHZ (2 << ADC_CR_BOOST_SHIFT)
|
||||||
/* Bits 9-15: Reserved */
|
# define ADC_CR_BOOST_50_MHZ (3 << ADC_CR_BOOST_SHIFT)
|
||||||
#endif
|
#define ADC_CR_BOOST (1 << 8) /* Bit 8: ADC Boost mode control */
|
||||||
|
/* Bits 10-15: Reserved */
|
||||||
|
|
||||||
#define ADC_CR_ADCALLIN (1 << 16) /* Bit 16: ADC Linearity calibration */
|
#define ADC_CR_ADCALLIN (1 << 16) /* Bit 16: ADC Linearity calibration */
|
||||||
/* Bits 17-21: Reserved */
|
/* Bits 17-21: Reserved */
|
||||||
#define ADC_CR_LINCALRDYW1 (1 << 22) /* Bit 22: ADC Linearity calibration ready Word 1 */
|
#define ADC_CR_LINCALRDYW1 (1 << 22) /* Bit 22: ADC Linearity calibration ready Word 1 */
|
||||||
|
|||||||
@@ -67,6 +67,7 @@
|
|||||||
#include "stm32_tim.h"
|
#include "stm32_tim.h"
|
||||||
#include "stm32_dma.h"
|
#include "stm32_dma.h"
|
||||||
#include "stm32_adc.h"
|
#include "stm32_adc.h"
|
||||||
|
#include "stm32_dbgmcu.h"
|
||||||
|
|
||||||
/* ADC "upper half" support must be enabled */
|
/* ADC "upper half" support must be enabled */
|
||||||
|
|
||||||
@@ -228,6 +229,7 @@ static void tim_dumpregs(struct stm32_dev_s *priv,
|
|||||||
/* ADC Miscellaneous Helpers */
|
/* ADC Miscellaneous Helpers */
|
||||||
|
|
||||||
static void adc_rccreset(struct stm32_dev_s *priv, bool reset);
|
static void adc_rccreset(struct stm32_dev_s *priv, bool reset);
|
||||||
|
static void adc_setupclock(struct stm32_dev_s *priv);
|
||||||
static void adc_enable(struct stm32_dev_s *priv);
|
static void adc_enable(struct stm32_dev_s *priv);
|
||||||
static uint32_t adc_sqrbits(struct stm32_dev_s *priv, int first,
|
static uint32_t adc_sqrbits(struct stm32_dev_s *priv, int first,
|
||||||
int last, int offset);
|
int last, int offset);
|
||||||
@@ -1413,12 +1415,14 @@ static int adc_setup(struct adc_dev_s *dev)
|
|||||||
|
|
||||||
clrbits = ADC_CCR_PRESC_MASK | ADC_CCR_VREFEN |
|
clrbits = ADC_CCR_PRESC_MASK | ADC_CCR_VREFEN |
|
||||||
ADC_CCR_VSENSEEN | ADC_CCR_VBATEN;
|
ADC_CCR_VSENSEEN | ADC_CCR_VBATEN;
|
||||||
setbits = ADC_CCR_PRESC_NOT_DIV | ADC_CCR_CKMODE_ASYCH;
|
setbits = ADC_CCR_CKMODE_ASYCH;
|
||||||
|
|
||||||
adc_internal(priv, &setbits);
|
adc_internal(priv, &setbits);
|
||||||
|
|
||||||
adc_modifyregm(priv, STM32_ADC_CCR_OFFSET, clrbits, setbits);
|
adc_modifyregm(priv, STM32_ADC_CCR_OFFSET, clrbits, setbits);
|
||||||
|
|
||||||
|
adc_setupclock(priv);
|
||||||
|
|
||||||
#ifdef ADC_HAVE_DMA
|
#ifdef ADC_HAVE_DMA
|
||||||
|
|
||||||
/* Enable DMA */
|
/* Enable DMA */
|
||||||
@@ -1571,6 +1575,147 @@ static void adc_rxint(struct adc_dev_s *dev, bool enable)
|
|||||||
adc_putreg(priv, STM32_ADC_IER_OFFSET, regval);
|
adc_putreg(priv, STM32_ADC_IER_OFFSET, regval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: adc_setupclock
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void adc_setupclock(struct stm32_dev_s *priv)
|
||||||
|
{
|
||||||
|
uint32_t max_clock = 36000000;
|
||||||
|
uint32_t src_clock;
|
||||||
|
uint32_t adc_clock;
|
||||||
|
uint32_t setbits;
|
||||||
|
|
||||||
|
/* The maximum clock is different for rev Y devices and rev V devices.
|
||||||
|
* rev V can support an ADC clock of up to 50MHz. rev Y only supports
|
||||||
|
* up to 36MHz.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((getreg32(STM32_DEBUGMCU_BASE) & DBGMCU_IDCODE_REVID_MASK) ==
|
||||||
|
STM32_IDCODE_REVID_V)
|
||||||
|
{
|
||||||
|
/* The max fadc is 50MHz, but there is an always-present /2 divider
|
||||||
|
* after the configurable prescaler. Therefore, the max clock out of
|
||||||
|
* the prescaler block is 2*50=100MHz
|
||||||
|
*/
|
||||||
|
|
||||||
|
max_clock = 100000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if STM32_RCC_D3CCIPR_ADCSRC == RCC_D3CCIPR_ADCSEL_PLL2
|
||||||
|
src_clock = STM32_PLL2P_FREQUENCY;
|
||||||
|
#elif STM32_RCC_D3CCIPR_ADCSRC == RCC_D3CCIPR_ADCSEL_PLL3
|
||||||
|
src_clock = STM32_PLL3R_FREQUENCY;
|
||||||
|
#elif STM32_RCC_D3CCIPR_ADCSRC == RCC_D3CCIPR_ADCSEL_PER
|
||||||
|
# error ADCSEL_PER not supported
|
||||||
|
#else
|
||||||
|
src_clock = STM32_PLL2P_FREQUENCY;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (src_clock <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_NOT_DIV;
|
||||||
|
adc_clock = src_clock;
|
||||||
|
}
|
||||||
|
else if (src_clock / 2 <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_DIV2;
|
||||||
|
adc_clock = src_clock / 2;
|
||||||
|
}
|
||||||
|
else if (src_clock / 4 <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_DIV4;
|
||||||
|
adc_clock = src_clock / 4;
|
||||||
|
}
|
||||||
|
else if (src_clock / 6 <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_DIV6;
|
||||||
|
adc_clock = src_clock / 6;
|
||||||
|
}
|
||||||
|
else if (src_clock / 8 <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_DIV8;
|
||||||
|
adc_clock = src_clock / 8;
|
||||||
|
}
|
||||||
|
else if (src_clock / 10 <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_DIV10;
|
||||||
|
adc_clock = src_clock / 10;
|
||||||
|
}
|
||||||
|
else if (src_clock / 12 <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_DIV12;
|
||||||
|
adc_clock = src_clock / 12;
|
||||||
|
}
|
||||||
|
else if (src_clock / 16 <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_DIV16;
|
||||||
|
adc_clock = src_clock / 16;
|
||||||
|
}
|
||||||
|
else if (src_clock / 32 <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_DIV32;
|
||||||
|
adc_clock = src_clock / 32;
|
||||||
|
}
|
||||||
|
else if (src_clock / 64 <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_DIV64;
|
||||||
|
adc_clock = src_clock / 64;
|
||||||
|
}
|
||||||
|
else if (src_clock / 128 <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_DIV128;
|
||||||
|
adc_clock = src_clock / 128;
|
||||||
|
}
|
||||||
|
else if (src_clock / 256 <= max_clock)
|
||||||
|
{
|
||||||
|
setbits = ADC_CCR_PRESC_DIV256;
|
||||||
|
adc_clock = src_clock / 256;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
aerr("ERROR: source clock too high\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write the prescaler to the CCR register */
|
||||||
|
|
||||||
|
adc_modifyregm(priv, STM32_ADC_CCR_OFFSET, ADC_CCR_PRESC_MASK, setbits);
|
||||||
|
|
||||||
|
if ((getreg32(STM32_DEBUGMCU_BASE) & DBGMCU_IDCODE_REVID_MASK) ==
|
||||||
|
STM32_IDCODE_REVID_V)
|
||||||
|
{
|
||||||
|
if (adc_clock >= 25000000)
|
||||||
|
{
|
||||||
|
setbits = ADC_CR_BOOST_50_MHZ;
|
||||||
|
}
|
||||||
|
else if (adc_clock >= 12500000)
|
||||||
|
{
|
||||||
|
setbits = ADC_CR_BOOST_25_MHZ;
|
||||||
|
}
|
||||||
|
else if (adc_clock >= 6250000)
|
||||||
|
{
|
||||||
|
setbits = ADC_CR_BOOST_12p5_MHZ;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setbits = ADC_CR_BOOST_6p25_MHZ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (adc_clock >= 20000000)
|
||||||
|
{
|
||||||
|
setbits = ADC_CR_BOOST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setbits = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_modifyregm(priv, STM32_ADC_CR_OFFSET, ADC_CR_BOOST_MASK, setbits);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: adc_sqrbits
|
* Name: adc_sqrbits
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|||||||
Reference in New Issue
Block a user