当前位置:   article > 正文

OpenHarmony中基于HDF框架的驱动开发和使用_openharmony hdf驱动开发

openharmony hdf驱动开发

代码版本:openharmony 3.2 release

主要内容

  1.         HDF框架基础知识
  2.         HDF驱动框架的开发
  3.         HDF驱动框架的应用

HDF框架基础知识 

HDF(Hardware Driver Foundation)驱动框架,为驱动开发者提供驱动框架能力,包括驱动加载、驱动服务管理和驱动消息机制。旨在构建统一的驱动架构平台,为驱动开发者提供更精准、更高效的开发环境,力求做到一次开发,多系统部署。

HDF驱动框架架构图:

HDF驱动架构主要组成部分:

  • HDI(Hardware Device Interface,硬件设备统一接口)层:通过规范化的设备接口标准,为系统提供统一、稳定的硬件设备操作接口。

  • HDF驱动框架:提供统一的硬件资源管理、驱动加载管理、设备节点管理、设备电源管理以及驱动服务模型等功能,需要包含设备管理、服务管理、DeviceHost、PnPManager等模块。

  • 统一的配置界面:支持硬件资源的抽象描述,屏蔽硬件差异,可以支撑开发者开发出与配置信息不绑定的通用驱动代码,提升开发及迁移效率,并可通过HC-Gen等工具快捷生成配置文件。

  • 操作系统抽象层(OSAL,Operating System Abstraction Layer):提供统一封装的内核操作相关接口,屏蔽不同系统操作差异,包含内存、锁、线程、信号量等接口。

  • 平台驱动:为外设驱动提供Board硬件(如:I2C/SPI/UART总线等平台资源)操作统一接口,同时对Board硬件操作进行统一的适配接口抽象以便于不同平台迁移。

  • 外设驱动模型:面向外设驱动,提供常见的驱动抽象模型,主要达成两个目的,提供标准化的器件驱动,开发者无需独立开发,通过配置即可完成驱动的部署;提供驱动模型抽象,屏蔽驱动与不同系统组件间的交互,使得驱动更具备通用性

以上的基础知识我也是从官方gitee中复制过来的,想具体了解的访问下面网址即可:

docs: OpenHarmony documentation | OpenHarmony开发者文档 - Gitee.comicon-default.png?t=N7T8https://gitee.com/openharmony/docs/tree/master/zh-cn/device-dev/driver

HDF驱动框架的开发:

基于HDF框架的驱动开发主要分为三个部分:实例化驱动入口、驱动编译配置和驱动配置属性。详细开发流程如下所示:

2.1、实例化驱动入口:

驱动入口必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量,且moduleName要和device_info.hcs中保持一致。HDF框架会将所有加载的驱动的HdfDriverEntry对象首地址汇总,形成一个类似数组的段地址空间,方便上层调用。

一般在加载驱动时HDF会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。

在//drivers/hdf_core/adapter/khdf/linux目录下新建个名为sample_test目录,再创建一个驱动入口代码。

  1. static int32_t HdfSampleDriverDispatch(
  2. struct HdfDeviceIoClient *client, int id, struct HdfSBuf *data, struct HdfSBuf *reply)
  3. {
  4. HDF_LOGI("%{public}s: received cmd %{public}d", __func__, id);
  5. if (id == SAMPLE_WRITE_READ) { //接收用户的命令参数
  6. const char *readData = HdfSbufReadString(data); //驱动读取用户的数据
  7. if (readData != NULL) {
  8. HDF_LOGE("%{public}s: read data is: %{public}s", __func__, readData);
  9. }
  10. if (!HdfSbufWriteInt32(reply, INT32_MAX)) { //驱动返回给用户的数据
  11. HDF_LOGE("%{public}s: reply int32 fail", __func__);
  12. }
  13. return HdfDeviceSendEvent(client->device, id, data);
  14. }
  15. return HDF_FAILURE;
  16. }
  17. static void HdflDriverRelease(struct HdfDeviceObject *deviceObject)
  18. {
  19. // release resources here
  20. return;
  21. }
  22. static int HdfDriverBind(struct HdfDeviceObject *deviceObject)
  23. {
  24. if (deviceObject == NULL) {
  25. return HDF_FAILURE;
  26. }
  27. static struct IDeviceIoService testService = {
  28. .Dispatch = HdfSampleDriverDispatch,
  29. };
  30. deviceObject->service = &testService;
  31. return HDF_SUCCESS;
  32. }
  33. static int HdfDriverInit(struct HdfDeviceObject *deviceObject)
  34. {
  35. if (deviceObject == NULL) {
  36. HDF_LOGE("%{public}s::ptr is null!", __func__);
  37. return HDF_FAILURE;
  38. }
  39. HDF_LOGI("Sample driver Init success");
  40. return HDF_SUCCESS;
  41. }
  42. static struct HdfDriverEntry DriverEntry = {
  43. .moduleVersion = 1,
  44. .moduleName = "sample_test",
  45. .Bind = HdfDriverBind,
  46. .Init = HdfDriverInit,
  47. .Release = HdflDriverRelease,
  48. };
  49. HDF_INIT(DriverEntry);

2.2、驱动编译配置:

完成驱动入口编写后,在驱动文件当前目录下添加一个Makefile文件,把驱动调用的头文件添加进来,然后再将所要编译的文件写进去,我没有用config配置的方式直接用的-y,这样比较简单些。

  1. include drivers/hdf/khdf/platform/platform.mk
  2. obj-y += sample_tset.o

还要将上一个目录的的文件的编译加进编译系统里面去,在当前驱动文件的上一级目录(//drivers/hdf_core/adapter/khdf/linux)中的Makefile中添加进这样一句话,为了避免麻烦还是选择-y的方式编译。

obj-y += sample_test/

2.3、驱动配置属性

在//vendor/hisilicon/hispark_taurus/hdf_config/device_info/device_info.hcs文件中添加deviceNode信息:

  1. device_sample_test :: device { // sample_test设备
  2. device0 :: deviceNode { // sample_test设备下的具体某个设备节点的配置
  3. policy = 2; // 驱动服务发布策略
  4. priority = 110; // 驱动启动优先级
  5. permission = 0644; // 驱动创建设备节点权限
  6. moduleName = "sample_test"; // 驱动名称,必须和驱动入口结构的moduleName值一致
  7. serviceName = "sample_test_service"; // 驱动对外发布服务的名称,必须唯一
  8. }
  9. }
成员名
policy驱动服务发布的策略,I2C管理器具体配置为2,表示驱动对内核态和用户态都发布服务
priority驱动启动优先级(0-200),值越大优先级越低。I2C管理器具体配置为50
permission驱动创建设备节点权限,I2C管理器具体配置为0664
moduleName驱动名称,I2C管理器固定为HDF_PLATFORM_I2C_MANAGER
serviceName驱动对外发布服务的名称,I2C管理器服务名设置为HDF_PLATFORM_I2C_MANAGER
deviceMatchAttr驱动私有数据匹配的关键字,I2C管理器设置为hdf_platform_i2c_manager

以上步骤操作完之后,再次编译的时候就会将sample_test.c编译为sample_test.o,将固件烧录进系统里面在/dev目录下就会有一个名为sample_test的设备

HDF框架的应用

应用程序通过服务名绑定驱动程序,和驱动建立联系,建立完之后就可以对这个驱动设备进行操作了,此处的sample_test_NAME要和上文2.3中的serviceName保持一致

  1. #define sample_test_NAME "sample_test_service"
  2. serv = HdfIoServiceBind(sample_test_NAME );
  3. if(serv == NULL){
  4. printf("fail to get service %s \n", sample_test_NAME );
  5. return HDF_FAILURE;
  6. }
  1. static int SendEvent(struct HdfIoService *serv, char *eventData)
  2. {
  3. int ret = 0;
  4. struct HdfSBuf *data = HdfSbufObtainDefaultSize(); //获取data缓冲区
  5. if (data == NULL) {
  6. HDF_LOGE("fail to obtain sbuf data");
  7. return 1;
  8. }
  9. struct HdfSBuf *reply = HdfSbufObtainDefaultSize(); //获取reply缓冲区
  10. if (reply == NULL) {
  11. HDF_LOGE("fail to obtain sbuf reply");
  12. ret = HDF_DEV_ERR_NO_MEMORY;
  13. goto out;
  14. }
  15. if (!HdfSbufWriteString(data, eventData)) { //将eventData写入data缓冲区
  16. HDF_LOGE("fail to write sbuf");
  17. ret = HDF_FAILURE;
  18. goto out;
  19. }
  20. //调用 Dispatch 将数据发送给驱动,SAMPLE_WRITE_READ为传入的命令参数
  21. ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
  22. if (ret != HDF_SUCCESS) {
  23. HDF_LOGE("fail to send service call");
  24. goto out;
  25. }
  26. int replyData = 0;
  27. if (!HdfSbufReadInt32(reply, &replyData)) { //读取驱动的返回值
  28. HDF_LOGE("fail to get service call reply");
  29. ret = HDF_ERR_INVALID_OBJECT;
  30. goto out;
  31. }
  32. HDF_LOGI("Get reply is: %{public}d", replyData);
  33. out:
  34. HdfSbufRecycle(data);
  35. HdfSbufRecycle(reply);
  36. return ret;
  37. }

编译应用的Build.gn文件:

  1. include_dirs = [
  2. "$HDF_FRAMEWORKS/ability/sbuf/include",
  3. "$HDF_FRAMEWORKS/core/shared/include",
  4. "$HDF_FRAMEWORKS/core/host/include",
  5. "$HDF_FRAMEWORKS/core/master/include",
  6. "$HDF_FRAMEWORKS/include/platform",
  7. "$HDF_FRAMEWORKS/include/core",
  8. "$HDF_FRAMEWORKS/include/utils",
  9. "$HDF_FRAMEWORKS/utils/include",
  10. "$HDF_FRAMEWORKS/include/osal",
  11. "//third_party/bounds_checking_function/include",
  12. "$HDF_ADAPTER/uhdf/posix/include",
  13. "$HDF_ADAPTER/khdf/linux/osal/include",
  14. "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
  15. ]
  16. public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ]
  17. deps = [
  18. "$HDF_ADAPTER/uhdf/manager:hdf_core",
  19. "$HDF_ADAPTER/uhdf/posix:hdf_posix_osal",
  20. "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
  21. ]
  22. cflags = [
  23. "-Wall",
  24. "-Wextra",
  25. "-Wno-format",
  26. "-Wno-format-extra-args",
  27. ]
  28. output_dir = "$root_out_dir/"

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/553325
推荐阅读
相关标签
  

闽ICP备14008679号