From fe0a14d1434098bfd0780d06a2a7e55f27940d27 Mon Sep 17 00:00:00 2001 From: batt Date: Fri, 12 Mar 2010 18:02:46 +0000 Subject: [PATCH] Better detection of concurrent ADC access. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@3197 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/arm/drv/adc_at91.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/bertos/cpu/arm/drv/adc_at91.c b/bertos/cpu/arm/drv/adc_at91.c index bb6a8d11..faa0d181 100644 --- a/bertos/cpu/arm/drv/adc_at91.c +++ b/bertos/cpu/arm/drv/adc_at91.c @@ -126,13 +126,13 @@ void adc_hw_select_ch(uint8_t ch) /** * Start an ADC convertion. * If a kernel is present, preempt until convertion is complete, otherwise - * a busy wait on ADCS bit is done. + * a busy wait on ADC_DRDY bit is done. */ uint16_t adc_hw_read(void) { - ASSERT(!(ADC_SR & ADC_EOC_MASK)); - #if CONFIG_KERN + /* Ensure ADC is not already in use by another process */ + ASSERT(adc_process == NULL); adc_process = proc_current(); #endif @@ -143,13 +143,19 @@ uint16_t adc_hw_read(void) // Ensure IRQs enabled. IRQ_ASSERT_ENABLED(); sig_wait(SIG_ADC_COMPLETE); + + /* Prevent race condition in case of preemptive kernel */ + uint16_t ret = ADC_LCDR; + MEMORY_BARRIER; + adc_process = NULL; + return ret; #else //Wait in polling until is done while (!(ADC_SR & BV(ADC_DRDY))); - #endif - //Return the last converted data - return(ADC_LCDR); + //Return the last converted data + return(ADC_LCDR); + #endif } /** -- 2.25.1