STM32F37x SDADC driver working.

git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5519 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
gdisirio 2013-03-30 09:12:52 +00:00
parent 042c2ddba8
commit 320f18b7af
3 changed files with 100 additions and 85 deletions

View File

@ -77,12 +77,70 @@ ADCDriver SDADCD3;
/* Driver local variables and types. */ /* 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. */ /* 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. * @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. * @brief ADC ISR service routine.
* *
* @param[in] adcp pointer to the @p ADCDriver object * @param[in] adcp pointer to the @p ADCDriver object
* @param[in] sr content of the ISR register * @param[in] sr content of the ISR register
*
* @notapi
*/ */
static void adc_lld_serve_interrupt(ADCDriver *adcp, uint32_t sr) { 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 */ #endif /* STM32_ADC_USE_ADC */
#if STM32_ADC_USE_SDADC #if STM32_ADC_USE_SDADC || defined(__DOXYGEN__)
/** /**
* @brief ADC ISR service routine. * @brief ADC ISR service routine.
* *
* @param[in] adcp pointer to the @p ADCDriver object * @param[in] adcp pointer to the @p ADCDriver object
* @param[in] isr content of the ISR register * @param[in] isr content of the ISR register
*
* @notapi
*/ */
static void sdadc_lld_serve_interrupt(ADCDriver *adcp, uint32_t isr) { 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"); chDbgAssert(!b, "adc_lld_start(), #1", "stream already allocated");
dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR); dmaStreamSetPeripheral(adcp->dmastp, &ADC1->DR);
rccEnableADC1(FALSE); 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 */ #endif /* STM32_ADC_USE_ADC1 */
@ -406,6 +462,8 @@ void adc_lld_start(ADCDriver *adcp) {
} }
#endif /* STM32_ADC_USE_SDADC3 */ #endif /* STM32_ADC_USE_SDADC3 */
} }
adc_lld_reconfig(adcp);
} }
/** /**
@ -531,9 +589,6 @@ void adc_lld_start_conversion(ADCDriver *adcp) {
/* SDADC setup.*/ /* SDADC setup.*/
adcp->sdadc->JCHGR = grpp->u.sdadc.jchgr; 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->CONFCHR1 = grpp->u.sdadc.confchr[0];
adcp->sdadc->CONFCHR2 = grpp->u.sdadc.confchr[1]; adcp->sdadc->CONFCHR2 = grpp->u.sdadc.confchr[1];
@ -564,32 +619,9 @@ void adc_lld_stop_conversion(ADCDriver *adcp) {
/* Disabling the associated DMA stream.*/ /* Disabling the associated DMA stream.*/
dmaStreamDisable(adcp->dmastp); dmaStreamDisable(adcp->dmastp);
#if STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC /* Stopping and restarting the whole ADC, apparently the only way to stop
if (adcp->adc != NULL) a conversion.*/
#endif /* STM32_ADC_USE_ADC && STM32_ADC_USE_SDADC */ adc_lld_reconfig(adcp);
#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 */
} }
/** /**

View File

@ -468,10 +468,6 @@ typedef struct {
* @brief SDADC JCHGR register initialization data. * @brief SDADC JCHGR register initialization data.
*/ */
uint32_t jchgr; uint32_t jchgr;
/**
* @brief SDADC CONFxR registers initialization data.
*/
uint32_t confxr[3];
/** /**
* @brief SDADC CONFCHxR registers initialization data. * @brief SDADC CONFCHxR registers initialization data.
*/ */
@ -491,6 +487,10 @@ typedef struct {
* @brief SDADC CR1 register initialization data. * @brief SDADC CR1 register initialization data.
*/ */
uint32_t cr1; uint32_t cr1;
/**
* @brief SDADC CONFxR registers initialization data.
*/
uint32_t confxr[3];
#else /* !STM32_ADC_USE_SDADC */ #else /* !STM32_ADC_USE_SDADC */
uint32_t dummy; uint32_t dummy;
#endif /* !STM32_ADC_USE_SDADC */ #endif /* !STM32_ADC_USE_SDADC */
@ -669,18 +669,6 @@ struct ADCDriver {
#define SDADC_CONFR_COMMON_VDDSD (2U << 30) #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. */ /* External declarations. */
/*===========================================================================*/ /*===========================================================================*/

View File

@ -24,8 +24,8 @@
#define ADC_GRP1_NUM_CHANNELS 1 #define ADC_GRP1_NUM_CHANNELS 1
#define ADC_GRP1_BUF_DEPTH 8 #define ADC_GRP1_BUF_DEPTH 8
#define ADC_GRP2_NUM_CHANNELS 8 #define ADC_GRP2_NUM_CHANNELS 1
#define ADC_GRP2_BUF_DEPTH 16 #define ADC_GRP2_BUF_DEPTH 32
static adcsample_t samples1[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH]; static adcsample_t samples1[ADC_GRP1_NUM_CHANNELS * ADC_GRP1_BUF_DEPTH];
static adcsample_t samples2[ADC_GRP2_NUM_CHANNELS * ADC_GRP2_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; (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. * ADC conversion group.
* Mode: Linear buffer, 8 samples of 1 channel, SW triggered. * Mode: Linear buffer, 8 samples of 1 channel, SW triggered.
@ -64,11 +76,6 @@ static const ADCConversionGroup adcgrpcfg1 = {
.u.sdadc = { .u.sdadc = {
SDADC_CR2_JSWSTART, /* CR2 */ SDADC_CR2_JSWSTART, /* CR2 */
SDADC_JCHGR_CH(5), /* JCHGR */ SDADC_JCHGR_CH(5), /* JCHGR */
{ /* CONFxR[3]*/
SDADC_CONFR_GAIN_1X | SDADC_CONFR_SE_DIFF | SDADC_CONFR_COMMON_VSSSD,
0,
0
},
{ /* CONFCHR[2]*/ { /* CONFCHR[2]*/
SDADC_CONFCHR1_CH5(0), SDADC_CONFCHR1_CH5(0),
0 0
@ -76,36 +83,25 @@ static const ADCConversionGroup adcgrpcfg1 = {
} }
}; };
#if 0
/* /*
* ADC conversion group. * ADC conversion group.
* Mode: Continuous, 16 samples of 8 channels, SW triggered. * Mode: Continuous, 32 samples of 1 channel, SW triggered.
* Channels: IN7, IN8, IN7, IN8, IN7, IN8, Sensor, VBat/2. * Channels: ADC_IN5P.
*/ */
static const ADCConversionGroup adcgrpcfg2 = { static const ADCConversionGroup adcgrpcfg2 = {
TRUE, TRUE,
ADC_GRP2_NUM_CHANNELS, ADC_GRP2_NUM_CHANNELS,
adccallback, adccallback,
adcerrorcallback, adcerrorcallback,
0, /* CFGR */ .u.sdadc = {
ADC_TR(0, 4095), /* TR1 */ SDADC_CR2_JSWSTART, /* CR2 */
ADC_CCR_TSEN | ADC_CCR_VBATEN, /* CCR */ SDADC_JCHGR_CH(5), /* JCHGR */
{ /* SMPR[2] */ { /* CONFCHR[2]*/
ADC_SMPR1_SMP_AN7(ADC_SMPR_SMP_19P5) SDADC_CONFCHR1_CH5(0),
| ADC_SMPR1_SMP_AN8(ADC_SMPR_SMP_19P5), 0
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
} }
}; };
#endif
/* /*
* Red LEDs blinker thread, times are in milliseconds. * Red LEDs blinker thread, times are in milliseconds.
@ -147,26 +143,25 @@ int main(void) {
/* /*
* Activates the SDADC1 driver. * Activates the SDADC1 driver.
*/ */
adcStart(&SDADCD1, NULL); adcStart(&SDADCD1, &sdadc_config);
adcSTM32Calibrate(&SDADCD1); adcSTM32Calibrate(&SDADCD1);
/* /*
* Linear conversion. * Linear conversion.
*/ */
adcConvert(&SDADCD1, &adcgrpcfg1, samples1, ADC_GRP1_BUF_DEPTH); adcConvert(&SDADCD1, &adcgrpcfg1, samples1, ADC_GRP1_BUF_DEPTH);
chThdSleepMilliseconds(1000);
/* /*
* Starts an ADC continuous conversion. * 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. * Normal main() thread activity, in this demo it does nothing.
*/ */
while (TRUE) { while (TRUE) {
if (palReadPad(GPIOA, GPIOA_WKUP_BUTTON)) { if (palReadPad(GPIOA, GPIOA_WKUP_BUTTON)) {
// adcStopConversion(&SDADCD1); adcStopConversion(&SDADCD1);
} }
chThdSleepMilliseconds(500); chThdSleepMilliseconds(500);
} }