本帖最后由 symic 于 2022-4-23 23:12 编辑
上次通过学习helloworld程序,熟悉了开发流程。为了进一步熟悉开发全过程,我们结合LED测试,如何从头开始进行驱动和APP开发。
LED测试共分为两部分,一是驱动部分,一是业务部分。驱动部分又可分为驱动代码、驱动配置文件。业务部分主要由代码和业务编译文件组成。
一、驱动部分
首先是驱动部分,这里的驱动都是基于HDF框架。HDF框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个node。
以上的理论看得比较难懂,直接看如何编写驱动代码。
1、驱动文件的编写
既然是LED驱动,那就在/device/st/drivers下创建驱动文件夹,直接取名叫LED。新建两个文件:LED.c和BUILD.gn,前者负责具体的驱动实现,后者则是与编译有关。
在LED.c中实现驱动代码,都是有制式的几个函数,包括
-
- int32_t HdfLedDriverInit(struct HdfDeviceObject *device)
-
- void HdfLedDriverRelease(struct HdfDeviceObject *deviceObject)
-
- int32_t LedDriverDispatch(struct HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
-
- static int32_t Stm32LedReadDrs(struct Stm32Mp1ILed *led, const struct DeviceResourceNode *node)
-
- int32_t HdfLedDriverBind(struct HdfDeviceObject *deviceObject)
-
最后用结构体赋值的方式定义驱动入口的对象
- struct HdfDriverEntry g_ledDriverEntry = {
- .moduleVersion = 1,
- .moduleName = "HDF_LED",
- .Bind = HdfLedDriverBind,
- .Init = HdfLedDriverInit,
- .Release = HdfLedDriverRelease,
- };
-
-
- HDF_INIT(g_ledDriverEntry);
2、BUILD.gn编译文件的编写
驱动文件编写完成后,接下来就是要进行编译文件的编写,在此编译文件都叫BUILD.gn,注意这里的BUILD.gn是大写的。相关的编译文件有2个。
(1)在同级文件夹下的BUILD.gn中添加编译方法,将LED.c编译成hdf_led,
(2)在上级(即/device/st/drivers)的BUILD.gn文件中将“led”添加到“group("drivers") ”,也可以理解为将新建的LED驱动文件添加到驱动列表中。
3、驱动配置
所谓驱动配置是HDF框架对驱动所需的设备信息的描述,具体操作上是对2个hcs文件的修改。
(1)device\st\bearpi_hm_micro\liteos_a\hdf_config\device_info\device_info.hcs,此为平台配置,主要在platform下添加对device_led :: device内容。
(2)device\st\bearpi_hm_micro\liteos_a\hdf_config\led\led_config.hcs,此为私有配置,用来填写一些驱动的默认配置信息,这里主要是定义了LED灯对应的GPIO口。
有两个注意事项
- device_info.hcs文件中的moduleName必须要和驱动文件中的moduleName字段匹配,这样驱动才会加载起来
- device_info.hcs文件中的deviceMatchAttr的字段必须和私有配置文件中led_config.hcs的match_attr的字段匹配,这样私有配置才能生效。
二、业务代码
业务代码是对驱动文件的实现,通过main函数获取(Bind),并发布(Dispatch)数据,其c文件所在路径是./applications/BearPi/BearPi-HM_Micro/samples/led,文件名为my_led_app.c
业务代码也需要编译文件BUILD.gn,由三部分内容(目标、源文件、头文件路径)构成,步骤如下
- 首先导入 gni 组件,将源码my_led_app.c编译成led_lib库文件
- 输出的可执行文件名称由 output_name 定义为my_led
- include_dirs 里面加入my_led_app.c里面需要用到的.h的头文件路径
- deps 里面加入所依赖的库。
- 然后将led_lib打包成 lite_component,命名为my_led_app组件。
最后是对两个json的操作。一个是build/lite/components/applications.json,另一个是vendor/bearpi/bearpi_hm_micro/config.json。
前者是在components中添加component,后者在applications的“components”中添加新的组件条目。
三、烧录与运行
./bin/my_led 0 关闭LED,./bin/my_led 1 打开LED,./bin/my_led 2 翻转LED
四、小结
总体来说写驱动还是比较复杂 的,涉及的内容多、步骤多,与linux驱动开发类似。用户程序是无法直接访问驱动的,只能通过Dispatch的方式发送指令到驱动程序,并可以将用户态的数据携带到驱动程序,也可以从驱动程序读出数据,下图是用户应用程序如何与驱动进行交互的。
- 发送LED_WRITE_READ命令到驱动,此处开发者可以自定义创建更多的命令。
- 携带数据到驱动,解析出开关灯的动作。
- 读取IO口电平状态并通过reply携带到用户程序。
由于主要参考的是gitee上的教程,详细的代码就不贴上来的。附上教程链接。
LED驱动教程链接
以上。