引言:花半秒钟就看透事物本质的人,和花一辈子都看不透事物本质的人,注定是截然不同的命运

做开发也一样,如果您能看透开发的整个过程,就不会出现“学会了某个RTOS的开发,同样的RTOS开发换一块开发板又不会了”,“跟着教程学会了某块开发板的某个Demo开发,自己开发另一个Demo又不会了”等等问题,只要能看透就能做到触类旁通,游刃有余!一定要活学活用,不能学死了,多想想为什么,不要死记过程。

在基于HarmonyOS开发Hi3861之前,需要对整个开发环境及过程有一个全局上的了解,首先还是从这一张最经典的框架图给大家讲起:

目前我们对Hi3861的开发主要涉及上图中的内核抽象层、系统能力子系统、DXF子系统、公共基础库子系统(提供KV存储、文件操作、定时器、IoT外设控制等能力供OpenHarmony各业务子系统及上层应用使用)、系统服务框架子系统(用于提供面向服务编程和对外提供能力用于分布式任务调度)

1、构建系统

该构建系统由python脚本配合gn、ninja组成,若是为了开发Demo或者应用,不必细究编译构建系统的具体实现细节,只需要做到会使用即可。

当我们输入python build.py wifiiot指令,python脚本开始读取build目录中与wifiiot设备相关的各项参数信息并构造编译指令如下:

gn工具所在目录/gn gen 源码所在目录/out/wifiiot --root=. --dotfile=build/lite/.gn --args='product = "wifiiot" ohos_build_type = "release"' 这条指令用于生成一些xxx.ninja文件,这些文件将在下一阶段指导ninja编译源码生成烧录文件

ninja工具所在目录/ninja -w dupbuild=warn -C 源码所在目录/out/wifiiot 这条指令用于根据前面生成的xxx.ninja文件调用工具链编译源码最终生成烧录文件

gn用于根据每个目录下的BUID,gn文件搜寻编译生成烧录文件所需的依赖文件,所以我们只要学会如何写BUILD.gn文件即可,关于具体实现本章就暂且略过,后期会给大家补上。

这里以led_example.c程序为例,给大家分析BUILD.gn文件,希望大家能举一反三:

在code-1.0\applications\sample\wifi-iot\app目录中有一个BUILD.gn文件,大家可以将该文件理解为一个管理者,它管理app目录中的每个子目录,通过这个BUILD.gn文件中的features字段可以决定哪一个子目录中的BUILD.gn中指定的源文件会被编译到烧录文件中,如下图所示:

假设我们要将app/iothardware目录中的led_example.c文件编译到烧录程序中,需要打开app/iothardware/BUILD.gn文件查看该文件中的源代码被为静态库的名称,可以看到名称为led_example,如下图所示:

这时我们将app/BUILD.gn文件中的startup修改为iothardware:led_example就大功告成啦!如下图所示:

.gn文件的feature字段格式为:模块源文件所在路径:模块名称

请注意:.gn文件中的空白都是空格,不是Tab键(制表符),如果您输入了制表符,在生成ninja文件时就会产生如下图所示错误:

我出一个问题考考大家,如果我们在app/iothardware目录中添加一个hello_world.c文件,主要用于打印hello_world,假设源代码已经写好了,如下图所示,您应该如何将其添加进编译列表中与其他程序一起进行编译呢?

您应该修改app/iothardware/BUILD.gn文件,将hello_world.c文件添加到sources字段中,如下图所示:

若这时我们在app/iothardware目录下新建一个head的目录,并在其中新建一个名为hello_world.h的头文件,内容如下图所示:

并修改hello_world.c的内容如下图所示:

这时如果直接进行编译,则会产生找不到头文件错误,如下图所示:

上面的路径中以 //开头的路径为绝对路径,//表示root参数指定的路径,也就是code-1,0,而test路径则为相对路径,以当前BUILD.gn文件所在目录作为参照。

这样一个简单的Demo就开发好了,不知道读者有没有这样的疑问:为什么我知道启动一个任务的宏是SYSY_RUN(),IIC、SPI等等外设操作的函数是什么?一系列类似的问题,那您继续往下看就能找到答案。

2、目录结构

注意:Hi3861模组只用到了部分组件

希望大家能跟随我对目录的介绍,自己打开对应本地SDK的目录来看一看


  1. ├── applications 存放例程
  2. └── sample
  3. ├── base
  4. ├── global 全球化子系统
  5. ├── hiviewdfx DXF子系统
  6. ├── iot_hardware iot设备的公共基础库子系统,提供外设操作,IICSPI等等
  7. ├── security 安全子系统
  8. └── startup 启动恢复相关
  9. ├── build 构建系统相关,存放各类芯片的编译构建参数等等
  10. └── lite
  11. ├── build.py -> build/lite/build.py 与构建系统相配合的python脚本(用于启动构建)
  12. ├── docs 文档
  13. ├── domains 集成各个厂商的SDK
  14. └── iot
  15. ├── drivers 驱动相关,HDF驱动框架
  16. ├── hdf
  17. └── liteos
  18. ├── foundation
  19. ├── aafwk 提供一个Want名称的数据类型用于加速应用的启动
  20. ├── ace JS应用开发框架
  21. ├── appexecfwk 用于程序框架子系统
  22. ├── communication 分布式通信子系统(软总线)
  23. ├── distributedschedule 系统服务框架子系统(面向服务编程,提供服务、使用服务等)、分布式任务调度子系统
  24. ├── graphic 图形子系统
  25. └── multimedia 媒体子系统
  26. ├── kernel 内核以及kal
  27. ├── liteos_a 面向Hi3516 3518等资源较丰富设备的内核
  28. └── liteos_m 面向资源受限设备的内核
  29. ├── out 编译输出文件
  30. ├── ipcamera_hi3516dv300
  31. └── wifiiot
  32. ├── prebuilts 提供一些库文件
  33. └── lite
  34. ├── test 测试子系统
  35. ├── developertest
  36. ├── xdevice
  37. └── xts
  38. ├── third_party 第三方库,例如cmsiscJSONFatfs等等
  39. ├── utils 公共基础系统,提供文件操作统一接口、KV存储、文件操作、定时器
  40. └── native
  41. └── vendor 各个厂商提供的SDK
  42. ├── hisi
  43. └── huawei

base以及foundation中的各个组件中都有两个名字相同的文件夹frameworks和interfaces,其中frameworks中存放该组件的具体实现,interfaces中存放对外提供的调用接口,这里以base/iot_hardware为例,其中hal文件夹中存放hi3861的SDK中提供的KV存储、文件操作、定时器和IoT外设控制的函数接口(函数接口指的是函数声明,我们只要知道函数声明,就不用关心函数的实现细节就能调用该函数完成相应操作),frameworks是对hal中的函数声明进行一定的封装,从而实现统一的接口,封装后的函数声明位于interfaces文件夹中,换句话说,我们想使用某个组件只需要查看interfaces文件夹中的声明,这样做的好处是:更换硬件或软件实现的情况下无需改动上层应用(例如目前我使用hi3861开发板实现了一些功能,这时甲方爸爸叫我用hi3516来实现同样的功能,我只需要将相应功能的底层支持函数的调用接口修改为interfaces文件夹中的形式,即可完成新的需求),大大的提高了开发效率。

3、如何创建一个任务?

SYS_RUN宏定义的正确用法为:

首先定义一个“初始化函数”,例如下面的“LedExampleEntry()”,所谓初始化是指初始化即将启动的任务需要的各类资源(例如:GPIO外设初始化),在这个“初始化”函数中初始化好了各类资源后调用osThreadNew函数(该创建线程的函数中调用了LOS_TASK_Create函数,也就是上面liblitekernel_flash.a库中提供的函数)创建线程即可。最后将“初始化”函数传入SYS_RUN宏中,在系统启动阶段时,系统会为其创建一个进程,优先级默认为2。SYS_RUN宏会在链接时将进程入口函数统一链接到某个段中,等待系统启动去这个段中将这些进程加载并运行(之前LiteOS的思想),这样做的优势是:可以让系统在合适的时候自动加载这些进程,无需用户考虑什么时候加载进程比较合适。

其中体现了一个进程和线程的思想,首先通过SYS_RUN宏创建了一个进程,该进程下面可以有多个线程。

  1. //来源于code-1.0\utils\native\lite\include\ohos_init.h
  2. /**
  3. * @brief Identifies the entry for initializing and starting a system running phase by the
  4. * priority 2.
  5. *
  6. * This macro is used to identify the entry called at the priority 2 in the system startup
  7. * phase of the startup process. \n
  8. *
  9. * @param func Indicates the entry function for initializing and starting a system running phase.
  10. * The type is void (*)(void).
  11. */
  12. #define SYS_RUN(func) LAYER_INITCALL_DEF(func, run, "run")
  13. //来源于code-1.0\applications\sample\wifi-iot\app\iothardware\led_example.c
  14. static void LedExampleEntry(void)
  15. {
  16. osThreadAttr_t attr;
  17. //第一步初始化该进程需要用到的资源
  18. GpioInit();
  19. IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_IO_FUNC_GPIO_9_GPIO);
  20. GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9, WIFI_IOT_GPIO_DIR_OUT);
  21. attr.name = "LedTask";
  22. attr.attr_bits = 0U;
  23. attr.cb_mem = NULL;
  24. attr.cb_size = 0U;
  25. attr.stack_mem = NULL;
  26. attr.stack_size = LED_TASK_STACK_SIZE;
  27. attr.priority = LED_TASK_PRIO;
  28. //第二步:为该进程创建线程
  29. if (osThreadNew((osThreadFunc_t)LedTask, NULL, &attr) == NULL) {
  30. printf("[LedExample] Falied to create LedTask!\n");
  31. }
  32. }
  33. SYS_RUN(LedExampleEntry);

4、如何找到您想使用函数API?

您首先需要对开头的框架图以及第2点的目录结构有一个大概的了解,并且根据您需要的API进行分析该API可能位于哪里。

例如:我需要找一个创建线程的函数,通过框架图我能得知,线程创建函数在KAL层或者内核层中,Hi3861设备遵循cmsis接口标准,首先我打开kernel\liteos_m\components目录,即可在其中寻找,最终在cmsis文件中找到该函数。

我需要寻找一个iic操作的函数,根据目录结构,我能得知该函数在base/iot_hardware/interfaces目录中,最终找到wifiiot_i2c.h。

搭建iot世界的积木已经交给您啦,最后能搭建出什么样子就全看您啦!

作者:wx5b77d97791813

想了解更多内容,请访问:

51CTO和华为官方战略合作共建的鸿蒙技术社区

https://harmonyos.51cto.com#bky

从本质上学会基于HarmonyOS开发Hi3861(主要讲授方法)的更多相关文章

  1. mahout demo——本质上是基于Hadoop的分步式算法实现,比如多节点的数据合并,数据排序,网路通信的效率,节点宕机重算,数据分步式存储

    摘自:http://blog.fens.me/mahout-recommendation-api/ 测试程序:RecommenderTest.java 测试数据集:item.csv 1,101,5.0 ...

  2. 伪基站,卒于5G——本质上是基于网络和UE辅助的伪基站检测,就是将相邻基站的CI、信号强度等信息通过测量报告上报给网络,网络结合网络拓扑、配置信息等相关数据,对所有数据进行综合分析,确认在某个区域中是否存在伪基站

    伪基站,卒于5G from:https://www.huxiu.com/article/251252.html?h_s=h8 2018-07-05 21:58收藏27评论6社交通讯     本文来自微 ...

  3. 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目

    系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 ... 基于. ...

  4. 基于.NetCore开发博客项目 StarBlog - (3) 模型设计

    系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...

  5. 基于.NetCore开发博客项目 StarBlog - (19) Markdown渲染方案探索

    前言 笔者认为,一个博客网站,最核心的是阅读体验. 在开发StarBlog的过程中,最耗时的恰恰也是文章的展示部分功能. 最开始还没研究出来如何很好的使用后端渲染,所以只能先用Editor.md组件做 ...

  6. [原创]基于SpringAOP开发的方法调用链分析框架

    新人熟悉项目必备工具!基于SpringAOP开发的一款方法调用链分析插件,简单到只需要一个注解,异步非阻塞,完美嵌入Spring Cloud.Dubbo项目!再也不用担心搞不懂项目! 很多新人进入一家 ...

  7. RxSwift 在本质上简化了开发异步程序

    RxSwift 是一个组合异步和事件驱动编程的库,通过使用可观察序列和功能样式运算符来,从而允许通过调度程序进行参数化执行. RxSwift 在本质上简化了开发异步程序,允许代码对新数据作出反应,并以 ...

  8. Python开发篇——基于React-Dropzone开发上传组件

    这次我要讲述的是在React-Flask框架上开发上传组件的技巧.我目前主要以React开发前端,在这个过程中认识到了许多有趣的前端UI框架--React-Bootstrap.Ant Design.M ...

  9. 基于.NetCore开发博客项目 StarBlog - (18) 实现本地Typora文章打包上传

    前言 九月太忙,只更新了三篇文章,本来这个功能是从九月初就开始做的,结果一直拖到现在国庆假期才有时间完善并且写文章~ 之前我更新了几篇关于 Python 的文章,有朋友留言问是不是不更新 .Net 了 ...

随机推荐

  1. docker gitlab搭建

    1,官方查找gitlab docker镜像 2,pull镜像 3,run docker run -d -p 443:443 -p 10080:80 -p 22:22 --name gitlab --r ...

  2. 一道在输入上有坑点的LCS

    原题连接 http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=114&p ...

  3. 将java的jar包,打包为rpm 安装包

    一.rpm包 介绍 RPM Package Manager (RPM) 是一个强大的命令行驱动的软件包管理工具,用来安装.卸载.校验.查询和更新 Linux 系统上的软件包 二.环境安装 一台cent ...

  4. Java学习的第五十五天

    1.例11.1继承学生类 import java.util.Scanner; import java.util.*; public class Cjava { public static void m ...

  5. 利用CNN进行中文文本分类(数据集是复旦中文语料)

    利用TfidfVectorizer进行中文文本分类(数据集是复旦中文语料) 利用RNN进行中文文本分类(数据集是复旦中文语料) 上一节我们利用了RNN(GRU)对中文文本进行了分类,本节我们将继续使用 ...

  6. python重要的第三方库pandas模块常用函数解析之DataFrame

    pandas模块常用函数解析之DataFrame 关注公众号"轻松学编程"了解更多. 以下命令都是在浏览器中输入. cmd命令窗口输入:jupyter notebook 打开浏览器 ...

  7. eyou升级弹窗、云插件库、接口配置、功能开关【按需显示插件】

    分享一个实用三方插件,如插件描述所言,很多时候我们不希望客户乱搞. hbh.cool/find/146.html

  8. (五)F5和CTRL+F5两种刷新的区别

    一.刷新原理不同: F5触发的HTTP请求的请求头中通常包含了If-Modified-Since 或 If-None-Match字段,或者两者兼有. CTRL+F5触发的HTTP请求的请求头中没有上面 ...

  9. docker部署redis主从和哨兵

    docker部署redis主从和哨兵 原文地址:https://www.jianshu.com/p/72ee9568c8ea 1主2从3哨兵 一.前期准备工作 1.电脑装有docker 2.假设本地i ...

  10. 【SpringCloud】02.微服务与SpringCloud

    微服务的特点 一系列微小的服务共同组成 跑在自己的进程里 每个服务为独立的业务开发 独立部署 分布式管理 异构--不同的语言.不同类型的数据库 微服务架构的基础框架/组件 服务注册发现 服务网关(Se ...