ChibiOS  21.6.0
hal_adc.c
Go to the documentation of this file.
1 /*
2  ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15 */
16 
17 /**
18  * @file hal_adc.c
19  * @brief ADC Driver code.
20  *
21  * @addtogroup ADC
22  * @{
23  */
24 
25 #include "hal.h"
26 
27 #if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
28 
29 /*===========================================================================*/
30 /* Driver local definitions. */
31 /*===========================================================================*/
32 
33 /*===========================================================================*/
34 /* Driver exported variables. */
35 /*===========================================================================*/
36 
37 /*===========================================================================*/
38 /* Driver local variables and types. */
39 /*===========================================================================*/
40 
41 /*===========================================================================*/
42 /* Driver local functions. */
43 /*===========================================================================*/
44 
45 /*===========================================================================*/
46 /* Driver exported functions. */
47 /*===========================================================================*/
48 
49 /**
50  * @brief ADC Driver initialization.
51  * @note This function is implicitly invoked by @p halInit(), there is
52  * no need to explicitly initialize the driver.
53  *
54  * @init
55  */
56 void adcInit(void) {
57 
58  adc_lld_init();
59 }
60 
61 /**
62  * @brief Initializes the standard part of a @p ADCDriver structure.
63  *
64  * @param[out] adcp pointer to the @p ADCDriver object
65  *
66  * @init
67  */
68 void adcObjectInit(ADCDriver *adcp) {
69 
70  adcp->state = ADC_STOP;
71  adcp->config = NULL;
72  adcp->samples = NULL;
73  adcp->depth = 0;
74  adcp->grpp = NULL;
75 #if ADC_USE_WAIT == TRUE
76  adcp->thread = NULL;
77 #endif
78 #if ADC_USE_MUTUAL_EXCLUSION == TRUE
79  osalMutexObjectInit(&adcp->mutex);
80 #endif
81 #if defined(ADC_DRIVER_EXT_INIT_HOOK)
82  ADC_DRIVER_EXT_INIT_HOOK(adcp);
83 #endif
84 }
85 
86 /**
87  * @brief Configures and activates the ADC peripheral.
88  *
89  * @param[in] adcp pointer to the @p ADCDriver object
90  * @param[in] config pointer to the @p ADCConfig object. Depending on
91  * the implementation the value can be @p NULL.
92  *
93  * @api
94  */
95 void adcStart(ADCDriver *adcp, const ADCConfig *config) {
96 
97  osalDbgCheck(adcp != NULL);
98 
99  osalSysLock();
100  osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY),
101  "invalid state");
102  adcp->config = config;
103  adc_lld_start(adcp);
104  adcp->state = ADC_READY;
105  osalSysUnlock();
106 }
107 
108 /**
109  * @brief Deactivates the ADC peripheral.
110  *
111  * @param[in] adcp pointer to the @p ADCDriver object
112  *
113  * @api
114  */
115 void adcStop(ADCDriver *adcp) {
116 
117  osalDbgCheck(adcp != NULL);
118 
119  osalSysLock();
120 
121  osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY),
122  "invalid state");
123 
124  adc_lld_stop(adcp);
125  adcp->config = NULL;
126  adcp->state = ADC_STOP;
127 
128  osalSysUnlock();
129 }
130 
131 /**
132  * @brief Starts an ADC conversion.
133  * @details Starts an asynchronous conversion operation.
134  * @note The buffer is organized as a matrix of M*N elements where M is the
135  * channels number configured into the conversion group and N is the
136  * buffer depth. The samples are sequentially written into the buffer
137  * with no gaps.
138  *
139  * @param[in] adcp pointer to the @p ADCDriver object
140  * @param[in] grpp pointer to a @p ADCConversionGroup object
141  * @param[out] samples pointer to the samples buffer
142  * @param[in] depth buffer depth (matrix rows number). The buffer depth
143  * must be one or an even number.
144  *
145  * @api
146  */
148  const ADCConversionGroup *grpp,
149  adcsample_t *samples,
150  size_t depth) {
151 
152  osalSysLock();
153  adcStartConversionI(adcp, grpp, samples, depth);
154  osalSysUnlock();
155 }
156 
157 /**
158  * @brief Starts an ADC conversion.
159  * @details Starts an asynchronous conversion operation.
160  * @post The callbacks associated to the conversion group will be invoked
161  * on buffer fill and error events.
162  * @note The buffer is organized as a matrix of M*N elements where M is the
163  * channels number configured into the conversion group and N is the
164  * buffer depth. The samples are sequentially written into the buffer
165  * with no gaps.
166  *
167  * @param[in] adcp pointer to the @p ADCDriver object
168  * @param[in] grpp pointer to a @p ADCConversionGroup object
169  * @param[out] samples pointer to the samples buffer
170  * @param[in] depth buffer depth (matrix rows number). The buffer depth
171  * must be one or an even number.
172  *
173  * @iclass
174  */
176  const ADCConversionGroup *grpp,
177  adcsample_t *samples,
178  size_t depth) {
179 
181  osalDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) &&
182  (depth > 0U) && ((depth == 1U) || ((depth & 1U) == 0U)));
183  osalDbgAssert((adcp->state == ADC_READY) ||
184  (adcp->state == ADC_ERROR),
185  "not ready");
186 
187  adcp->samples = samples;
188  adcp->depth = depth;
189  adcp->grpp = grpp;
190  adcp->state = ADC_ACTIVE;
192 }
193 
194 /**
195  * @brief Stops an ongoing conversion.
196  * @details This function stops the currently ongoing conversion and returns
197  * the driver in the @p ADC_READY state. If there was no conversion
198  * being processed then the function does nothing.
199  *
200  * @param[in] adcp pointer to the @p ADCDriver object
201  *
202  * @api
203  */
205 
206  osalDbgCheck(adcp != NULL);
207 
208  osalSysLock();
209  osalDbgAssert((adcp->state == ADC_READY) || (adcp->state == ADC_ACTIVE),
210  "invalid state");
211  if (adcp->state != ADC_READY) {
213  adcp->grpp = NULL;
214  adcp->state = ADC_READY;
215  _adc_reset_s(adcp);
216  }
217  osalSysUnlock();
218 }
219 
220 /**
221  * @brief Stops an ongoing conversion.
222  * @details This function stops the currently ongoing conversion and returns
223  * the driver in the @p ADC_READY state. If there was no conversion
224  * being processed then the function does nothing.
225  *
226  * @param[in] adcp pointer to the @p ADCDriver object
227  *
228  * @iclass
229  */
231 
233  osalDbgCheck(adcp != NULL);
234  osalDbgAssert((adcp->state == ADC_READY) ||
235  (adcp->state == ADC_ACTIVE) ||
236  (adcp->state == ADC_COMPLETE),
237  "invalid state");
238 
239  if (adcp->state != ADC_READY) {
241  adcp->grpp = NULL;
242  adcp->state = ADC_READY;
243  _adc_reset_i(adcp);
244  }
245 }
246 
247 #if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
248 /**
249  * @brief Performs an ADC conversion.
250  * @details Performs a synchronous conversion operation.
251  * @note The buffer is organized as a matrix of M*N elements where M is the
252  * channels number configured into the conversion group and N is the
253  * buffer depth. The samples are sequentially written into the buffer
254  * with no gaps.
255  *
256  * @param[in] adcp pointer to the @p ADCDriver object
257  * @param[in] grpp pointer to a @p ADCConversionGroup object
258  * @param[out] samples pointer to the samples buffer
259  * @param[in] depth buffer depth (matrix rows number). The buffer depth
260  * must be one or an even number.
261  * @return The operation result.
262  * @retval MSG_OK Conversion finished.
263  * @retval MSG_RESET The conversion has been stopped using
264  * @p acdStopConversion() or @p acdStopConversionI(),
265  * the result buffer may contain incorrect data.
266  * @retval MSG_TIMEOUT The conversion has been stopped because an hardware
267  * error.
268  *
269  * @api
270  */
272  const ADCConversionGroup *grpp,
273  adcsample_t *samples,
274  size_t depth) {
275  msg_t msg;
276 
277  osalSysLock();
278  osalDbgAssert(adcp->thread == NULL, "already waiting");
279  adcStartConversionI(adcp, grpp, samples, depth);
280  msg = osalThreadSuspendS(&adcp->thread);
281  osalSysUnlock();
282  return msg;
283 }
284 #endif /* ADC_USE_WAIT == TRUE */
285 
286 #if (ADC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
287 /**
288  * @brief Gains exclusive access to the ADC peripheral.
289  * @details This function tries to gain ownership to the ADC bus, if the bus
290  * is already being used then the invoking thread is queued.
291  * @pre In order to use this function the option
292  * @p ADC_USE_MUTUAL_EXCLUSION must be enabled.
293  *
294  * @param[in] adcp pointer to the @p ADCDriver object
295  *
296  * @api
297  */
299 
300  osalDbgCheck(adcp != NULL);
301 
302  osalMutexLock(&adcp->mutex);
303 }
304 
305 /**
306  * @brief Releases exclusive access to the ADC peripheral.
307  * @pre In order to use this function the option
308  * @p ADC_USE_MUTUAL_EXCLUSION must be enabled.
309  *
310  * @param[in] adcp pointer to the @p ADCDriver object
311  *
312  * @api
313  */
315 
316  osalDbgCheck(adcp != NULL);
317 
318  osalMutexUnlock(&adcp->mutex);
319 }
320 #endif /* ADC_USE_MUTUAL_EXCLUSION == TRUE */
321 
322 #endif /* HAL_USE_ADC == TRUE */
323 
324 /** @} */
ADC_ACTIVE
@ ADC_ACTIVE
Definition: hal_adc.h:74
_adc_reset_i
#define _adc_reset_i(adcp)
Resumes a thread waiting for a conversion completion.
Definition: hal_adc.h:236
adc_lld_init
void adc_lld_init(void)
Low level ADC driver initialization.
Definition: hal_adc_lld.c:65
ADC_COMPLETE
@ ADC_COMPLETE
Definition: hal_adc.h:75
osalThreadSuspendS
msg_t osalThreadSuspendS(thread_reference_t *trp)
Sends the current thread sleeping and sets a reference variable.
Definition: osal.c:185
ADC_READY
@ ADC_READY
Definition: hal_adc.h:73
hal.h
HAL subsystem header.
hal_adc_driver::thread
thread_reference_t thread
Waiting thread.
Definition: hal_adc.h:185
adcsample_t
uint16_t adcsample_t
ADC sample data type.
Definition: hal_adc_lld.h:72
osalDbgCheckClassI
#define osalDbgCheckClassI()
I-Class state check.
Definition: osal.h:298
adcConvert
msg_t adcConvert(ADCDriver *adcp, const ADCConversionGroup *grpp, adcsample_t *samples, size_t depth)
Performs an ADC conversion.
Definition: hal_adc.c:271
osalSysUnlock
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition: osal.h:611
adcObjectInit
void adcObjectInit(ADCDriver *adcp)
Initializes the standard part of a ADCDriver structure.
Definition: hal_adc.c:68
hal_adc_driver::mutex
mutex_t mutex
Mutex protecting the peripheral.
Definition: hal_adc.h:191
hal_adc_configuration_group
Conversion group configuration structure.
Definition: hal_adc.h:128
msg_t
int32_t msg_t
Definition: chearly.h:88
adcStopConversion
void adcStopConversion(ADCDriver *adcp)
Stops an ongoing conversion.
Definition: hal_adc.c:204
osalMutexLock
void osalMutexLock(mutex_t *mp)
Locks the specified mutex.
Definition: osal.c:384
adcStartConversion
void adcStartConversion(ADCDriver *adcp, const ADCConversionGroup *grpp, adcsample_t *samples, size_t depth)
Starts an ADC conversion.
Definition: hal_adc.c:147
adcInit
void adcInit(void)
ADC Driver initialization.
Definition: hal_adc.c:56
hal_adc_driver::depth
size_t depth
Current samples buffer depth or 0.
Definition: hal_adc.h:176
hal_adc_driver
Structure representing an ADC driver.
Definition: hal_adc.h:160
adc_lld_start
void adc_lld_start(ADCDriver *adcp)
Configures and activates the ADC peripheral.
Definition: hal_adc_lld.c:80
adc_lld_stop_conversion
void adc_lld_stop_conversion(ADCDriver *adcp)
Stops an ongoing conversion.
Definition: hal_adc_lld.c:134
adc_lld_start_conversion
void adc_lld_start_conversion(ADCDriver *adcp)
Starts an ADC conversion.
Definition: hal_adc_lld.c:122
ADC_STOP
@ ADC_STOP
Definition: hal_adc.h:72
ADC_ERROR
@ ADC_ERROR
Definition: hal_adc.h:76
hal_adc_driver::samples
adcsample_t * samples
Current samples buffer pointer or NULL.
Definition: hal_adc.h:172
_adc_reset_s
#define _adc_reset_s(adcp)
Resumes a thread waiting for a conversion completion.
Definition: hal_adc.h:246
osalDbgCheck
#define osalDbgCheck(c)
Function parameters check.
Definition: osal.h:284
adcStartConversionI
void adcStartConversionI(ADCDriver *adcp, const ADCConversionGroup *grpp, adcsample_t *samples, size_t depth)
Starts an ADC conversion.
Definition: hal_adc.c:175
osalSysLock
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition: osal.h:601
adcAcquireBus
void adcAcquireBus(ADCDriver *adcp)
Gains exclusive access to the ADC peripheral.
Definition: hal_adc.c:298
adcStopConversionI
void adcStopConversionI(ADCDriver *adcp)
Stops an ongoing conversion.
Definition: hal_adc.c:230
adcReleaseBus
void adcReleaseBus(ADCDriver *adcp)
Releases exclusive access to the ADC peripheral.
Definition: hal_adc.c:314
osalDbgAssert
#define osalDbgAssert(c, remark)
Condition assertion.
Definition: osal.h:264
adcStop
void adcStop(ADCDriver *adcp)
Deactivates the ADC peripheral.
Definition: hal_adc.c:115
hal_adc_config
Driver configuration structure.
Definition: hal_adc.h:152
hal_adc_driver::state
adcstate_t state
Driver state.
Definition: hal_adc.h:164
hal_adc_driver::grpp
const ADCConversionGroup * grpp
Current conversion group pointer or NULL.
Definition: hal_adc.h:180
adcStart
void adcStart(ADCDriver *adcp, const ADCConfig *config)
Configures and activates the ADC peripheral.
Definition: hal_adc.c:95
osalMutexUnlock
void osalMutexUnlock(mutex_t *mp)
Unlocks the specified mutex.
Definition: osal.c:404
hal_adc_driver::config
const ADCConfig * config
Current configuration data.
Definition: hal_adc.h:168
adc_lld_stop
void adc_lld_stop(ADCDriver *adcp)
Deactivates the ADC peripheral.
Definition: hal_adc_lld.c:101
osalMutexObjectInit
static void osalMutexObjectInit(mutex_t *mp)
Initializes s mutex_t object.
Definition: osal.h:753