前言: 自己一直是板端开发也就是南向开发,对于北向应用端开发一直是个短板,九联提供的开发板对南北向开发过程提供了样例,非常感兴趣这一部分,如何实现,下面就自己根据样例实现开发板上使用APP控制板端接口来学习。下面根据Openharmony NAPI框架实现GPIO接口。
一、开发环境
- 搭载OpenHarmony-3.2-Beat2版本的九联开发板。
- Ubuntu20.04虚拟机。
- USB_Burning_Tool烧录工具。
- 自己准备LED灯及接口线。
以上除4部分,其他都在前面的帖子中搭建完成。第4部分自己准备几根杜邦线和几个LED灯。
二、NAPI框架简介
NAPI(Native API)是OpenHarmony标准系统的一种JS API实现机制,适合封装IO、CPU密集型、OS底层等能力并对外暴露JS接口,实现JS与C/C++代码互相访问。
三、实现NAPI扩展库
1、创建NAPI扩展库
新增子系统napisubsys
在OpenHarmony源码目录下创建一个目录napisubsys作为子系统目录(子系统可以在OpenHarmony源码目录任意位置),目前创建在九联开发板目录下sample/napi目录下,具体相对OpenHarmony目录为vendor/unionman/unionpi_tiger/sample/napi/napisubsys,在创建的目录下新建ohos.build文件,构建时会先读取这个文件。将新增子系统配置到OpenHarmony目录下的build/subsystem_config.json文件中参与编译。subsystem_config.json增加如下代码:
"napisubsys": {
"path": "vendor/unionman/unionpi_tiger/sample/napi/napisubsys",
"name": "napisubsys"
},
2、新增gpioled_part组件
在子系统napisubsys目录下创建一个子组件目录gpioled_part,打开napisubsys目录下的ohos.build文件,在"parts":中添加下列语句:
"gpioled_part": {
"variants": [
"phone"
],
"module_list": [ "//vendor/unionman/unionpi_tiger/sample/napi/napisubsys/gpioled_part/gpioled_demo:gpioled"
]
}
3、新增扩展动态库
在组件目录gpioled_part下面新建gpioled_demo目录,作为NAPI扩展库的代码目录。在gpioled_demo目录下创建gpioled.cpp和BUILD.gn文件,编写构建配置也即BUILD.gn文件内容如下:
import("//build/ohos.gni")
ohos_shared_library("gpioled") {
include_dirs = [ "//foundation/ace/napi/interfaces/kits" ]
sources = [
"gpioled.cpp",
"um_gpio.c",
]
deps = [
"//foundation/ace/napi:ace_napi",
"//utils/native/base:utils",
]
external_deps = [ "hiviewdfx_hilog_native:libhilog" ]
relative_install_dir = "module"
subsystem_name = "napisubsys"
part_name = "gpioled_part"
}
4、将组件添加到产品定义中
打开vendor/unionman/unionpi_tiger/config.json文件,在“subsystems”:中添加如下语句:
{
"subsystem": "napisubsys",
"components": [
{
"component": "gpioled_part",
"features": []
}
]
},
四、NAPI接口开发
模块注册
1)添加NAPI框架头文件,引入框架提供的方法。
#include "napi/native_api.h"
#include "napi/native_node_api.h"
2)定义模块。
3)注册模块,加载动态库时自动调用注册。
static napi_module gpioled_demoModule = {
.nm_version = 1,
.nm_flags = 0,
.nm_filename = nullptr,
.nm_register_func = registerGpioLed_DemoApis,
.nm_modname = "gpioled_demo",
.nm_priv = ((void *) 0),
.reserved = {0},
};
extern "C" __attribute__((constructor)) void RegisterGpioLed_DemoModule(void) {
napi_module_register(&gpioled_demoModule);
}
使用DECLARE_NAPI_FUNCTION("js函数名", c++实现函数名)定义接口函数、DECLARE_NAPI_PROPERTY、 DECLARE_NAPI_STATIC_PROPERTY等定义属性,再通过napi_define_properties赋给exports对象,最后返回exports对象。
static napi_value registerGpioLed_DemoApis(napi_env env, napi_value exports) {
napi_value gpioValHigh = gpioValHigh;
napi_value gpioValLow = nullptr;
napi_create_int32(env, UM_GPIO_HIGH_LEVE, &gpioValHig);
napi_create_int32(env, UM_GPIO_LOW_LEVE, &gpioValLow);
napi_property_descriptor desc[] = {
DECLARE_NAPI_FUNCTION("setLedStatusWithCallback", setLedStatusWithCallback),
DECLARE_NAPI_FUNCTION("getLedStatusWithCallback", getLedStatusWithCallback),
DECLARE_NAPI_FUNCTION("setLedStatusWithPromise", setLedStatusWithPromise),
DECLARE_NAPI_FUNCTION("getLedStatusWithPromise", getLedStatusWithPromise),
DECLARE_NAPI_FUNCTION("setLedStatus", setLedStatus),
DECLARE_NAPI_FUNCTION("getLedStatus", getLedStatus),
DECLARE_NAPI_STATIC_PROPERTY("LED_ON", gpioValHigh),
DECLARE_NAPI_STATIC_PROPERTY("LED_OFF", gpioValLow),
};
NAPI_CALL(env, napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc));
return exports;
}
具体实现代码可去代码仓库进行下载学习。
修改device\board\unionman\unionpi_tiger\config\init\arm\init.A311D.cfg 文件,在cmds中添加相关命令
"write /sys/class/gpio/export 380",
"write /sys/class/gpio/export 381",
"write /sys/class/gpio/export 382",
"write /sys/class/gpio/export 383",
"write /sys/class/gpio/export 384",
"write /sys/class/gpio/export 385",
"write /sys/class/gpio/export 386",
"write /sys/class/gpio/export 387",
"write /sys/class/gpio/export 388",
"write /sys/class/gpio/export 389",
"chmod 666 /sys/class/gpio/gpio380/direction",
"chmod 666 /sys/class/gpio/gpio381/direction",
"chmod 666 /sys/class/gpio/gpio382/direction",
"chmod 666 /sys/class/gpio/gpio383/direction",
"chmod 666 /sys/class/gpio/gpio384/direction",
"chmod 666 /sys/class/gpio/gpio385/direction",
"chmod 666 /sys/class/gpio/gpio386/direction",
"chmod 666 /sys/class/gpio/gpio387/direction",
"chmod 666 /sys/class/gpio/gpio388/direction",
"chmod 666 /sys/class/gpio/gpio389/direction",
"chmod 666 /sys/class/gpio/gpio380/value",
"chmod 666 /sys/class/gpio/gpio381/value",
"chmod 666 /sys/class/gpio/gpio382/value",
"chmod 666 /sys/class/gpio/gpio383/value",
"chmod 666 /sys/class/gpio/gpio384/value",
"chmod 666 /sys/class/gpio/gpio385/value",
"chmod 666 /sys/class/gpio/gpio386/value",
"chmod 666 /sys/class/gpio/gpio387/value",
"chmod 666 /sys/class/gpio/gpio388/value",
"chmod 666 /sys/class/gpio/gpio389/value"
五、Ubuntu下进行编译NAPI
将以上文件修改完成后,编译镜像文件,前面帖子中已有编译方法,自行查阅,如有问题帖子留言,我会进行回答。进入到Ubuntu下进行编译,编译指令如下:
./build.sh --product-name unionpi_tiger –ccache
编译完成如下图所示。
编译完成后需要,进行对镜像进行打包,然后进行烧写。 执行以下命令固件打包
./device/board/unionman/unionpi_tiger/common/tools/packer-unionpi.sh
打包完成如下图所示,打包最终烧录程序目录为out/unionpi_tiger/packages/phone/images/OpenHarmony.img
打开烧录工具,使用Micro USB数据线连接PC与开发板OTG口并接通电源,导入烧录包后开始烧录即可(可关闭校验IMG)。具体如何烧录可参考我的其他博文。
六、应用程序编译
- 打开DevEco Studio 3.0.0.993版本的软件,打开vendor_unionman/unionpi_tiger/sample/app/gpioled_app/gpioled-javascript目录,如下图所示程序代码。
- 将目录vendor_unionman/unionpi_tiger/sample/napi/napisubsys下的@ohos.gpioled.d.ts文件拷贝到OpenHarmony的SDK下面,如图所示具体路径。
- 将编译后的hap文件拷贝到USB中,因SDK中的hdc_std.exe不运行,用USB安装应用程序了,文件如下图所示,可自行修改文件名。
七、板端安装应用控制LED灯
- 将USB插入USB3.0接口,串口端显示如下所示。
- 挂载/dev/block/sda1到/mnt/usb目录,如果没有/mnt/usb目录进行自建,运行如下命令进行安装hap,如图所示。
bm install -p 包名.hap
弄了hdc_std.exe,但它不运行,有问题。正在查找问题。有了hdc,直接连接板子OTG将hap运行到板子上看app效果,可以看调试信息,一口两用。