• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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