鸿蒙HI3516-驱动开发(1.1-LTS)
代码在: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)的更多相关文章
- 《Android深度探索》(卷1)HAL与驱动开发读后感:
第一章:安卓系统移植与驱动开发概述 全书分为4篇,分别从搭建开发环境,Linux驱动和Android HAL的基础知识,开发Linux驱动的高级技术和分析典型的Linux驱动源代码4个方面介绍Andr ...
- 使用IdleTest进行TDD单元测试驱动开发演练(3) 之 ASP.NET MVC
一.[前言] (1)本文将用到IOC框架Unity,可参照<Unity V3 初步使用 —— 为我的.NET项目从简单三层架构转到IOC做准备>(2)本文的解决方案是基于前述<使用I ...
- 使用IdleTest进行TDD单元测试驱动开发演练(2)
[前言] 1. 有关上篇请参见<使用IdleTest进行TDD单元测试驱动开发演练(1)>,有关本篇用到Entity Framework Code First请参见<使用NuGet助 ...
- 使用IdleTest进行TDD单元测试驱动开发演练(1)
[前言] 开发工具:Visual Studio 2012 测试库:Visual Studio 2012自带的MSTest DI框架:Unity 数据持久层:Entity Framework 前端UI: ...
- 行为驱动开发iOS <收藏>
前段时间在design+code购买了一个学习iOS设计和编码在线课程,使用Sketch设计App,然后使用Swift语言实现Designer News客户端.作者Meng To已经开源到Github ...
- TDD测试驱动开发
TDD测试驱动开发 一.概念 TDD故名思意就是用测试的方法驱动开发,简单说就是先写测试代码,再写开发代码.传统的方式是先写代码,再测试,它的开发方式与之正好相反. TDD是极限编程的一个最重要的设计 ...
- Linux驱动开发概述
原文出处:http://www.cnblogs.com/jacklu/p/4722563.html Linux设备分类 设备的驱动程序也要像裸机程序那样进行一些硬件操作,不同的是驱动程序需要" ...
- Android驱动开发5-8章读书笔记
Android驱动开发读书笔记 第五章 S5PV210是一款32位处理器,具有 ...
- 【OpenWRT】【RT5350】【三】MakeFile文件编写规则和OpenWRT驱动开发步骤
一.Makefile文件编写 http://www.cnblogs.com/majiangjiang/articles/3218002.html 可以看下上面的博客,总结的比较全了,在此不再复述 二. ...
随机推荐
- 第43天学习打卡(JVM探究)
JVM探究 请你谈谈你对JVM的理解?Java8虚拟机和之前的变化更新? 什么是OOM,什么是栈溢出StackOverFlowError? 怎么分析? JVM的常用调优参数有哪些? 内存快照如何抓取, ...
- 后端程序员之路 50、Go语言开发环境
Downloads - The Go Programming Languagehttps://golang.org/dl/ - windows下的开发环境 - 下载go1.8.1.windows ...
- CCF(管道清洁):最小费用最大流
管道清洁 201812-5 需要清洁的管道下界为1, 不需要清洁的管道下界为0, 可重复经过的管道上界为正无穷, 不可重复经过的管道上界为1. 这属于无源无汇的有容量下界的最小费用可行流.解决的方法就 ...
- JS动态获取select中被选中的option的值,并在控制台输出
生活城市: <select id="province"> <option>河南省</option> <option>黑龙江省< ...
- STM32 ADC详细篇(基于HAL库)
一.基础认识 ADC就是模数转换,即将模拟量转换为数字量 l 分辨率,读出的数据的长度,如8位就是最大值为255的意思,即范围[0,255],12位就是最大值为4096,即范围[0,4096] l ...
- 初探JavaScript原型链污染
18年p师傅在知识星球出了一些代码审计题目,其中就有一道难度为hard的js题目(Thejs)为原型链污染攻击,而当时我因为太忙了(其实是太菜了,流下了没技术的泪水)并没有认真看过,后续在p师傅写出w ...
- 趣谈 DHCP 协议,有点意思。
计算机网络我也连载了很多篇了,大家可以在我的公众号「程序员cxuan」 或者我的 github 系统学习. 计算机网络第一篇,聊一聊网络基础 :计算机网络基础知识总结 计算机网络第二篇,聊一聊 TCP ...
- 写个锤子JS!它应该是你最后的选择
本文翻译自:https://dev.to/olpeh/javascript-should-be-your-last-resort-5dje 在进行现代化Web前端开发时,使用着自己最爱的框架,有时候可 ...
- Typora的一些快捷键
语法格式 快捷键 标题 # + 空格 = 一级标题, ## + 空格 =二级标题, 以此类推 shift + 数字1 =一级标题 ,shift + 数字2 =二级标题 , 以此类推 有序列表 1 ...
- idea启动项目address localhost:1099 is already in use异常解决
IDEA中启动Tomcat报错,Error running Tomcat7.0.52: Address localhost:1099 is already in use 或者是 java.rmi.se ...