diff --git a/radio/src/hal/adc_driver.cpp b/radio/src/hal/adc_driver.cpp index 4b36440a3..fdeb1595b 100644 --- a/radio/src/hal/adc_driver.cpp +++ b/radio/src/hal/adc_driver.cpp @@ -67,30 +67,49 @@ uint16_t adcValues[NUM_ANALOGS] __DMA; uint16_t rtcBatteryVoltage; #endif -void adcInit(const etx_hal_adc_driver_t* driver) +bool adcInit(const etx_hal_adc_driver_t* driver) { etx_hal_adc_driver = driver; if (etx_hal_adc_driver && etx_hal_adc_driver->init) - etx_hal_adc_driver->init(); + { + if(!etx_hal_adc_driver->init()) + return false; + + return true; + } + return false; } -static void adcSingleRead() +static bool adcSingleRead() { - if (!etx_hal_adc_driver) return; + if (!etx_hal_adc_driver) + return false; if (etx_hal_adc_driver->start_conversion) - etx_hal_adc_driver->start_conversion(); + { + if (!etx_hal_adc_driver->start_conversion()) + return false; + } + else + return false; if (etx_hal_adc_driver->wait_completion) + { etx_hal_adc_driver->wait_completion(); + } + else + return false; + + return true; } -void adcRead() +bool adcRead() { uint16_t temp[NUM_ANALOGS] = { 0 }; for (int i=0; i<4; i++) { - adcSingleRead(); + if (!adcSingleRead()) + return false; for (uint8_t x=FIRST_ANALOG_ADC; xCR = DMA_SxCR_PL | ADC_DMA_SxCR_CHSEL | DMA_SxCR_MSIZE_0 | - DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC; dma_stream->PAR = CONVERT_PTR_UINT(&adc->DR); dma_stream->M0AR = CONVERT_PTR_UINT(dest); dma_stream->NDTR = nconv; + // Very high priority, 1 byte transfers, increment memory + dma_stream->CR = DMA_SxCR_PL | ADC_DMA_SxCR_CHSEL | DMA_SxCR_MSIZE_0 | + DMA_SxCR_PSIZE_0 | DMA_SxCR_MINC; + // disable direct mode, half full FIFO dma_stream->FCR = DMA_SxFCR_DMDIS | DMA_SxFCR_FTH_0; + return true; } -static void stm32_hal_adc_init() +static bool stm32_hal_adc_init() { adc_init_pins(); @@ -242,7 +255,8 @@ static void stm32_hal_adc_init() if (adc_def->dma_stream && adc_def->get_dma_buffer) { uint16_t* dma_buffer = adc_def->get_dma_buffer(); - adc_init_dma_stream(adc_def->adc, adc_def->dma_stream, dma_buffer, nconv); + if (!adc_init_dma_stream(adc_def->adc, adc_def->dma_stream, dma_buffer, nconv)) + return false; } } } @@ -260,6 +274,7 @@ static void stm32_hal_adc_init() sticksPwmInit(); } #endif + return true; } #define DMA_Stream0_IT_MASK (uint32_t)(DMA_LISR_FEIF0 | DMA_LISR_DMEIF0 | \ @@ -283,20 +298,32 @@ static void adc_dma_clear_flags(DMA_Stream_TypeDef * dma_stream) } } -static void adc_start_dma_conversion(ADC_TypeDef* ADCx, +static bool adc_start_dma_conversion(ADC_TypeDef* ADCx, DMA_Stream_TypeDef * dma_stream) { - dma_stream->CR &= ~DMA_SxCR_EN; // Disable DMA - ADCx->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR); + // Disable DMA before continuing (see ref. manual "Stream configuration procedure") + if (!adc_disable_dma(dma_stream)) + return false; + + // Clear Interrupt flags adc_dma_clear_flags(dma_stream); + ADCx->SR &= ~(uint32_t)(ADC_SR_EOC | ADC_SR_STRT | ADC_SR_OVR); + dma_stream->CR |= DMA_SxCR_EN; // Enable DMA ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; + return true; } -static void adc_disable_dma(DMA_Stream_TypeDef * dma_stream) +static bool adc_disable_dma(DMA_Stream_TypeDef * dma_stream) { - dma_stream->CR &= ~DMA_SxCR_EN; // Disable DMA stream + dma_stream->CR &= ~(uint32_t)DMA_SxCR_EN; + uint16_t uiTimeout = 1000; + do + { + if (--uiTimeout == 0) return false; // Timeout. Failed to disable DMA + } while (dma_stream->CR & (uint32_t)DMA_SxCR_EN); // wait until DMA enable bit gets cleared by hardware + return true; } static void adc_start_single_conversion(ADC_TypeDef* ADCx) @@ -305,7 +332,7 @@ static void adc_start_single_conversion(ADC_TypeDef* ADCx) ADCx->CR2 |= (uint32_t)ADC_CR2_SWSTART; } -static void stm32_hal_adc_start_read() +static bool stm32_hal_adc_start_read() { const stm32_hal_adc* adc_def = ADC_hal_def; while (adc_def->adc) { @@ -314,8 +341,9 @@ static void stm32_hal_adc_start_read() nconv = adc_def->get_nconv(); if (nconv > 0) { if (adc_def->dma_stream && adc_def->get_dma_buffer) { - adc_start_dma_conversion(adc_def->adc, adc_def->dma_stream); - } else if (nconv == 1){ + if (!adc_start_dma_conversion(adc_def->adc, adc_def->dma_stream)) + return false; + } else if (nconv == 1) { adc_start_single_conversion(adc_def->adc); } } @@ -323,6 +351,7 @@ static void stm32_hal_adc_start_read() // move to next ADC definition adc_def++; } + return true; } static void stm32_hal_adc_wait_completion() diff --git a/radio/src/targets/horus/board.cpp b/radio/src/targets/horus/board.cpp index b192cdda8..f3d10e507 100644 --- a/radio/src/targets/horus/board.cpp +++ b/radio/src/targets/horus/board.cpp @@ -200,7 +200,9 @@ void boardInit() } #endif - adcInit(&stm32_hal_adc_driver); + if (!adcInit(&stm32_hal_adc_driver)) + TRACE("adcInit failed"); + lcdInit(); backlightInit(); diff --git a/radio/src/targets/taranis/board.cpp b/radio/src/targets/taranis/board.cpp index c85907b2e..db8d4cebb 100644 --- a/radio/src/targets/taranis/board.cpp +++ b/radio/src/targets/taranis/board.cpp @@ -162,7 +162,8 @@ void boardInit() } #endif - adcInit(&stm32_hal_adc_driver); + if (!adcInit(&stm32_hal_adc_driver)) + TRACE("adcInit failed"); lcdInit(); // delaysInit() must be called before audioInit(); init2MhzTimer();