1 /*
2 * Copyright (c) 2022 HPMicro
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7 #ifndef HPM_ADC_H
8 #define HPM_ADC_H
9
10 #include "hpm_common.h"
11 #ifdef HPMSOC_HAS_HPMSDK_ADC12
12 #include "hpm_adc12_drv.h"
13 #endif
14 #ifdef HPMSOC_HAS_HPMSDK_ADC16
15 #include "hpm_adc16_drv.h"
16 #endif
17 #include "hpm_soc_feature.h"
18 /**
19 * @brief ADC HAL driver APIs
20 * @defgroup hpm_adc_interface HPM ADC driver APIs
21 * @ingroup hpm_adc_interfaces
22 * @{
23 */
24
25 /**
26 * @brief An ADC peripheral base address.
27 *
28 */
29 typedef union {
30 #ifdef HPMSOC_HAS_HPMSDK_ADC12
31 ADC12_Type *adc12;
32 #endif
33 #ifdef HPMSOC_HAS_HPMSDK_ADC16
34 ADC16_Type *adc16;
35 #endif
36 } adc_base;
37
38 /**
39 * @brief use adc12 or adc16.
40 *
41 */
42 #define ADCX_MODULE_ADC12 1
43 #define ADCX_MODULE_ADC16 2
44
45 typedef enum {
46 adc_module_adc12 = ADCX_MODULE_ADC12,
47 adc_module_adc16 = ADCX_MODULE_ADC16
48 } adc_module;
49
50 /**
51 * @brief ADC common configuration struct.
52 *
53 */
54 typedef struct {
55 adc_module module;
56 adc_base adc_base;
57 struct {
58 #ifdef HPMSOC_HAS_HPMSDK_ADC12
59 adc12_config_t adc12;
60 #endif
61 #ifdef HPMSOC_HAS_HPMSDK_ADC16
62 adc16_config_t adc16;
63 #endif
64 } config;
65 } adc_config_t;
66
67 /**
68 * @brief ADC channel configuration struct.
69 *
70 */
71 typedef struct {
72 adc_module module;
73 adc_base adc_base;
74 struct {
75 #ifdef HPMSOC_HAS_HPMSDK_ADC12
76 adc12_channel_config_t adc12_ch;
77 #endif
78 #ifdef HPMSOC_HAS_HPMSDK_ADC16
79 adc16_channel_config_t adc16_ch;
80 #endif
81 } config;
82 } adc_channel_config_t;
83
84 /**
85 * @brief ADC DMA configuration struct.
86 *
87 */
88 typedef struct {
89 adc_module module;
90 adc_base adc_base;
91 struct {
92 #ifdef HPMSOC_HAS_HPMSDK_ADC12
93 adc12_dma_config_t adc12;
94 #endif
95 #ifdef HPMSOC_HAS_HPMSDK_ADC16
96 adc16_dma_config_t adc16;
97 #endif
98 } config;
99 } adc_dma_config_t;
100
101 /**
102 * @brief ADC configuration struct for period mode.
103 *
104 */
105 typedef struct {
106 adc_module module;
107 adc_base adc_base;
108 struct {
109 #ifdef HPMSOC_HAS_HPMSDK_ADC12
110 adc12_prd_config_t adc12;
111 #endif
112 #ifdef HPMSOC_HAS_HPMSDK_ADC16
113 adc16_prd_config_t adc16;
114 #endif
115 } config;
116 } adc_prd_config_t;
117
118 /**
119 * @brief ADC configuration struct for sequence mode.
120 *
121 */
122 typedef struct {
123 adc_module module;
124 adc_base adc_base;
125 struct {
126 #ifdef HPMSOC_HAS_HPMSDK_ADC12
127 adc12_seq_config_t adc12;
128 #endif
129 #ifdef HPMSOC_HAS_HPMSDK_ADC16
130 adc16_seq_config_t adc16;
131 #endif
132 } config;
133 } adc_seq_config_t;
134
135 /**
136 * @brief ADC trigger configuration struct for preempt mode.
137 *
138 */
139 typedef struct {
140 adc_module module;
141 adc_base adc_base;
142 struct {
143 #ifdef HPMSOC_HAS_HPMSDK_ADC12
144 adc12_pmt_config_t adc12;
145 #endif
146 #ifdef HPMSOC_HAS_HPMSDK_ADC16
147 adc16_pmt_config_t adc16;
148 #endif
149 } config;
150 } adc_pmt_config_t;
151
152
153 typedef struct {
154 adc_module module;
155 adc_base adc_base;
156 } adc_type;
157
158
159
160 #ifdef __cplusplus
161 extern "C" {
162 #endif
163
164 /**
165 * @brief Get a default configuration for an ADC instance.
166 *
167 * @param[out] config A pointer to the configuration struct of "adc_config_t".
168 *
169 */
hpm_adc_init_default_config(adc_config_t * config)170 static inline void hpm_adc_init_default_config(adc_config_t *config)
171 {
172 if (config->module == adc_module_adc12) {
173 #ifdef HPMSOC_HAS_HPMSDK_ADC12
174 adc12_get_default_config(&config->config.adc12);
175 #endif
176 } else if (config->module == adc_module_adc16) {
177 #ifdef HPMSOC_HAS_HPMSDK_ADC16
178 adc16_get_default_config(&config->config.adc16);
179 #endif
180 }
181 }
182
183 /**
184 * @brief Get a default configuration for an ADC channel instance.
185 *
186 * @param[out] config A pointer to the configuration struct of "adc_channel_config_t".
187 *
188 */
hpm_adc_init_channel_default_config(adc_channel_config_t * config)189 static inline void hpm_adc_init_channel_default_config(adc_channel_config_t *config)
190 {
191 if (config->module == adc_module_adc12) {
192 #ifdef HPMSOC_HAS_HPMSDK_ADC12
193 adc12_get_channel_default_config(&config->config.adc12_ch);
194 #endif
195 } else if (config->module == adc_module_adc16) {
196 #ifdef HPMSOC_HAS_HPMSDK_ADC16
197 adc16_get_channel_default_config(&config->config.adc16_ch);
198 #endif
199 }
200 }
201
202 /**
203 * @brief Initialize an ADC instance.
204 *
205 * @param[in] config A pointer to the configuration struct of "adc_config_t".
206 * @retval status_success Initialize an ADC instance successfully.
207 * @retval status_invalid_argument Initialize an ADC instance unsuccessfully because of passing one or more invalid arguments.
208 */
hpm_adc_init(adc_config_t * config)209 static inline hpm_stat_t hpm_adc_init(adc_config_t *config)
210 {
211 if (config->module == adc_module_adc12) {
212 #ifdef HPMSOC_HAS_HPMSDK_ADC12
213 return adc12_init(config->adc_base.adc12, &config->config.adc12);
214 #else
215 return status_invalid_argument;
216 #endif
217 } else if (config->module == adc_module_adc16) {
218 #ifdef HPMSOC_HAS_HPMSDK_ADC16
219 return adc16_init(config->adc_base.adc16, &config->config.adc16);
220 #else
221 return status_invalid_argument;
222 #endif
223 } else {
224 return status_invalid_argument;
225 }
226 }
227
228 /**
229 * @brief Initialize an ADC channel.
230 *
231 * @param[in] config A pointer to the configuration struct of "adc_config_t".
232 * @retval status_success Initialize an ADC instance successfully.
233 * @retval status_invalid_argument Initialize an ADC instance unsuccessfully because of passing one or more invalid arguments.
234 */
hpm_adc_channel_init(adc_channel_config_t * config)235 static inline hpm_stat_t hpm_adc_channel_init(adc_channel_config_t *config)
236 {
237 if (config->module == adc_module_adc12) {
238 #ifdef HPMSOC_HAS_HPMSDK_ADC12
239 return adc12_init_channel(config->adc_base.adc12, &config->config.adc12_ch);
240 #else
241 return status_invalid_argument;
242 #endif
243 } else if (config->module == adc_module_adc16) {
244 #ifdef HPMSOC_HAS_HPMSDK_ADC16
245 return adc16_init_channel(config->adc_base.adc16, &config->config.adc16_ch);
246 #else
247 return status_invalid_argument;
248 #endif
249 } else {
250 return status_invalid_argument;
251 }
252 }
253
254 /**
255 * @brief Configure the periodic mode for an ADC instance.
256 *
257 * @param[in] config A pointer to the configuration struct of "adc_prd_config_t".
258 * @retval status_success Configure the periodic mode for an ADC instance successfully.
259 * @retval status_invalid_argument Configure the periodic mode for an ADC instance unsuccessfully because of passing one or more invalid arguments.
260 *
261 */
hpm_adc_set_period_config(adc_prd_config_t * config)262 static inline hpm_stat_t hpm_adc_set_period_config(adc_prd_config_t *config)
263 {
264 if (config->module == adc_module_adc12) {
265 #ifdef HPMSOC_HAS_HPMSDK_ADC12
266 return adc12_set_prd_config(config->adc_base.adc12, &config->config.adc12);
267 #else
268 return status_invalid_argument;
269 #endif
270 } else if (config->module == adc_module_adc16) {
271 #ifdef HPMSOC_HAS_HPMSDK_ADC16
272 return adc16_set_prd_config(config->adc_base.adc16, &config->config.adc16);
273 #else
274 return status_invalid_argument;
275 #endif
276 } else {
277 return status_invalid_argument;
278 }
279 }
280
281 /**
282 * @brief Configure the sequence mode for an ADC instance.
283 *
284 * @param[in] config A pointer to configuration struct of "adc_seq_config_t".
285 * @retval status_success Configure the sequence mode for an ADC instance successfully.
286 * @retval status_invalid_argument Configure the sequence mode for an ADC instance unsuccessfully because of passing one or more invalid arguments.
287 */
hpm_adc_set_sequence_config(adc_seq_config_t * config)288 static inline hpm_stat_t hpm_adc_set_sequence_config(adc_seq_config_t *config)
289 {
290 if (config->module == adc_module_adc12) {
291 #ifdef HPMSOC_HAS_HPMSDK_ADC12
292 return adc12_set_seq_config(config->adc_base.adc12, &config->config.adc12);
293 #else
294 return status_invalid_argument;
295 #endif
296 } else if (config->module == adc_module_adc16) {
297 #ifdef HPMSOC_HAS_HPMSDK_ADC16
298 return adc16_set_seq_config(config->adc_base.adc16, &config->config.adc16);
299 #else
300 return status_invalid_argument;
301 #endif
302 } else {
303 return status_invalid_argument;
304 }
305 }
306
307 /**
308 * @brief Configure the preemption mode for an ADC instance.
309 *
310 * @param[in] config a pointer to configuration struct of "adc_pmt_config_t".
311 * @retval status_success Configure the preemption mode for an ADC instance successfully.
312 * @retval status_invalid_argument Configure the preemption mode for an ADC instance unsuccessfully because of passing one or more invalid arguments.
313 */
hpm_adc_set_preempt_config(adc_pmt_config_t * config)314 static inline hpm_stat_t hpm_adc_set_preempt_config(adc_pmt_config_t *config)
315 {
316 if (config->module == adc_module_adc12) {
317 #ifdef HPMSOC_HAS_HPMSDK_ADC12
318 return adc12_set_pmt_config(config->adc_base.adc12, &config->config.adc12);
319 #else
320 return status_invalid_argument;
321 #endif
322 } else if (config->module == adc_module_adc16) {
323 #ifdef HPMSOC_HAS_HPMSDK_ADC16
324 return adc16_set_pmt_config(config->adc_base.adc16, &config->config.adc16);
325 #else
326 return status_invalid_argument;
327 #endif
328 } else {
329 return status_invalid_argument;
330 }
331 }
332
333 /**
334 * @brief Configure the stop position offset in the specified memory for DMA write operation for sequence mode.
335 *
336 * @param[in] ptr An ADC peripheral base address.
337 * @param[in] stop_pos The stop position offset.
338 */
hpm_adc_set_seq_stop_pos(adc_type * ptr,uint16_t stop_pos)339 static inline void hpm_adc_set_seq_stop_pos(adc_type *ptr, uint16_t stop_pos)
340 {
341 if (ptr->module == adc_module_adc12) {
342 #ifdef HPMSOC_HAS_HPMSDK_ADC12
343 adc12_set_seq_stop_pos(ptr->adc_base.adc12, stop_pos);
344 #endif
345 } else if (ptr->module == adc_module_adc16) {
346 #ifdef HPMSOC_HAS_HPMSDK_ADC16
347 adc16_set_seq_stop_pos(ptr->adc_base.adc16, stop_pos);
348 #endif
349 }
350 }
351
352 /**
353 * @brief Configure the start address of DMA write operation for preemption mode.
354 *
355 * @param[in] ptr An ADC peripheral base address.
356 * @param[in] addr The start address of DMA write operation.
357 */
hpm_adc_init_pmt_dma(adc_type * ptr,uint32_t addr)358 static inline void hpm_adc_init_pmt_dma(adc_type *ptr, uint32_t addr)
359 {
360 if (ptr->module == adc_module_adc12) {
361 #ifdef HPMSOC_HAS_HPMSDK_ADC12
362 adc12_init_pmt_dma(ptr->adc_base.adc12, addr);
363 #endif
364 } else if (ptr->module == adc_module_adc16) {
365 #ifdef HPMSOC_HAS_HPMSDK_ADC16
366 adc16_init_pmt_dma(ptr->adc_base.adc16, addr);
367 #endif
368 }
369 }
370
371 /**
372 * @brief Configure the start address of DMA write operation for preemption mode.
373 *
374 * @param[in] config A pointer to configuration struct of "adc_dma_config_t".
375 */
hpm_adc_init_seq_dma(adc_dma_config_t * config)376 static inline void hpm_adc_init_seq_dma(adc_dma_config_t *config)
377 {
378 if (config->module == adc_module_adc12) {
379 #ifdef HPMSOC_HAS_HPMSDK_ADC12
380 adc12_init_seq_dma(config->adc_base.adc12, &config->config.adc12);
381 #endif
382 } else if (config->module == adc_module_adc16) {
383 #ifdef HPMSOC_HAS_HPMSDK_ADC16
384 adc16_init_seq_dma(config->adc_base.adc16, &config->config.adc16);
385 #endif
386 }
387 }
388
389 /**
390 * @brief Reset value of the WAIT_DIS bit. ADC blocks access to the associated peripheral bus
391 * until the ADC completes the conversion.
392 *
393 * @param[in] config A pointer to configuration struct of "adc_dma_config_t".
394 */
hpm_adc_disable_busywait(adc_dma_config_t * config)395 static inline void hpm_adc_disable_busywait(adc_dma_config_t *config)
396 {
397 if (config->module == adc_module_adc12) {
398 #ifdef HPMSOC_HAS_HPMSDK_ADC12
399 adc12_disable_busywait(config->adc_base.adc12);
400 #endif
401 } else if (config->module == adc_module_adc16) {
402 #ifdef HPMSOC_HAS_HPMSDK_ADC16
403 adc16_disable_busywait(config->adc_base.adc16);
404 #endif
405 }
406 }
407
408 /**
409 * @brief Set value of the WAIT_DIS bit. The ADC does not block access to the associated peripheral bus
410 * until the ADC has completed its conversion.
411 *
412 * @param[in] config A pointer to configuration struct of "adc_dma_config_t".
413 */
hpm_adc_enable_busywait(adc_dma_config_t * config)414 static inline void hpm_adc_enable_busywait(adc_dma_config_t *config)
415 {
416 if (config->module == adc_module_adc12) {
417 #ifdef HPMSOC_HAS_HPMSDK_ADC12
418 adc12_enable_busywait(config->adc_base.adc12);
419 #endif
420 } else if (config->module == adc_module_adc16) {
421 #ifdef HPMSOC_HAS_HPMSDK_ADC16
422 adc16_enable_busywait(config->adc_base.adc16);
423 #endif
424 }
425 }
426
427
428 /**
429 * @brief Get ADC status flags.
430 *
431 * This function gets all ADC status flags.
432 * @param[in] ptr An ADC peripheral base address.
433 * @retval Status The ADC interrupt status flags.
434 */
hpm_adc_get_status_flags(adc_type * ptr)435 static inline uint32_t hpm_adc_get_status_flags(adc_type *ptr)
436 {
437 if (ptr->module == adc_module_adc12) {
438 #ifdef HPMSOC_HAS_HPMSDK_ADC12
439 return adc12_get_status_flags(ptr->adc_base.adc12);
440 #else
441 return status_invalid_argument;
442 #endif
443 } else if (ptr->module == adc_module_adc16) {
444 #ifdef HPMSOC_HAS_HPMSDK_ADC16
445 return adc16_get_status_flags(ptr->adc_base.adc16);
446 #else
447 return status_invalid_argument;
448 #endif
449 } else {
450 return status_invalid_argument;
451 }
452 }
453
454 /**
455 * @brief Get status flag of a conversion.
456 *
457 * This status flag is only used when wait_dis is set to disable.
458 *
459 * @param[in] ptr An ADC peripheral base address.
460 * @param[in] ch An ADC peripheral channel.
461 * @retval Status It means the current conversion is valid.
462 */
hpm_adc_get_conv_valid_status(adc_type * ptr,uint8_t ch)463 static inline bool hpm_adc_get_conv_valid_status(adc_type *ptr, uint8_t ch)
464 {
465 if (ptr->module == adc_module_adc12) {
466 #ifdef HPMSOC_HAS_HPMSDK_ADC12
467 return adc12_get_conv_valid_status(ptr->adc_base.adc12, ch);
468 #else
469 return status_invalid_argument;
470 #endif
471 } else if (ptr->module == adc_module_adc16) {
472 #ifdef HPMSOC_HAS_HPMSDK_ADC16
473 return adc16_get_conv_valid_status(ptr->adc_base.adc16, ch);
474 #else
475 return status_invalid_argument;
476 #endif
477 } else {
478 return status_invalid_argument;
479 }
480 }
481
482 /**
483 * @brief Clear status flags.
484 *
485 * Only the specified flags can be cleared by writing INT_STS register.
486 *
487 * @param[in] ptr An ADC peripheral base address.
488 * @param[in] mask Mask value for flags to be cleared. Refer to "adc12_irq_event_t". Refer to "adc16_irq_event_t".
489 */
hpm_adc_clear_status_flags(adc_type * ptr,uint32_t mask)490 static inline void hpm_adc_clear_status_flags(adc_type *ptr, uint32_t mask)
491 {
492 if (ptr->module == adc_module_adc12) {
493 #ifdef HPMSOC_HAS_HPMSDK_ADC12
494 adc12_clear_status_flags(ptr->adc_base.adc12, mask);
495 #endif
496 } else if (ptr->module == adc_module_adc16) {
497 #ifdef HPMSOC_HAS_HPMSDK_ADC16
498 adc16_clear_status_flags(ptr->adc_base.adc16, mask);
499 #endif
500 }
501 }
502
503 /**
504 * @brief Enable interrupts.
505 *
506 * @param[in] ptr An ADC peripheral base address.
507 * @param[in] mask Mask value for interrupt events. Refer to "adc12_irq_event_t".Refer to "adc16_irq_event_t".
508 */
hpm_adc_enable_interrupts(adc_type * ptr,uint32_t mask)509 static inline void hpm_adc_enable_interrupts(adc_type *ptr, uint32_t mask)
510 {
511 if (ptr->module == adc_module_adc12) {
512 #ifdef HPMSOC_HAS_HPMSDK_ADC12
513 adc12_enable_interrupts(ptr->adc_base.adc12, mask);
514 #endif
515 } else if (ptr->module == adc_module_adc16) {
516 #ifdef HPMSOC_HAS_HPMSDK_ADC16
517 adc16_enable_interrupts(ptr->adc_base.adc16, mask);
518 #endif
519 }
520 }
521
522 /**
523 * @brief Disable interrupts.
524 *
525 * @param[in] ptr An ADC peripheral base address.
526 * @param[in] mask Mask value for interrupt events. Refer to "adc12_irq_event_t".Refer to "adc16_irq_event_t".
527 */
hpm_adc_disable_interrupts(adc_type * ptr,uint32_t mask)528 static inline void hpm_adc_disable_interrupts(adc_type *ptr, uint32_t mask)
529 {
530 if (ptr->module == adc_module_adc12) {
531 #ifdef HPMSOC_HAS_HPMSDK_ADC12
532 adc12_disable_interrupts(ptr->adc_base.adc12, mask);
533 #endif
534 } else if (ptr->module == adc_module_adc16) {
535 #ifdef HPMSOC_HAS_HPMSDK_ADC16
536 adc16_disable_interrupts(ptr->adc_base.adc16, mask);
537 #endif
538 }
539 }
540
541 /**
542 * @brief Get the result in oneshot mode.
543 *
544 * @param[in] ptr An ADC peripheral base address.
545 * @param[in] ch An ADC peripheral channel.
546 * @param[out] result The result of an ADC12 conversion.
547 *
548 * @retval status_success Get the result of an ADC12 conversion in oneshot mode successfully.
549 * @retval status_invalid_argument Get the result of an ADC12 conversion in oneshot mode unsuccessfully because of passing invalid arguments.
550 */
hpm_adc_get_oneshot_result(adc_type * ptr,uint8_t ch,uint16_t * result)551 static inline hpm_stat_t hpm_adc_get_oneshot_result(adc_type *ptr, uint8_t ch, uint16_t *result)
552 {
553 if (ptr->module == adc_module_adc12) {
554 #ifdef HPMSOC_HAS_HPMSDK_ADC12
555 return adc12_get_oneshot_result(ptr->adc_base.adc12, ch, result);
556 #else
557 return status_invalid_argument;
558 #endif
559 } else if (ptr->module == adc_module_adc16) {
560 #ifdef HPMSOC_HAS_HPMSDK_ADC16
561 return adc16_get_oneshot_result(ptr->adc_base.adc16, ch, result);
562 #else
563 return status_invalid_argument;
564 #endif
565 } else {
566 return status_invalid_argument;
567 }
568 }
569
570 /**
571 * @brief Get the result in periodic mode.
572 *
573 * @param[in] ptr An ADC12 peripheral base address.
574 * @param[in] ch An ADC12 peripheral channel.
575 * @param[out] result The result of an ADC12 conversion.
576 *
577 * @retval status_success Get the result of an ADC12 conversion in periodic mode successfully.
578 * @retval status_invalid_argument Get the result of an ADC12 conversion in periodic mode unsuccessfully because of passing invalid arguments.
579 */
hpm_adc_get_prd_result(adc_type * ptr,uint8_t ch,uint16_t * result)580 static inline hpm_stat_t hpm_adc_get_prd_result(adc_type *ptr, uint8_t ch, uint16_t *result)
581 {
582 if (ptr->module == adc_module_adc12) {
583 #ifdef HPMSOC_HAS_HPMSDK_ADC12
584 return adc12_get_prd_result(ptr->adc_base.adc12, ch, result);
585 #else
586 return status_invalid_argument;
587 #endif
588 } else if (ptr->module == adc_module_adc16) {
589 #ifdef HPMSOC_HAS_HPMSDK_ADC16
590 return adc16_get_prd_result(ptr->adc_base.adc16, ch, result);
591 #else
592 return status_invalid_argument;
593 #endif
594 } else {
595 return status_invalid_argument;
596 }
597 }
598
599 /**
600 * @brief Do a software trigger for sequence mode.
601 *
602 * @param[in] ptr An adc peripheral base address.
603 *
604 */
hpm_adc_trigger_seq_by_sw(adc_type * ptr)605 static inline hpm_stat_t hpm_adc_trigger_seq_by_sw(adc_type *ptr)
606 {
607 if (ptr->module == adc_module_adc12) {
608 #ifdef HPMSOC_HAS_HPMSDK_ADC12
609 return adc12_trigger_seq_by_sw(ptr->adc_base.adc12);
610 #endif
611 } else if (ptr->module == adc_module_adc16) {
612 #ifdef HPMSOC_HAS_HPMSDK_ADC16
613 return adc16_trigger_seq_by_sw(ptr->adc_base.adc16);
614 #endif
615 } else {
616 return status_invalid_argument;
617 }
618 }
619
620 #ifdef __cplusplus
621 }
622 #endif
623
624 /** @} */
625
626 #endif
627