ChibiOS/HAL 9.0.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 */
56void adcInit(void) {
57
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 */
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
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 * @return The operation status.
93 *
94 * @api
95 */
96msg_t adcStart(ADCDriver *adcp, const ADCConfig *config) {
97 msg_t msg;
98
99 osalDbgCheck(adcp != NULL);
100
101 osalSysLock();
102 osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY),
103 "invalid state");
104 adcp->config = config;
105
106#if defined(ADC_LLD_ENHANCED_API)
107 msg = adc_lld_start(adcp);
108 if (msg == HAL_RET_SUCCESS) {
109 adcp->state = ADC_READY;
110 }
111 else {
112 adcp->state = ADC_STOP;
113 }
114#else
115 adc_lld_start(adcp);
116 adcp->state = ADC_READY;
117 msg = HAL_RET_SUCCESS;
118#endif
119
121
122 return msg;
123}
124
125/**
126 * @brief Deactivates the ADC peripheral.
127 *
128 * @param[in] adcp pointer to the @p ADCDriver object
129 *
130 * @api
131 */
132void adcStop(ADCDriver *adcp) {
133
134 osalDbgCheck(adcp != NULL);
135
136 osalSysLock();
137
138 osalDbgAssert((adcp->state == ADC_STOP) || (adcp->state == ADC_READY),
139 "invalid state");
140
141 adc_lld_stop(adcp);
142 adcp->config = NULL;
143 adcp->state = ADC_STOP;
144
146}
147
148/**
149 * @brief Starts an ADC conversion.
150 * @details Starts an asynchronous conversion operation.
151 * @note The buffer is organized as a matrix of M*N elements where M is the
152 * channels number configured into the conversion group and N is the
153 * buffer depth. The samples are sequentially written into the buffer
154 * with no gaps.
155 *
156 * @param[in] adcp pointer to the @p ADCDriver object
157 * @param[in] grpp pointer to a @p ADCConversionGroup object
158 * @param[out] samples pointer to the samples buffer
159 * @param[in] depth buffer depth (matrix rows number). The buffer depth
160 * must be one or an even number.
161 *
162 * @api
163 */
165 const ADCConversionGroup *grpp,
166 adcsample_t *samples,
167 size_t depth) {
168
169 osalSysLock();
170 adcStartConversionI(adcp, grpp, samples, depth);
172}
173
174/**
175 * @brief Starts an ADC conversion.
176 * @details Starts an asynchronous conversion operation.
177 * @post The callbacks associated to the conversion group will be invoked
178 * on buffer fill and error events.
179 * @note The buffer is organized as a matrix of M*N elements where M is the
180 * channels number configured into the conversion group and N is the
181 * buffer depth. The samples are sequentially written into the buffer
182 * with no gaps.
183 *
184 * @param[in] adcp pointer to the @p ADCDriver object
185 * @param[in] grpp pointer to a @p ADCConversionGroup object
186 * @param[out] samples pointer to the samples buffer
187 * @param[in] depth buffer depth (matrix rows number). The buffer depth
188 * must be one or an even number.
189 *
190 * @iclass
191 */
193 const ADCConversionGroup *grpp,
194 adcsample_t *samples,
195 size_t depth) {
196
198 osalDbgCheck((adcp != NULL) && (grpp != NULL) && (samples != NULL) &&
199 (depth > 0U) && ((depth == 1U) || ((depth & 1U) == 0U)));
200 osalDbgAssert((adcp->state == ADC_READY) ||
201 (adcp->state == ADC_ERROR),
202 "not ready");
203
204 adcp->samples = samples;
205 adcp->depth = depth;
206 adcp->grpp = grpp;
207 adcp->state = ADC_ACTIVE;
209}
210
211/**
212 * @brief Stops an ongoing conversion.
213 * @details This function stops the currently ongoing conversion and returns
214 * the driver in the @p ADC_READY state. If there was no conversion
215 * being processed then the function does nothing.
216 *
217 * @param[in] adcp pointer to the @p ADCDriver object
218 *
219 * @api
220 */
222
223 osalDbgCheck(adcp != NULL);
224
225 osalSysLock();
226 osalDbgAssert((adcp->state == ADC_READY) || (adcp->state == ADC_ACTIVE),
227 "invalid state");
228 if (adcp->state != ADC_READY) {
230 adcp->grpp = NULL;
231 adcp->state = ADC_READY;
232 _adc_reset_s(adcp);
233 }
235}
236
237/**
238 * @brief Stops an ongoing conversion.
239 * @details This function stops the currently ongoing conversion and returns
240 * the driver in the @p ADC_READY state. If there was no conversion
241 * being processed then the function does nothing.
242 *
243 * @param[in] adcp pointer to the @p ADCDriver object
244 *
245 * @iclass
246 */
248
250 osalDbgCheck(adcp != NULL);
251 osalDbgAssert((adcp->state == ADC_READY) ||
252 (adcp->state == ADC_ACTIVE) ||
253 (adcp->state == ADC_COMPLETE),
254 "invalid state");
255
256 if (adcp->state != ADC_READY) {
258 adcp->grpp = NULL;
259 adcp->state = ADC_READY;
260 _adc_reset_i(adcp);
261 }
262}
263
264#if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
265/**
266 * @brief Performs an ADC conversion.
267 * @details Performs a synchronous conversion operation.
268 * @note The buffer is organized as a matrix of M*N elements where M is the
269 * channels number configured into the conversion group and N is the
270 * buffer depth. The samples are sequentially written into the buffer
271 * with no gaps.
272 *
273 * @param[in] adcp pointer to the @p ADCDriver object
274 * @param[in] grpp pointer to a @p ADCConversionGroup object
275 * @param[out] samples pointer to the samples buffer
276 * @param[in] depth buffer depth (matrix rows number). The buffer depth
277 * must be one or an even number.
278 * @return The operation result.
279 * @retval MSG_OK Conversion finished.
280 * @retval MSG_RESET The conversion has been stopped using
281 * @p acdStopConversion() or @p acdStopConversionI(),
282 * the result buffer may contain incorrect data.
283 * @retval MSG_TIMEOUT The conversion has been stopped because an hardware
284 * error.
285 *
286 * @api
287 */
289 const ADCConversionGroup *grpp,
290 adcsample_t *samples,
291 size_t depth) {
292 msg_t msg;
293
294 osalSysLock();
295 osalDbgAssert(adcp->thread == NULL, "already waiting");
296 adcStartConversionI(adcp, grpp, samples, depth);
297 msg = osalThreadSuspendS(&adcp->thread);
299 return msg;
300}
301#endif /* ADC_USE_WAIT == TRUE */
302
303#if (ADC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
304/**
305 * @brief Gains exclusive access to the ADC peripheral.
306 * @details This function tries to gain ownership to the ADC bus, if the bus
307 * is already being used then the invoking thread is queued.
308 * @pre In order to use this function the option
309 * @p ADC_USE_MUTUAL_EXCLUSION must be enabled.
310 *
311 * @param[in] adcp pointer to the @p ADCDriver object
312 *
313 * @api
314 */
316
317 osalDbgCheck(adcp != NULL);
318
319 osalMutexLock(&adcp->mutex);
320}
321
322/**
323 * @brief Releases exclusive access to the ADC peripheral.
324 * @pre In order to use this function the option
325 * @p ADC_USE_MUTUAL_EXCLUSION must be enabled.
326 *
327 * @param[in] adcp pointer to the @p ADCDriver object
328 *
329 * @api
330 */
332
333 osalDbgCheck(adcp != NULL);
334
335 osalMutexUnlock(&adcp->mutex);
336}
337#endif /* ADC_USE_MUTUAL_EXCLUSION == TRUE */
338
339#endif /* HAL_USE_ADC == TRUE */
340
341/** @} */
void adc_lld_stop_conversion(ADCDriver *adcp)
Stops an ongoing conversion.
struct hal_adc_driver ADCDriver
Type of a structure representing an ADC driver.
Definition hal_adc.h:82
void adcStartConversionI(ADCDriver *adcp, const ADCConversionGroup *grpp, adcsample_t *samples, size_t depth)
Starts an ADC conversion.
Definition hal_adc.c:192
void adc_lld_init(void)
Low level ADC driver initialization.
Definition hal_adc_lld.c:65
msg_t adcStart(ADCDriver *adcp, const ADCConfig *config)
Configures and activates the ADC peripheral.
Definition hal_adc.c:96
void adcStop(ADCDriver *adcp)
Deactivates the ADC peripheral.
Definition hal_adc.c:132
void adc_lld_start_conversion(ADCDriver *adcp)
Starts an ADC conversion.
void adc_lld_stop(ADCDriver *adcp)
Deactivates the ADC peripheral.
void adcAcquireBus(ADCDriver *adcp)
Gains exclusive access to the ADC peripheral.
Definition hal_adc.c:315
struct hal_adc_configuration_group ADCConversionGroup
Conversion group configuration structure.
Definition hal_adc.h:97
#define _adc_reset_s(adcp)
Resumes a thread waiting for a conversion completion.
Definition hal_adc.h:246
struct hal_adc_config ADCConfig
Type of a structure representing an ADC driver configuration.
Definition hal_adc.h:87
void adc_lld_start(ADCDriver *adcp)
Configures and activates the ADC peripheral.
Definition hal_adc_lld.c:80
void adcStopConversionI(ADCDriver *adcp)
Stops an ongoing conversion.
Definition hal_adc.c:247
#define _adc_reset_i(adcp)
Resumes a thread waiting for a conversion completion.
Definition hal_adc.h:236
void adcStartConversion(ADCDriver *adcp, const ADCConversionGroup *grpp, adcsample_t *samples, size_t depth)
Starts an ADC conversion.
Definition hal_adc.c:164
void adcStopConversion(ADCDriver *adcp)
Stops an ongoing conversion.
Definition hal_adc.c:221
uint16_t adcsample_t
ADC sample data type.
Definition hal_adc_lld.h:72
void adcObjectInit(ADCDriver *adcp)
Initializes the standard part of a ADCDriver structure.
Definition hal_adc.c:68
void adcReleaseBus(ADCDriver *adcp)
Releases exclusive access to the ADC peripheral.
Definition hal_adc.c:331
msg_t adcConvert(ADCDriver *adcp, const ADCConversionGroup *grpp, adcsample_t *samples, size_t depth)
Performs an ADC conversion.
Definition hal_adc.c:288
void adcInit(void)
ADC Driver initialization.
Definition hal_adc.c:56
@ ADC_STOP
Definition hal_adc.h:72
@ ADC_ERROR
Definition hal_adc.h:76
@ ADC_READY
Definition hal_adc.h:73
@ ADC_COMPLETE
Definition hal_adc.h:75
@ ADC_ACTIVE
Definition hal_adc.h:74
#define HAL_RET_SUCCESS
Definition hal.h:93
static void osalSysLock(void)
Enters a critical zone from thread context.
Definition osal.h:601
static void osalMutexObjectInit(mutex_t *mp)
Initializes a mutex_t object.
Definition osal.h:753
static void osalSysUnlock(void)
Leaves a critical zone from thread context.
Definition osal.h:611
int32_t msg_t
Type of a message.
Definition osal.h:159
msg_t osalThreadSuspendS(thread_reference_t *trp)
Sends the current thread sleeping and sets a reference variable.
Definition osal.c:183
void osalMutexLock(mutex_t *mp)
Locks the specified mutex.
Definition osal.c:380
#define osalDbgAssert(c, remark)
Condition assertion.
Definition osal.h:264
void osalMutexUnlock(mutex_t *mp)
Unlocks the specified mutex.
Definition osal.c:400
#define osalDbgCheck(c)
Function parameters check.
Definition osal.h:284
#define osalDbgCheckClassI()
I-Class state check.
Definition osal.h:298
HAL subsystem header.
adcsample_t * samples
Current samples buffer pointer or NULL.
Definition hal_adc.h:172
const ADCConversionGroup * grpp
Current conversion group pointer or NULL.
Definition hal_adc.h:180
adcstate_t state
Driver state.
Definition hal_adc.h:164
size_t depth
Current samples buffer depth or 0.
Definition hal_adc.h:176
const ADCConfig * config
Current configuration data.
Definition hal_adc.h:168
thread_reference_t thread
Waiting thread.
Definition hal_adc.h:185
mutex_t mutex
Mutex protecting the peripheral.
Definition hal_adc.h:191