3785|4

2549

帖子

0

TA的资源

五彩晶圆(初级)

楼主
 

【小熊派BearPi-HM Micro】五:利用HDF驱动框架实现LED闪烁 [复制链接]

本帖最后由 数码小叶 于 2022-4-19 08:26 编辑

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

       基于HDF框架进行驱动的开发主要分为两个部分,驱动实现和驱动配置,驱动实现包含驱动业务代码和驱动入口注册,这两者开发文档里都提供了模板,比如驱动业务代码,一个简单的模板如下:

#include"hdf_device_desc.h"// HDF框架对驱动开放相关能力接口的头文件
#include"hdf_log.h"// HDF 框架提供的日志接口头文件
#define HDF_LOG_TAG sample_driver   // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签

//驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架
int32_t HdfSampleDriverBind(structHdfDeviceObject*deviceObject)
{
    HDF_LOGD("Sample driver bind success");
    return0;
}

// 驱动自身业务初始的接口
int32_t HdfSampleDriverInit(structHdfDeviceObject*deviceObject)
{
    HDF_LOGD("Sample driver Init success");
    return0;
}

// 驱动资源释放的接口
void HdfSampleDriverRelease(structHdfDeviceObject*deviceObject)
{
    HDF_LOGD("Sample driver release success");
    return;
}

 

实际编程时,就可以直接在此模板上扩展,比如BearPi-HM Micro提供的demo

//驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架
int32_t HdfLedDriverBind(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL)
    {
        HDF_LOGE("Led driver bind failed!");
        return HDF_ERR_INVALID_OBJECT;
    }
    static struct IDeviceIoService ledDriver = {
        .Dispatch = LedDriverDispatch,
    };
    deviceObject->service = (struct IDeviceIoService *)(&ledDriver);
    HDF_LOGD("Led driver bind success");
    return HDF_SUCCESS;
}

       

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

struct HdfDriverEntry g_ledDriverEntry = {
  .moduleVersion = 1,
  .Bind = HdfLedDriverBind,            //GPIO不需要实现Bind,本例是一个空实现,厂商可根据自身需要添加相关操作
  .Init = HdfLedDriverInit,            //见Init参考
  .Release = HdfLedDriverRelease,     //见Release参考
  .moduleName = "HDF_LED",,//【必要且需要与HCS文件中里面的moduleName匹配】
};
//调用HDF_INIT将驱动入口注册到HDF框架中
HDF_INIT(g_ledDriverEntry);

        而对于驱动配置,HDF框架使用的是.HCS文件,.HCS文件全称是HDF Configuration Source,是HDF驱动框架的配置描述源码,内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。HC-GEN(HDF Configuration Generator)是HCS配置转换工具,可以将HDF配置文件转换为软件可读取的文件格式:在弱性能环境中,转换为配置树源码或配置树宏定义,驱动可直接调用C代码或宏式APIs获取配置。在高性能环境中,转换为HCB(HDF Configuration Binary)二进制文件,驱动可使用HDF框架提供的配置解析接口获取配置。HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。

       

        和驱动实现一样,驱动配置同样包含两部分,HDF框架定义的驱动设备描述和驱动的私有配置信息,HDF框架定义的驱动设备描述位于:~\bearpi\project\bearpi-hm_micro_small\device\st\bearpi_hm_micro\liteos_a\hdf_config\device_info\device_info.hcs。驱动的私有配置信息,则是用户自己添加的配置信息,比如这里的~\bearpi\project\bearpi-hm_micro_small\device\st\bearpi_hm_micro\liteos_a\hdf_config\led\led_config.hcs

 

device_led :: device {                  // led设备节点
    device0 :: deviceNode {             // led驱动的DeviceNode节点
        policy = 2;                     // policy字段是驱动服务发布的策略,等于0,不需要发布服务
        priority = 10;                 // 驱动启动优先级(0-200),值越大优先级越低,
        preload = 1;                    // 驱动按需加载字段
        permission = 0777;              // 驱动创建设备节点权限
        moduleName = "HDF_LED";        // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
        serviceName = "hdf_led";    // 驱动对外发布服务的名称,必须唯一
        deviceMatchAttr = "st_stm32mp157_led"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
    }
}  

 

root {
    LedDriverConfig {
        led_gpio_num = 13;
        match_attr = "st_stm32mp157_led";   //该字段的值必须和device_info.hcs中的deviceMatchAttr值一致
    }
}

 

 

最后,是需要将需要将该配置文件添加到板级配置入口文件hdf.hcs

device\st\bearpi_hm_micro\liteos_a\hdf_config\hdf.hcs

#include "device_info/device_info.hcs"
#include "led/led_config.hcs"

关于GPIO口的操作,GPIO驱动已经提供了相关的接口

 

然后就是led闪烁的业务代码编写了,就是驱动程序指令接受的的代码,用户态向内核态发送指令

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;
            }
            else
            {
                GpioWrite(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;
}

 

        通过代码可以感受到OpenHarmony的设备开发中的驱动调用与单片机的驱动开发不太相同,单片机的驱动调用往往是采用函数调用的方式,但是OpenHarmony没有这样的操作,驱动调用采用的是驱动程序向用户态暴露server后,程序才能通过Dispatch的方式发送指令到驱动程序,并可以将用户态的数据携带到驱动程序,也可以从驱动程序读出数据。像上面的代码就是通过Dispatch向驱动程序发送指令从而实现LED灯的亮灭,当然,内核态也可以向用户态发送数据。

        和上一篇,helloword一样,还需要编译文件,对于业务代码,和上一篇一模一样的操作,配置BUILD.gn、applications.json、config.json。对于驱动文件,不但需要自己写的BUILD.gn,还需要修改~\bearpi\project\bearpi-hm_micro_small\device\st\drivers\BUILD.gn

import("//drivers/adapter/khdf/liteos/hdf.gni")

hdf_driver("hdf_led") {
    sources = [
    "led.c",
    ]
}

 

 

最后编译,烧录到板子了,和之前一样,打开串口助手 ,通过指令操作led的亮灭状态变化

 

 

 

 

此帖出自Linux开发论坛

最新回复

感觉OpenHarmony更像是内核微服务,你请求服务器再去执行,不像别的直接底层调用  详情 回复 发表于 2022-6-8 12:22
点赞 关注

回复
举报

6850

帖子

0

TA的资源

五彩晶圆(高级)

沙发
 

确实,OpenHarmony的设备开发中的驱动调用和单片机的驱动开发相差还是比较大的。

此帖出自Linux开发论坛
 
 

回复

7671

帖子

2

TA的资源

五彩晶圆(高级)

板凳
 

可以可以,学习了。

此帖出自Linux开发论坛
 
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 

回复

7

帖子

0

TA的资源

一粒金砂(初级)

4
 
写的不错!
此帖出自Linux开发论坛
 
 
 

回复

4947

帖子

12

TA的资源

版主

5
 
感觉OpenHarmony更像是内核微服务,你请求服务器再去执行,不像别的直接底层调用
此帖出自Linux开发论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表