1 /**************************************************************************//**
2 * @copyright (C) 2020 Nuvoton Technology Corp. All rights reserved.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-9-23 Wayne First version
9 *
10 ******************************************************************************/
11
12 #include <rtconfig.h>
13
14 #if defined(BSP_USING_EADC)
15
16 #include <rtdevice.h>
17 #include "NuMicro.h"
18
19 /* Private define --------------------------------------------------------------- */
20 #define DEF_EADC_MAX_CHANNEL_NUM 8
21
22 enum
23 {
24 EADC_START = -1,
25 #if defined(BSP_USING_EADC0)
26 EADC0_IDX,
27 #endif
28 EADC_CNT
29 };
30
31 /* Private Typedef -------------------------------------------------------------- */
32 struct nu_eadc
33 {
34 struct rt_adc_device parent;
35 char *name;
36 EADC_T *base;
37 uint32_t rstidx;
38 uint32_t modid;
39 uint32_t chnmask;
40 };
41 typedef struct nu_eadc *nu_eadc_t;
42
43 /* Private functions ------------------------------------------------------------ */
44 static rt_err_t nu_eadc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled);
45 static rt_err_t nu_get_eadc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value);
46
47 /* Public functions ------------------------------------------------------------ */
48 int rt_hw_eadc_init(void);
49
50 /* Private variables ------------------------------------------------------------ */
51
52 static struct nu_eadc nu_eadc_arr [] =
53 {
54 #if defined(BSP_USING_EADC0)
55 { .name = "eadc0", .base = EADC0, .rstidx = EADC0_RST, .modid = EADC0_MODULE, .chnmask = 0 },
56 #endif
57 };
58
59 static const struct rt_adc_ops nu_adc_ops =
60 {
61 nu_eadc_enabled,
62 nu_get_eadc_value,
63 };
64 typedef struct rt_adc_ops *rt_adc_ops_t;
65
66
67 /* nu_adc_enabled - Enable ADC clock and wait for ready */
nu_eadc_enabled(struct rt_adc_device * device,rt_int8_t channel,rt_bool_t enabled)68 static rt_err_t nu_eadc_enabled(struct rt_adc_device *device, rt_int8_t channel, rt_bool_t enabled)
69 {
70 nu_eadc_t psNuEadc = (nu_eadc_t)device;
71 RT_ASSERT(device != RT_NULL);
72
73 if (channel >= DEF_EADC_MAX_CHANNEL_NUM)
74 return -(RT_EINVAL);
75
76 if (enabled)
77 {
78 if (psNuEadc->chnmask == 0)
79 {
80 /* Invoke Open function at first call. */
81 EADC_Open(psNuEadc->base, EADC_CTL_DIFFEN_SINGLE_END);
82 }
83 psNuEadc->chnmask |= (1 << channel);
84 }
85 else
86 {
87 psNuEadc->chnmask &= ~(1 << channel);
88
89 if (psNuEadc->chnmask == 0)
90 {
91 /* Invoke Open function at last call. */
92 EADC_Close(psNuEadc->base);
93 }
94 }
95
96 return RT_EOK;
97 }
98
nu_get_eadc_value(struct rt_adc_device * device,rt_int8_t channel,rt_uint32_t * value)99 static rt_err_t nu_get_eadc_value(struct rt_adc_device *device, rt_int8_t channel, rt_uint32_t *value)
100 {
101 nu_eadc_t psNuEadc = (nu_eadc_t)device;
102
103 RT_ASSERT(device != RT_NULL);
104 RT_ASSERT(value != RT_NULL);
105
106 if (channel >= DEF_EADC_MAX_CHANNEL_NUM)
107 {
108 *value = 0xFFFFFFFF;
109 return -(RT_EINVAL);
110 }
111
112 if ((psNuEadc->chnmask & (1 << channel)) == 0)
113 {
114 *value = 0xFFFFFFFF;
115 return -(RT_EBUSY);
116 }
117
118 EADC_ConfigSampleModule(psNuEadc->base, 0, EADC_SOFTWARE_TRIGGER, channel);
119
120 EADC_CLR_INT_FLAG(psNuEadc->base, EADC_STATUS2_ADIF0_Msk);
121
122 EADC_ENABLE_INT(psNuEadc->base, BIT0);
123
124 EADC_ENABLE_SAMPLE_MODULE_INT(psNuEadc->base, 0, BIT0);
125
126 EADC_START_CONV(psNuEadc->base, BIT0);
127
128 while (EADC_GET_INT_FLAG(psNuEadc->base, BIT0) == 0);
129
130 *value = EADC_GET_CONV_DATA(psNuEadc->base, 0);
131
132 return RT_EOK;
133 }
134
rt_hw_eadc_init(void)135 int rt_hw_eadc_init(void)
136 {
137 int i;
138 rt_err_t ret = RT_EOK;
139
140 for (i = (EADC_START + 1); i < EADC_CNT; i++)
141 {
142 CLK_EnableModuleClock(nu_eadc_arr[i].modid);
143 SYS_ResetModule(nu_eadc_arr[i].rstidx);
144
145 ret = rt_hw_adc_register(&nu_eadc_arr[i].parent, nu_eadc_arr[i].name, &nu_adc_ops, &nu_eadc_arr[i]);
146 RT_ASSERT(ret == RT_EOK);
147 }
148
149 return (int)ret;
150 }
151 INIT_BOARD_EXPORT(rt_hw_eadc_init);
152
153 #endif /* #if defined(BSP_USING_EADC) */
154