git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5338 35acf78f-673a-0410-8e92-d51de3d6d3f4
This commit is contained in:
parent
d8914f064f
commit
03ef7de020
|
@ -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.
|
||||
|
|
|
@ -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) {
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue