ChibiOS  21.6.0
hal_adc.h
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.h
19  * @brief ADC Driver macros and structures.
20  *
21  * @addtogroup ADC
22  * @{
23  */
24 
25 #ifndef HAL_ADC_H
26 #define HAL_ADC_H
27 
28 #if (HAL_USE_ADC == TRUE) || defined(__DOXYGEN__)
29 
30 /*===========================================================================*/
31 /* Driver constants. */
32 /*===========================================================================*/
33 
34 /*===========================================================================*/
35 /* Driver pre-compile time settings. */
36 /*===========================================================================*/
37 
38 /**
39  * @name ADC configuration options
40  * @{
41  */
42 /**
43  * @brief Enables synchronous APIs.
44  * @note Disabling this option saves both code and data space.
45  */
46 #if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__)
47 #define ADC_USE_WAIT TRUE
48 #endif
49 
50 /**
51  * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs.
52  * @note Disabling this option saves both code and data space.
53  */
54 #if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__)
55 #define ADC_USE_MUTUAL_EXCLUSION TRUE
56 #endif
57 /** @} */
58 
59 /*===========================================================================*/
60 /* Derived constants and error checks. */
61 /*===========================================================================*/
62 
63 /*===========================================================================*/
64 /* Driver data structures and types. */
65 /*===========================================================================*/
66 
67 /**
68  * @brief Driver state machine possible states.
69  */
70 typedef enum {
71  ADC_UNINIT = 0, /**< Not initialized. */
72  ADC_STOP = 1, /**< Stopped. */
73  ADC_READY = 2, /**< Ready. */
74  ADC_ACTIVE = 3, /**< Converting. */
75  ADC_COMPLETE = 4, /**< Conversion complete. */
76  ADC_ERROR = 5 /**< Conversion error. */
77 } adcstate_t;
78 
79 /**
80  * @brief Type of a structure representing an ADC driver.
81  */
82 typedef struct hal_adc_driver ADCDriver;
83 
84 /**
85  * @brief Type of a structure representing an ADC driver configuration.
86  */
87 typedef struct hal_adc_config ADCConfig;
88 
89 /**
90  * @brief Conversion group configuration structure.
91  * @details This implementation-dependent structure describes a conversion
92  * operation.
93  * @note The use of this configuration structure requires knowledge of
94  * STM32 ADC cell registers interface, please refer to the STM32
95  * reference manual for details.
96  */
98 
99 /* Including the low level driver header, it exports information required
100  for completing types.*/
101 #include "hal_adc_lld.h"
102 
103 /**
104  * @brief Type of an ADC notification callback.
105  *
106  * @param[in] adcp pointer to the @p ADCDriver object triggering the
107  * callback
108  */
109 typedef void (*adccallback_t)(ADCDriver *adcp);
110 
111 /**
112  * @brief Type of an ADC error callback.
113  *
114  * @param[in] adcp pointer to the @p ADCDriver object triggering the
115  * callback
116  * @param[in] err ADC error code
117  */
118 typedef void (*adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err);
119 
120 /**
121  * @brief Conversion group configuration structure.
122  * @details This implementation-dependent structure describes a conversion
123  * operation.
124  * @note The use of this configuration structure requires knowledge of
125  * STM32 ADC cell registers interface, please refer to the STM32
126  * reference manual for details.
127  */
129  /**
130  * @brief Enables the circular buffer mode for the group.
131  */
132  bool circular;
133  /**
134  * @brief Number of the analog channels belonging to the conversion group.
135  */
137  /**
138  * @brief Callback function associated to the group or @p NULL.
139  */
141  /**
142  * @brief Error callback or @p NULL.
143  */
145  /* End of the mandatory fields.*/
146  adc_lld_configuration_group_fields;
147 };
148 
149 /**
150  * @brief Driver configuration structure.
151  */
153  /* End of the mandatory fields.*/
154  adc_lld_config_fields;
155 };
156 
157 /**
158  * @brief Structure representing an ADC driver.
159  */
161  /**
162  * @brief Driver state.
163  */
165  /**
166  * @brief Current configuration data.
167  */
169  /**
170  * @brief Current samples buffer pointer or @p NULL.
171  */
173  /**
174  * @brief Current samples buffer depth or @p 0.
175  */
176  size_t depth;
177  /**
178  * @brief Current conversion group pointer or @p NULL.
179  */
181 #if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
182  /**
183  * @brief Waiting thread.
184  */
186 #endif /* ADC_USE_WAIT == TRUE */
187 #if (ADC_USE_MUTUAL_EXCLUSION == TRUE) || defined(__DOXYGEN__)
188  /**
189  * @brief Mutex protecting the peripheral.
190  */
192 #endif /* ADC_USE_MUTUAL_EXCLUSION == TRUE */
193 #if defined(ADC_DRIVER_EXT_FIELDS)
194  ADC_DRIVER_EXT_FIELDS
195 #endif
196  /* End of the mandatory fields.*/
197  adc_lld_driver_fields;
198 };
199 
200 /*===========================================================================*/
201 /* Driver macros. */
202 /*===========================================================================*/
203 
204 /**
205  * @name Macro Functions
206  * @{
207  */
208 /**
209  * @brief Buffer state.
210  * @note This function is meant to be called from the ADC callback only.
211  *
212  * @param[in] adcp pointer to the @p ADCDriver object
213  * @return The buffer state.
214  * @retval false if the driver filled/sent the first half of the
215  * buffer.
216  * @retval true if the driver filled/sent the second half of the
217  * buffer.
218  *
219  * @special
220  */
221 #define adcIsBufferComplete(adcp) ((bool)((adcp)->state == ADC_COMPLETE))
222 /** @} */
223 
224 /**
225  * @name Low level driver helper macros
226  * @{
227  */
228 #if (ADC_USE_WAIT == TRUE) || defined(__DOXYGEN__)
229 /**
230  * @brief Resumes a thread waiting for a conversion completion.
231  *
232  * @param[in] adcp pointer to the @p ADCDriver object
233  *
234  * @notapi
235  */
236 #define _adc_reset_i(adcp) \
237  osalThreadResumeI(&(adcp)->thread, MSG_RESET)
238 
239 /**
240  * @brief Resumes a thread waiting for a conversion completion.
241  *
242  * @param[in] adcp pointer to the @p ADCDriver object
243  *
244  * @notapi
245  */
246 #define _adc_reset_s(adcp) \
247  osalThreadResumeS(&(adcp)->thread, MSG_RESET)
248 
249 /**
250  * @brief Wakes up the waiting thread.
251  *
252  * @param[in] adcp pointer to the @p ADCDriver object
253  *
254  * @notapi
255  */
256 #define _adc_wakeup_isr(adcp) { \
257  osalSysLockFromISR(); \
258  osalThreadResumeI(&(adcp)->thread, MSG_OK); \
259  osalSysUnlockFromISR(); \
260 }
261 
262 /**
263  * @brief Wakes up the waiting thread with a timeout message.
264  *
265  * @param[in] adcp pointer to the @p ADCDriver object
266  *
267  * @notapi
268  */
269 #define _adc_timeout_isr(adcp) { \
270  osalSysLockFromISR(); \
271  osalThreadResumeI(&(adcp)->thread, MSG_TIMEOUT); \
272  osalSysUnlockFromISR(); \
273 }
274 
275 #else /* !ADC_USE_WAIT */
276 #define _adc_reset_i(adcp)
277 #define _adc_reset_s(adcp)
278 #define _adc_wakeup_isr(adcp)
279 #define _adc_timeout_isr(adcp)
280 #endif /* !ADC_USE_WAIT */
281 
282 /**
283  * @brief Common ISR code, half buffer event.
284  * @details This code handles the portable part of the ISR code:
285  * - Callback invocation.
286  * .
287  * @note This macro is meant to be used in the low level drivers
288  * implementation only.
289  *
290  * @param[in] adcp pointer to the @p ADCDriver object
291  *
292  * @notapi
293  */
294 #define _adc_isr_half_code(adcp) { \
295  if ((adcp)->grpp->end_cb != NULL) { \
296  (adcp)->grpp->end_cb(adcp); \
297  } \
298 }
299 
300 /**
301  * @brief Common ISR code, full buffer event.
302  * @details This code handles the portable part of the ISR code:
303  * - Callback invocation.
304  * - Waiting thread wakeup, if any.
305  * - Driver state transitions.
306  * .
307  * @note This macro is meant to be used in the low level drivers
308  * implementation only.
309  *
310  * @param[in] adcp pointer to the @p ADCDriver object
311  *
312  * @notapi
313  */
314 #define _adc_isr_full_code(adcp) { \
315  if ((adcp)->grpp->circular) { \
316  /* Callback handling.*/ \
317  if ((adcp)->grpp->end_cb != NULL) { \
318  (adcp)->state = ADC_COMPLETE; \
319  (adcp)->grpp->end_cb(adcp); \
320  if ((adcp)->state == ADC_COMPLETE) { \
321  (adcp)->state = ADC_ACTIVE; \
322  } \
323  } \
324  } \
325  else { \
326  /* End conversion.*/ \
327  adc_lld_stop_conversion(adcp); \
328  if ((adcp)->grpp->end_cb != NULL) { \
329  (adcp)->state = ADC_COMPLETE; \
330  (adcp)->grpp->end_cb(adcp); \
331  if ((adcp)->state == ADC_COMPLETE) { \
332  (adcp)->state = ADC_READY; \
333  (adcp)->grpp = NULL; \
334  } \
335  } \
336  else { \
337  (adcp)->state = ADC_READY; \
338  (adcp)->grpp = NULL; \
339  } \
340  _adc_wakeup_isr(adcp); \
341  } \
342 }
343 
344 /**
345  * @brief Common ISR code, error event.
346  * @details This code handles the portable part of the ISR code:
347  * - Callback invocation.
348  * - Waiting thread timeout signaling, if any.
349  * - Driver state transitions.
350  * .
351  * @note This macro is meant to be used in the low level drivers
352  * implementation only.
353  *
354  * @param[in] adcp pointer to the @p ADCDriver object
355  * @param[in] err platform dependent error code
356  *
357  * @notapi
358  */
359 #define _adc_isr_error_code(adcp, err) { \
360  adc_lld_stop_conversion(adcp); \
361  if ((adcp)->grpp->error_cb != NULL) { \
362  (adcp)->state = ADC_ERROR; \
363  (adcp)->grpp->error_cb(adcp, err); \
364  if ((adcp)->state == ADC_ERROR) { \
365  (adcp)->state = ADC_READY; \
366  (adcp)->grpp = NULL; \
367  } \
368  } \
369  else { \
370  (adcp)->state = ADC_READY; \
371  (adcp)->grpp = NULL; \
372  } \
373  _adc_timeout_isr(adcp); \
374 }
375 /** @} */
376 
377 /*===========================================================================*/
378 /* External declarations. */
379 /*===========================================================================*/
380 
381 #ifdef __cplusplus
382 extern "C" {
383 #endif
384  void adcInit(void);
385  void adcObjectInit(ADCDriver *adcp);
386  void adcStart(ADCDriver *adcp, const ADCConfig *config);
387  void adcStop(ADCDriver *adcp);
388  void adcStartConversion(ADCDriver *adcp,
389  const ADCConversionGroup *grpp,
390  adcsample_t *samples,
391  size_t depth);
392  void adcStartConversionI(ADCDriver *adcp,
393  const ADCConversionGroup *grpp,
394  adcsample_t *samples,
395  size_t depth);
396  void adcStopConversion(ADCDriver *adcp);
397  void adcStopConversionI(ADCDriver *adcp);
398 #if ADC_USE_WAIT == TRUE
399  msg_t adcConvert(ADCDriver *adcp,
400  const ADCConversionGroup *grpp,
401  adcsample_t *samples,
402  size_t depth);
403 #endif
404 #if ADC_USE_MUTUAL_EXCLUSION == TRUE
405  void adcAcquireBus(ADCDriver *adcp);
406  void adcReleaseBus(ADCDriver *adcp);
407 #endif
408 #ifdef __cplusplus
409 }
410 #endif
411 
412 #endif /* HAL_USE_ADC == TRUE */
413 
414 #endif /* HAL_ADC_H */
415 
416 /** @} */
ADC_ACTIVE
@ ADC_ACTIVE
Definition: hal_adc.h:74
ADC_COMPLETE
@ ADC_COMPLETE
Definition: hal_adc.h:75
ADC_READY
@ ADC_READY
Definition: hal_adc.h:73
adcerror_t
uint32_t adcerror_t
Type of an ADC error mask.
Definition: hal_adc_lld.h:82
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
adcConvert
msg_t adcConvert(ADCDriver *adcp, const ADCConversionGroup *grpp, adcsample_t *samples, size_t depth)
Performs an ADC conversion.
Definition: hal_adc.c:271
hal_adc_configuration_group::end_cb
adccallback_t end_cb
Callback function associated to the group or NULL.
Definition: hal_adc.h:140
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
hal_adc_configuration_group::circular
bool circular
Enables the circular buffer mode for the group.
Definition: hal_adc.h:132
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
ch_thread
Structure representing a thread.
Definition: chobjects.h:156
hal_adc_lld.h
PLATFORM ADC subsystem low level driver header.
adc_channels_num_t
uint16_t adc_channels_num_t
Channels number in a conversion group.
Definition: hal_adc_lld.h:77
ADC_STOP
@ ADC_STOP
Definition: hal_adc.h:72
adccallback_t
void(* adccallback_t)(ADCDriver *adcp)
Type of an ADC notification callback.
Definition: hal_adc.h:109
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
adcerrorcallback_t
void(* adcerrorcallback_t)(ADCDriver *adcp, adcerror_t err)
Type of an ADC error callback.
Definition: hal_adc.h:118
adcStartConversionI
void adcStartConversionI(ADCDriver *adcp, const ADCConversionGroup *grpp, adcsample_t *samples, size_t depth)
Starts an ADC conversion.
Definition: hal_adc.c:175
ch_mutex
Mutex structure.
Definition: chmtx.h:57
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
ADC_UNINIT
@ ADC_UNINIT
Definition: hal_adc.h:71
adcstate_t
adcstate_t
Driver state machine possible states.
Definition: hal_adc.h:70
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_configuration_group::error_cb
adcerrorcallback_t error_cb
Error callback or NULL.
Definition: hal_adc.h:144
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
hal_adc_driver::config
const ADCConfig * config
Current configuration data.
Definition: hal_adc.h:168
hal_adc_configuration_group::num_channels
adc_channels_num_t num_channels
Number of the analog channels belonging to the conversion group.
Definition: hal_adc.h:136