From 4a3e3fc01ec6dfb4a710db771bee262d5dc9327e Mon Sep 17 00:00:00 2001 From: gdisirio Date: Thu, 22 Sep 2011 14:53:42 +0000 Subject: git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@3381 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/hal/platforms/STM32F1xx/adc_lld.c | 26 +++++++++--------- os/hal/platforms/STM32F1xx/adc_lld.h | 30 ++++++++++++++------- os/hal/platforms/STM32L1xx/adc_lld.c | 51 +++++++++++++++++++++++++++--------- os/hal/platforms/STM32L1xx/adc_lld.h | 34 ++++++++++++++++-------- 4 files changed, 95 insertions(+), 46 deletions(-) (limited to 'os/hal/platforms') diff --git a/os/hal/platforms/STM32F1xx/adc_lld.c b/os/hal/platforms/STM32F1xx/adc_lld.c index ac74251f8..84b194c0f 100644 --- a/os/hal/platforms/STM32F1xx/adc_lld.c +++ b/os/hal/platforms/STM32F1xx/adc_lld.c @@ -57,20 +57,20 @@ ADCDriver ADCD1; static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { /* DMA errors handling.*/ -#if defined(STM32_ADC_DMA_ERROR_HOOK) if ((flags & STM32_DMA_ISR_TEIF) != 0) { - STM32_ADC_DMA_ERROR_HOOK(spip); + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); } -#else - (void)flags; -#endif - if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); + else { + if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } } } @@ -146,7 +146,7 @@ void adc_lld_start(ADCDriver *adcp) { /* ADC setup, the calibration procedure has already been performed during initialization.*/ - adcp->adc->CR1 = ADC_CR1_SCAN; + adcp->adc->CR1 = 0; adcp->adc->CR2 = 0; } } diff --git a/os/hal/platforms/STM32F1xx/adc_lld.h b/os/hal/platforms/STM32F1xx/adc_lld.h index 1d1052f50..e3a327afa 100644 --- a/os/hal/platforms/STM32F1xx/adc_lld.h +++ b/os/hal/platforms/STM32F1xx/adc_lld.h @@ -108,15 +108,6 @@ #define STM32_ADC_ADC1_IRQ_PRIORITY 5 #endif -/** - * @brief ADC DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_ADC_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt() -#endif - /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ @@ -147,6 +138,15 @@ typedef uint16_t adcsample_t; */ typedef uint16_t adc_channels_num_t; +/** + * @brief Possible ADC failure causes. + * @note Error codes are architecture dependent and should not relied + * upon. + */ +typedef enum { + ADC_ERR_DMAFAILURE = 0 /**< DMA operations failure. */ +} adcerror_t; + /** * @brief Type of a structure representing an ADC driver. */ @@ -162,6 +162,14 @@ typedef struct ADCDriver ADCDriver; */ typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n); +/** + * @brief ADC error callback type. + * + * @param[in] adcp pointer to the @p ADCDriver object triggering the + * callback + */ +typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err); + /** * @brief Conversion group configuration structure. * @details This implementation-dependent structure describes a conversion @@ -183,6 +191,10 @@ typedef struct { * @brief Callback function associated to the group or @p NULL. */ adccallback_t end_cb; + /** + * @brief Error callback or @p NULL. + */ + adcerrorcallback_t error_cb; /* End of the mandatory fields.*/ /** * @brief ADC CR1 register initialization data. diff --git a/os/hal/platforms/STM32L1xx/adc_lld.c b/os/hal/platforms/STM32L1xx/adc_lld.c index 9ccb198e4..a2149b6ae 100644 --- a/os/hal/platforms/STM32L1xx/adc_lld.c +++ b/os/hal/platforms/STM32L1xx/adc_lld.c @@ -57,20 +57,20 @@ ADCDriver ADCD1; static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { /* DMA errors handling.*/ -#if defined(STM32_ADC_DMA_ERROR_HOOK) if ((flags & STM32_DMA_ISR_TEIF) != 0) { - STM32_ADC_DMA_ERROR_HOOK(spip); + /* DMA, this could help only if the DMA tries to access an unmapped + address space or violates alignment rules.*/ + _adc_isr_error_code(adcp, ADC_ERR_DMAFAILURE); } -#else - (void)flags; -#endif - if ((flags & STM32_DMA_ISR_HTIF) != 0) { - /* Half transfer processing.*/ - _adc_isr_half_code(adcp); - } - if ((flags & STM32_DMA_ISR_TCIF) != 0) { - /* Transfer complete processing.*/ - _adc_isr_full_code(adcp); + else { + if ((flags & STM32_DMA_ISR_HTIF) != 0) { + /* Half transfer processing.*/ + _adc_isr_half_code(adcp); + } + if ((flags & STM32_DMA_ISR_TCIF) != 0) { + /* Transfer complete processing.*/ + _adc_isr_full_code(adcp); + } } } @@ -78,6 +78,29 @@ static void adc_lld_serve_rx_interrupt(ADCDriver *adcp, uint32_t flags) { /* Driver interrupt handlers. */ /*===========================================================================*/ +#if STM32_ADC_USE_ADC1 || defined(__DOXYGEN__) +/** + * @brief ADC1 interrupt handler. + * + * @isr + */ +CH_IRQ_HANDLER(UART5_IRQHandler) { + uint32_t sr; + + CH_IRQ_PROLOGUE(); + + sr = ADC1->SR; + ADC1->SR = 0; + if (sr & ADC_SR_OVR) { + /* ADC overflow condition, this could happen only if the DMA is unable + to read data fast enough.*/ + _adc_isr_error_code(&ADCD1, ADC_ERR_OVERFLOW); + } + + CH_IRQ_EPILOGUE(); +} +#endif + /*===========================================================================*/ /* Driver exported functions. */ /*===========================================================================*/ @@ -145,6 +168,7 @@ void adc_lld_stop(ADCDriver *adcp) { if (adcp->state == ADC_READY) { #if STM32_ADC_USE_ADC1 if (&ADCD1 == adcp) { + ADC1->CR1 = 0; ADC1->CR2 = 0; dmaStreamRelease(adcp->dmastp); rccDisableADC1(FALSE); @@ -182,7 +206,7 @@ void adc_lld_start_conversion(ADCDriver *adcp) { /* ADC setup.*/ adcp->adc->SR = 0; - adcp->adc->CR1 = grpp->cr1 | ADC_CR1_SCAN; + adcp->adc->CR1 = grpp->cr1 | ADC_CR1_OVRIE | ADC_CR1_SCAN; adcp->adc->SMPR1 = grpp->smpr1; /* Writing SMPRx requires ADON=0. */ adcp->adc->SMPR2 = grpp->smpr2; adcp->adc->SMPR3 = grpp->smpr3; @@ -211,6 +235,7 @@ void adc_lld_start_conversion(ADCDriver *adcp) { void adc_lld_stop_conversion(ADCDriver *adcp) { dmaStreamDisable(adcp->dmastp); + adcp->adc->CR1 = 0; adcp->adc->CR2 = 0; } diff --git a/os/hal/platforms/STM32L1xx/adc_lld.h b/os/hal/platforms/STM32L1xx/adc_lld.h index 2889387ab..0ca41c269 100644 --- a/os/hal/platforms/STM32L1xx/adc_lld.h +++ b/os/hal/platforms/STM32L1xx/adc_lld.h @@ -39,8 +39,7 @@ * @name Triggers selection * @{ */ -#define ADC_CR2_EXTSEL_SRC(n) ((n) << 17) /**< @brief Trigger source. */ -#define ADC_CR2_EXTSEL_SWSTART (7 << 17) /**< @brief Software trigger. */ +#define ADC_CR2_EXTSEL_SRC(n) ((n) << 24) /**< @brief Trigger source. */ /** @} */ /** @@ -136,15 +135,6 @@ #define STM32_ADC_ADC1_IRQ_PRIORITY 5 #endif -/** - * @brief ADC DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_ADC_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_ADC_DMA_ERROR_HOOK(adcp) chSysHalt() -#endif - /*===========================================================================*/ /* Derived constants and error checks. */ /*===========================================================================*/ @@ -175,6 +165,16 @@ typedef uint16_t adcsample_t; */ typedef uint16_t adc_channels_num_t; +/** + * @brief Possible ADC failure causes. + * @note Error codes are architecture dependent and should not relied + * upon. + */ +typedef enum { + ADC_ERR_DMAFAILURE = 0, /**< DMA operations failure. */ + ADC_ERR_OVERFLOW = 1 /**< ADC overflow condition. */ +} adcerror_t; + /** * @brief Type of a structure representing an ADC driver. */ @@ -190,6 +190,14 @@ typedef struct ADCDriver ADCDriver; */ typedef void (*adccallback_t)(ADCDriver *adcp, adcsample_t *buffer, size_t n); +/** + * @brief ADC error callback type. + * + * @param[in] adcp pointer to the @p ADCDriver object triggering the + * callback + */ +typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err); + /** * @brief Conversion group configuration structure. * @details This implementation-dependent structure describes a conversion @@ -211,6 +219,10 @@ typedef struct { * @brief Callback function associated to the group or @p NULL. */ adccallback_t end_cb; + /** + * @brief Error callback or @p NULL. + */ + adcerrorcallback_t error_cb; /* End of the mandatory fields.*/ /** * @brief ADC CR1 register initialization data. -- cgit v1.2.3