BeRTOS
|
00001 00047 #include "adc_at91.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 #include <cfg/macros.h> 00055 #include <cfg/compiler.h> 00056 00057 // Define log settings for cfg/log.h. 00058 #define LOG_LEVEL ADC_LOG_LEVEL 00059 #define LOG_FORMAT ADC_LOG_FORMAT 00060 #include <cfg/log.h> 00061 00062 #include <drv/adc.h> 00063 00064 #include <io/arm.h> 00065 00066 #if CONFIG_KERN 00067 #include <cfg/module.h> 00068 #include <kern/proc.h> 00069 #include <kern/signal.h> 00070 00071 00072 #if !CONFIG_KERN_SIGNALS 00073 #error Signals must be active to use ADC with kernel 00074 #endif 00075 00076 /* Signal adc convertion end */ 00077 #define SIG_ADC_COMPLETE SIG_USER0 00078 00079 /* ADC waiting process */ 00080 static struct Process *adc_process; 00081 00086 static DECLARE_ISR(adc_conversion_end_irq) 00087 { 00088 sig_post(adc_process, SIG_ADC_COMPLETE); 00089 00090 /* Inform hw that we have served the IRQ */ 00091 AIC_EOICR = 0; 00092 } 00093 00094 static void adc_enable_irq(void) 00095 { 00096 00097 // Disable all interrupt 00098 ADC_IDR = 0xFFFFFFFF; 00099 00100 //Register interrupt vector 00101 AIC_SVR(ADC_ID) = adc_conversion_end_irq; 00102 AIC_SMR(ADC_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED; 00103 AIC_IECR = BV(ADC_ID); 00104 00105 //Enable data ready irq 00106 ADC_IER = BV(ADC_DRDY); 00107 } 00108 00109 #endif /* CONFIG_KERN */ 00110 00111 00116 void adc_hw_select_ch(uint8_t ch) 00117 { 00118 //Disable all channels 00119 ADC_CHDR = ADC_CH_MASK; 00120 //Enable select channel 00121 ADC_CHER = BV(ch); 00122 } 00123 00124 00130 uint16_t adc_hw_read(void) 00131 { 00132 #if CONFIG_KERN 00133 /* Ensure ADC is not already in use by another process */ 00134 ASSERT(adc_process == NULL); 00135 adc_process = proc_current(); 00136 #endif 00137 00138 // Start convertion 00139 ADC_CR = BV(ADC_START); 00140 00141 #if CONFIG_KERN 00142 // Ensure IRQs enabled. 00143 IRQ_ASSERT_ENABLED(); 00144 sig_wait(SIG_ADC_COMPLETE); 00145 00146 /* Prevent race condition in case of preemptive kernel */ 00147 uint16_t ret = ADC_LCDR; 00148 MEMORY_BARRIER; 00149 adc_process = NULL; 00150 return ret; 00151 #else 00152 //Wait in polling until is done 00153 while (!(ADC_SR & BV(ADC_DRDY))); 00154 00155 //Return the last converted data 00156 return(ADC_LCDR); 00157 #endif 00158 } 00159 00163 void adc_hw_init(void) 00164 { 00165 //Init ADC pins. 00166 ADC_INIT_PINS(); 00167 00168 /* 00169 * Set adc mode register: 00170 * - Disable hardware trigger and enable software trigger. 00171 * - Select normal mode. 00172 * - Set ADC_BITS bit convertion resolution. 00173 * 00174 * \{ 00175 */ 00176 ADC_MR = 0; 00177 #if ADC_BITS == 10 00178 ADC_MR &= ~BV(ADC_LOWRES); 00179 #elif ADC_BITS == 8 00180 ADC_MR |= BV(ADC_LOWRES); 00181 #else 00182 #error No select bit resolution is supported to this CPU 00183 #endif 00184 /* \} */ 00185 00186 LOG_INFO("Computed ADC_CLOCK %ld\n", ADC_COMPUTED_CLOCK); 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 }