git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5338 35acf78f-673a-0410-8e92-d51de3d6d3f4

This commit is contained in:
gdisirio 2013-02-28 14:12:58 +00:00
parent d8914f064f
commit 03ef7de020
3 changed files with 308 additions and 17 deletions

View File

@ -45,7 +45,13 @@
/*
* ADC driver settings.
*/
#define SPC5_ADC_USE_EQADC_Q0 TRUE
#define SPC5_ADC_USE_ADC0_Q0 TRUE
#define SPC5_ADC_USE_ADC0_Q1 FALSE
#define SPC5_ADC_USE_ADC0_Q2 FALSE
#define SPC5_ADC_USE_ADC1_Q3 TRUE
#define SPC5_ADC_USE_ADC1_Q4 FALSE
#define SPC5_ADC_USE_ADC1_Q5 FALSE
#define SPC5_ADC_CR_CLK_PS ADC_CR_CLK_PS(5)
/*
* SERIAL driver system settings.

View File

@ -29,6 +29,12 @@
/* Driver local definitions. */
/*===========================================================================*/
/**
* @brief Calibration constant.
* @details Ideal conversion result for 75%(VRH - VRL) minus 2.
*/
#define ADC_IDEAL_RES75_2 12286
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
@ -36,16 +42,51 @@
/**
* @brief ADCD1 driver identifier.
*/
#if SPC5_ADC_USE_EQADC_Q0 || defined(__DOXYGEN__)
#if SPC5_ADC_USE_ADC0_Q0 || defined(__DOXYGEN__)
ADCDriver ADCD1;
#endif
/**
* @brief ADCD2 driver identifier.
*/
#if SPC5_ADC_USE_ADC0_Q1 || defined(__DOXYGEN__)
ADCDriver ADCD2;
#endif
/**
* @brief ADCD3 driver identifier.
*/
#if SPC5_ADC_USE_ADC0_Q2 || defined(__DOXYGEN__)
ADCDriver ADCD3;
#endif
/**
* @brief ADCD4 driver identifier.
*/
#if SPC5_ADC_USE_ADC1_Q3 || defined(__DOXYGEN__)
ADCDriver ADCD4;
#endif
/**
* @brief ADCD5 driver identifier.
*/
#if SPC5_ADC_USE_ADC1_Q4 || defined(__DOXYGEN__)
ADCDriver ADCD5;
#endif
/**
* @brief ADCD6 driver identifier.
*/
#if SPC5_ADC_USE_ADC1_Q5 || defined(__DOXYGEN__)
ADCDriver ADCD6;
#endif
/*===========================================================================*/
/* Driver local variables. */
/*===========================================================================*/
/*===========================================================================*/
/* Driver local functions. */
/* Driver local functions and macros. */
/*===========================================================================*/
/**
@ -121,6 +162,93 @@ static void cfifo0_wait_rfifo(uint32_t n) {
EQADC.FISR[0].R = EQADC_FISR_CLEAR_MASK;
}
/**
* @brief Reads a sample from the RFIFO0.
*
* @notapi
*/
#define rfifo0_get_value() (EQADC.RFPR[0].R)
/**
* @brief Writes an internal ADC register.
*
* @param[in] adc the ADC unit
* @param[in] reg the register index
* @param[in] value value to be written into the register
*
* @notapi
*/
#define adc_write_register(adc, reg, value) \
cfifo0_push_command(EQADC_RW_WRITE | (adc) | EQADC_RW_REG_ADDR(reg) | \
EQADC_RW_VALUE(value))
/**
* @brief Enables both ADCs.
*
* @notapi
*/
static void adc_enable(void) {
/* Both ADCs must be enabled because this sentence in the reference manual:
"Both ADC0 and ADC1 of an eQADC module pair must be enabled before
calibrating or using either ADC0 or ADC1 of the pair. Failure to
enable both ADC0 and ADC1 of the pair can result in inaccurate
conversions.".*/
adc_write_register(EQADC_RW_BN_ADC0, ADC_REG_CR,
SPC5_ADC_CR_CLK_PS | ADC_CR_EN);
adc_write_register(EQADC_RW_BN_ADC1, ADC_REG_CR,
SPC5_ADC_CR_CLK_PS | ADC_CR_EN);
}
/**
* @brief Disables both ADCs.
*
* @notapi
*/
static void adc_disable(void) {
adc_write_register(EQADC_RW_BN_ADC0, ADC_REG_CR,
SPC5_ADC_CR_CLK_PS);
adc_write_register(EQADC_RW_BN_ADC1, ADC_REG_CR,
SPC5_ADC_CR_CLK_PS);
}
/**
* @brief Calibrates both ADCs.
*
* @notapi
*/
static void adc_calibrate(uint32_t adc) {
uint16_t res25, res75;
uint32_t gcc, occ;
/* Starts the calibration, write command messages to sample 25% and
75% VREF.*/
cfifo0_push_command(0x00002C00 | adc); /* Vref 25%.*/
cfifo0_push_command(0x00002B00 | adc); /* Vref 75%.*/
cfifo0_wait_rfifo(2);
/* Reads the results and compute calibration register values.*/
res25 = rfifo0_get_value();
res75 = rfifo0_get_value();
gcc = 0x08000000UL / ((uint32_t)res75 - (uint32_t)res25);
occ = (uint32_t)ADC_IDEAL_RES75_2 - ((gcc * (uint32_t)res75) >> 14);
/* Loads the gain and offset values (default configuration, 12 bits).*/
adc_write_register(adc, ADC_REG_GCCR, gcc);
adc_write_register(adc, ADC_REG_OCCR, occ & 0xFFFF);
/* Loads gain and offset values (alternate configuration 1, 10 bits).*/
adc_write_register(adc, ADC_REG_AC1GCCR, gcc);
adc_write_register(adc, ADC_REG_AC1OCCR, occ & 0xFFFF);
/* Loads gain and offset values (alternate configuration 1, 8 bits).*/
adc_write_register(adc, ADC_REG_AC2GCCR, gcc);
adc_write_register(adc, ADC_REG_AC2OCCR, occ & 0xFFFF);
}
/*===========================================================================*/
/* Driver interrupt handlers. */
/*===========================================================================*/
@ -140,6 +268,27 @@ void adc_lld_init(void) {
/* Driver initialization.*/
adcObjectInit(&ADCD1);
#endif /* SPC5_ADC_USE_EQADC_Q0 */
/* Temporarily enables CFIFO0 for calibration and initialization.*/
cfifo_enable(ADC_FIFO_0, EQADC_CFCR_SSE | EQADC_CFCR_MODE_SWCS, 0);
adc_enable();
/* Calibration of both ADC units then programming alternate configs
one and two for 10 and 8 bits operations.*/
#if SPC5_ADC_USE_ADC0
adc_calibrate(EQADC_RW_BN_ADC0);
adc_write_register(EQADC_RW_BN_ADC0, ADC_REG_AC1CR, ADC_ACR_RESSEL_10BITS);
adc_write_register(EQADC_RW_BN_ADC0, ADC_REG_AC2CR, ADC_ACR_RESSEL_8BITS);
#endif
#if SPC5_ADC_USE_ADC1
adc_calibrate(EQADC_RW_BN_ADC1);
adc_write_register(EQADC_RW_BN_ADC1, ADC_REG_AC1CR, ADC_ACR_RESSEL_10BITS);
adc_write_register(EQADC_RW_BN_ADC1, ADC_REG_AC2CR, ADC_ACR_RESSEL_8BITS);
#endif
/* ADCs disabled until the driver is started by the application.*/
adc_disable();
cfifo_disable(ADC_FIFO_0);
}
/**
@ -153,7 +302,7 @@ void adc_lld_start(ADCDriver *adcp) {
if (adcp->state == ADC_STOP) {
/* Enables the peripheral.*/
#if SPC5_ADC_USE_EQADC_Q0
#if SPC5_ADC_USE_ADC0
if (&ADCD1 == adcp) {
}
@ -176,7 +325,7 @@ void adc_lld_stop(ADCDriver *adcp) {
/* Resets the peripheral.*/
/* Disables the peripheral.*/
#if SPC5_ADC_USE_EQADC_Q0
#if SPC5_ADC_USE_ADC0
if (&ADCD1 == adcp) {
}

View File

@ -78,7 +78,7 @@
#define EQADC_CFCR_MODE_HWSS_FE EQADC_CFCR_MODE(4)
#define EQADC_CFCR_MODE_HWSS_RE EQADC_CFCR_MODE(5)
#define EQADC_CFCR_MODE_HWSS_BE EQADC_CFCR_MODE(6)
#define EQADC_CFCR_MODE_MODE_SWCS EQADC_CFCR_MODE(9)
#define EQADC_CFCR_MODE_SWCS EQADC_CFCR_MODE(9)
#define EQADC_CFCR_MODE_HWCS_LL EQADC_CFCR_MODE(10)
#define EQADC_CFCR_MODE_HWCS_HL EQADC_CFCR_MODE(11)
#define EQADC_CFCR_MODE_HWCS_FE EQADC_CFCR_MODE(12)
@ -112,10 +112,18 @@
/** @} */
/**
* @name EQADC Conversion commands
* @name EQADC conversion/configuration commands
* @{
*/
#define EQADC_CONV_CHANNEL_MASK (0xFFU << 8)/**< @brief Channel number mask.*/
#define EQADC_CONV_CONFIG_SEL1 (8U << 0) /**< @brief Alt.config.1. */
#define EQADC_CONV_CONFIG_SEL2 (9U << 0) /**< @brief Alt.config.2. */
#define EQADC_CONV_CONFIG_SEL3 (10U << 0) /**< @brief Alt.config.3. */
#define EQADC_CONV_CONFIG_SEL4 (11U << 0) /**< @brief Alt.config.4. */
#define EQADC_CONV_CONFIG_SEL5 (12U << 0) /**< @brief Alt.config.5. */
#define EQADC_CONV_CONFIG_SEL6 (13U << 0) /**< @brief Alt.config.6. */
#define EQADC_CONV_CONFIG_SEL7 (14U << 0) /**< @brief Alt.config.7. */
#define EQADC_CONV_CONFIG_SEL8 (15U << 0) /**< @brief Alt.config.8. */
#define EQADC_CONV_CHANNEL_MASK (255U << 8) /**< @brief Channel number mask.*/
#define EQADC_CONV_CHANNEL(n) ((n) << 8) /**< @brief Channel number. */
#define EQADC_CONV_FMT_RJU (0U << 16) /**< @brief Unsigned samples. */
#define EQADC_CONV_FMT_RJS (1U << 16) /**< @brief Signed samples. */
@ -130,12 +138,60 @@
#define EQADC_CONV_MSG_NULL (6U << 20) /**< @brief Null message. */
#define EQADC_CONV_CAL (1U << 24) /**< @brief Calibrated result. */
#define EQADC_CONV_BN_MASK (1U << 25) /**< @brief Buffer number mask. */
#define EQADC_CONV_BN(n) ((n) << 25) /**< @brief Buffer number. */
#define EQADC_CONV_BN_ADC0 (0U << 25) /**< @brief ADC0 selection. */
#define EQADC_CONV_BN_ADC1 (1U << 25) /**< @brief ADC1 selection. */
#define EQADC_CONV_REP (1U << 29) /**< @brief Repeat loop flag. */
#define EQADC_CONV_PAUSE (1U << 30) /**< @brief Pause flag. */
#define EQADC_CONV_EOQ (1U << 31) /**< @brief End of queue flag. */
/** @} */
/**
* @name EQADC read/write commands
* @{
*/
#define EQADC_RW_REG_ADDR_MASK (255U << 0)
#define EQADC_RW_REG_ADDR(n) ((n) << 0)
#define EQADC_RW_VALUE_MASK (0xFFFF << 8)
#define EQADC_RW_VALUE(n) ((n) << 8)
#define EQADC_RW_WRITE (0U << 24)
#define EQADC_RW_READ (1U << 24)
#define EQADC_RW_BN_ADC0 (0U << 25)
#define EQADC_RW_BN_ADC1 (1U << 25)
#define EQADC_RW_REP (1U << 29)
#define EQADC_RW_PAUSE (1U << 30)
#define EQADC_RW_EOQ (1U << 31)
/** @} */
/**
* @name ADC CR register definitions
* @{
*/
#define ADC_CR_CLK_PS_MASK (31U << 0)
#define ADC_CR_CLK_PS(n) ((((n) >> 1) - 1) | ((n) & 1 ? ADC_CR_ODD_PS\
: 0))
#define ADC_CR_CLK_SEL (1U << 5)
#define ADC_CR_CLK_DTY (1U << 6)
#define ADC_CR_ODD_PS (1U << 7)
#define ADC_CR_TBSEL_MASK (3U << 8)
#define ADC_CR_TBSEL(n) ((n) << 8)
#define ADC_CR_EMUX (1U << 11)
#define ADC_CR_EN (1U << 15)
/** @} */
/**
* @name ADC AxCR registers definitions
* @{
*/
#define ADC_ACR_PRE_GAIN_MASK (3U << 0)
#define ADC_ACR_PRE_GAIN_X1 (0U << 0)
#define ADC_ACR_PRE_GAIN_X2 (1U << 0)
#define ADC_ACR_PRE_GAIN_X4 (2U << 0)
#define ADC_ACR_RESSEL_MASK (3U << 6)
#define ADC_ACR_RESSEL_12BITS (0U << 6)
#define ADC_ACR_RESSEL_10BITS (1U << 6)
#define ADC_ACR_RESSEL_8BITS (2U << 6)
/** @} */
/*===========================================================================*/
/* Driver pre-compile time settings. */
/*===========================================================================*/
@ -145,12 +201,65 @@
* @{
*/
/**
* @brief ADCD10 driver enable switch.
* @details If set to @p TRUE the support for EQADC1 queue 0 is included.
* @brief ADCD1 driver enable switch.
* @details If set to @p TRUE the support for ADC0 queue 0 is included.
* @note The default is @p FALSE.
*/
#if !defined(SPC5_ADC_USE_EQADC_Q0) || defined(__DOXYGEN__)
#define SPC5_ADC_USE_EQADC_Q0 FALSE
#if !defined(SPC5_ADC_USE_ADC0_Q0) || defined(__DOXYGEN__)
#define SPC5_ADC_USE_ADC0_Q0 FALSE
#endif
/**
* @brief ADCD2 driver enable switch.
* @details If set to @p TRUE the support for ADC0 queue 1 is included.
* @note The default is @p FALSE.
*/
#if !defined(SPC5_ADC_USE_ADC0_Q1) || defined(__DOXYGEN__)
#define SPC5_ADC_USE_ADC0_Q1 FALSE
#endif
/**
* @brief ADCD3 driver enable switch.
* @details If set to @p TRUE the support for ADC0 queue 2 is included.
* @note The default is @p FALSE.
*/
#if !defined(SPC5_ADC_USE_ADC0_Q2) || defined(__DOXYGEN__)
#define SPC5_ADC_USE_ADC0_Q2 FALSE
#endif
/**
* @brief ADCD4 driver enable switch.
* @details If set to @p TRUE the support for ADC1 queue 3 is included.
* @note The default is @p FALSE.
*/
#if !defined(SPC5_ADC_USE_ADC1_Q3) || defined(__DOXYGEN__)
#define SPC5_ADC_USE_ADC1_Q3 FALSE
#endif
/**
* @brief ADCD5 driver enable switch.
* @details If set to @p TRUE the support for ADC1 queue 4 is included.
* @note The default is @p FALSE.
*/
#if !defined(SPC5_ADC_USE_ADC1_Q4) || defined(__DOXYGEN__)
#define SPC5_ADC_USE_ADC1_Q4 FALSE
#endif
/**
* @brief ADCD6 driver enable switch.
* @details If set to @p TRUE the support for ADC1 queue 5 is included.
* @note The default is @p FALSE.
*/
#if !defined(SPC5_ADC_USE_ADC1_Q5) || defined(__DOXYGEN__)
#define SPC5_ADC_USE_ADC1_Q5 FALSE
#endif
/**
*
* @brief EQADC clock prescaler value.
*/
#if !defined(SPC5_ADC_CR_CLK_PS) || defined(__DOXYGEN__)
#define SPC5_ADC_CR_CLK_PS ADC_CR_CLK_PS(5)
#endif
/** @} */
@ -158,12 +267,19 @@
/* Derived constants and error checks. */
/*===========================================================================*/
#if SPC5_ADC_USE_EQADC_Q0 && !SPC5_HAS_EQADC
#if !SPC5_HAS_EQADC
#error "EQADC1 not present in the selected device"
#endif
#if !SPC5_ADC_USE_EQADC_Q0
#error "ADC driver activated but no EQADC peripheral assigned"
#define SPC5_ADC_USE_ADC0 (SPC5_ADC_USE_ADC0_Q0 | \
SPC5_ADC_USE_ADC0_Q1 | \
SPC5_ADC_USE_ADC0_Q2)
#define SPC5_ADC_USE_ADC1 (SPC5_ADC_USE_ADC1_Q3 | \
SPC5_ADC_USE_ADC1_Q4 | \
SPC5_ADC_USE_ADC1_Q5)
#if !SPC5_ADC_USE_ADC0 && !SPC5_ADC_USE_ADC1
#error "ADC driver activated but no ADC peripheral assigned"
#endif
/*===========================================================================*/
@ -334,10 +450,30 @@ struct ADCDriver {
/* External declarations. */
/*===========================================================================*/
#if SPC5_ADC_USE_EQADC_Q0 && !defined(__DOXYGEN__)
#if SPC5_ADC_USE_ADC0_Q0 && !defined(__DOXYGEN__)
extern ADCDriver ADCD1;
#endif
#if SPC5_ADC_USE_ADC0_Q1 && !defined(__DOXYGEN__)
extern ADCDriver ADCD2;
#endif
#if SPC5_ADC_USE_ADC0_Q2 && !defined(__DOXYGEN__)
extern ADCDriver ADCD3;
#endif
#if SPC5_ADC_USE_ADC1_Q3 && !defined(__DOXYGEN__)
extern ADCDriver ADCD4;
#endif
#if SPC5_ADC_USE_ADC1_Q4 && !defined(__DOXYGEN__)
extern ADCDriver ADCD5;
#endif
#if SPC5_ADC_USE_ADC1_Q5 && !defined(__DOXYGEN__)
extern ADCDriver ADCD6;
#endif
#ifdef __cplusplus
extern "C" {
#endif