集成介绍

本次集成采用zephyr(RTOS)内核 + LiteOS部件静态库的方式,集成LiteOS部件后,完成ActsBootstrapTest 、ActsSamgrTest、ActsDfxFuncTest、ActsHieventLiteTest四项测试套的测试。

LiteOS的代码为OpenHarmony-v6.1-Release分支代码,NRF52832集成SDK和编译工具链为v3.3.0版本。

环境准备

开发、编译环境分为oh的编译环境和nrfk52832开发环境。

oh的编译环境主要是编译出需要集成的LiteOS部件静态库,nrfk52832开发环境则包含了nrfk52832的开发、编译、烧录等功能。

oh的编译环境

参考官方文档:https://gitcode.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/Readme-CN.md

nrfk52832开发环境

nrfk52832开发环境只需要下载vscode,并安装"nRF Connect Visual Studio Code Extension Pack"插件即可,它是一套nRF芯片开发的集合插件。

安装插件后,可以使用插件自动下载安装sdk和编译工具链,注意这里建议在linux环境也下载一份编译工具链,后续编译编译oh静态库需要用到。

img

编译oh静态库

下载OpenHarmony-v6.1-Release代码和预编译工具链后,参考vendor/ohemu/qemu_mini_system_demo产品,创建一个nrf52832的产品,另外其对应的device仓为device/qemu/arm_mps2_an386,可以直接复制然后修改相关产品名称。

其中有两个重要文件需要进行修改

  • vendor/ohemu/nrf52832/config.json
{
  "product_name": "nrf52832",
  "device_company": "qemu",
  "board": "nrf52832",
  "version": "3.0",
  "ohos_version": "OpenHarmony-v6.1-Release",
  "type":"mini",
  "kernel_type": "liteos_m",
  "kernel_version": "3.1.0",
  "target_cpu": "arm",
  "force_link_libs": [],
  "subsystems": [
    {
      "subsystem": "startup",
      "components": [
        { "component": "bootstrap_lite" },
        { "component": "init",
          "features": [
            "init_feature_begetctl_liteos = true",
            "init_lite_use_posix_file_api = true",
            "init_lite_memory_size=5120"
          ]
        }
      ]
    },
    {
      "subsystem": "hiviewdfx",
      "components": [
        {
          "component": "hilog_lite",
          "features": [
            "hilog_lite_log_static_cache_size = 512",
            "hilog_lite_hiview_hilog_file_buf_size = 256",
            "hilog_lite_disable_hilog_static = true"
          ]
        },
        { "component": "hievent_lite" },
        {
          "component": "hiview_lite",
          "features": [
            "hiview_lite_stack_size = 2048"
          ]
        }
      ]
    },
    {
      "subsystem": "systemabilitymgr",
      "components": [
        { "component": "samgr_lite" }
      ]
    },
    {
      "subsystem": "commonlibrary",
      "components": [
        {
          "component": "utils_lite",
          "features":[ "utils_lite_feature_file = true" ]
        }
      ]
    },
    {
      "subsystem": "xts",
      "components": [
        { "component": "device_attest_lite" },
        { "component": "tools" },
        { "component": "acts" }
      ]
    }
  ],
  "third_party_dir": "//third_party",
  "vendor_adapter_dir": "",
  "product_adapter_dir": "//vendor/ohemu/nrf52832/hals"
}
  • device/qemu/nrf52832/liteos_m/config.gni
kernel_type = "liteos_m"
kernel_version = "3.1.0"
board_cpu = "cortex-m4"
board_arch = ""
board_toolchain = "arm-zephyr-eabi-gcc"

use_board_toolchain = true

board_toolchain_path = "/xxx/ncs/toolchains/911f4c5c26/opt/zephyr-sdk/arm-zephyr-eabi/bin"

board_toolchain_prefix = "arm-zephyr-eabi-"

board_toolchain_type = "gcc"

if (product_path != "") {
  product_conf = read_file("${product_path}/config.json", "json")
  force_link_libs = product_conf.force_link_libs
}

board_opt_flags = []
board_cflags = [
  "-mthumb",
  "-Wall",
  "-fdata-sections",
  "-ffunction-sections",
  "-fno-builtin",
  "-fno-strict-aliasing",
  "-fsigned-char",
  "-std=c99",
  "-Os",
  # "-flto",
  # "-fno-stack-protector",
  "-DUSE_HAL_DRIVER",
  "-D__LITEOS_M__",
]
board_cflags += board_opt_flags

board_asmflags = [
  "-mcpu=cortex-m4",
  "-mthumb",
  "-static",
  "-Os",
]
board_asmflags += board_opt_flags

board_cxx_flags = board_cflags

board_ld_flags = []
board_ld_flags += [
  "-Wl,-gc-sections",
  "-Wl,--wrap=_free_r",
  "-Wl,--wrap,_malloc_usable_size_r",
  "-Wl,--wrap,_malloc_r",
  "-Wl,--wrap,_memalign_r",
  "-Wl,--wrap,_realloc_r",
  "-Wl,--wrap,_calloc_r",
]

board_include_dirs = [ "//commonlibrary/utils_lite/include" ]
board_adapter_dir = ""
board_configed_sysroot = ""
storage_type = ""

这里需要注意board_toolchain、board_toolchain_path、board_toolchain_prefix等配置需要自行修改,需要使用到nrfk52832开发环境下载的编译工具链,其中board_toolchain_path为nrf52832编译工具链地址。

集成oh静态库

编译成功后,在out/nrf52832/nrf52832/libs中即可找到LiteOS部件的编译产物,需要将这些静态库集成到nrfk52832的sdk中。

解压附件 openharmony.rar,将解压后的openharmony复制到nrfk52832的sdk目录xxx\ncs\v3.3.0。

修改xxx\ncs\v3.3.0\nrf\west.yml文件,在最后的 self: 之前添加:

...
    - name: hostap
      repo-path: sdk-hostap
      path: modules/lib/hostap
      revision: 957e9578648b7da0e35f20dbf9a0c35fce9dc4af
    ***添加oh集成部分***************************
    - name: ohos_lite
      repo-path: ohos_lite_adaptor
      path: openharmony
      revision: v6.1-Release
    ******************************************

  # West-related configuration for the nrf repository.
  self:
...

静态库集成

out/nrf52832/nrf52832/libs中LiteOS部件的编译产物放在xxx\ncs\v3.3.0\openharmony\kits\libs目录下,编写CMakeList.txt文件使静态库参与项目编译。

img

在xxx\ncs\v3.3.0\openharmony\kits\includes文件夹中是参与编译的部件的头文件,如果在编译时出现未定义的报错,需要在oh对应的部件中找到对应的头文件并复制到对应的文件节中:

img

LiteOS_M内核集成

在集成oh部件静态库时,oh部件中存在直接调用LiteOS_M的内核接口,这些接口在内核中定义和实现,需要手动适配,使用zephyr内核接口实现一遍:

img

以中断中断控制为例,通过调用 Zephyr 的底层中断控制 API (irq_lock / irq_unlock),来实现符合 LiteOS-M 规范的中断加锁、解锁和恢复功能:

img

Hilog集成

在openharmony中,大部分的日志打印主要是hilog部件提供相关接口,因此很多部件都依赖hilog部件,而zephyr中也提供了自己的日志模块,集成静态库后需要对接hilog与zephyr的日志模块,而hilog部件也提供了集成方法,通过注册日志打印接口,hilog在打印时可以走注册的接口传输日志信息,在注册的方法中则可以接收信息后通过zephyr的日志模块进行打印:

img

启动集成

liteos的启动主要是在bootstrap部件中,通过OHOS_SystemInit();启动各个服务,在启动之前需要先完成hilog的日志输出注册:

img

开发nrf52832应用

解压附件 liteos_app.rar,将其导入到项目中,参考:

img

链接器配置

上面集成静态库完成后,虽然oh的代码及适配层都可参与项目编译,但需要在链接文/xxx/ncs/liteos_app/linker/linker.ld中手动新增如下段:

__zinitcall_bsp_start = .;
KEEP (*(.zinitcall.bsp0.init))
KEEP (*(.zinitcall.bsp1.init))
KEEP (*(.zinitcall.bsp2.init))
KEEP (*(.zinitcall.bsp3.init))
KEEP (*(.zinitcall.bsp4.init))
__zinitcall_bsp_end = .;
__zinitcall_device_start = .;
KEEP (*(.zinitcall.device0.init))
KEEP (*(.zinitcall.device1.init))
KEEP (*(.zinitcall.device2.init))
KEEP (*(.zinitcall.device3.init))
KEEP (*(.zinitcall.device4.init))
__zinitcall_device_end = .;
__zinitcall_core_start = .;
KEEP (*(.zinitcall.core0.init))
KEEP (*(.zinitcall.core1.init))
KEEP (*(.zinitcall.core2.init))
KEEP (*(.zinitcall.core3.init))
KEEP (*(.zinitcall.core4.init))
__zinitcall_core_end = .;
__zinitcall_sys_service_start = .;
KEEP (*(.zinitcall.sys.service0.init))
KEEP (*(.zinitcall.sys.service1.init))
KEEP (*(.zinitcall.sys.service2.init))
KEEP (*(.zinitcall.sys.service3.init))
KEEP (*(.zinitcall.sys.service4.init))
__zinitcall_sys_service_end = .;
__zinitcall_sys_feature_start = .;
KEEP (*(.zinitcall.sys.feature0.init))
KEEP (*(.zinitcall.sys.feature1.init))
KEEP (*(.zinitcall.sys.feature2.init))
KEEP (*(.zinitcall.sys.feature3.init))
KEEP (*(.zinitcall.sys.feature4.init))
__zinitcall_sys_feature_end = .;
__zinitcall_run_start = .;
KEEP (*(.zinitcall.run0.init))
KEEP (*(.zinitcall.run1.init))
KEEP (*(.zinitcall.run2.init))
KEEP (*(.zinitcall.run3.init))
KEEP (*(.zinitcall.run4.init))
__zinitcall_run_end = .;
__zinitcall_app_service_start = .;
KEEP (*(.zinitcall.app.service0.init))
KEEP (*(.zinitcall.app.service1.init))
KEEP (*(.zinitcall.app.service2.init))
KEEP (*(.zinitcall.app.service3.init))
KEEP (*(.zinitcall.app.service4.init))
__zinitcall_app_service_end = .;
__zinitcall_app_feature_start = .;
KEEP (*(.zinitcall.app.feature0.init))
KEEP (*(.zinitcall.app.feature1.init))
KEEP (*(.zinitcall.app.feature2.init))
KEEP (*(.zinitcall.app.feature3.init))
KEEP (*(.zinitcall.app.feature4.init))
__zinitcall_app_feature_end = .;
__zinitcall_test_start = .;
KEEP (*(.zinitcall.test0.init))
KEEP (*(.zinitcall.test1.init))
KEEP (*(.zinitcall.test2.init))
KEEP (*(.zinitcall.test3.init))
KEEP (*(.zinitcall.test4.init))
__zinitcall_test_end = .;
__zinitcall_exit_start = .;
KEEP (*(.zinitcall.exit0.init))
KEEP (*(.zinitcall.exit1.init))
KEEP (*(.zinitcall.exit2.init))
KEEP (*(.zinitcall.exit3.init))
KEEP (*(.zinitcall.exit4.init))
__zinitcall_exit_end = .;

需要新增上述段是因为bootstrap_init提供的对外接口,见//utils/native/lite/include/ohos_init.h文件,采用的是灌段的形式,最终会保存到上述链接段中。主要的服务自动初始化宏如下表格所示:

接口名 描述
SYS_SERVICE_INIT(func) 标识核心系统服务的初始化启动入口。
SYS_FEATURE_INIT(func) 标识核心系统功能的初始化启动入口。
APP_SERVICE_INIT(func) 标识应用层服务的初始化启动入口。
APP_FEATURE_INIT(func) 标识应用层功能的初始化启动入口。

通过上面加载的组件编译出来的lib文件需要手动加入强制链接。

/xxx/ncs/liteos_app/linker/linker.ld是项目的链接器文件,它的基础内容是/xxx/ncs/v3.3.0/zephyr/include/zephyr/arch/arm/cortex_m/scripts/linker.ld的内容,这是由于nrf52832芯片是Arm Cortex-M4芯片,使用默认的链接器文件,当需要自定义链接器时,可以通过设置liteos_app/prj.conf,在其中添加:

CONFIG_HAVE_CUSTOM_LINKER_SCRIPT=y
CONFIG_CUSTOM_LINKER_SCRIPT="linker/linker.ld"

img

img

串口输出日志配置

系统uart口输出日志,通过查看设备原理图,USB串口RX、TX对应的引脚是P0.06,P0.07:

img

打开设备树,查看引脚配置,如果不是这两个引脚,修改后保存即可:

img

img

修改后保存即可自动保存到/xxx/ncs/liteos_app/nrf52dk_nrf52832.overlay文件中。

启动入口

在liteos_app/src/main.c文件中导入 oh_lite_init.h 头文件,然后在main方法中调用ohos_lite_init();接口, 即可完成LiteOS的集成启动。

img

应用打包和烧录

应用开发后,可以直接使用vscode的nrf插件进行打包、烧录等操作:

img

XTS测试

XTS测试用例可以单独运行也可以一起运行,查看/xxx/ncs/v3.3.0/openharmony/kits/CMakeLists.txt文件:

img

在进行测试时,需要查看测试日志,使用串口调试助手工具即可,在windows商店直接搜索 "串口调试助" 安装。

链接设备后,端口名选择 USB-SERIAL CH340 , 波特率选择 115200,数据位选择 8, 校验位选择 None,停止位选择 1,最下面的自动重连勾选上,然后点击打开即可,点击打开后正常情况下会变成绿色的关闭按钮,此时就可以记录并查看日志。

img

相关文件下载
liteos_app.rar
5.61 KB
下载
openharmony.rar
814.58 KB
下载
Logo

社区规范:仅讨论OpenHarmony相关问题。

更多推荐