ChibiOS/RT Architecture - Reference Manual - Guides |
00001 /* 00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. 00003 00004 This file is part of ChibiOS/RT. 00005 00006 ChibiOS/RT is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 ChibiOS/RT is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 00019 --- 00020 00021 A special exception to the GPL can be applied should you wish to distribute 00022 a combined work that includes ChibiOS/RT, without being obliged to provide 00023 the source code for any proprietary components. See the file exception.txt 00024 for full details of how and when the exception can be applied. 00025 */ 00026 00027 /** 00028 * @file adc.c 00029 * @brief ADC Driver code. 00030 * 00031 * @addtogroup ADC 00032 * @{ 00033 */ 00034 00035 #include "ch.h" 00036 #include "hal.h" 00037 00038 #if CH_HAL_USE_ADC || defined(__DOXYGEN__) 00039 00040 /*===========================================================================*/ 00041 /* Driver exported variables. */ 00042 /*===========================================================================*/ 00043 00044 /*===========================================================================*/ 00045 /* Driver local variables. */ 00046 /*===========================================================================*/ 00047 00048 /*===========================================================================*/ 00049 /* Driver local functions. */ 00050 /*===========================================================================*/ 00051 00052 /*===========================================================================*/ 00053 /* Driver exported functions. */ 00054 /*===========================================================================*/ 00055 00056 /** 00057 * @brief ADC Driver initialization. 00058 */ 00059 void adcInit(void) { 00060 00061 adc_lld_init(); 00062 } 00063 00064 /** 00065 * @brief Initializes the standard part of a @p ADCDriver structure. 00066 * 00067 * @param[in] adcp pointer to the @p ADCDriver object 00068 */ 00069 void adcObjectInit(ADCDriver *adcp) { 00070 00071 adcp->ad_state = ADC_STOP; 00072 adcp->ad_config = NULL; 00073 adcp->ad_callback = NULL; 00074 adcp->ad_samples = NULL; 00075 adcp->ad_depth = 0; 00076 adcp->ad_grpp = NULL; 00077 chSemInit(&adcp->ad_sem, 0); 00078 } 00079 00080 /** 00081 * @brief Configures and activates the ADC peripheral. 00082 * 00083 * @param[in] adcp pointer to the @p ADCDriver object 00084 * @param[in] config pointer to the @p ADCConfig object 00085 */ 00086 void adcStart(ADCDriver *adcp, const ADCConfig *config) { 00087 00088 chDbgCheck((adcp != NULL) && (config != NULL), "adcStart"); 00089 00090 chSysLock(); 00091 chDbgAssert((adcp->ad_state == ADC_STOP) || (adcp->ad_state == ADC_READY), 00092 "adcStart(), #1", 00093 "invalid state"); 00094 adcp->ad_config = config; 00095 adc_lld_start(adcp); 00096 adcp->ad_state = ADC_READY; 00097 chSysUnlock(); 00098 } 00099 00100 /** 00101 * @brief Deactivates the ADC peripheral. 00102 * 00103 * @param[in] adcp pointer to the @p ADCDriver object 00104 */ 00105 void adcStop(ADCDriver *adcp) { 00106 00107 chDbgCheck(adcp != NULL, "adcStop"); 00108 00109 chSysLock(); 00110 chDbgAssert((adcp->ad_state == ADC_STOP) || 00111 (adcp->ad_state == ADC_READY) || 00112 (adcp->ad_state == ADC_COMPLETE), 00113 "adcStop(), #1", 00114 "invalid state"); 00115 adc_lld_stop(adcp); 00116 adcp->ad_state = ADC_STOP; 00117 chSysUnlock(); 00118 } 00119 00120 /** 00121 * @brief Starts an ADC conversion. 00122 * @details Starts a conversion operation, there are two kind of conversion 00123 * modes: 00124 * - <b>LINEAR</b>, in this mode the buffer is filled once and then 00125 * the conversion stops automatically. 00126 * - <b>CIRCULAR</b>, in this mode the conversion never stops and 00127 * the buffer is filled circularly.<br> 00128 * During the conversion the callback function is invoked when 00129 * the buffer is 50% filled and when the buffer is 100% filled, 00130 * this way is possible to process the conversion stream in real 00131 * time. This kind of conversion can only be stopped by explicitly 00132 * invoking @p adcStopConversion(). 00133 * . 00134 * @note The buffer is organized as a matrix of M*N elements where M is the 00135 * channels number configured into the conversion group and N is the 00136 * buffer depth. The samples are sequentially written into the buffer 00137 * with no gaps. 00138 * 00139 * @param[in] adcp pointer to the @p ADCDriver object 00140 * @param[in] grpp pointer to a @p ADCConversionGroup object 00141 * @param[out] samples pointer to the samples buffer 00142 * @param[in] depth buffer depth (matrix rows number). The buffer depth 00143 * must be one or an even number. 00144 * @param[in] callback pointer to the conversion callback function, this 00145 * parameter can be @p NULL if a callback is not required 00146 * @return The operation status. 00147 * @retval FALSE the conversion has been started. 00148 * @retval TRUE the driver is busy, conversion not started. 00149 */ 00150 bool_t adcStartConversion(ADCDriver *adcp, 00151 const ADCConversionGroup *grpp, 00152 adcsample_t *samples, 00153 size_t depth, 00154 adccallback_t callback) { 00155 00156 chDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) && 00157 ((depth == 1) || ((depth & 1) == 0)), 00158 "adcStartConversion"); 00159 00160 chSysLock(); 00161 chDbgAssert((adcp->ad_state == ADC_READY) || 00162 (adcp->ad_state == ADC_RUNNING) || 00163 (adcp->ad_state == ADC_COMPLETE), 00164 "adcStartConversion(), #1", 00165 "invalid state"); 00166 if (adcp->ad_state == ADC_RUNNING) { 00167 chSysUnlock(); 00168 return TRUE; 00169 } 00170 adcp->ad_callback = callback; 00171 adcp->ad_samples = samples; 00172 adcp->ad_depth = depth; 00173 adcp->ad_grpp = grpp; 00174 adc_lld_start_conversion(adcp); 00175 adcp->ad_state = ADC_RUNNING; 00176 chSysUnlock(); 00177 return FALSE; 00178 } 00179 00180 /** 00181 * @brief Stops an ongoing conversion. 00182 * 00183 * @param[in] adcp pointer to the @p ADCDriver object 00184 */ 00185 void adcStopConversion(ADCDriver *adcp) { 00186 00187 chDbgCheck(adcp != NULL, "adcStopConversion"); 00188 00189 chSysLock(); 00190 chDbgAssert((adcp->ad_state == ADC_READY) || 00191 (adcp->ad_state == ADC_RUNNING) || 00192 (adcp->ad_state == ADC_COMPLETE), 00193 "adcStopConversion(), #1", 00194 "invalid state"); 00195 if (adcp->ad_state == ADC_RUNNING) { 00196 adc_lld_stop_conversion(adcp); 00197 adcp->ad_grpp = NULL; 00198 adcp->ad_state = ADC_READY; 00199 chSemResetI(&adcp->ad_sem, 0); 00200 chSchRescheduleS(); 00201 } 00202 else 00203 adcp->ad_state = ADC_READY; 00204 chSysUnlock(); 00205 } 00206 00207 /** 00208 * @brief Waits for completion. 00209 * @details If the conversion is not completed or not yet started then the 00210 * invoking thread waits for a conversion completion event. 00211 * 00212 * @param[in] adcp pointer to the @p ADCDriver object 00213 * @param[in] timeout the number of ticks before the operation timeouts, 00214 * the following special values are allowed: 00215 * - @a TIME_IMMEDIATE immediate timeout. 00216 * - @a TIME_INFINITE no timeout. 00217 * . 00218 * @return The operation result. 00219 * @retval RDY_OK conversion finished. 00220 * @retval RDY_TIMEOUT conversion not finished within the specified time. 00221 */ 00222 msg_t adcWaitConversion(ADCDriver *adcp, systime_t timeout) { 00223 00224 chSysLock(); 00225 chDbgAssert((adcp->ad_state == ADC_READY) || 00226 (adcp->ad_state == ADC_RUNNING) || 00227 (adcp->ad_state == ADC_COMPLETE), 00228 "adcWaitConversion(), #1", 00229 "invalid state"); 00230 if (adcp->ad_state != ADC_COMPLETE) { 00231 if (chSemWaitTimeoutS(&adcp->ad_sem, timeout) == RDY_TIMEOUT) { 00232 chSysUnlock(); 00233 return RDY_TIMEOUT; 00234 } 00235 } 00236 chSysUnlock(); 00237 return RDY_OK; 00238 } 00239 00240 #endif /* CH_HAL_USE_ADC */ 00241 00242 /** @} */