aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpcirillo <pcirillo@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-11-18 14:23:46 +0000
committerpcirillo <pcirillo@35acf78f-673a-0410-8e92-d51de3d6d3f4>2013-11-18 14:23:46 +0000
commit8ba7e03ed5fbb8c642fbd0c665b1c8a3f37d6dbc (patch)
treee6d47f1e2f61425aeaf7dc1a46568f2083b4784b
parentd9385f98fabacaae4df012e5de1cb9bf21e939e1 (diff)
downloadChibiOS-8ba7e03ed5fbb8c642fbd0c665b1c8a3f37d6dbc.tar.gz
ChibiOS-8ba7e03ed5fbb8c642fbd0c665b1c8a3f37d6dbc.tar.bz2
ChibiOS-8ba7e03ed5fbb8c642fbd0c665b1c8a3f37d6dbc.zip
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@6487 35acf78f-673a-0410-8e92-d51de3d6d3f4
-rw-r--r--os/hal/platforms/SPC5xx/ADC_v1/adc_lld.c206
-rw-r--r--os/hal/platforms/SPC5xx/ADC_v1/adc_lld.h114
2 files changed, 221 insertions, 99 deletions
diff --git a/os/hal/platforms/SPC5xx/ADC_v1/adc_lld.c b/os/hal/platforms/SPC5xx/ADC_v1/adc_lld.c
index 2080c6fde..07c49e564 100644
--- a/os/hal/platforms/SPC5xx/ADC_v1/adc_lld.c
+++ b/os/hal/platforms/SPC5xx/ADC_v1/adc_lld.c
@@ -271,12 +271,22 @@ void adc_lld_init(void) {
INTC.PSR[SPC5_ADC0_EOC_NUMBER].R = SPC5_ADC_ADC0_EOC_PRIORITY;
INTC.PSR[SPC5_ADC0_ER_NUMBER].R = SPC5_ADC_ADC0_ER_PRIORITY;
INTC.PSR[SPC5_ADC0_WD_NUMBER].R = SPC5_ADC_ADC0_WD_PRIORITY;
+
+ /* Sets peripheral clock.*/
+ halSPCSetPeripheralClockMode(SPC5_ADC0_PCTL, SPC5_ADC_ADC0_START_PCTL);
+ ADCD1.adc_tagp->MCR.B.ADCLKSEL = SPC5_ADC_ADC0_CLK_FREQUENCY;
+ halSPCSetPeripheralClockMode(SPC5_ADC0_PCTL, SPC5_ADC_ADC0_STOP_PCTL);
#endif
#if SPC5_ADC_USE_ADC1
INTC.PSR[SPC5_ADC1_EOC_NUMBER].R = SPC5_ADC_ADC1_EOC_PRIORITY;
INTC.PSR[SPC5_ADC1_ER_NUMBER].R = SPC5_ADC_ADC1_ER_PRIORITY;
INTC.PSR[SPC5_ADC1_WD_NUMBER].R = SPC5_ADC_ADC1_WD_PRIORITY;
+
+ /* Sets peripheral clock.*/
+ halSPCSetPeripheralClockMode(SPC5_ADC1_PCTL, SPC5_ADC_ADC1_START_PCTL);
+ ADCD2.adc_tagp->MCR.B.ADCLKSEL = SPC5_ADC_ADC1_CLK_FREQUENCY;
+ halSPCSetPeripheralClockMode(SPC5_ADC1_PCTL, SPC5_ADC_ADC1_STOP_PCTL);
#endif
}
@@ -328,15 +338,7 @@ void adc_lld_start(ADCDriver *adcp) {
adcp->adc_tagp->MCR.B.PWDN = 0;
/* Power up delay.*/
- /* TODO: add a delay of 5uS.*/
-
- /* Sets analog clock.*/
- /* TODO: make it a static option, move in adc_lld_init().*/
- if (adcp->config->clock == HALF_PERIPHERAL_SET_CLOCK_FREQUENCY) {
- adcp->adc_tagp->MCR.B.ADCLKSEL = 0;
- } else if (adcp->config->clock == PERIPHERAL_SET_CLOCK_FREQUENCY) {
- adcp->adc_tagp->MCR.B.ADCLKSEL = 1;
- }
+ osalThreadSleep(US2ST(5));
/* Sets MCR Register.*/
adcp->adc_tagp->MCR.R = ADC_MCR_OWREN | ADC_MCR_MODE;
@@ -358,22 +360,54 @@ void adc_lld_stop(ADCDriver *adcp) {
/* Releases the allocated DMA channel.*/
edmaChannelRelease(adcp->adc_dma_channel);
- /* Clears thresholds’ values and deactives watchdog threshold interrupts.*/
- /* TODO: make the number of WD registers a parameter in the registry, modify
- the configuration structure.*/
- if (adcp->grpp->wtimr != 0) {
- adcp->adc_tagp->TRC[0].R = 0;
- adcp->adc_tagp->TRC[1].R = 0;
- adcp->adc_tagp->TRC[2].R = 0;
- adcp->adc_tagp->TRC[3].R = 0;
- adcp->adc_tagp->THRHLR[0].R = 0;
- adcp->adc_tagp->THRHLR[1].R = 0;
- adcp->adc_tagp->THRHLR[2].R = 0;
- adcp->adc_tagp->THRHLR[3].R = 0;
- adcp->adc_tagp->WTIMR.R = 0;
- }
+ /* Clears thresholds’ values and deactive watchdog threshold interrupts.*/
+#if SPC5_ADC_NTRESHOLD == 4
+ adcp->adc_tagp->TRC[0].R = 0;
+ adcp->adc_tagp->TRC[1].R = 0;
+ adcp->adc_tagp->TRC[2].R = 0;
+ adcp->adc_tagp->TRC[3].R = 0;
+ adcp->adc_tagp->THRHLR[0].R = 0;
+ adcp->adc_tagp->THRHLR[1].R = 0;
+ adcp->adc_tagp->THRHLR[2].R = 0;
+ adcp->adc_tagp->THRHLR[3].R = 0;
+ adcp->adc_tagp->WTIMR.R = 0;
+
+ /* Disables the watchdog interrupts if any.*/
+ adcp->adc_tagp->CIMR[0].R = 0;
+
+ /* Clears watchdog interrupts if any.*/
+ adcp->adc_tagp->WTISR.R = 0xFFFF;
+#elif SPC5_ADC_NTRESHOLD == 16
+ adcp->adc_tagp->THRHLR[0].R = 0;
+ adcp->adc_tagp->THRHLR[1].R = 0;
+ adcp->adc_tagp->THRHLR[2].R = 0;
+ adcp->adc_tagp->THRHLR[3].R = 0;
+ adcp->adc_tagp->THRHLR_2[0].R = 0;
+ adcp->adc_tagp->THRHLR_2[1].R = 0;
+ adcp->adc_tagp->THRHLR_2[2].R = 0;
+ adcp->adc_tagp->THRHLR_2[3].R = 0;
+ adcp->adc_tagp->THRHLR_2[4].R = 0;
+ adcp->adc_tagp->THRHLR_2[5].R = 0;
+ adcp->adc_tagp->THRHLR_2[6].R = 0;
+ adcp->adc_tagp->THRHLR_2[7].R = 0;
+ adcp->adc_tagp->THRHLR_2[8].R = 0;
+ adcp->adc_tagp->THRHLR_2[9].R = 0;
+ adcp->adc_tagp->THRHLR_2[10].R = 0;
+ adcp->adc_tagp->THRHLR_2[11].R = 0;
+ adcp->adc_tagp->CWSEL[0].R = 0;
+ adcp->adc_tagp->CWSEL[1].R = 0;
+ adcp->adc_tagp->CWENR[0].R = 0;
+ adcp->adc_tagp->AWORR[0].R = 0;
+ adcp->adc_tagp->WTIMR.R = 0;
+
+ /* Disables the watchdog interrupts if any.*/
+ adcp->adc_tagp->CIMR[0].R = 0;
+
+ /* Clears watchdog interrupts if any.*/
+ adcp->adc_tagp->WTISR.R = 0xFFFFFFFF;
+#endif
- /* Deactives ADC channels and the ADC DMA channels.*/
+ /* Deactive ADC channels and the ADC DMA channels.*/
adcp->adc_tagp->NCMR[0].R = 0;
adcp->adc_tagp->DMAR[0].R = 0;
@@ -405,14 +439,12 @@ void adc_lld_stop(ADCDriver *adcp) {
* @notapi
*/
void adc_lld_start_conversion(ADCDriver *adcp) {
+ uint32_t ch_mask;
uint8_t i;
- //osalDbgAssert(adcp->grpp->num_channels*2 >= adcp->depth,
- // "adc_lld_start_conversion(), #1", "too many elements");
-
/* Setting up DMA TCD parameters.*/
edmaChannelSetup(adcp->adc_dma_channel, /* channel. */
- ((uint8_t *)adcp->adc_tagp->CDR[adcp->grpp->init_channel].R) + 2, /* src. */
+ ((uint8_t *)&adcp->adc_tagp->CDR[adcp->grpp->init_channel].R) + 2, /* src. */
adcp->samples, /* dst. */
4, /* soff, advance by four. */
2, /* doff, advance by two. */
@@ -434,25 +466,111 @@ void adc_lld_start_conversion(ADCDriver *adcp) {
/* TODO: make the number of WD registers a parameter in the registry, modify
the configuration structure.*/
/* Sets thresholds’ values and active watchdog threshold interrupts if any.*/
- if (adcp->grpp->wtimr != 0) {
- adcp->adc_tagp->TRC[0].R = adcp->grpp->trcr[0];
- adcp->adc_tagp->TRC[1].R = adcp->grpp->trcr[1];
- adcp->adc_tagp->TRC[2].R = adcp->grpp->trcr[2];
- adcp->adc_tagp->TRC[3].R = adcp->grpp->trcr[3];
- adcp->adc_tagp->THRHLR[0].R = adcp->grpp->thrhlr[0];
- adcp->adc_tagp->THRHLR[1].R = adcp->grpp->thrhlr[1];
- adcp->adc_tagp->THRHLR[2].R = adcp->grpp->thrhlr[2];
- adcp->adc_tagp->THRHLR[3].R = adcp->grpp->thrhlr[3];
- adcp->adc_tagp->WTIMR.R = adcp->grpp->wtimr;
+#if SPC5_ADC_NTRESHOLD == 4
+ for (i = 0; i < SPC5_ADC_NTRESHOLD; i++) {
+ switch (adcp->grpp->thresholds[i].threshold_mode){
+ case ADC_THRHLR_DISABLED:
+ break;
+ case ADC_THRHLR_HIGHER:
+ /* Sets threshold registers.*/
+ adcp->adc_tagp->TRC[i].R = (1U << 15) | adcp->grpp->thresholds[i].adc_ch;
+ adcp->adc_tagp->THRHLR[i].B.THRH = adcp->grpp->thresholds[i].high_threshold_value;
+
+ /* Active interrupts.*/
+ adcp->adc_tagp->WTIMR.R = 1U << (4U + i);
+ adcp->adc_tagp->CIMR[0].R = 1U << adcp->grpp->thresholds[i].adc_ch;
+ break;
+ case ADC_THRHLR_LOWER:
+ /* Sets threshold registers.*/
+ adcp->adc_tagp->TRC[i].R = (1U << 15) | adcp->grpp->thresholds[i].adc_ch;
+ adcp->adc_tagp->THRHLR[i].B.THRH = adcp->grpp->thresholds[i].high_threshold_value;
+
+ /* Active interrupts.*/
+ adcp->adc_tagp->WTIMR.R = 1U << i;
+ adcp->adc_tagp->CIMR[0].R = 1U << adcp->grpp->thresholds[i].adc_ch;
+ break;
+ case ADC_THRHLR_BOTH_HL:
+ /* Sets threshold registers.*/
+ adcp->adc_tagp->TRC[i].R = (1U << 15) | adcp->grpp->thresholds[i].adc_ch;
+ adcp->adc_tagp->THRHLR[i].B.THRL = adcp->grpp->thresholds[i].low_threshold_value;
+ adcp->adc_tagp->THRHLR[i].B.THRH = adcp->grpp->thresholds[i].high_threshold_value;
+
+ /* Active interrupts.*/
+ adcp->adc_tagp->WTIMR.R = (1U << i) | (1U << (4U + i));
+ adcp->adc_tagp->CIMR[0].R = 1U << adcp->grpp->thresholds[i].adc_ch;
+ break;
+ }
}
+#elif SPC5_ADC_NTRESHOLD == 16
+ for (i = 0; i < SPC5_ADC_NTRESHOLD; i++) {
+ switch (adcp->grpp->thresholds[i].threshold_mode){
+ case ADC_THRHLR_DISABLED:
+ break;
+ case ADC_THRHLR_HIGHER:
+ /* Sets threshold registers.*/
+ if (adcp->grpp->thresholds[i].adc_ch > 7U) {
+ adcp->adc_tagp->CWSEL[1].R = i << ((adcp->grpp->thresholds[i].adc_ch - 8U) * 4U);
+ } else {
+ adcp->adc_tagp->CWSEL[0].R = i << (adcp->grpp->thresholds[i].adc_ch * 4U);
+ }
- /* mask = ((1 << nchannels) - 1) << firstchannel.*/
- /* TODO: Make the channels a mash in the configuration and just assign it.*/
- /* Active ADC channels for the conversion and sets the ADC DMA channels.*/
- for (i = adcp->grpp->init_channel; i <= adcp->grpp->final_channel; i++) {
- adcp->adc_tagp->NCMR[0].R |= 1U << i;
- adcp->adc_tagp->DMAR[0].R |= 1U << i;
+ adcp->adc_tagp->CWENR[0].R = 1U << adcp->grpp->thresholds[i].adc_ch;
+ if (i > 4U) {
+ adcp->adc_tagp->THRHLR_2[i - 4U].B.THRH = adcp->grpp->thresholds[i].high_threshold_value;
+ } else {
+ adcp->adc_tagp->THRHLR[i].B.THRH = adcp->grpp->thresholds[i].high_threshold_value;
+ }
+
+ /* Active interrupts.*/
+ adcp->adc_tagp->WTIMR.R = 1U << (1U + i * 2U);
+ adcp->adc_tagp->CIMR[0].R = 1U << adcp->grpp->thresholds[i].adc_ch;
+ break;
+ case ADC_THRHLR_LOWER:
+ /* Sets threshold registers.*/
+ if (adcp->grpp->thresholds[i].adc_ch > 7U) {
+ adcp->adc_tagp->CWSEL[1].R = i << ((adcp->grpp->thresholds[i].adc_ch - 8U) * 4U);
+ } else {
+ adcp->adc_tagp->CWSEL[0].R = i << (adcp->grpp->thresholds[i].adc_ch * 4U);
+ }
+ adcp->adc_tagp->CWENR[0].R = 1U << adcp->grpp->thresholds[i].adc_ch;
+ if (i > 4U) {
+ adcp->adc_tagp->THRHLR_2[i - 4U].B.THRH = adcp->grpp->thresholds[i].high_threshold_value;
+ } else {
+ adcp->adc_tagp->THRHLR[i].B.THRH = adcp->grpp->thresholds[i].high_threshold_value;
+ }
+
+ /* Active interrupts.*/
+ adcp->adc_tagp->WTIMR.R = 1U << (i * 2U);
+ adcp->adc_tagp->CIMR[0].R = 1U << adcp->grpp->thresholds[i].adc_ch;
+ break;
+ case ADC_THRHLR_BOTH_HL:
+ /* Sets threshold registers.*/
+ if (adcp->grpp->thresholds[i].adc_ch > 7U) {
+ adcp->adc_tagp->CWSEL[1].R = i << ((adcp->grpp->thresholds[i].adc_ch - 8U) * 4U);
+ } else {
+ adcp->adc_tagp->CWSEL[0].R = i << (adcp->grpp->thresholds[i].adc_ch * 4U);
+ }
+ adcp->adc_tagp->CWENR[0].R = 1U << adcp->grpp->thresholds[i].adc_ch;
+ if (i > 4U) {
+ adcp->adc_tagp->THRHLR_2[i - 4U].B.THRL = adcp->grpp->thresholds[i].low_threshold_value;
+ adcp->adc_tagp->THRHLR_2[i - 4U].B.THRH = adcp->grpp->thresholds[i].high_threshold_value;
+ } else {
+ adcp->adc_tagp->THRHLR[i].B.THRL = adcp->grpp->thresholds[i].low_threshold_value;
+ adcp->adc_tagp->THRHLR[i].B.THRH = adcp->grpp->thresholds[i].high_threshold_value;
+ }
+
+ /* Active interrupts.*/
+ adcp->adc_tagp->WTIMR.R = (1U << (1U + i * 2U)) | (1U << (i * 2U));
+ adcp->adc_tagp->CIMR[0].R = 1U << adcp->grpp->thresholds[i].adc_ch;
+ break;
+ }
}
+#endif
+
+ /* Active ADC channels for the conversion and sets the ADC DMA channels.*/
+ ch_mask = ((1 << adcp->grpp->num_channels) - 1) << adcp->grpp->init_channel;
+ adcp->adc_tagp->NCMR[0].R = ch_mask;
+ adcp->adc_tagp->DMAR[0].R = ch_mask;
/* Sets ADC conversion timing register.*/
adcp->adc_tagp->CTR[0].R = adcp->grpp->ctr;
diff --git a/os/hal/platforms/SPC5xx/ADC_v1/adc_lld.h b/os/hal/platforms/SPC5xx/ADC_v1/adc_lld.h
index b08c0f1a1..da46b14ca 100644
--- a/os/hal/platforms/SPC5xx/ADC_v1/adc_lld.h
+++ b/os/hal/platforms/SPC5xx/ADC_v1/adc_lld.h
@@ -37,42 +37,23 @@
* @name Analog channel identifiers
* @{
*/
-#if SPC5_HAS_ADC0 || defined(__DOXYGEN__)
-#define ADC0_CHN_AN0 0U
-#define ADC0_CHN_AN1 1U
-#define ADC0_CHN_AN2 2U
-#define ADC0_CHN_AN3 3U
-#define ADC0_CHN_AN4 4U
-#define ADC0_CHN_AN5 5U
-#define ADC0_CHN_AN6 6U
-#define ADC0_CHN_AN7 7U
-#define ADC0_CHN_AN8 8U
-#define ADC0_CHN_AN9 9U
-#define ADC0_CHN_AN10 10U
-#define ADC0_CHN_AN11 11U
-#define ADC0_CHN_AN12 12U
-#define ADC0_CHN_AN13 13U
-#define ADC0_CHN_AN14 14U
-#define ADC0_CHN_AN15 15U
-#endif
-
-#if SPC5_HAS_ADC1 || defined(__DOXYGEN__)
-#define ADC1_CHN_AN0 0U
-#define ADC1_CHN_AN1 1U
-#define ADC1_CHN_AN2 2U
-#define ADC1_CHN_AN3 3U
-#define ADC1_CHN_AN4 4U
-#define ADC1_CHN_AN5 5U
-#define ADC1_CHN_AN6 6U
-#define ADC1_CHN_AN7 7U
-#define ADC1_CHN_AN8 8U
-#define ADC1_CHN_AN9 9U
-#define ADC1_CHN_AN10 10U
-#define ADC1_CHN_AN11 11U
-#define ADC1_CHN_AN12 12U
-#define ADC1_CHN_AN13 13U
-#define ADC1_CHN_AN14 14U
-#define ADC1_CHN_AN15 15U
+#if SPC5_HAS_ADC0 || SPC5_HAS_ADC1 || defined(__DOXYGEN__)
+#define ADC_CHN_AN0 0U
+#define ADC_CHN_AN1 1U
+#define ADC_CHN_AN2 2U
+#define ADC_CHN_AN3 3U
+#define ADC_CHN_AN4 4U
+#define ADC_CHN_AN5 5U
+#define ADC_CHN_AN6 6U
+#define ADC_CHN_AN7 7U
+#define ADC_CHN_AN8 8U
+#define ADC_CHN_AN9 9U
+#define ADC_CHN_AN10 10U
+#define ADC_CHN_AN11 11U
+#define ADC_CHN_AN12 12U
+#define ADC_CHN_AN13 13U
+#define ADC_CHN_AN14 14U
+#define ADC_CHN_AN15 15U
#endif
/** @} */
@@ -324,6 +305,17 @@ typedef enum {
} adc_clock;
/**
+ * @brief ADC thresholds.
+ */
+typedef enum {
+ ADC_THRHLR_DISABLED = 0, /**< Watchdog threshold disabled. */
+ ADC_THRHLR_HIGHER = 1, /**< Watchdog higher threshold enabled. */
+ ADC_THRHLR_LOWER = 2, /**< Watchdog lower threshold enabled. */
+ ADC_THRHLR_BOTH_HL = 3, /**< Watchdog higher and lower thresholds enabled.*/
+
+} adcthrhlr_t;
+
+/**
* @brief ADC sample data type.
*/
typedef uint16_t adcsample_t;
@@ -348,6 +340,7 @@ typedef enum {
ADC_ERR_AWD2_LT = 6, /**< Watchdog 2 triggered Lower Threshold. */
ADC_ERR_AWD3_HT = 7, /**< Watchdog 3 triggered Higher Threshold. */
ADC_ERR_AWD3_LT = 8, /**< Watchdog 3 triggered Lower Threshold. */
+
} adcerror_t;
/**
@@ -375,6 +368,28 @@ typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n);
typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err);
/**
+ * @brief ADC threshold structure.
+ */
+typedef struct {
+ /**
+ * @brief ADC channel watchdog mode selection.
+ */
+ adcthrhlr_t threshold_mode;
+ /**
+ * @brief ADC channel selection.
+ */
+ uint16_t adc_ch;
+ /**
+ * @brief ADC channel high threshold value.
+ */
+ uint16_t high_threshold_value;
+ /**
+ * @brief ADC channel low threshold value.
+ */
+ uint16_t low_threshold_value;
+} ADCThrhlr;
+
+/**
* @brief Conversion group configuration structure.
* @details This implementation-dependent structure describes a conversion
* operation.
@@ -400,17 +415,13 @@ typedef struct {
adcerrorcallback_t error_cb;
/* End of the mandatory fields.*/
/**
- * @brief ADC WTIMR register initialization data.
- */
- uint32_t wtimr;
- /**
- * @brief ADC TRCx register initialization data.
+ * @brief ADC Threshold configuration data.
*/
- uint32_t trcr[4];
- /**
- * @brief ADC THRHLRx register initialization data.
- */
- uint32_t thrhlr[4];
+#if SPC5_ADC_NTRESHOLD == 4
+ ADCThrhlr thresholds[4];
+#elif SPC5_ADC_NTRESHOLD == 16
+ ADCThrhlr thresholds[16];
+#endif
/**
* @brief ADC CTR0 register initialization data.
*/
@@ -423,21 +434,14 @@ typedef struct {
* @brief ADC Initial conversion channel.
*/
uint32_t init_channel;
- /**
- * @brief ADC Final conversion channel.
- */
- uint32_t final_channel;
} ADCConversionGroup;
/**
* @brief Driver configuration structure.
- * @note It could be empty on some architectures.
+ * @note Empty in this implementation can be ignored.
*/
typedef struct {
- /**
- * @brief Analog clock frequency.
- */
- adc_clock clock;
+ uint32_t dummy;
} ADCConfig;
/**