代码在:https://gitee.com/kwydm/open-harmony-taurus

目录大致结构

1.驱动开发
创建目录://vendor/huawei/hdf/LED/src

新建Makefile

include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk

MODULE_NAME := hdf_led_driver
LOCAL_SRCS += led.c
LOCAL_INCLUDE := ./include
LOCAL_CFLAGS += -fstack-protector-strong -Wextra -Wall -Werror
include $(HDF_DRIVER)

打开//device/hisilicon/drivers/lite.mk 编译结果文件链接到内核镜像

## 在头部添加变量
VENDOR_HDF_DRIVERS_ROOT := $(LITEOSTOPDIR)/../../vendor/huawei/hdf LITEOS_BASELIB += -lhdf_led_driver
LIB_SUBDIRS += $(VENDOR_HDF_DRIVERS_ROOT)/LED/src

新建led.c

#include "hdf_device_desc.h" // HDF框架对驱动开放相关能力接口的头文件
#include "hdf_log.h" // HDF 框架提供的日志接口头文件
#include "device_resource_if.h"
#include "osal_io.h"
#include "osal_mem.h"
#include "gpio_if.h"
#include "osal_irq.h"
#include "osal_time.h" #define HDF_LOG_TAG led_driver // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签
#define LED_WRITE_READ 1 // 读写操作码1 static int32_t CtlLED(int mode)
{
int32_t ret;
uint16_t valRead;
/* LED的GPIO管脚号 */
uint16_t gpio = 5 * 8 + 1; // 红外补光灯
// uint16_t gpio = 2 * 8 + 3; // 绿色指示灯
// uint16_t gpio = 3 * 8 + 4; // 红色指示灯 /* 将GPIO管脚配置为输出 */
ret = GpioSetDir(gpio, GPIO_DIR_OUT);
if (ret != 0)
{
HDF_LOGE("GpioSerDir: failed, ret %d\n", ret);
return ret;
} if (mode == -1)
{
// 翻转输出口
(void)GpioRead(gpio, &valRead);
ret = GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW);
}
else
{
ret = GpioWrite(gpio, mode);
} if (ret != 0)
{
HDF_LOGE("GpioWrite: failed, ret %d\n", ret);
return ret;
}
return ret;
} // Dispatch是用来处理用户态发下来的消息
int32_t LedDriverDispatch(struct HdfDeviceIoClient *client, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply)
{
int32_t result = HDF_FAILURE;
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){
case LED_WRITE_READ:
const char *recv = HdfSbufReadString(data);
if (recv != NULL)
{
//HDF_LOGI("recv: %s", recv);
result = CtlLED(-1);
// CtlLED(GPIO_VAL_HIGH);
if (!HdfSbufWriteInt32(reply, result)){
//HDF_LOGE("replay is fail");
}
return HdfDeviceSendEvent(client->device, cmdCode, data);
}
break; default:
break;
}
return result;
} //驱动对外提供的服务能力,将相关的服务接口绑定到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;
} // 驱动自身业务初始的接口
int32_t HdfLedDriverInit(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL)
{
HDF_LOGE("Led driver Init failed!");
return HDF_ERR_INVALID_OBJECT;
}
HDF_LOGD("Led driver Init success");
return HDF_SUCCESS;
} // 驱动资源释放的接口
void HdfLedDriverRelease(struct HdfDeviceObject *deviceObject)
{
if (deviceObject == NULL)
{
HDF_LOGE("Led driver release failed!");
return;
} HDF_LOGD("Led driver release success");
return;
} // 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量
struct HdfDriverEntry g_ledDriverEntry = {
.moduleVersion = 1,
.moduleName = "led_driver",
.Bind = HdfLedDriverBind,
.Init = HdfLedDriverInit,
.Release = HdfLedDriverRelease,
}; // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
HDF_INIT(g_ledDriverEntry);

2.用户态
\vendor\huawei\hdf\LED\dispatch\CallLED.c

#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "hdf_io_service_if.h" #define LED_WRITE_READ 1
#define HDF_LOG_TAG LED_APP
#define LED_SERVICE "led_service" // 接收驱动上报事件
static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
{
const char *string = HdfSbufReadString(data);
if (string == NULL)
{
HDF_LOGE("fail to read string in event data");
return HDF_FAILURE;
}
HDF_LOGE("%s: dev event received: %u %s", (char *)priv, id, string); return HDF_SUCCESS;
} static int SendEvent(struct HdfIoService *serv, char *eventData)
{
int ret = 0;
struct HdfSBuf *data = HdfSBufObtainDefaultSize();
if (data == NULL)
{
HDF_LOGE("fail to obtain sbuf data");
return 1;
} struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
if (reply == NULL)
{
HDF_LOGE("fail to obtain sbuf reply");
ret = HDF_DEV_ERR_NO_MEMORY;
goto out;
} if (!HdfSbufWriteString(data, eventData))
{
HDF_LOGE("fail to write sbuf");
ret = HDF_FAILURE;
goto out;
} ret = serv->dispatcher->Dispatch(&serv->object, LED_WRITE_READ, data, reply);
if (ret != HDF_SUCCESS)
{
HDF_LOGE("fail to send service call");
goto out;
} int replyData = 0;
if (!HdfSbufReadInt32(reply, &replyData))
{
HDF_LOGE("fail to get service call reply");
ret = HDF_ERR_INVALID_OBJECT;
goto out;
}
HDF_LOGE("Get reply is: %d", replyData);
out:
HdfSBufRecycle(data);
HdfSBufRecycle(reply);
return ret;
} int main(void)
{
struct HdfIoService *serv = HdfIoServiceBind(LED_SERVICE);// 用户态获取驱动的服务
if (serv == NULL)
{
HDF_LOGE("fail to get service %s", LED_SERVICE);
return HDF_FAILURE;
}
static struct HdfDevEventlistener listener = {
.callBack = OnDevEventReceived,
.priv = "Service0"}; // 用户态程序注册接收驱动上报事件的操作方法。
if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS)
{
HDF_LOGE("fail to register event listener");
return HDF_FAILURE;
} char *send_cmd = "toggle LED";
while (1)
{
if (SendEvent(serv, send_cmd))
{
HDF_LOGE("fail to send event");
return HDF_FAILURE;
}
sleep(1);
} if (HdfDeviceUnregisterEventListener(serv, &listener))
{
HDF_LOGE("fail to unregister listener");
return HDF_FAILURE;
} HdfIoServiceRecycle(serv);// 释放驱动服务。
HDF_LOGI("exit"); return HDF_SUCCESS;
}

\vendor\huawei\hdf\LED\dispatch\BUILD.gn

# Copyright (c) 2020 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License. HDF_FRAMEWORKS = "//drivers/framework" # 暂时放在这里编译用户态设备驱动消息调用程序,回头在考虑移到独立组件去编译Gavin Lee
executable("CallLED") {
sources = [
"//vendor/huawei/hdf/LED/dispatch/CallLED.c"
] include_dirs = [
"//vendor/huawei/hdf/LED/include",
"$HDF_FRAMEWORKS/core/adapter/vnode/include",
"$HDF_FRAMEWORKS/core/adapter/syscall/include",
"$HDF_FRAMEWORKS/core/shared/include",
"$HDF_FRAMEWORKS/core/host/include",
"$HDF_FRAMEWORKS/core/manager/include",
"$HDF_FRAMEWORKS/ability/sbuf/include",
"$HDF_FRAMEWORKS/include/core",
"$HDF_FRAMEWORKS/include/utils",
"$HDF_FRAMEWORKS/utils/include",
"$HDF_FRAMEWORKS/include/osal",
"$HDF_FRAMEWORKS/../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/posix:hdf_posix",
"//drivers/adapter/uhdf/manager:hdf_core",
"//drivers/adapter/uhdf/posix:hdf_posix_osal"
] public_deps = [
"//third_party/bounds_checking_function:libsec_shared",
] defines = [
"__USER__",
] cflags = [
"-Wall",
"-Wextra",
"-Werror",
]
}

vendor\huawei\hdf\LED\BUILD.gn

import("//build/lite/config/component/lite_component.gni")

lite_component("led_gpio"){
features = ["dispatch:CallLED"]
}

build\lite\components\drivers.json

3.烧录运行
串口发送下面的代码

./bin/CallLED

执行之后这个补光灯会1S闪一次

参考:https://harmonyos.51cto.com/posts/2820,Gavin,Dweb九弓子

作者:卡哇伊大喵

想了解更多内容,请访问51CTO和华为合作共建的鸿蒙社区:https://harmonyos.51cto.com

鸿蒙HI3516-驱动开发(1.1-LTS)的更多相关文章

  1. 《Android深度探索》(卷1)HAL与驱动开发读后感:

    第一章:安卓系统移植与驱动开发概述 全书分为4篇,分别从搭建开发环境,Linux驱动和Android HAL的基础知识,开发Linux驱动的高级技术和分析典型的Linux驱动源代码4个方面介绍Andr ...

  2. 使用IdleTest进行TDD单元测试驱动开发演练(3) 之 ASP.NET MVC

    一.[前言] (1)本文将用到IOC框架Unity,可参照<Unity V3 初步使用 —— 为我的.NET项目从简单三层架构转到IOC做准备>(2)本文的解决方案是基于前述<使用I ...

  3. 使用IdleTest进行TDD单元测试驱动开发演练(2)

    [前言] 1. 有关上篇请参见<使用IdleTest进行TDD单元测试驱动开发演练(1)>,有关本篇用到Entity Framework Code First请参见<使用NuGet助 ...

  4. 使用IdleTest进行TDD单元测试驱动开发演练(1)

    [前言] 开发工具:Visual Studio 2012 测试库:Visual Studio 2012自带的MSTest DI框架:Unity 数据持久层:Entity Framework 前端UI: ...

  5. 行为驱动开发iOS <收藏>

    前段时间在design+code购买了一个学习iOS设计和编码在线课程,使用Sketch设计App,然后使用Swift语言实现Designer News客户端.作者Meng To已经开源到Github ...

  6. TDD测试驱动开发

    TDD测试驱动开发 一.概念 TDD故名思意就是用测试的方法驱动开发,简单说就是先写测试代码,再写开发代码.传统的方式是先写代码,再测试,它的开发方式与之正好相反. TDD是极限编程的一个最重要的设计 ...

  7. Linux驱动开发概述

    原文出处:http://www.cnblogs.com/jacklu/p/4722563.html Linux设备分类 设备的驱动程序也要像裸机程序那样进行一些硬件操作,不同的是驱动程序需要" ...

  8. Android驱动开发5-8章读书笔记

    Android驱动开发读书笔记                                                              第五章 S5PV210是一款32位处理器,具有 ...

  9. 【OpenWRT】【RT5350】【三】MakeFile文件编写规则和OpenWRT驱动开发步骤

    一.Makefile文件编写 http://www.cnblogs.com/majiangjiang/articles/3218002.html 可以看下上面的博客,总结的比较全了,在此不再复述 二. ...

随机推荐

  1. Same Origin Policy 浏览器同源策略详解

    同源策略 Same Origin Policy 日常开发中最常与网络打交道,那关于浏览器的同源策略和跨域相关的知识是该整理一下了. 首先需要明确的是,同源策略是浏览器的安全策略,由于存在这个策略,我们 ...

  2. Vue框架简介及简单使用

    目录 一.前端框架介绍 二.vue框架简介 三.vue使用初体验 1. vue如何在页面中引入 2. 插值表达式 3. 文本指令 4. 方法指令(事件指令) 5. 属性指令 四.js数据类型补充 1. ...

  3. Linux自学之旅-基础命令(chown和chgrp)

    转: Linux自学之旅-基础命令(chown和chgrp) Linux自学之旅-基础命令(改变所有者与所属组的命令) 文章目录 前言 一.chown命令 二.chgrp命令 总结 前言 1.上一节我 ...

  4. Spring-05 使用注解开发

    Spring-05 使用注解开发 使用注解开发 1.项目准备 在spring4之后,想要使用注解形式,必须得要引入aop的包5 <!-- https://mvnrepository.com/ar ...

  5. Git 常用命令 和 安装

    这年头不会点git还真不能与别人进行代码交流 安装 windowns版下载:https://git-scm.com/download/win ,下载完成后就自己手动安装 ,很简单就不多说. Ubunt ...

  6. 为什么要从 Linux 迁移到 BSD2

    OpenZFS on Linux,是项目的 Linux 部分,目前有 345 个活跃的贡献者,有超过 5600 个提交,而且几乎每天都有提交!一些世界上最大的 CDN 和数据存储服务在 FreeBSD ...

  7. 2017算法期末复习练习赛-G Beihang Couple Pairing Comunity 2017 题解(网络流)

    理解不够透彻.好题不可浪费,写题解以增进理解.会陆续补充题目.(咕咕咕) G Beihang Couple Pairing Comunity 2017 题目链接 Beihang Couple Pair ...

  8. LAB1 启动操作系统

    从机器上电到运行OS发生了什么? 在电脑主板上有一个Flash块,存放了BIOS的可执行代码.它是ROM,断电不会丢掉数据.在机器上电的时候,CPU要求内存控制器从0地址读取数据(程序第一条指令)的时 ...

  9. ch2_8_1求解n阶螺旋矩阵问题

    思路:循环输出,注意边界控制 import java.util.Scanner; public class ch2_8_1求解n阶螺旋矩阵问题 { public static void main(St ...

  10. ch1_6_1求解两种排序方法问题

    考拉有n个字符串字符串,任意两个字符串长度都是不同的.  考拉最近学习到有两种字符串的排序方法:   1.根据字符串的字典序排序.例如: "car" < "carr ...