1 /*
2 * Copyright (c) 2022 Hunan OpenValley Digital Industry Development Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <stdlib.h>
17 #include "los_task.h"
18 #include "los_event.h"
19 #include "gpio_types.h"
20 #include "gpio_core.h"
21 #include "gpio_if.h"
22 #include "hdf_base.h"
23 #include "hcs_macro.h"
24 #include "hdf_config_macro.h"
25 #include "driver/gpio.h"
26
27 #define HDF_GPIO_DEBUG
28 #define HDF_LOG_TAG "ESP32U4_HDF_GPIO"
29
30 struct GpioSourceStr {
31 char *pin_index;
32 char *pull_mode;
33 char *drive_capability;
34 };
35
36 struct GpioSourceValue {
37 int pin_index;
38 int pull_mode;
39 int drive_capability;
40 int direction;
41 };
42
43 int g_pin_nums = 0; // hcs文件中定义的pin个数
44
45 #ifdef GPIO_NUM_MAX
46 #undef GPIO_NUM_MAX
47 #endif
48 struct GpioSourceValue all_gpio_config[GPIO_NUM_MAX]; // 单个GPIO配置,最大支持40个GPIO配置
49
50 #define PLATFORM_CONFIG HCS_NODE(HCS_ROOT, platform)
51 #define PLATFORM_GPIO_CONFIG HCS_NODE(HCS_NODE(HCS_ROOT, platform), gpio_config)
52 #define HDF_GPIO_FIND_SOURCE(node, name) \
53 do { \
54 if (strcmp(HCS_PROP(node, match_attr), name) == 0) { \
55 struct GpioSourceStr cur_gpio_attr = HCS_ARRAYS(HCS_PROP(node, gpio_attr)); \
56 all_gpio_config[g_pin_nums].pin_index = GetPinIndexFromStr(cur_gpio_attr.pin_index); \
57 all_gpio_config[g_pin_nums].pull_mode = GetPullModeFromStr(cur_gpio_attr.pull_mode); \
58 all_gpio_config[g_pin_nums].drive_capability = GetDriveCapabilityFromStr(cur_gpio_attr.drive_capability); \
59 HDF_LOGI("----- GPIO Index [%d] Config -----", g_pin_nums); \
60 HDF_LOGI("pin_index = %s[%d]", cur_gpio_attr.pin_index, all_gpio_config[g_pin_nums].pin_index); \
61 HDF_LOGI("pull_mode = %s[%d]", cur_gpio_attr.pull_mode, all_gpio_config[g_pin_nums].pull_mode); \
62 HDF_LOGI("drive_capability = %s[%d]", cur_gpio_attr.drive_capability, \
63 all_gpio_config[g_pin_nums].drive_capability); \
64 gpio_reset_pin(all_gpio_config[g_pin_nums].pin_index); \
65 gpio_set_pull_mode(all_gpio_config[g_pin_nums].pin_index, all_gpio_config[g_pin_nums].pull_mode); \
66 gpio_set_drive_capability(all_gpio_config[g_pin_nums].pin_index, \
67 all_gpio_config[g_pin_nums].drive_capability); \
68 g_pin_nums++; \
69 } \
70 } while (0)
71
72 #define DIR_PARAM_OFFSET 1
73 #define ESP_INTR_FLAG_DEFAULT 0
74
75 static unsigned int lastTickCount = 0;
76 static struct GpioCntlr g_EspGpioCntlr;
77
Esp32u4GpioWrite(struct GpioCntlr * cntlr,uint16_t local,uint16_t val)78 static int32_t Esp32u4GpioWrite(struct GpioCntlr *cntlr, uint16_t local, uint16_t val)
79 {
80 gpio_set_level(all_gpio_config[local].pin_index, val);
81 return 0;
82 }
83
Esp32u4GpioRead(struct GpioCntlr * cntlr,uint16_t local,uint16_t * val)84 static int32_t Esp32u4GpioRead(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val)
85 {
86 if (val == NULL)
87 return -1;
88 *val = gpio_get_level(all_gpio_config[local].pin_index);
89 return *val;
90 }
91
92 #define FUNC_2 2
Esp32u4GpioSetDir(struct GpioCntlr * cntlr,uint16_t local,uint16_t dir)93 static int32_t Esp32u4GpioSetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t dir)
94 {
95 all_gpio_config[local].direction = dir;
96 if (dir == GPIO_DIR_OUT) {
97 gpio_iomux_out(all_gpio_config[local].pin_index, FUNC_2, 0);
98 }
99 gpio_set_direction(all_gpio_config[local].pin_index, dir + DIR_PARAM_OFFSET);
100 return 0;
101 }
102
Esp32u4GpioGetDir(struct GpioCntlr * cntlr,uint16_t local,uint16_t * dir)103 static int32_t Esp32u4GpioGetDir(struct GpioCntlr *cntlr, uint16_t local, uint16_t *dir)
104 {
105 *dir = all_gpio_config[local].direction;
106 return 0;
107 }
108
109 #define SHAKE_COUNT 10
gpio_interrupt_callback_func(VOID * arg)110 static void gpio_interrupt_callback_func(VOID *arg)
111 {
112 unsigned int tickCount = osKernelGetTickCount();
113 unsigned int count = tickCount - lastTickCount;
114 lastTickCount = tickCount;
115 if (count > SHAKE_COUNT) { // 消抖
116 uint16_t *gpio_num = (uint16_t *)arg;
117 GpioCntlrIrqCallback(&g_EspGpioCntlr, *gpio_num); // 调用用户注册的回调函数
118 }
119 return;
120 }
121
Esp32u4GpioSetIrq(struct GpioCntlr * cntlr,uint16_t local,uint16_t mode)122 static int32_t Esp32u4GpioSetIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode)
123 {
124 int interrupt_type = GPIO_INTR_DISABLE;
125 uint32_t *irq_args = (uint32_t *)malloc(sizeof(uint32_t));
126 switch (mode) {
127 case OSAL_IRQF_TRIGGER_NONE:
128 interrupt_type = GPIO_INTR_DISABLE;
129 break;
130 case OSAL_IRQF_TRIGGER_RISING:
131 interrupt_type = GPIO_INTR_POSEDGE;
132 break;
133 case OSAL_IRQF_TRIGGER_FALLING:
134 interrupt_type = GPIO_INTR_NEGEDGE;
135 break;
136 case OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING:
137 interrupt_type = GPIO_INTR_ANYEDGE;
138 break;
139 case OSAL_IRQF_TRIGGER_HIGH:
140 interrupt_type = GPIO_INTR_HIGH_LEVEL;
141 break;
142 case OSAL_IRQF_TRIGGER_LOW:
143 interrupt_type = GPIO_INTR_LOW_LEVEL;
144 break;
145 default:
146 HDF_LOGE("Unknow interrupt mode! (mode = %d)", mode);
147 break;
148 }
149 #ifdef HDF_GPIO_DEBUG
150 HDF_LOGE("---> Set %d interrupt mode %d!", all_gpio_config[local].pin_index, interrupt_type);
151 #endif
152 gpio_set_intr_type(all_gpio_config[local].pin_index, interrupt_type); // 设置中断类型
153 if (irq_args != NULL) {
154 *irq_args = (uint32_t)local;
155 int ret = gpio_isr_handler_add(all_gpio_config[local].pin_index,
156 gpio_interrupt_callback_func, irq_args); // 使能中断
157 if (ret == -1) {
158 HDF_LOGE("GpioDevEnableIrq failed!\n");
159 }
160 } else {
161 HDF_LOGE("irq_args malloc failed!");
162 return HDF_FAILURE;
163 }
164 return 0;
165 }
166
Esp32u4GpioUnsetIrq(struct GpioCntlr * cntlr,uint16_t local)167 static int32_t Esp32u4GpioUnsetIrq(struct GpioCntlr *cntlr, uint16_t local)
168 {
169 gpio_set_intr_type(all_gpio_config[local].pin_index, GPIO_INTR_DISABLE); // 设置取消中断设置
170 gpio_isr_handler_remove(all_gpio_config[local].pin_index);
171 return 0;
172 }
173
Esp32u4GpioEnableIrq(struct GpioCntlr * cntlr,uint16_t local)174 static int32_t Esp32u4GpioEnableIrq(struct GpioCntlr *cntlr, uint16_t local)
175 {
176 gpio_intr_enable(all_gpio_config[local].pin_index);
177 return HDF_SUCCESS;
178 }
179
Esp32u4GpioDisableIrq(struct GpioCntlr * cntlr,uint16_t local)180 static int32_t Esp32u4GpioDisableIrq(struct GpioCntlr *cntlr, uint16_t local)
181 {
182 gpio_intr_disable(all_gpio_config[local].pin_index);
183 return 0;
184 }
185
186 struct GpioMethod g_GpioCntlrMethod = {
187 .request = NULL,
188 .release = NULL,
189 .write = Esp32u4GpioWrite,
190 .read = Esp32u4GpioRead,
191 .setDir = Esp32u4GpioSetDir,
192 .getDir = Esp32u4GpioGetDir,
193 .toIrq = NULL,
194 .setIrq = Esp32u4GpioSetIrq,
195 .unsetIrq = Esp32u4GpioUnsetIrq,
196 .enableIrq = Esp32u4GpioEnableIrq,
197 .disableIrq = Esp32u4GpioDisableIrq,
198 };
199
Esp32u4GpioBind(struct HdfDeviceObject * device)200 static int32_t Esp32u4GpioBind(struct HdfDeviceObject *device)
201 {
202 return HDF_SUCCESS;
203 }
204 #define NUM_10 10
GetPinIndexFromStr(const char * str)205 static int GetPinIndexFromStr(const char *str)
206 {
207 if (str == NULL || strlen(str) < NUM_10) {
208 HDF_LOGE("pin index config is illegal!");
209 return GPIO_NUM_NC;
210 }
211
212 char *ptr_nun = &str[9];
213 int level = strlen(ptr_nun); // 获取下标位数
214 int pin_index = 0; // GPIO号
215 for (int i = 0; i < level; i++) {
216 if (i != 0) {
217 pin_index = NUM_10 * pin_index;
218 }
219 int num = ptr_nun[i] - '0';
220 if (num >= NUM_10) { // 字符非法
221 HDF_LOGE("pin index config is illegal!");
222 return GPIO_NUM_NC;
223 }
224 pin_index += num;
225 }
226 return pin_index;
227 }
228
GetPullModeFromStr(const char * str)229 static int GetPullModeFromStr(const char *str)
230 {
231 if (!strcmp(str, "GPIO_PULLUP_ONLY")) {
232 return GPIO_PULLUP_ONLY;
233 } else if (!strcmp(str, "GPIO_PULLDOWN_ONLY")) {
234 return GPIO_PULLDOWN_ONLY;
235 } else if (!strcmp(str, "GPIO_PULLUP_PULLDOWN")) {
236 return GPIO_PULLUP_PULLDOWN;
237 }
238 return GPIO_FLOATING;
239 }
240
GetDriveCapabilityFromStr(const char * str)241 static int GetDriveCapabilityFromStr(const char *str)
242 {
243 if (!strcmp(str, "GPIO_DRIVE_CAP_0")) {
244 return GPIO_DRIVE_CAP_0;
245 } else if (!strcmp(str, "GPIO_DRIVE_CAP_1")) {
246 return GPIO_DRIVE_CAP_1;
247 } else if (!strcmp(str, "GPIO_DRIVE_CAP_2")) {
248 return GPIO_DRIVE_CAP_2;
249 } else if (!strcmp(str, "GPIO_DRIVE_CAP_3")) {
250 return GPIO_DRIVE_CAP_3;
251 } else if (!strcmp(str, "GPIO_DRIVE_CAP_MAX")) {
252 return GPIO_DRIVE_CAP_MAX;
253 }
254 return GPIO_DRIVE_CAP_DEFAULT;
255 }
256
AttachGpioDevice(struct GpioCntlr * gpioCntlr,struct HdfDeviceObject * device)257 static int32_t AttachGpioDevice(struct GpioCntlr *gpioCntlr, struct HdfDeviceObject *device)
258 {
259 int32_t ret;
260 if (device == NULL) {
261 HDF_LOGE("%s: property is NULL", __func__);
262 return HDF_ERR_INVALID_PARAM;
263 }
264
265 HCS_FOREACH_CHILD_VARGS(PLATFORM_GPIO_CONFIG, HDF_GPIO_FIND_SOURCE, device->deviceMatchAttr);
266
267 gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
268
269 gpioCntlr->priv = NULL;
270 gpioCntlr->count = g_pin_nums;
271
272 return HDF_SUCCESS;
273 }
274
Esp32u4GpioInit(struct HdfDeviceObject * device)275 static int32_t Esp32u4GpioInit(struct HdfDeviceObject *device)
276 {
277 int32_t ret;
278 struct GpioCntlr *gpioCntlr = NULL;
279
280 if (device == NULL) {
281 HDF_LOGE("%s: device is NULL", __func__);
282 return HDF_ERR_INVALID_PARAM;
283 }
284
285 ret = PlatformDeviceBind(&g_EspGpioCntlr.device, device);
286 if (ret != HDF_SUCCESS) {
287 HDF_LOGE("%s: bind hdf device failed:%d", __func__, ret);
288 return ret;
289 }
290
291 gpioCntlr = GpioCntlrFromHdfDev(device);
292 if (gpioCntlr == NULL) {
293 HDF_LOGE("GpioCntlrFromHdfDev fail\r\n");
294 return HDF_DEV_ERR_NO_DEVICE_SERVICE;
295 }
296
297 ret = AttachGpioDevice(gpioCntlr, device); /* GpioCntlr add GpioDevice to priv */
298 if (ret != HDF_SUCCESS) {
299 HDF_LOGE("AttachGpioDevice fail\r\n");
300 return HDF_DEV_ERR_ATTACHDEV_FAIL;
301 }
302
303 gpioCntlr->ops = &g_GpioCntlrMethod; /* register callback */
304 ret = GpioCntlrAdd(gpioCntlr);
305 if (ret != HDF_SUCCESS) {
306 HDF_LOGE("GpioCntlrAdd fail %d\r\n", gpioCntlr->start);
307 return HDF_FAILURE;
308 }
309
310 HDF_LOGI("Esp32u4GpioInit success!\r\n");
311 return HDF_SUCCESS;
312 }
313
Esp32u4GpioRelease(struct HdfDeviceObject * device)314 static void Esp32u4GpioRelease(struct HdfDeviceObject *device)
315 {
316 printf("========> Func: %s Line:%d\r\n", __FUNCTION__, __LINE__);
317 }
318
319 static const struct HdfDriverEntry GPIO_DriverEntry = {
320 .moduleVersion = 1,
321 .moduleName = "ESP32U4_HDF_GPIO",
322 .Bind = Esp32u4GpioBind,
323 .Init = Esp32u4GpioInit,
324 .Release = Esp32u4GpioRelease,
325 };
326
327 HDF_INIT(GPIO_DriverEntry);