X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=bertos%2Fcpu%2Farm%2Fdrv%2Fadc_at91.c;h=66d0bde9c2335c66417e1d6b25d888c2171ede8e;hb=6fffd0614f75137e8fed424c87835d4e7d478ef7;hp=dbeb6117ffbc57e7da78be8bd5913e376bd30310;hpb=36e34ca0af43a27f0092cc5217192b1c4a0ba104;p=bertos.git diff --git a/bertos/cpu/arm/drv/adc_at91.c b/bertos/cpu/arm/drv/adc_at91.c index dbeb6117..66d0bde9 100644 --- a/bertos/cpu/arm/drv/adc_at91.c +++ b/bertos/cpu/arm/drv/adc_at91.c @@ -40,15 +40,17 @@ * whit a loop the finishing of conversion. * * - * \version $Id$ * \author Daniele Basile */ #include "adc_at91.h" +#include + #include "cfg/cfg_adc.h" -#include "cfg/cfg_kern.h" +#include "cfg/cfg_proc.h" +#include "cfg/cfg_signal.h" #include #include @@ -61,7 +63,7 @@ #include -#if CONFIG_KERNEL +#if CONFIG_KERN #include #include #include @@ -81,9 +83,9 @@ * ADC ISR. * Simply signal the adc process that convertion is complete. */ - static void ISR_FUNC adc_conversion_end_irq(void) + static DECLARE_ISR(adc_conversion_end_irq) { - sig_signal(adc_process, SIG_ADC_COMPLETE); + sig_post(adc_process, SIG_ADC_COMPLETE); /* Inform hw that we have served the IRQ */ AIC_EOICR = 0; @@ -104,14 +106,14 @@ ADC_IER = BV(ADC_DRDY); } -#endif /* CONFIG_KERNEL */ +#endif /* CONFIG_KERN */ /** * Select mux channel \a ch. * \todo only first 8 channels are selectable! */ -INLINE void adc_hw_select_ch(uint8_t ch) +void adc_hw_select_ch(uint8_t ch) { //Disable all channels ADC_CHDR = ADC_CH_MASK; @@ -123,36 +125,42 @@ INLINE 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. */ -INLINE uint16_t adc_hw_read(void) +uint16_t adc_hw_read(void) { - ASSERT(!(ADC_SR & ADC_EOC_MASK)); - - #if CONFIG_KERNEL + #if CONFIG_KERN + /* Ensure ADC is not already in use by another process */ + ASSERT(adc_process == NULL); adc_process = proc_current(); #endif // Start convertion ADC_CR = BV(ADC_START); - #if CONFIG_KERNEL + #if CONFIG_KERN // Ensure IRQs enabled. - ASSERT(IRQ_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 } /** * Init ADC hardware. */ -INLINE void adc_hw_init(void) +void adc_hw_init(void) { //Init ADC pins. ADC_INIT_PINS(); @@ -175,6 +183,7 @@ INLINE void adc_hw_init(void) #endif /* \} */ + LOG_INFO("Computed ADC_CLOCK %ld\n", ADC_COMPUTED_CLOCK); LOG_INFO("prescaler[%ld], stup[%ld], shtim[%ld]\n",ADC_COMPUTED_PRESCALER, ADC_COMPUTED_STARTUPTIME, ADC_COMPUTED_SHTIME); @@ -193,7 +202,7 @@ INLINE void adc_hw_init(void) ADC_MR |= ((ADC_COMPUTED_SHTIME << ADC_SHTIME_SHIFT) & ADC_SHTIME_MASK); LOG_INFO("shtime[%ld]\n", (ADC_COMPUTED_SHTIME << ADC_SHTIME_SHIFT) & ADC_SHTIME_MASK); - #if CONFIG_KERNEL + #if CONFIG_KERN //Register and enable irq for adc. adc_enable_irq(); #endif