OpenHarmony设备开发 移植子系统

zh_ff
发布于 2023-3-22 10:32
浏览
0收藏

移植子系统概述

OpenHarmony系统功能按照“系统 > 子系统 > 部件”逐级展开,支持根据实际需求裁剪某些非必要的部件,本文以部分子系统、部件为例进行介绍。若想使用OpenHarmony系统的能力,需要对相应子系统进行适配。

OpenHarmony芯片适配常见子系统列表如下(详见表1),需结合具体芯片再做增删减操作。

表1 OpenHarmony子系统

子系统

作用

applications

应用程序demo。可将应用相关源码存放在此目录下。

kernel

内核子系统。负责任务调度、内存管理等常见的内核功能。

hiviewdfx

可维可测子系统。提供日志相关功能。

communication

通信子系统。包含Wi-Fi,蓝牙功能。

iothardware

IOT外设子系统。提供常见的外设接口,例如GPIO,I2C,SPI等。

startup

启动子系统。内核启动后运行的第一个子系统,负责在内核启动之后到应用启动之前的系统关键进程和服务的启动过程的功能。

update

升级子系统。用来支持OpenHarmony设备的OTA升级。

utils

公共基础库子系统。提供了一些常用的C、C++开发增强API。

distributed_schedule

分布式调度子系统。负责跨设备部件管理,提供访问和控制远程组件的能力,支持分布式场景下的应用协同。

security

安全子系统。包括系统安全、数据安全、应用安全等功能,为OpenHarmony提供有效保护应用和用户数据的能力。当前开源的功能,包括应用完整性保护、应用权限管理、设备认证、密钥管理服务、数据传输管控。

test

测试子系统。OpenHarmony为开发者提供了一套全面的自测试框架,开发者可根据测试需求开发相关测试用例,开发阶段提前发现缺陷,大幅提高代码质量。

移植启动恢复子系统

启动恢复子系统负责在内核启动之后到应用启动之前的系统关键进程和服务的启动过程的功能。

移植指导

针对轻量系统主要提供了各服务和功能的启动入口标识。在SAMGR启动时,会调用bootstrap标识的入口函数,并启动系统服务。

适配完成后,调用OHOS_SystemInit()接口,即可启动系统。

路径:“base/startup/bootstrap_lite/services/source/system_init.c”

void OHOS_SystemInit(void)
{
    MODULE_INIT(bsp);           //执行.zinitcall.bspX.init段中的函数
    MODULE_INIT(device);        //执行.zinitcall.deviceX.init段中的函数
    MODULE_INIT(core);          //执行.zinitcall.coreX.init段中的函数
    SYS_INIT(service);          //执行.zinitcall.sys.serviceX.init段中的函数
    SYS_INIT(feature);          //执行.zinitcall.sys.featureX.init段中的函数
    MODULE_INIT(run);           //执行.zinitcall.runX.init段中的函数
    SAMGR_Bootstrap();          //SAMGR服务初始化
}

移植实例

  1. 在“config.json”中添加启动子系统。 路径:“vendor/MyVendorCompany/MyProduct/config.json”
    修改如下:

{
    subsystem": "startup",
    components": [
        { "component": "bootstrap_lite", "features":[] },
        { "component": "syspara_lite", "features":[] }
    ]
},

在startup子系统中有部分部件(如:syspara_lite等),会依赖“$ohos_product_adapter_dir/utils”中的模块。其中“ohos_product_adapter_dir”就是在config.json文件中配置的“product_adapter_dir”,我们通常配置其为“vendor/MyVendorCompany/MyProduct/hals”。

2.添加zinitcall以及run定义。 在厂商ld链接脚本中.text段中,添加如下代码:

__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 = .;  //SAMGR执行.zinitcall.app.serviceX.init段中的函数
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 = .; //SAMGR执行.zinitcall.app.featureX.init段中的函数
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 = .;

3.芯片SDK创建任务。 配置任务参数,系统启动后,启动任务,示例如下:

void mainTask(void) {
   //厂商自定义功能
    OHOS_SystemInit();        //启动子系统初始化
    printf("MainTask running...\n");
}
 
void main(VOID) {
   //硬件初始化,printf输出重定向到debug串口等
    if (LOS_KernelInit() == 0) {            //ohos内核初始化
        task_init_param.usTaskPrio = 10;    //任务优先级
        task_init_param.pcName = "mainTask"; //任务进程名
        task_init_param.pfnTaskEntry = (TSK_ENTRY_FUNC)mainTask; //任务入口函数
        task_init_param.uwStackSize = 8192;          //任务栈大小
        LOS_TaskCreate(&tid, &task_init_param);      //创建任务
        LOS_Start();                                 //启动任务
    }
    else {
        printf("[BUG] LOS_KernelInit fail\n");
    }
    printf("[BUG] reach to unexpected code\n");
    while (1);
}

移植文件子系统

utils部件可被各业务子系统及上层应用使用,依赖芯片文件系统实现,需要芯片平台提供文件打开、关闭、读写、获取大小等功能。

移植指导

OpenHarmony文件系统需要适配如下HAL层接口:

表1 文件打开或关闭

接口名

描述

HalFileOpen

文件打开或创建新文件。

HalFileClose

文件关闭。

表2 文件操作

接口名

描述

HalFileRead

读文件。

HalFileWrite

写文件。

HalFileDelete

删除文件。

HalFileStat

获取文件属性。

HalFileSeek

文件查找。

厂商适配相关接口的实现,请参考OpenHarmony中file的接口和hal层适配接口的定义:

//utils/native/lite/file
├── BUILD.gn
└── src
     └── file_impl_hal
            └── file.c             #file接口

//utils/native/lite/hals
└── file
└── hal_file.h                   #hal层接口头文件

其中BUILD.gn的内容如下:

import("//build/lite/config/component/lite_component.gni")
 
static_library("native_file") {
  sources = [
    "src/file_impl_hal/file.c",
  ]
  include_dirs = [
    "//utils/native/lite/include",
    "//utils/native/lite/hals/file",
  ]
  deps = ["$ohos_vendor_adapter_dir/hals/utils/file:hal_file_static"]  #依赖厂商的适配
}
 
lite_component("file") {
  features = [
    ":native_file",
  ]
}

从中可以看到厂商适配相关接口的存放目录应为“$ohos_vendor_adapter_dir/hals/utils/file”,且该目录下BUILD.gn文件中的目标应为hal_file_static。

通常厂商可以采用下面三种方式适配hal层接口:

  1. 直接flash读写,模拟文件的操作。
  2. 使用littlefs或者fatfs文件系统进行适配,littlefs或者fatfs都是轻量级文件系统适配简单,其中OpenHarmony的“//thirdparty”目录下已有fatfs可供参考。
  3. 使用厂商已有的文件系统进行适配。

移植实例

  1. “config.json”添加文件系统。 路径:“vendor/MyVendorCompany/MyProduct/config.json”
    修改如下:

{
"subsystem": "utils",
"components": [
    { "component": "file", "features":[] }
  ]
},

2.添加适配文件。 在“vendor/MyVendorCompany/MyProduct/config.json”文件中,vendor_adapter_dir配置项通常进行如下配置:
“vendor_adapter_dir”: “//device/MyDeviceCompany/MyBoard/adapter”。
在该目录下进行UtilsFile接口适配:

hals/utils/file
├── BUILD.gn
└── src
    └── hal_file.c

其中BUILD.gn内容如下:

import("//build/lite/config/component/lite_component.gni")
static_library("hal_file_static") {     #目标名
  sources = [ "src/hal_file.c" ]        #厂商适配的源文件
  include_dirs = [
    "//utils/native/lite/hals/file",
  ]
}

移植安全子系统

安全子系统提供网络设备连接、认证鉴权等功能,依赖mbedtls实现硬件随机数以及联网功能。

由于每个厂商芯片硬件与实现硬件随机数的方式不同,需要适配硬件随机数接口。

移植指导

OpenHarmony提供了mbedtls的开源三方库,路径为“//third_party/mbedtls”。此库中提供了“mbedtls_platform_entropy_poll”、“mbedtls_hardclock_poll”、“mbedtls_havege_poll”、“mbedtls_hardware_poll”等几种产生随机数的方式。厂商需要根据芯片适配“mbedtls_hardware_poll”方式。

移植实例

  1. “config.json”添加文件系统。 路径:“vendor/MyVendorCompany/MyProduct/config.json”
    修改如下:

{
  "subsystem": "security",
  "components": [
    { "component": "hichainsdk", "features":[] },
    { "component": "huks", "features":[]}
  ]
},

2.配置宏,打开硬件随机数接口相关代码。 根据mbedtls的编译文件可以看出,配置宏的位置在"MBEDTLS_CONFIG_FILE=<…/port/config/config_liteos_m.h>"文件中。
路径:“third_party/mbedtls/BUILD.gn”

if (ohos_kernel_type == "liteos_m") {
  defines += [
    "__unix__",
    "MBEDTLS_CONFIG_FILE=<../port/config/config_liteos_m.h>",
  ]
}

根据代码我们可以看出需要配置“MBEDTLS_NO_PLATFORM_ENTROPY”、“MBEDTLS_ENTROPY_HARDWARE_ALT”两个宏,才能编译硬件随机数的相关代码。

路径:“third_party/mbedtls/library/entropy.c”

#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
    mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL,
                                MBEDTLS_ENTROPY_MIN_PLATFORM,
                                MBEDTLS_ENTROPY_SOURCE_STRONG );
#endif
......
#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
    mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL,
                                MBEDTLS_ENTROPY_MIN_HARDWARE,
                                MBEDTLS_ENTROPY_SOURCE_STRONG );
#endif
......
#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
}

3.适配硬件随机数接口 接口定义如下:
路径:“third_party/mbedtls/include/mbedtls/entropy_poll.h”

int mbedtls_hardware_poll( void *data,unsigned char *output, size_t len, size_t *olen );

表1 安全子系统配置项

配置项

意义

disable_huks_binary

是否编译HUKS源码。

(1) 默认值: false,不编译HUKS源码。

(2) 其他值: true,编译HUKS源码。

disable_authenticate

是否需要裁剪hichain认证功能。

(1) 默认值: true,不裁剪。

(2) 其他值: false,裁剪hichain认证功能。

huks_use_lite_storage

是否采用轻量化存储方案。无文件系统、仅有flash存储的设备,可采用轻量化存储方案。

(1) 默认值: true,使用轻量化存储。

(2) 其他值: false,不使用轻量化存储。

huks_use_hardware_root_key

是否使用硬件根密钥。设备存在硬件根密钥能力时,需要根据自身能力适配硬件根密钥方案;HUKS提供的RKC方案仅为模拟实现。

(1) 默认值:false,默认值,默认无硬件根密钥。

(2) 其他值:true,设备具有硬件根密钥相关能力时,应自行适配。

huks_config_file

是否使用HUKS默认配置文件。

(1) 默认值:“”:使用HUKS默认配置文件hks_config.h。

(2) 其他文件:产品可在HUKS支持能力集合中自行选择所要支持的特性。

说明:

 在添加安全子系统时,可直接通过配置feature来选择安全子系统特性。

{  "subsystem": "security",
  "components": [
    { "component": "hichainsdk", "features":[] },
    { "component": "huks", "features":
      [
        "disable_huks_binary = false",
        "disable_authenticate = false"
      ]
    }
  ]
},

移植通信子系统

通信子系统目前涉及Wi-Fi和蓝牙适配,厂商应当根据芯片自身情况进行适配。

移植指导

Wi-Fi编译文件内容如下:

路径:“foundation/communication/wifi_lite/BUILD.gn”

group("wifi") {
  deps = [ "$ohos_board_adapter_dir/hals/communication/wifi_lite/wifiservice:wifiservice" ]
}

从中可以看到厂商适配相关接口的.c文件存放目录应为“$ohos_board_adapter_dir/hals/communication/wifi_lite/wifiservice”,且该目录下BUILD.gn文件中的目标应为“wifiservice”。需要厂商适配的Wi-Fi接口见表1 、表2 和表3,蓝牙接口见表4和表5。

表1 wifi_device.h

接口

作用

EnableWifi

启用Wi-Fista模式。

DisableWifi

禁用Wi-Fi sta模式。

IsWifiActive

检查Wi-Fi sta模式是否启用。

Scan

扫描热点信息。

GetScanInfoList

获取所有扫描到的热点列表。

AddDeviceConfig

配置连接到的热点信息。

GetDeviceConfigs

获取配置连接到的热点信息。

RemoveDevice

删除指定的热点配置信息。

ConnectTo

接到指定的热点。

Disconnect

断开Wi-Fi连接。

GetLinkedInfo

获取热点连接信息。

RegisterWifiEvent

为指定的Wi-Fi事件注册回调。

UnRegisterWifiEvent

取消注册以前为指定Wi-Fi事件注册的回调。

GetDeviceMacAddress

获取设备的MAC地址。

AdvanceScan

根据指定参数启动Wi-Fi扫描。

表2 wifi_hotspot_config.h

接口

作用

SetBand

设置该热点的频段。

GetBand

获取该热点的频段。

表3 wifi_hotspot.h

接口

作用

EnableHotspot

启用Ap热点模式。

DisableHotspot

禁用Ap热点模式。

SetHotspotConfig

设置指定的热点配置。

GetHotspotConfig

获取指定的热点配置。

IsHotspotActive

检查Ap热点模式是否启用。

GetStationList

获取连接到此热点的一系列STA。

GetSignalLevel

获取指定接收信号强度指示器(RSSI)和频带指示的信号电平。

DisassociateSta

使用指定的MAC地址断开与STA的连接。

AddTxPowerInfo

将hotspot功率发送到beacon。

表4 ohos_bt_gatt.h

接口

作用

InitBtStack

初始化蓝牙协议栈。

EnableBtStack

使能蓝牙协议栈。

DisableBtStack

禁用蓝牙协议栈。

SetDeviceName

设置蓝牙设备名称。

BleSetAdvData

设置广播数据。

BleStartAdv

开始广播。

BleStartAdvEx

传入构建好的广播数据,参数,开启蓝牙广播。

BleStopAdv

停止发送广播。

BleUpdateAdv

更新advertising参数。

BleSetSecurityIoCap

设置蓝牙的IO能力为NONE,配对方式为justworks。

BleSetSecurityAuthReq

设置蓝牙是否需要配对绑定。

BleGattSecurityRsp

响应安全连接请求。

ReadBtMacAddr

获取设备MAC地址。

BleSetScanParameters

设置扫描参数。

BleStartScan

开始扫描。

BleStopScan

停止扫描。

BleGattRegisterCallbacks

注册gap,GATT事件回调函数。

表5 ohos_bt_gatt_server.h

接口

作用

BleGattsRegister

使用指定的应用程序UUID注册GATT服务器。

BleGattsUnRegister

断开GATT服务器与客户端的连接。

BleGattsDisconnect

断开GATT服务器与客户端的连接。

BleGattsAddService

添加了一个服务。

BleGattsAddIncludedService

将包含的服务添加到指定的服务。

BleGattsAddCharacteristic

向指定的服务添加特征。

BleGattsAddDescriptor

将描述符添加到指定的特征。

BleGattsStartService

启动一个服务。

BleGattsStopService

停止服务。

BleGattsDeleteService

删除一个服务。

BleGattsClearServices

清除所有服务。

BleGattsSendResponse

向接收到读取或写入请求的客户端发送响应。

BleGattsSendIndication

设备侧向APP发送蓝牙数据。

BleGattsSetEncryption

设置GATT连接的加密类型。

BleGattsRegisterCallbacks

注册GATT服务器回调。

BleGattsStartServiceEx

根据传入的服务列表,创建gatt服务。

BleGattsStopServiceEx

传入gatt服务句柄,停止gatt服务。

说明:

 不同版本接口可能存在差异,需要根据当前版本的具体文件进行适配。

适配实例

  1. 在“config.json”中添加communication子系统。 路径:“vendor/MyVendorCompany/MyProduct/config.json”
    修改如下:

{ 
    "subsystem": "communication", 
    "components": [ 
        { "component": "wifi_lite", "features":[] }
    ] 
},

2.添加适配文件。
在“vendor/MyVendorCompany/MyProduct/config.json”文件中,通常将配置“ohos_board_adapter_dir”配置为 “//vendor/MyVendorCompany/MyProduct/adapter”。
在“ohos_board_adapter_dir”目录下根据上述适配指导中提到的头文件,适配Wi-Fi、蓝牙接口。

移植外设驱动子系统

外设驱动子系统提供OpenHarmony专有的外部设备操作接口。本模块提供设备操作接口有:FLASH, GPIO, I2C, PWM, UART, WATCHDOG等。

OpenHarmony提供了两种驱动适配方式:使用外设驱动子系统、使用HDF驱动框架。由于轻量级系统的资源有限,这里建议使用IOT子系统方式。

移植指导

厂商需要根据OpenHarmony提供的接口定义实现其功能,IOT子系统接口定义的头文件如下:

base/iot_hardware/peripheral/
├── BUILD.gn
└── interfaces
    └── kits
        ├── iot_errno.h
        ├── iot_flash.h
        ├── iot_gpio.h
        ├── iot_i2c.h
        ├── iot_pwm.h
        ├── iot_uart.h
        ├── iot_watchdog.h
        ├── lowpower.h
        └── reset.h

其中“base/iot_hardware/peripheral/BUILD.gn”文件如下:

import("//build/lite/config/subsystem/lite_subsystem.gni")
import("//build/lite/ndk/ndk.gni")
       
lite_subsystem("iothardware") {
  subsystem_components = [
    "$ohos_vendor_adapter_dir/hals/iot_hardware/wifiiot_lite:hal_iothardware",
  ]
}
if (ohos_kernel_type == "liteos_m") {
  ndk_lib("iothardware_ndk") {
    deps = [
      "$ohos_vendor_adapter_dir/hals/iot_hardware/wifiiot_lite:hal_iothardware", #依赖厂商的适配
    ]
    head_files = [ "//base/iot_hardware/peripheral/interfaces/kits" ]
  }
}

从中可以看到厂商适配相关接口的存放目录应为“$ohos_vendor_adapter_dir/hals/iot_hardware/wifiiot_lite”,且该目录下BUILD.gn文件中的目标应为hal_iothardware。

移植实例

  1. 在“config.json”中添加iot_hardware子系统。 路径:“vendor/MyVendorCompany/MyProduct/config.json”
    修改如下:

{ 
    subsystem": "iot_hardware", 
    components": [ 
        { "component": "iot_controller", "features":[] }
    ] 
},

2.添加适配文件。
在“vendor/MyVendorCompany/MyProduct/config.json”文件中,通常将配置“vendor_adapter_dir”配置为 “//device/MyDeviceCompany/MyBoard/adapter”。
在“vendor_adapter_dir”目录下进行适配:

hals/iot_hardware/wifiiot_lite
├── BUILD.gn
├── iot_flash.c
├── iot_gpio.c
├── iot_i2c.c
├── iot_lowpower.c
├── iot_pwm.c
├── iot_reset.c
├── iot_uart.c
└── iot_watchdog.c

其中BUILD.gn内容如下:

static_library("hal_iothardware") {   #目标名
    sources = [                       #厂商适配的源文件
      "iot_watchdog.c",
      "iot_reset.c",
      "iot_flash.c",
      "iot_i2c.c",
      "iot_gpio.c",
      "iot_pwm.c",
      "iot_uart.c"
    ]
    include_dirs = [ ]
}

其中,“include_dirs”需要根据工程实际情况包含两个路径:

  • iot子系统的头文件路径
  • 适配iot子系统所使用到的SDK的头文件路径

配置其他子系统

除上述子系统之外,还有一些必要但是无需进行移植的子系统。如:分布式任务调度子系统、DFX子系统。

这些子系统添加方式比较简单,在“vendor/MyVendorCompany/MyProduct/config.json”文件中进行如下配置即可:

{
  "subsystem": "distributed_schedule",
  "components": [
    { "component": "system_ability_manager", "features":[] }  # 此处部件名不同版本可能有变化,请根据实际代码填写
  ]
},
{
  "subsystem": "hiviewdfx",
  "components": [
    { "component": "hilog_lite", "features":[] },
    { "component": "hievent_lite", "features":[] }
  ]
},


文章转载自:​​https://docs.openharmony.cn/pages/v3.2Beta/zh-cn/device-dev/porting/porting-minichip-subsys-overview.md/​

分类
收藏
回复
举报
回复
    相关推荐