FFH小熊派驱动调用流程(以调用LED灯驱动为例)

一卷旌收千骑虏,万全身出百重围。这篇文章主要讲述FFH小熊派驱动调用流程(以调用LED灯驱动为例)相关的知识,希望能为你提供帮助。
春节不停更,此文正在参加「星光计划-春节更帖活动」
一、流程总览驱动调用的流程和纯代码开发的流程十分相似,本文着重点在于驱动调用的逻辑。
创建目录及相应源码文件--> 编写驱动调用代码--> 编写编译构建文件BUILD.gn--> 编译烧录运行
二、源码目录结构在./applications/BearPi/BearPi-HM_Micro/samples/目录下创建
my_led_app 源码目录
*my_led_app.c驱动调用源码
【FFH小熊派驱动调用流程(以调用LED灯驱动为例)】*BUILD.gn源码编译脚本
如图所示

FFH小熊派驱动调用流程(以调用LED灯驱动为例)

文章图片

三、编写驱动调用代码在my_led_app.c中编写如下代码
#include < fcntl.h> #include < sys/stat.h> #include < sys/ioctl.h> #include < unistd.h> #include < stdio.h> #include "hdf_sbuf.h" #include "hdf_io_service_if.h"#define LED_WRITE_READ 1 #define LED_SERVICE "hdf_led"static int SendEvent(struct Hdfioservice *serv, uint8_t eventData)int ret = 0; struct HdfSBuf *data = https://www.songbingjia.com/android/HdfSBufObtainDefaultSize(); if (data == NULL)printf("fail to obtain sbuf data!\\r\\n"); return 1; struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); if (reply == NULL)printf("fail to obtain sbuf reply!\\r\\n"); ret = HDF_DEV_ERR_NO_MEMORY; goto out; /* 写入数据 */ if (!HdfSbufWriteUint8(data, eventData))printf("fail to write sbuf!\\r\\n"); ret = HDF_FAILURE; goto out; /* 通过Dispatch发送到驱动 */ ret = serv-> dispatcher-> Dispatch(& serv-> object, LED_WRITE_READ, data, reply); if (ret != HDF_SUCCESS)printf("fail to send service call!\\r\\n"); goto out; int replyData = https://www.songbingjia.com/android/0; /* 读取驱动的回复数据 */ if (!HdfSbufReadInt32(reply, & replyData))printf("fail to get service call reply!\\r\\n"); ret = HDF_ERR_INVALID_OBJECT; goto out; printf("\\r\\nGet reply is: %d\\r\\n", replyData); out: HdfSBufRecycle(data); HdfSBufRecycle(reply); return ret; int main(int argc, char **argv)int i; /* 获取服务 */ struct HdfIoService *serv = HdfIoServiceBind(LED_SERVICE); if (serv == NULL)printf("fail to get service %s!\\r\\n", LED_SERVICE); return HDF_FAILURE; for (i=0; i < argc; i++)printf("\\r\\nArgument %d is %s.\\r\\n", i, argv[i]); SendEvent(serv, atoi(argv[1])); HdfIoServiceRecycle(serv); printf("exit"); return HDF_SUCCESS;

这一部分是本文的重点部分
OpenHarmony的设备开发中的驱动调用与单片机的驱动开发不太相同,以往单片机的驱动调用往往是采用库函数调用的方式,但OpenHarmony的驱动调用采用的是驱动程序暴露出一个server,程序通过Dispatch发送指令的方式。有点类似与ROS的消息通信机制中的话题发布和订阅。在OpenHarmony中驱动调用的这部分程序属于用户程序,是用户态的内容,而驱动是内核态的内容。所以用户程序无法直接访问驱动,上面代码通过Dispatch向驱动程序发送指令从而实现LED灯的亮灭。
3.1 发送指令到驱动程序
我们看下my_led_app.c中SendEvent函数中通过Dispatch发送到驱动的代码
/* 通过Dispatch发送到驱动 */ ret = serv-> dispatcher-> Dispatch(& serv-> object, LED_WRITE_READ, data, reply); if (ret != HDF_SUCCESS)printf("fail to send service call!\\r\\n"); goto out; int replyData = https://www.songbingjia.com/android/0;

这段代码实现将指令发送到驱动程序
驱动程序指令接受的的代码在上一篇文章中的led.c驱动代码中的LedDriverDispatch函数
// Dispatch是用来处理用户态发下来的消息 int32_t LedDriverDispatch(struct HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)uint8_t contrl; HDF_LOGE("Led driver dispatch"); if (client == NULL || client-> device == NULL)HDF_LOGE("Led driver device is NULL"); return HDF_ERR_INVALID_OBJECT; switch (cmdCode)/* 接收到用户态发来的LED_WRITE_READ命令 */ case LED_WRITE_READ: /* 读取data里的数据,赋值给contrl */ HdfSbufReadUint8(data,& contrl); switch (contrl)/* 开灯 */ case LED_ON: GpioWrite(g_Stm32Mp1ILed.gpioNum, GPIO_VAL_LOW); status = 1; break; /* 关灯 */ case LED_OFF: GpioWrite(g_Stm32Mp1ILed.gpioNum, GPIO_VAL_HIGH); status = 0; break; /* 状态翻转 */ case LED_TOGGLE: if(status == 0)GpioWrite(g_Stm32Mp1ILed.gpioNum, GPIO_VAL_LOW); status = 1; elseGpioWrite(g_Stm32Mp1ILed.gpioNum, GPIO_VAL_HIGH); status = 0; break; default: break; /* 把LED的状态值写入reply, 可被带至用户程序 */ if (!HdfSbufWriteInt32(reply, status))HDF_LOGE("replay is fail"); return HDF_FAILURE; break; default: break; return HDF_SUCCESS;

3.2 从驱动程序接受数据
刚刚实现了用户态向内核态发送指令,同理,内核态也可以向用户态发送数据。
让我们看看驱动代码中向用户发送LED状态信息的代码(在led.c中LedDriverDispatch函数的一部分)
/* 把LED的状态值写入reply, 可被带至用户程序 */ if (!HdfSbufWriteInt32(reply, status))HDF_LOGE("replay is fail"); return HDF_FAILURE;

下面是用户程序接收的部分
/* 读取驱动的回复数据 */ if (!HdfSbufReadInt32(reply, & replyData))printf("fail to get service call reply!\\r\\n"); ret = HDF_ERR_INVALID_OBJECT; goto out; printf("\\r\\nGet reply is: %d\\r\\n", replyData);

四、编写编译构建文件BUILD.gn在BUILD.gn中添加以下代码
import("//build/lite/config/component/lite_component.gni")HDF_FRAMEWORKS = "//drivers/framework"executable("led_lib") output_name = "my_led" sources = [ "my_led_app.c", ]include_dirs = [ "$HDF_FRAMEWORKS/ability/sbuf/include", "$HDF_FRAMEWORKS/core/shared/include", "$HDF_FRAMEWORKS/core/host/include", "$HDF_FRAMEWORKS/core/master/include", "$HDF_FRAMEWORKS/include/core", "$HDF_FRAMEWORKS/include/utils", "$HDF_FRAMEWORKS/utils/include", "$HDF_FRAMEWORKS/include/osal", "//drivers/adapter/uhdf/posix/include", "//third_party/bounds_checking_function/include", "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits", ]deps = [ "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared", "//drivers/adapter/uhdf/manager:hdf_core", "//drivers/adapter/uhdf/posix:hdf_posix_osal", ]lite_component("my_led_app") features = [ ":led_lib", ]

五、编译烧录参考之前文章Linux下配置小熊派-鸿蒙·叔设备开发(南向)的开发环境
六、运行串口连接小熊派终端
./bin/my_led 0 #关闭LED ./bin/my_led 1 #开启LED ./bin/my_led 2 #翻转LED

想了解更多关于鸿蒙的内容,请访问:
51CTO和华为官方合作共建的鸿蒙技术社区
https://harmonyos.51cto.com/#bkwz
::: hljs-center
FFH小熊派驱动调用流程(以调用LED灯驱动为例)

文章图片

:::

    推荐阅读