adc_at91.c
Go to the documentation of this file.00001 00048 #include "adc_at91.h" 00049 00050 #include <cpu/irq.h> 00051 00052 #include "cfg/cfg_adc.h" 00053 #include "cfg/cfg_proc.h" 00054 #include "cfg/cfg_signal.h" 00055 #include <cfg/macros.h> 00056 #include <cfg/compiler.h> 00057 00058 // Define log settings for cfg/log.h. 00059 #define LOG_LEVEL ADC_LOG_LEVEL 00060 #define LOG_FORMAT ADC_LOG_FORMAT 00061 #include <cfg/log.h> 00062 00063 #include <drv/adc.h> 00064 00065 #include <io/arm.h> 00066 00067 #if CONFIG_KERN 00068 #include <cfg/module.h> 00069 #include <kern/proc.h> 00070 #include <kern/signal.h> 00071 00072 00073 #if !CONFIG_KERN_SIGNALS 00074 #error Signals must be active to use ADC with kernel 00075 #endif 00076 00077 /* Signal adc convertion end */ 00078 #define SIG_ADC_COMPLETE SIG_USER0 00079 00080 /* ADC waiting process */ 00081 static struct Process *adc_process; 00082 00087 static DECLARE_ISR(adc_conversion_end_irq) 00088 { 00089 sig_post(adc_process, SIG_ADC_COMPLETE); 00090 00091 /* Inform hw that we have served the IRQ */ 00092 AIC_EOICR = 0; 00093 } 00094 00095 static void adc_enable_irq(void) 00096 { 00097 00098 // Disable all interrupt 00099 ADC_IDR = 0xFFFFFFFF; 00100 00101 //Register interrupt vector 00102 AIC_SVR(ADC_ID) = adc_conversion_end_irq; 00103 AIC_SMR(ADC_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED; 00104 AIC_IECR = BV(ADC_ID); 00105 00106 //Enable data ready irq 00107 ADC_IER = BV(ADC_DRDY); 00108 } 00109 00110 #endif /* CONFIG_KERN */ 00111 00112 00117 void adc_hw_select_ch(uint8_t ch) 00118 { 00119 //Disable all channels 00120 ADC_CHDR = ADC_CH_MASK; 00121 //Enable select channel 00122 ADC_CHER = BV(ch); 00123 } 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_CR = BV(ADC_START); 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_LCDR; 00149 MEMORY_BARRIER; 00150 adc_process = NULL; 00151 return ret; 00152 #else 00153 //Wait in polling until is done 00154 while (!(ADC_SR & BV(ADC_DRDY))); 00155 00156 //Return the last converted data 00157 return(ADC_LCDR); 00158 #endif 00159 } 00160 00164 void adc_hw_init(void) 00165 { 00166 //Init ADC pins. 00167 ADC_INIT_PINS(); 00168 00169 /* 00170 * Set adc mode register: 00171 * - Disable hardware trigger and enable software trigger. 00172 * - Select normal mode. 00173 * - Set ADC_BITS bit convertion resolution. 00174 * 00175 * \{ 00176 */ 00177 ADC_MR = 0; 00178 #if ADC_BITS == 10 00179 ADC_MR &= ~BV(ADC_LOWRES); 00180 #elif ADC_BITS == 8 00181 ADC_MR |= BV(ADC_LOWRES); 00182 #else 00183 #error No select bit resolution is supported to this CPU 00184 #endif 00185 /* \} */ 00186 00187 LOG_INFO("prescaler[%ld], stup[%ld], shtim[%ld]\n",ADC_COMPUTED_PRESCALER, ADC_COMPUTED_STARTUPTIME, ADC_COMPUTED_SHTIME); 00188 00189 00190 //Apply computed prescaler value 00191 ADC_MR &= ~ADC_PRESCALER_MASK; 00192 ADC_MR |= ((ADC_COMPUTED_PRESCALER << ADC_PRESCALER_SHIFT) & ADC_PRESCALER_MASK); 00193 LOG_INFO("prescaler[%ld]\n", (ADC_COMPUTED_PRESCALER << ADC_PRESCALER_SHIFT) & ADC_PRESCALER_MASK); 00194 00195 //Apply computed start up time 00196 ADC_MR &= ~ADC_STARTUP_MASK; 00197 ADC_MR |= ((ADC_COMPUTED_STARTUPTIME << ADC_STARTUP_SHIFT) & ADC_STARTUP_MASK); 00198 LOG_INFO("sttime[%ld]\n", (ADC_COMPUTED_STARTUPTIME << ADC_STARTUP_SHIFT) & ADC_STARTUP_MASK); 00199 00200 //Apply computed sample and hold time 00201 ADC_MR &= ~ADC_SHTIME_MASK; 00202 ADC_MR |= ((ADC_COMPUTED_SHTIME << ADC_SHTIME_SHIFT) & ADC_SHTIME_MASK); 00203 LOG_INFO("shtime[%ld]\n", (ADC_COMPUTED_SHTIME << ADC_SHTIME_SHIFT) & ADC_SHTIME_MASK); 00204 00205 #if CONFIG_KERN 00206 //Register and enable irq for adc. 00207 adc_enable_irq(); 00208 #endif 00209 00210 }
