BeRTOS
adc_stm32.c
Go to the documentation of this file.
00001 
00047 #include "adc_stm32.h"
00048 
00049 #include <cpu/irq.h>
00050 
00051 #include "cfg/cfg_adc.h"
00052 #include "cfg/cfg_proc.h"
00053 #include "cfg/cfg_signal.h"
00054 
00055 #include <cfg/macros.h>
00056 #include <cfg/compiler.h>
00057 #include <cfg/debug.h>
00058 
00059 // Define log settings for cfg/log.h.
00060 #define LOG_LEVEL         ADC_LOG_LEVEL
00061 #define LOG_FORMAT        ADC_LOG_FORMAT
00062 #include <cfg/log.h>
00063 
00064 #include <drv/adc.h>
00065 #include <drv/clock_stm32.h>
00066 #include <drv/gpio_stm32.h>
00067 
00068 #include <io/stm32.h>
00069 
00070 struct stm32_adc *adc = (struct stm32_adc *)ADC1_BASE;
00071 
00072 #if CONFIG_KERN
00073     #include <cfg/module.h>
00074 
00075     #include <kern/proc.h>
00076     #include <kern/signal.h>
00077 
00078     #include <drv/irq_cm3.h>
00079 
00080 
00081     #if !CONFIG_KERN_SIGNALS
00082         #error Signals must be active to use ADC with kernel
00083     #endif
00084 
00085     /* Signal adc convertion end */
00086     #define SIG_ADC_COMPLETE SIG_USER0
00087 
00088     /* ADC waiting process */
00089     static struct Process *adc_process;
00090 
00095     static DECLARE_ISR(adc_conversion_end_irq)
00096     {
00097         sig_post(adc_process, SIG_ADC_COMPLETE);
00098 
00099         /* Clear the status bit */
00100         adc->SR &= ~BV(SR_EOC);
00101     }
00102 
00103     static void adc_enable_irq(void)
00104     {
00105         /* Register the IRQ handler */
00106         sysirq_setHandler(ADC_IRQHANDLER, adc_conversion_end_irq);
00107         adc->CR1 |= BV(CR1_EOCIE);
00108     }
00109 
00110 #endif /* CONFIG_KERN */
00111 
00119 void adc_hw_select_ch(uint8_t ch)
00120 {
00121     /* We sample only from one channel */
00122     adc->SQR1 |= BV(SQR1_SQ_LEN_SHIFT);
00123     adc->SQR3 = (ch & SQR3_SQ_MASK);
00124 }
00125 
00131 uint16_t adc_hw_read(void)
00132 {
00133     #if CONFIG_KERN
00134         /* Ensure ADC is not already in use by another process */
00135         ASSERT(adc_process == NULL);
00136         adc_process = proc_current();
00137     #endif
00138 
00139     /* Start convertion */
00140     adc->CR2 |= CR2_EXTTRIG_SWSTRT_SET;
00141 
00142     #if CONFIG_KERN
00143         /* Ensure IRQs enabled. */
00144         IRQ_ASSERT_ENABLED();
00145         sig_wait(SIG_ADC_COMPLETE);
00146 
00147         /* Prevent race condition in case of preemptive kernel */
00148         uint16_t ret = adc->DR;
00149         MEMORY_BARRIER;
00150         adc_process = NULL;
00151         return ret;
00152     #else
00153         /* Wait in polling until conversion is done */
00154         while (!(adc->SR & BV(SR_EOC)));
00155 
00156         /* Return the last converted data */
00157         return (adc->DR);
00158     #endif
00159 }
00160 
00164 void adc_hw_init(void)
00165 {
00166     RCC->APB2ENR |= (RCC_APB2_GPIOA | RCC_APB2_GPIOB | RCC_APB2_GPIOC);
00167     RCC->APB2ENR |= RCC_APB2_ADC1;
00168 
00169     /* Reset registry */
00170     adc->CR1 = 0;
00171     adc->CR2 = 0;
00172     adc->SQR1 = 0;
00173     adc->SQR2 = 0;
00174     adc->SQR3 = 0;
00175 
00176     /* Calibrate ADC */
00177     adc->CR2 |= BV(CR2_RTSCAL);
00178     adc->CR2 |= BV(CR2_CAL);
00179 
00180     /* Wait in polling until calibration is done */
00181     while (adc->CR2 & BV(CR2_CAL));
00182 
00183     /*
00184      * Configure ADC
00185      *  - Regular mode
00186      *  - Wake up adc
00187      *  - Wake up temperature and Vrefint
00188      */
00189     adc->CR2 |= (BV(CR2_ADON) | ADC_EXTERNALTRIGCONV_NONE | BV(CR2_TSVREFE));
00190 
00191     /* Set 17.1usec sampling time*/
00192     adc->SMPR1 |= ((ADC_SAMPLETIME_239CYCLES5 << SMPR1_CH17) |
00193         (ADC_SAMPLETIME_239CYCLES5 << SMPR1_CH16) |
00194         (ADC_SAMPLETIME_239CYCLES5 << SMPR1_CH15) |
00195         (ADC_SAMPLETIME_239CYCLES5 << SMPR1_CH14) |
00196         (ADC_SAMPLETIME_239CYCLES5 << SMPR1_CH13) |
00197         (ADC_SAMPLETIME_239CYCLES5 << SMPR1_CH12) |
00198         (ADC_SAMPLETIME_239CYCLES5 << SMPR1_CH11) |
00199         (ADC_SAMPLETIME_239CYCLES5 << SMPR1_CH10));
00200 
00201     adc->SMPR2 |= ((ADC_SAMPLETIME_239CYCLES5 << SMPR2_CH9) |
00202         (ADC_SAMPLETIME_239CYCLES5 << SMPR2_CH8) |
00203         (ADC_SAMPLETIME_239CYCLES5 << SMPR2_CH7) |
00204         (ADC_SAMPLETIME_239CYCLES5 << SMPR2_CH6) |
00205         (ADC_SAMPLETIME_239CYCLES5 << SMPR2_CH5) |
00206         (ADC_SAMPLETIME_239CYCLES5 << SMPR2_CH4) |
00207         (ADC_SAMPLETIME_239CYCLES5 << SMPR2_CH3) |
00208         (ADC_SAMPLETIME_239CYCLES5 << SMPR2_CH2) |
00209         (ADC_SAMPLETIME_239CYCLES5 << SMPR2_CH1) |
00210         (ADC_SAMPLETIME_239CYCLES5 << SMPR2_CH0));
00211 
00212     #if CONFIG_KERN
00213         adc_enable_irq();
00214     #endif
00215 }