From 9ddf162200f452b2d928c5eefac1256436d22fd2 Mon Sep 17 00:00:00 2001 From: gdisirio Date: Mon, 4 Mar 2013 11:10:29 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@5356 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/SPC563Mxx/spc563m_registry.h | 3 +- os/hal/platforms/SPC5xx/EDMA_v1/spc5_edma.c | 604 +++++++++++++++++++++++++- os/hal/platforms/SPC5xx/EDMA_v1/spc5_edma.h | 47 +- os/hal/platforms/SPC5xx/EQADC_v1/adc_lld.c | 27 +- os/hal/platforms/SPC5xx/EQADC_v1/adc_lld.h | 7 + 5 files changed, 679 insertions(+), 9 deletions(-) (limited to 'os/hal') diff --git a/os/hal/platforms/SPC563Mxx/spc563m_registry.h b/os/hal/platforms/SPC563Mxx/spc563m_registry.h index 66a3e74d0..6b9cb2d7d 100644 --- a/os/hal/platforms/SPC563Mxx/spc563m_registry.h +++ b/os/hal/platforms/SPC563Mxx/spc563m_registry.h @@ -32,7 +32,8 @@ * @{ */ /* eDMA attributes.*/ -#define SPC5_EDMA_NCHANNELS 64 +#define SPC5_HAS_EDMAA TRUE +#define SPC5_EDMA_NCHANNELS 32 #define SPC5_EDMA_HAS_MUX FALSE /* eQADC attributes.*/ diff --git a/os/hal/platforms/SPC5xx/EDMA_v1/spc5_edma.c b/os/hal/platforms/SPC5xx/EDMA_v1/spc5_edma.c index 94db29da7..6f0d5447b 100644 --- a/os/hal/platforms/SPC5xx/EDMA_v1/spc5_edma.c +++ b/os/hal/platforms/SPC5xx/EDMA_v1/spc5_edma.c @@ -54,6 +54,599 @@ static const edma_channel_config_t *channels[SPC5_EDMA_NCHANNELS]; /* Driver interrupt handlers. */ /*===========================================================================*/ +/** + * @brief EDMA error interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector10) { + + CH_IRQ_PROLOGUE(); + + /* TODO: Pass to the drivers somehow.*/ + chSysHalt(); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 0 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector11) { + + CH_IRQ_PROLOGUE(); + + if (channels[0] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 0; + channels[0]->dma_func(0, channels[0]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 1 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector12) { + + CH_IRQ_PROLOGUE(); + + if (channels[1] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 1; + channels[1]->dma_func(1, channels[1]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 2 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector13) { + + CH_IRQ_PROLOGUE(); + + if (channels[2] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 2; + channels[2]->dma_func(2, channels[2]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 3 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector14) { + + CH_IRQ_PROLOGUE(); + + if (channels[3] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 3; + channels[3]->dma_func(3, channels[3]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 4 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector15) { + + CH_IRQ_PROLOGUE(); + + if (channels[4] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 4; + channels[4]->dma_func(4, channels[4]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 5 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector16) { + + CH_IRQ_PROLOGUE(); + + if (channels[5] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 5; + channels[5]->dma_func(5, channels[5]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 6 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector17) { + + CH_IRQ_PROLOGUE(); + + if (channels[6] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 6; + channels[6]->dma_func(6, channels[6]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 7 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector18) { + + CH_IRQ_PROLOGUE(); + + if (channels[7] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 7; + channels[7]->dma_func(7, channels[7]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 8 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector19) { + + CH_IRQ_PROLOGUE(); + + if (channels[8] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 8; + channels[8]->dma_func(8, channels[8]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 9 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector20) { + + CH_IRQ_PROLOGUE(); + + if (channels[9] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 9; + channels[9]->dma_func(9, channels[9]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 10 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector21) { + + CH_IRQ_PROLOGUE(); + + if (channels[10] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 10; + channels[10]->dma_func(10, channels[10]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 11 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector22) { + + CH_IRQ_PROLOGUE(); + + if (channels[11] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 11; + channels[11]->dma_func(11, channels[11]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 12 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector23) { + + CH_IRQ_PROLOGUE(); + + if (channels[12] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 12; + channels[12]->dma_func(12, channels[12]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 13 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector24) { + + CH_IRQ_PROLOGUE(); + + if (channels[13] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 13; + channels[13]->dma_func(13, channels[13]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 14 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector25) { + + CH_IRQ_PROLOGUE(); + + if (channels[14] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 14; + channels[14]->dma_func(14, channels[14]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 15 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector26) { + + CH_IRQ_PROLOGUE(); + + if (channels[15] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 15; + channels[15]->dma_func(15, channels[15]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +#if (SPC5_EDMA_NCHANNELS > 16) || defined(__DOXYGEN__) +/** + * @brief EDMA channel 16 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector27) { + + CH_IRQ_PROLOGUE(); + + if (channels[16] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 16; + channels[16]->dma_func(16, channels[16]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 17 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector28) { + + CH_IRQ_PROLOGUE(); + + if (channels[17] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 17; + channels[17]->dma_func(17, channels[17]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 18 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector29) { + + CH_IRQ_PROLOGUE(); + + if (channels[18] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 18; + channels[18]->dma_func(18, channels[18]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 19 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector30) { + + CH_IRQ_PROLOGUE(); + + if (channels[19] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 19; + channels[19]->dma_func(19, channels[19]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 20 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector31) { + + CH_IRQ_PROLOGUE(); + + if (channels[20] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 20; + channels[20]->dma_func(20, channels[20]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 21 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector32) { + + CH_IRQ_PROLOGUE(); + + if (channels[21] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 21; + channels[21]->dma_func(21, channels[21]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 22 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector33) { + + CH_IRQ_PROLOGUE(); + + if (channels[22] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 22; + channels[22]->dma_func(22, channels[22]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 23 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector34) { + + CH_IRQ_PROLOGUE(); + + if (channels[23] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 23; + channels[23]->dma_func(23, channels[23]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 24 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector35) { + + CH_IRQ_PROLOGUE(); + + if (channels[24] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 24; + channels[24]->dma_func(24, channels[24]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 25 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector36) { + + CH_IRQ_PROLOGUE(); + + if (channels[25] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 25; + channels[25]->dma_func(25, channels[25]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 26 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector37) { + + CH_IRQ_PROLOGUE(); + + if (channels[26] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 26; + channels[26]->dma_func(26, channels[26]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 27 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector38) { + + CH_IRQ_PROLOGUE(); + + if (channels[27] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 27; + channels[27]->dma_func(27, channels[27]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 28 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector39) { + + CH_IRQ_PROLOGUE(); + + if (channels[28] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 28; + channels[28]->dma_func(28, channels[28]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 29 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector40) { + + CH_IRQ_PROLOGUE(); + + if (channels[29] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 29; + channels[29]->dma_func(29, channels[29]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 30 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector41) { + + CH_IRQ_PROLOGUE(); + + if (channels[30] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 30; + channels[30]->dma_func(30, channels[30]->dma_param); + + CH_IRQ_EPILOGUE(); +} + +/** + * @brief EDMA channel 31 interrupt. + * + * @isr + */ +CH_IRQ_HANDLER(vector42) { + + CH_IRQ_PROLOGUE(); + + if (channels[31] == NULL) { + SPC5_EDMA_ERROR_HANDLER(); + } + EDMA.CIRQR.R = 31; + channels[31]->dma_func(31, channels[31]->dma_param); + + CH_IRQ_EPILOGUE(); +} +#endif /* SPC5_EDMA_NCHANNELS > 16 */ + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ @@ -64,7 +657,15 @@ static const edma_channel_config_t *channels[SPC5_EDMA_NCHANNELS]; * @special */ void edmaInit(void) { + unsigned i; + EDMA.CR.R = SPC5_EDMA_CR_SETTING; + EDMA.ERQRL.R = 0x00000000; + EDMA.EEIRL.R = 0x00000000; + EDMA.IRQRL.R = 0xFFFFFFFF; + EDMA.ERL.R = 0xFFFFFFFF; + for (i = 0; i < SPC5_EDMA_NCHANNELS; i++) + EDMA.CPR[i].R = 0; } /** @@ -79,7 +680,8 @@ void edmaInit(void) { edma_channel_t edmaChannelAllocate(const edma_channel_config_t *ccfg) { edma_channel_t channel; - chDbgCheck((ccfg != NULL) && (ccfg->dma_func != NULL), + chDbgCheck((ccfg != NULL) && ((ccfg->dma_priority & 15) < 16) && + (ccfg->dma_func != NULL) && (ccfg->dma_error_func != NULL), "edmaChannelAllocate"); #if SPC5_EDMA_HAS_MUX diff --git a/os/hal/platforms/SPC5xx/EDMA_v1/spc5_edma.h b/os/hal/platforms/SPC5xx/EDMA_v1/spc5_edma.h index 03d85b138..3812254aa 100644 --- a/os/hal/platforms/SPC5xx/EDMA_v1/spc5_edma.h +++ b/os/hal/platforms/SPC5xx/EDMA_v1/spc5_edma.h @@ -42,10 +42,28 @@ /* Driver pre-compile time settings. */ /*===========================================================================*/ +/** + * @brief Default EDMA CR register initialization. + */ +#if !defined(SPC5_EDMA_ERROR_HANDLER) || defined(__DOXYGEN__) +#define SPC5_EDMA_CR_SETTING 0x0000C400 +#endif + +/** + * @brief EDMA critical error handler, must not return. + */ +#if !defined(SPC5_EDMA_ERROR_HANDLER) || defined(__DOXYGEN__) +#define SPC5_EDMA_ERROR_HANDLER() chSysHalt() +#endif + /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ +#if !SPC5_HAS_EDMAA +#error "this device does not have an eDMA unit" +#endif + /*===========================================================================*/ /* Driver data structures and types. */ /*===========================================================================*/ @@ -65,18 +83,21 @@ typedef struct { /** * @brief DMA ISR function type. * - * @param[in] tcd pointer to the TCD associated to this ISR + * @param[in] channel the channel number * @param[in] p parameter for the registered function */ -typedef void (*edma_isr_t)(edma_tcd_t *tcd, void *p); +typedef void (*edma_callback_t)(edma_channel_t channel, void *p); /** * @brief Type of an EDMA channel configuration structure. */ typedef struct { - uint32_t dma_periph; /**< @brief Peripheral to be + uint8_t dma_periph; /**< @brief Peripheral to be associated to the channel. */ - edma_isr_t dma_func; /**< @brief Channel ISR callback. */ + uint8_t dma_priority; /**< @brief Priority register value + for this channel. */ + edma_callback_t dma_func; /**< @brief Channel callback. */ + edma_callback_t dma_error_func; /**< @brief Channel error callback. */ void *dma_param; /**< @brief Channel callback param. */ } edma_channel_config_t; @@ -84,6 +105,24 @@ typedef struct { /* Driver macros. */ /*===========================================================================*/ +/** + * @brief Starts or restarts an EDMA channel. + * + * @param[in] channel the channel number + * + * @api + */ +#define edmaChannelStart(channel) (EDMA.SERQR.R = (channel)) + +/** + * @brief Stops an EDMA channel. + * + * @param[in] channel the channel number + * + * @api + */ +#define edmaChannelStop(channel) (EDMA.CERQR.R = (channel)) + /*===========================================================================*/ /* External declarations. */ /*===========================================================================*/ diff --git a/os/hal/platforms/SPC5xx/EQADC_v1/adc_lld.c b/os/hal/platforms/SPC5xx/EQADC_v1/adc_lld.c index 28ff64d96..a677a25e2 100644 --- a/os/hal/platforms/SPC5xx/EQADC_v1/adc_lld.c +++ b/os/hal/platforms/SPC5xx/EQADC_v1/adc_lld.c @@ -85,6 +85,8 @@ ADCDriver ADCD6; /* Driver local variables and types. */ /*===========================================================================*/ +static const uint16_t pudcrs[8] = SPC5_ADC_PUDCR; + /*===========================================================================*/ /* Driver local functions and macros. */ /*===========================================================================*/ @@ -215,7 +217,9 @@ static void adc_disable(void) { } /** - * @brief Calibrates both ADCs. + * @brief Calibrates an ADC unit. + * + * @param[in] adc the ADC unit * * @notapi */ @@ -249,6 +253,20 @@ static void adc_calibrate(uint32_t adc) { adc_write_register(adc, ADC_REG_AC2OCCR, occ & 0xFFFF); } +/** + * @brief Calibrates an ADC unit. + * + * @param[in] adc the ADC unit + * + * @notapi + */ +static void adc_setup_resistors(uint32_t adc) { + unsigned i; + + for (i = 0; i < 8; i++) + adc_write_register(adc, ADC_REG_PUDCR(i), pudcrs[i]); +} + /*===========================================================================*/ /* Driver interrupt handlers. */ /*===========================================================================*/ @@ -273,17 +291,20 @@ void adc_lld_init(void) { 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.*/ + /* Calibration of both ADC units, programming alternate configs + one and two for 10 and 8 bits operations, setting up pull up/down + resistors.*/ #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); + adc_setup_resistors(EQADC_RW_BN_ADC0); #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); + adc_setup_resistors(EQADC_RW_BN_ADC1); #endif /* ADCs disabled until the driver is started by the application.*/ diff --git a/os/hal/platforms/SPC5xx/EQADC_v1/adc_lld.h b/os/hal/platforms/SPC5xx/EQADC_v1/adc_lld.h index a946e3ee8..6b1fd4b1c 100644 --- a/os/hal/platforms/SPC5xx/EQADC_v1/adc_lld.h +++ b/os/hal/platforms/SPC5xx/EQADC_v1/adc_lld.h @@ -261,6 +261,13 @@ #if !defined(SPC5_ADC_CR_CLK_PS) || defined(__DOXYGEN__) #define SPC5_ADC_CR_CLK_PS ADC_CR_CLK_PS(5) #endif + +/** + * @brief Initialization value for PUDCRx registers. + */ +#if !defined(SPC5_ADC_PUDCR) || defined(__DOXYGEN__) +#define SPC5_ADC_PUDCR {0, 0, 0, 0, 0, 0, 0, 0} +#endif /** @} */ /*===========================================================================*/ -- cgit v1.2.3