• Home
Name Date Size #Lines LOC

..--

BUILD.gnD12-May-20241.2 KiB3328

README_zh.mdD12-May-20248.4 KiB225207

hdf_gpio_test.cD12-May-20243.1 KiB11988

README_zh.md

1# Niobe407开发板OpenHarmony基于HDF驱动框架编程开发——GPIO
2本示例将演示如何在Niobe407开发板上通过HDF驱动框架,使用GPIO按键中断。
3
4
5## 编译调试
6- 进入//kernel/liteos_m目录, 在menuconfig配置中进入如下选项:
7
8     `(Top) → Platform → Board Selection → select board niobe407 → use talkweb niobe407 application → niobe407 application choose`
9
10- 选择 `201_hdf_gpio_key`
11
12- 在menuconfig的`(Top) → Driver`选项中使能如下配置:
13
14```
15    [*] Enable Driver
16    [*]     HDF driver framework support
17    [*]         Enable HDF platform driver
18    [*]             Enable HDF platform gpio driver
19```
20- 回到sdk根目录,执行`hb build -f`脚本进行编译。
21
22### 运行结果
23
24示例代码编译烧录代码后,按下开发板的RESET按键,通过串口助手查看日志
25```
26Entering scheduler
27[HDF:E/HDF_LOG_TAG]DeviceManagerStart in
28[HDF:I/devmgr_service]start svcmgr result 0
29[HDF:I/hcs_blob_if]CheckHcsBlobLength: the blobLength: 1884, byteAlign: 1
30[HDF:I/device_node]launch devnode HDF_PLATFORM_GPIO
31GpioDriverBind
32[HDF:I/gpio_manager]GpioManagerAdd: start:0 count:8 added success
33[HDF:D/HDF_LOG_TAG]PlatformManagerAddDevice: add dev:(null)(0) to PLATFORM_MODULE_GPIO success
34[HDF:D/HDF_LOG_TAG]PlatformDeviceAdd: add dev:(null)(0) success
35[HDF:E/HDF_LOG_TAG]HdfDriverManagerGetDriver:driver STM_TW_SPI_MODULE_HDF not found
36[HDF:E/devhost_service_clnt]failed to install driver HDF_PLATFORM_SPI_0, ret = -207
37hiview init success.
38[HDF:E/HDF_LOG_TAG]HdfGpioTestEntry: mode:2
39```
40
41当按下开发板上的按钮sw2时,点亮或者点灭, 按下开发板上按钮sw3时, 绿灯点亮或者点灭 ,可通过串口助手查看到如下日志:
42```
43[HDF:E/HDF_LOG_TAG]TestCaseGpioIrqHandler1: irq triggered! on gpio:2, data=(nil)
44[HDF:E/gpio_stm32_c]GpioDevWrite 433 ,write pin num 5
45[HDF:E/HDF_LOG_TAG]TestCaseGpioIrqHandler1: irq triggered! on gpio:2, data=(nil)
46[HDF:E/gpio_stm32_c]GpioDevWrite 433 ,write pin num 5
47[HDF:E/HDF_LOG_TAG]TestCaseGpioIrqHandler2: irq triggered! on gpio:3, data=(nil)
48[HDF:E/gpio_stm32_c]GpioDevWrite 433 ,write pin num 6
49```
50## GPIO HDF hcs配置文件解析
51- device_gpio_info 在/device/board/talkweb/niobe407/sdk/hdf_config/device_gpio_info.hcs
52```
53root {
54    module = "talkweb,stm32f407";
55    device_info {
56        match_attr = "hdf_manager";
57        template host {
58            hostName = "";
59            priority = 100;
60            template device {
61                template deviceNode { //gpio信息的模板,集成模板可以缺省
62                    policy = 0;
63                    priority = 100;
64                    preload = 0;
65                    permission = 0664;
66                    moduleName = "";
67                    serviceName = "";
68                    deviceMatchAttr = "";
69                }
70            }
71        }
72        platform :: host {
73            hostName = "platform_host";
74            priority = 50;
75            device_gpio :: device {
76                gpio0 :: deviceNode {
77                    policy = 2;
78                    priority = 60; //权限决定加载的顺序
79                    moduleName = "STM_TW_GPIO_MODULE_HDF";
80                    serviceName = "HDF_PLATFORM_GPIO";//驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
81                    deviceMatchAttr = "gpio_config"; // 与hdf_gpio_.hcs中的config匹配
82                }
83            }
84        }
85    }
86}
87```
88- hdf_gpio.hcs解析 在/device/board/talkweb/niobe407/sdk/hdf_config/目录下,配置具体gpio引脚的信息
89```
90#include "device_gpio_info.hcs"      // 包含具体的device_info文件
91root {
92    platform {
93        gpio_config {
94            match_attr = "gpio_config"; // 与device_gpio_info.hcs中的deviceMatchAttr对应
95            pin = [0, 1, 2, 3]; // 框架注册pin号,在使用接口时用作GPIO号来使用
96            realPin = [5, 6, 0, 1]; // 与pin对应的真实的在stm32中真实的引脚编号(0-15)开发板,此示例为 led2 pe5, led3 pe6, key1按键终端 pe0,sw2, key2按键终端pe1,sw3
97            group = [4, 4, 4, 4]; // gpio引脚所属的group 0到8 分别对应GPIOA~GPIOI,此例4个gpio属于GPIOE
98			mode = [1, 1, 0, 0];  // 0: input 1: output 2:alternate 3:analog
99            speed = [0, 0, 0, 0]; // 0: low 1: middle 2:high 3:very_high
100            pull = [0, 0, 0, 0]; // 0: nopull 1:up 2:down
101            pinNum = 4; //总注册gpio个数 如果发现因为加载的gpio个数过多导致无法申请到锁资源,可修改target_config.h中的LOSCFG_BASE_IPC_MUX_LIMIT 增大锁的数量限制
102            output = [0, 0, 0, 0];  // 0:pushpull 1:opendrain
103            alternate = [0, 0, 0, 0]; // 对应的stm32的管脚复用功能gpio作为每种外设都对应一种复用功能(0-15,具体参考编程手册)
104        }
105    }
106}
107```
108## 接口说明
109
110```
111 1.读写GPIO管脚, 如果要读取一个GPIO管脚电平,通过以下函数完成:
112 int32_t GpioRead(uint16_t gpio, uint16_t *val);
113 参数说明:
114            gpio: 对应hcs文件中的pin号
115            val:  存储读取的值
116 返回值:
117            0:   读取成功
118            负数:读取失败
119
1202.如果要向GPIO管脚写入电平值,通过以下函数完成:
121int32_t GpioWrite(uint16_t gpio, uint16_t val);
122参数说明:
123            gpio: 对应hcs文件中的pin号
124            val:  需要设置的电平值
125返回值:
126            0:   设置成功
127            负数:设置失败
1283.如果要为一个GPIO管脚设置中断响应程序,使用如下函数:
129int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg);
130参数说明:
131            gpio: 对应hcs文件中的pin号
132            mode: 中断触发模式
133            func: 中断回调函数
134            arg:  回调函数参数
135返回值:
136            0:   设置成功
137            负数:设置失败
1384.当不再需要响应中断服务函数时,使用如下函数取消中断设置:
139int32_t GpioUnSetIrq(uint16_t gpio);
140参数说明:
141            gpio: 对应hcs文件中的pin号
142返回值:
143            0:   设置成功
144            负数:设置失败
1455.在中断服务程序设置完成后,还需要先通过如下函数使能GPIO管脚的中断:
146int32_t GpioEnableIrq(uint16_t gpio);
147参数说明:
148            gpio: 对应hcs文件中的pin号
149返回值:
150            0:   使能成功
151            负数: 使能失败
1526.如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断
153int32_t GpioDisableIrq(uint16_t gpio);
154参数说明:
155            gpio: 对应hcs文件中的pin号
156返回值:
157            0:   禁止成功
158            负数: 禁止失败
159```
160## 示例代码
161``` c
162/* 中断服务函数*/
163static int32_t TestCaseGpioIrqHandler1(uint16_t gpio, void *data) // pin2 回调函数
164{
165    HDF_LOGE("%s: irq triggered! on gpio:%u, data=%p", __func__, gpio, data);
166    uint16_t val = 0;
167    GpioRead(0, &val); // 读取pin0 的电平值,中断产生则设置相反的电平
168    if (val) {
169        GpioWrite(0, 0);
170    } else {
171        GpioWrite(0, 1);
172    }
173}
174
175static int32_t TestCaseGpioIrqHandler2(uint16_t gpio, void *data) // pin3 回调函数
176{
177    HDF_LOGE("%s: irq triggered! on gpio:%u, data=%p", __func__, gpio, data);
178    uint16_t val = 0;
179    GpioRead(1, &val); // 读取pin1 的电平值,中断产生则设置相反的电平
180    if (val) {
181        GpioWrite(1, 0);
182    } else {
183        GpioWrite(1, 1);
184    }
185}
186
187
188static void* HdfGpioTestEntry(void* arg)
189{
190    int32_t ret;
191    uint16_t valRead;
192    uint16_t mode;
193    uint16_t gpio0 = 0; // hcs 中对应的pin值
194    uint16_t gpio1 = 1;
195    uint16_t gpio2 = 2;
196    uint16_t gpio3 = 3;
197    uint32_t timeout;
198    mode = OSAL_IRQF_TRIGGER_FALLING;
199    HDF_LOGE("%s: mode:%0x\n", __func__, mode);
200    ret = GpioSetIrq(gpio2, mode, TestCaseGpioIrqHandler1, NULL); // 设置中断函数
201    if (ret != HDF_SUCCESS) {
202        HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret);
203        return ret;
204    }
205
206    ret = GpioSetIrq(gpio3, mode, TestCaseGpioIrqHandler2, NULL); // 设置中断函数
207    if (ret != HDF_SUCCESS) {
208        HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret);
209        return ret;
210    }
211
212    ret = GpioEnableIrq(gpio2); // 使能中断
213    if (ret != HDF_SUCCESS) {
214        HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret);
215        return ret;
216    }
217
218    ret = GpioEnableIrq(gpio3); // 使能中断
219    if (ret != HDF_SUCCESS) {
220        HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret);
221        return ret;
222    }
223}
224```
225