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