当前位置: 首页 > 科技观察

本质学习基于HarmonyOS开发Hi3861(主要教学方法)

时间:2023-03-17 20:17:46 科技观察

更多内容请访问:Harmonyos.51cto.com/#zz简介:花一个能在半秒内看透事物本质的人是命中注定和一个一辈子都看不到事物本质的人有着截然不同的命运。一个RTOS的开发,同样的RTOS开发不能换成开发板”,“跟着教程学了某个开发板某个demo的开发,再也不可能自己开发另一个demo了”等问题,只要你能看透,触类旁通,就能游刃有余!一定要学会灵活运用,不能死记硬背,想想为什么,不要死记硬背过程。在基于HarmonyOS开发Hi3861之前,需要对整个开发环境和流程有一个全局的了解。首先从这张最经典的框架图说起:目前我们开发Hi3861主要涉及到上图中的内核。抽象层、系统能力子系统、DXF子系统、公共基础库子系统(提供KV存储、文件操作、定时器、物联网外设控制等能力供OpenHarmony业务子系统和上层应用使用)、系统服务框架子系统System(使用提供面向服务的编程,为分布式任务调度提供外部能力)1.构建系统构建系统由python脚本结合gn和ninja组成。如果是为了Demo或者应用的开发,没有必要去研究编译构建系统的具体实现细节,只需要会用就可以了。当我们输入pythonbuild.pywifiiot命令时,python脚本开始读取build目录下wifiiot设备相关的参数信息,构建编译命令如下:gn工具所在目录/gn工具所在目录gngen源码位于/out/wifiiot--root=.--dotfile=build/lite/.gn--args='product="wifiiot"ohos_build_type="release"'这个命令用来生成一些xxx.ninja文件,在接下来会引导ninja编译源码stage生成烧录文件ninja工具所在目录/ninja-wdupbuild=warn-C源码所在目录/out/wifiiot该命令用于调用工具链根据之前生成xxx.ninja文件,最后生成烧录文件gnfor根据各个目录下的BUID和gn文件,搜索编译生成烧录文件所需的依赖文件,所以我们只需要学习如何编写BUILD即可。.gn文件。具体实现本章略过,后面补上。这里我们以led_example.c程序为例,为大家分析一下BUILD.gn文件。希望大家举一反三:在code-1.0\applications\sample\wifi-iot\app目录下有一个BUILD.gn文件,你可以将该文件理解为manager,管理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字段的格式为:module源文件路径:模块名称请注意:.gn文件中的空格是空格,不是制表符(tabs)。如果进入tab,在生成ninja文件的时候会出现如下图的错误:我有个问题请教大家,如果我们在app/iothardware目录下添加一个hello_world.c文件,这个文件主要用来打印hello_world,假设源码已经写好了,如下图,你应该怎么把它添加到编译列表中和其他程序一起编译呢?修改app/iothardware/BUILD.gn文件,将hello_world.c文件添加到sources字段中,如下图所示:如果我们新建一个A头目录,并在其中新建一个名为hello_world.h的头文件it,内容如下图:修改hello_world.c的内容如下图:如果此时直接编译,会找不到头文件文件错误,如下图下图:继续修改app/iothardware/BUILD.gn文件,在include_dirs中添加hello_world.h头文件所在路径,如下图:上面的path是绝对路径,//表示根参数指定的路径,即code-1,0,测试路径是相对路径,基于当前BUILD.gn文件所在的目录作为开发这样一个简单demo的参考。不知道读者有没有这样的疑问:为什么我知道启动任务的宏是SYSY_RUN(),而IIC、SPI等外设操作的函数是什么?一系列类似的问题,然后您可以通过阅读找到答案。2.目录结构注:Hi3861模块只使用了部分组件。希望大家按照我对目录的介绍,打开本地SDK对应的目录看看。├──应用存储例程│└──sample├──base│├──globalglobalizationsubsystem│├──hiviewdfxDXFsubsystem│├──iot_hardwarepublicbaselibrarysubsystemforiotdevices,提供外设操作,IIC,SPI,etc│├──security安全子系统│└──startup与启动和恢复相关├──build与构建系统相关,存储各种芯片的编译和构建参数等协调python脚本(用于启动构建)├──docsdocuments├──domains集成各厂商SDK│└──iot├──drivers驱动相关,HDF驱动框架│├──hdf│└──liteos├──foundation│├──aafwk提供数据类型以Want为名加速应用启动│├──aceJS应用开发框架│├──appexecfwk用于程序框架子系统│├──通信分布式通信器系统(软总线)│├──分布式调度系统服务框架子系统(面向服务的编程,提供服务,使用services等),分布式任务调度子系统│├──图形图形子系统│└──多媒体媒体子系统├──kernel内核和kal层│├──用于Hi3516、3518等资源丰富设备的liteos_a内核│└──用于资源受限设备的liteos_m内核├──编译输出文件│├──ipcamera_hi3516dv300│└────wifiiot├──prebuilts提供一些库文件│└──lite├──test测试子系统│├──developertest│├──xdevice│└──xts├──third_party第三方库,如cmsis、cJSON、Fatfs等├──utils公共基础系统,提供文件操作、KV存储、文件操作的统一接口,Timer│└──native└──各厂商提供的vendorSDK├──hisi└──huaweibase和foundation中的每个组件都有两个同名的文件夹frameworks和interfaces,其中组件存放在frameworks中具体实现接口的of存放对外提供的调用接口。这里以base/iot_hardware为例。hal文件夹存放的是hi3861SDK提供的KV存储、文件操作、定时器、物联网外设控制的函数接口(函数接口指的是函数声明,我们只要知道函数声明就可以调用函数来完成相应的操作而不关心函数的实现细节)。框架将函数声明封装在hal中,实现统一的接口。封装的函数声明位于interfaces文件夹中。也就是说,如果我们要使用某个组件,只需要查看interfaces文件夹中的声明即可。这样做的好处是不需要改动上层应用(比如我目前使用hi3861开发板实现部分功能,这时候甲方爸爸让我用hi3516实现同样的功能。我只需要将对应函数的底层支持函数的调用接口修改为interfaces文件夹中的形式即可,即3.如何创建任务?SYS_RUN宏定义的正确用法是:先定义一个“初始化”function”,比如下面的“LedExampleEntry()”,所谓初始化是指初始化要启动的任务所需的各种资源(例如:GPIO外设初始化),在这个“初始化”函数中初始化各种资源后,调用osThreadNew函数(线程创建函数中调用了LOS_TASK_Create函数,也就是上面liblitekernel_flash.a库中提供的函数)创建线程.最后,“初始化”函数被传递到SYS_RUN宏中。在系统启动阶段,系统会为其创建一个进程,默认优先级为2。SYS_RUN宏在链接的时候会将进程入口函数链接到某个段中,等待系统开始加载并运行这个段中的这些进程(之前LiteOS的思路)。这些进程是随时自动加载的,用户无需考虑什么时候加载进程合适。它体现了进程和线程的思想。首先通过SYS_RUN宏创建一个进程,进程下可以有多个线程。//来自code-1.0\utils\native\lite\include\ohos_init.h/***@briefIdentifiestheentryforinitializingandstartingasystemrunningphasebythe*priority2.**这个宏用于识别在系统启动*阶段调用的entry。\n**@paramfunc指示entryfunctionforinitializingandstartingasystemrunningphasebythe*priority2。*/#defineSYS_RUN(func)LAYER_INITCALL_DEF(func,run,"run")//来自code-1.0\applications\sample\wifi-iot\app\iothardware\led_example.cstaticvoidLedExampleEntry(void){osThreadAttr_tattr;//首先GpioInit();IoSetFunc(WIFI_IOT_IO_NAME_GPIO_9,WIFI_IOT_IO_FUNC_GPIO_9_GPIO);GpioSetDir(WIFI_IOT_IO_NAME_GPIO_9,WIFI_IOT_GPIO_DIR_OUT);attr.name="LedTask";attr.attr_UL_bits=0U;attrize.c=0U;attr.stack_mempriority=LED_TASK_PRIO;//第二步:为此进程创建线程tocreateLedTask!\n");}}SYS_RUN(LedExampleEntry);4、如何找到你要使用的函数API?首先需要对开头的框架图和第2点的目录结构有一个大概的了解,并根据你的需求分析API可能在什么地方,比如:我需要找一个创建线程的函数,从框架图可以知道线程创建函数是在KAL层还是内核层.Hi3861设备遵循cmsis接口标准,首先我打开kernel\liteos_m\components目录下可以找到,最后在cmsis文件中找到函数,我需要找到一个iic操作函数,根据目录结构,可以知道函数在base/iot_hardware/interfaces目录下,最后找到wifiiot_i2c.h,搭建iot世界的积木已经交给你了,你最终能搭建的是up给你!欲了解更多信息,请访问:与华为官方共建的鸿蒙科技社区https://harmonyos.51cto.com/#zz