BeRTOS
|
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 }