文章目录
前言
本文主要记录使用Hi3861实现点亮LED的功能(小熊派开发板为例),并以此为基础介绍OpenHarmony的编译框架。
点亮LED
单片机开发
学习硬件开发的老套路,上手先点灯。
需要注意的是这个点灯流程与以往的单片机有所不同,在学习单片机裸机前后台、时间片轮询或者实时操作系统开发时 ,使用的是IDE集成开发环境,在新建工程时IDE会自动帮我们链接好所需的编译文件,不需要有太多额外的操作,工程建好后编写一个main函数,然后所有的代码都是在main函数的基础上开始编写,整个系统的代码运行也是从mian函数开始执行的。单片机三种代码框架如下:
1.前后台框架
2. 时间片轮询框架
int main(void)
{
System_Init();
while (1)
{
if (TIM_1msFlag)// 1ms
{
Led_Task(); //
TIM_1msFlag = 0;
}
if (TIM_10msFlag) // 10ms
{
KEY_ScanTask(); // 按键扫描处理任务
TIM_10msFlag = 0;
}
...
}
}
3. 实时操作系统框架
int main(void)
{
All_Init();//初始化所需资源
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
OpenHarmony开发
OpenHarmony系统目录
要进行开发,按照上面的思路肯定是要新建一个工程,然后开始写代码,但是在Hi3861的开发中,没有这一个环节了,取而代之的是使用OpenHarmony的系统目录来进行开发。使用VS Code打开系统目录,可以看见如下所示的文件夹,这么多文件夹都有什么作用呢?
结合这个架构图以及目录名我们就可以大致了解到每个文件夹的作用。
可以注意到applications这个文件夹是用来保存应用程序代码的,也就是说我们的代码需要在这个文件夹下进行编写。由于没有IDE,所以新建一个应用工程时,除了需要新建类似上面单片机开发的业务代码,还需要新建一个BUILD.gn的构建文件,为后面的编译做好铺垫。而且为了方便管理工程代码,还需要新建一个文件夹用来放置编译构建文件以及业务代码。例如此处,笔者就设置了一个my_led的文件夹。
代码结构可以参考此文——只要三步!连老师带你初探Hi3861代码结构。
业务代码
在VS Code新建好这两个文件后可以开始撸代码了,本次主要实现一个LED的闪烁,使用的是GPIO的输出功能,这里类似32的GPIO初始化过程,首先需要初始化GPIO,然后初始化对应的引脚,再然后需要配置成普通GPIO关闭复用功能,再然后是配置GPIO的方向为输出,最后配置GPIO的高低电平,实现效果,代码如下:
#include <stdio.h>
#include <unistd.h>
#include "ohos_init.h"
#include "wifiiot_gpio.h"
#include "wifiiot_gpio_ex.h"
void Led_Sample(void)
{
GpioInit(); //初始化GPIO
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_2, WIFI_IOT_IO_FUNC_GPIO_2_GPIO);//设置GPIO_2的复用功能为普通GPIO
GpioSetDir(WIFI_IOT_IO_NAME_GPIO_2, WIFI_IOT_GPIO_DIR_OUT);//设置GPIO_2为输出模式
GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_2,1);//设置GPIO_2输出高电平点亮LED灯
}
APP_FEATURE_INIT(Led_Sample);
编译构建文件
由于Hi3861的编译是在Linux的环境下进行的,所以还需要配置一下编译构建文件,将业务代码的路径给到编译器中。所以就需要配置BULID.gn。
static_library("myled") {
sources = [
"led_example.c"
]//需要编译的.c文件名称
include_dirs = [
"//utils/native/lite/include",
"//base/iot_hardware/interfaces/kits/wifiiot_lite"
]//工程所需的头文件路径
}
需要注意的是,这里的BUILD.gn还只是完成了my_led这个文件夹内部需要编译的内容的指定,并没有与整个工程关联起来,要与整个工程关联还需要配置my_led上层目录的BULID.gn文件。修改内容也很简单,只需要按照格式链接my_led的路径即可。并注意使用#将前面的其它路径给注释掉。
然后是保存,打开终端进行编译(详细步骤参考上一篇),下载bin文件,就可以发现成功点亮了LED小灯;稍作修改,就可以实现小灯闪烁,效果如下(不是实物效果,这里笔者使用了linkboy来演示):
小结
至此,点灯大师又多了一个点灯的板子,到此,OpenHarmony的开发流程就有所了解了,下面来扒一扒整个代码的编译结构。
OpenHarmony的编译框架
在输入编译指令hpm dist后,可以发现,系统去编译了一个名叫“BearPi-HM_Nano”的json文件。
打开这个json文件,可以发现里面全是文件夹名称和路径,此步骤主要是把整个系统运行所需要的代码进行抓包(笔者理解为就是在整个系统目录里面调出工程运行所需的内容)。
在打包所需文件和路径后 可以注意到有个ninja开头的写入目录,下面的内容中可以发现编译产生了.a文件。
可以发现后面很多内容都是将.c编译成.a,然后在如下标记的位置,将前面编译产生的.a文件进行了一个组合,最终打包生成了.bin文件,也就是二进制代码机器码,此时就已经完成了代码转换成二进制文件的操作,将.bin文件下载到Hi3861中即可运行。
这个过程中使用到的Ninja编译器介绍(来自小熊派)如下:
代码运行
可以发现在编写点亮led的业务代码时,我们并没有写main函数,但是程序也按照我们的预期执行了,这是为啥呢?是因为我们的业务代码在主函数中被调用了吗。
继续扒一扒
首先,真个系统代码目录中有一个appmain.c的函数,打开可以看到有一个app_main的入口函数,整个代码就是从此处开始运行的。
运用左盟主的办法,凡是有条件编译的都先不看,然后对照打印的日志文件我们可以发现前面大部分内容都是系统初始化以及对应的日志打印。
去除这些后,整个app_main()里面的代码就只剩下了下图所示的内容。整个app_main函数中没有发现我们的业务代码函数led_example()。那程序是怎么跑起来的呢,重点也就在下图的内容中。
通过下面的SYS_INIT()函数,这个小熊派的讲解是通过代码段拼接以及函数嵌套来实现用户代码的运行的,听着有点嘛。笔者理解为在主函数中系统通过整几个函数分配了一段内存用来运行用户的业务代码,而这段内存是用一个指针来表示的,用户在写自己的代码的时候,只需要将代码指向这段地址即可。
总结
笔者关于使用OpenHarmony点亮LED的总结就记录到这,新手上道,文内如有错误欢迎批评指出。