本文章基于意法半导体 STM32MP157
芯片的小熊派 BearPi-HM Micro 开发板,进行小型带屏开发板的移植,实现了 ace_engine_lite
、arkui_ui_lite
、aafwk_lite
、appexecfwk_lite
、HDF
等部件基于 OpenHarmony LiteOS-A
内核的适配。移植架构上采用 Board
与 SoC
分离的方案。
编译构建
目录规划
本方案的目录结构使用 Board 和 SoC 解耦的设计思路,并把芯片适配目录规划为:
device
├── board --- 单板厂商目录
│ └── bearpi --- 单板厂商名字:小熊派
│ └── bearpi_hm_micro --- 单板名:bearpi_hm_micro
└── soc --- SoC厂商目录
└── common --- 存放公共HDF驱动
└── st --- SoC厂商名字:ST意法半导体
└── stm32mp1xx --- SoC Series名:stm32mp1xx系列芯片
产品样例目录规划为:
vendor
└── bearpi --- 开发产品样例厂商目录,小熊派的产品样例
└── bearpi_hm_micro --- 产品名字:bearpi_hm_micro开发板
预编译适配
在进行移植之前,需要进行预编译适配。
预编译适配主要使用 hb set
命令,设置整个项目的根目录、单板目录、产品目录、单板公司名等环境变量,为编译做准备。
具体的预编译适配步骤如下:
-
在
vendor/bearpi/bearpi_hm_micro
目录下新增config.json
文件,用于描述这个产品样例所使用的单板、内核等信息,描述信息可参考如下内容:{ "product_name": "bearpi_hm_micro", --- 用于hb set进行选择时,显示的产品名称 "version": "3.0", --- 构建系统的版本,1.0/2.0/3.0 "type": "small", --- 构建系统的类型,mini/small/standard "ohos_version": "OpenHarmony 3.0", --- OpenHarmony系统版本 "device_company": "bearpi", --- 单板厂商名,用于编译时找到/device/board/bearpi目录 "board": "bearpi_hm_micro", --- 单板名,用于编译时找到/device/board/bearpi/bearpi_hm_micro目录 "kernel_type": "liteos_a", --- 内核类型,因为OpenHarmony支持多内核,一块单板可能适配了多个内核,所以需要指定某个内核进行编译 "kernel_version": "", --- 内核版本,一块单板可能适配了多个linux内核版本,所以需要指定某个具体的内核版本进行编译 "subsystems": [ ] --- 选择所需要编译构建的子系统 }
-
在
device/board/bearpi/bearpi_hm_micro/liteos_a
目录下新增config.gni
文件,用于描述这个产品样例所使用的单板、内核等信息,描述信息可参考如下内容:# Kernel type, e.g. "linux", "liteos_a", "liteos_m". kernel_type = "liteos_a" # Kernel version. kernel_version = "" # Board CPU type, e.g. "cortex-a7", "riscv32". board_cpu = "cortex-a7" # Board arch, e.g. "armv7-a", "rv32imac". board_arch = "" # Toolchain name used for system compiling. # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toolchain. board_toolchain = "" # The toolchain path installed, it's not mandatory if you have added toolchain path to your ~/.bashrc. board_toolchain_path = "" # Compiler prefix. board_toolchain_prefix = "" # Compiler type, "gcc" or "clang". board_toolchain_type = "clang" # Board related common compile flags. board_cflags = [ "-mfloat-abi=softfp", "-mfpu=neon-vfpv4", ] board_cxx_flags = [ "-mfloat-abi=softfp", "-mfpu=neon-vfpv4", ] board_ld_flags = [] # Board related headfiles search path. board_include_dirs = [] # Board adapter dir for OHOS components. board_adapter_dir = "//device/board/bearpi/bearpi_hm_micro/hal" # Sysroot path. board_configed_sysroot = "" # Board storage type, it used for file system generation. storage_type = "emmc"
-
验证
hb set
配置是否正确,输入hb set
能够显示如下图片表示配置正确。
执行hb set
输入项目根目录,并且回车,hb
命令会遍历所有//vendor/<product_company>/<product_name>
目录下的config.json
,给出可选产品编译选项,config.json
的product_name
用于显示产品名,device_company
和board
用于关联出//device/board/<device_company>/<board>
目录,并且匹配<any_dir_name>/config.gni
文件,如果能够匹配多个文件,表示该单板适配了多个内核,那么可以根据config.json
的kernel_type
和kernel_version
来唯一匹配config.gni
的kernel_type
和kernel_version
,即可确定了需要编译适配了哪个内核的单板。选择好产品后,输入回车就会在根目录下自动生成 ohos_config.json 文件,这里会将要编译的产品信息列出。通过
hb env
也可以查看选择出来的预编译环境变量。
内核移植
内核移植需要完成 LiteOS-A Kconfig
适配、gn
的编译构建和内核启动最小适配。
详细移植步骤参考:LiteOS-A 内核移植
Kconfig 适配
- 在//device/board/bearpi/bearpi_hm_micro/liteos_a/drivers/Kconfig 中添加芯片、产品名称、厂商名称相关配置。
source "../../device/soc/st/common/platform/Kconfig" config PLATFORM string default "stm32mp157" if PLATFORM_STM32MP157 config PRODUCT_NAME string "product name" default "bearpi_hm_micro" if PRODUCT_BEARPI_HM_MICRO config DEVICE_COMPANY string "vendor name" default "st" if PLATFORM_STM32MP157 config TEE_ENABLE bool "Enable TEE" default n depends on PLATFORM_STM32MP157 help Enable teeos in platform
- 在//device/soc/st/common/platform/Kconfig 中添加驱动相关配置。
config DRIVERS_MMC depends on DRIVERS bool "Enable MMC" default y depends on DRIVERS && FS_VFS help Answer Y to enable LiteOS support MMC driver. config DRIVERS_EMMC depends on DRIVERS_MMC && PLATFORM_STM32MP157 bool "Enable MMC0 support eMMC type" config DRIVERS_HI3881 bool "Enable Hi3881 Host driver" default n depends on DRIVERS_HDF_WIFI help Answer Y to enable Hi3881 Host driver. config HW_RANDOM_ENABLE depends on DRIVERS_RANDOM bool "Select hw random" default y help Answer Y to select hw random.
- 在//vendor/bearpi/bearpi_hm_micro/kernel_configs/debug_tee.config 中使能相关配置。
... LOSCFG_PLATFORM="stm32mp157" LOSCFG_PRODUCT_NAME="bearpi_hm_micro" LOSCFG_DEVICE_COMPANY="st" # LOSCFG_PLATFORM_HI3516DV300 is not set # LOSCFG_PLATFORM_HI3518EV300 is not set # LOSCFG_PLATFORM_QEMU_ARM_VIRT_CA7 is not set LOSCFG_PLATFORM_STM32MP157=y LOSCFG_PRODUCT_BEARPI_HM_MICRO=y LOSCFG_BOARD_CONFIG_PATH="device/board/bearpi/bearpi_hm_micro/liteos_a/board" LOSCFG_TEE_ENABLE=y ...
gn 编译适配
- 在//device/board/bearpi/bearpi_hm_micro/liteos_a 中新建 BUILD.gn,添加代码如下,此模块依赖 board、drivers、hdf_config。
cmd = "if [ -f $product_path/hdf_config/BUILD.gn ]; then echo true; else echo false; fi" HAVE_PRODUCT_CONFIG = exec_script("//build/lite/run_shell_cmd.py", [ cmd ], "value") group("liteos_a") { deps = [ "board", "drivers", ] if (HAVE_PRODUCT_CONFIG) { deps += [ "$product_path/hdf_config" ] } else { deps += [ "hdf_config" ] } } config("public") { configs = [ "board:public", "drivers:public", ] }
- 在//device/board/bearpi/bearpi_hm_micro/liteos_a/board 中新建 BUILD.gn,添加代码如下。将 os_adapt.c 内核启动相关代码编译进系统。
import("//kernel/liteos_a/liteos.gni") module_name = "bsp_config" kernel_module(module_name) { sources = [] if (defined(LOSCFG_PLATFORM_ADAPT)) { sources += [ "os_adapt/os_adapt.c" ] } } config("public") { include_dirs = [ "." ] include_dirs += [ "include" ] include_dirs += [ "$LITEOSTOPDIR/drivers/block/disk/include" ] include_dirs += [ "$LITEOSTOPDIR/../../drivers/adapter/khdf/liteos/osal/include" ] }
- 在//device/board/bearpi/bearpi_hm_micro/liteos_a/drivers 中新建 BUILD.gn,添加代码如下,将 device/soc/st/common/platform 路径下的 HDF 驱动编译进系统。
import("//drivers/adapter/khdf/liteos/hdf.gni") group("drivers") { public_deps = [ "//device/soc/st/common/platform:drivers" ] } config("public") { configs = [ "//device/soc/st/common/platform:public" ] }
- 在//vendor/bearpi/bearpi_hm_micro/hdf_config 中新建 BUILD.gn,添加代码如下,将 HCS 配置文件编译进系统。
module_switch = defined(LOSCFG_DRIVERS_HDF) && !defined(LOSCFG_DRIVERS_HDF_TEST) module_name = "libhdf_config" hdf_driver(module_name) { hcs_sources = [ "hdf.hcs" ] } group("hdf_config") { public_deps = [ ":$module_name" ] deps = [ "hdf_test", "hdf_test/hcs_macro_test", ] }
内核启动适配
- 在//device/board/bearpi/bearpi_hm_micro/liteos_a/board/os_adapt.c 中添加以下内核启动相关代码,详细解释参考 LiteOS-A 内核移植。
... void SystemInit(void) { #ifdef LOSCFG_DRIVERS_RANDOM dprintf("dev random init ...\n"); Mp1xxRngInit(); #endif #ifdef LOSCFG_DRIVERS_MEM dprintf("mem dev init ...\n"); extern int mem_dev_register(void); mem_dev_register(); #endif dprintf("Date:%s.\n", __DATE__); dprintf("Time:%s.\n", __TIME__); #ifdef LOSCFG_DRIVERS_HDF dprintf("DeviceManagerStart start ...\n"); if (DeviceManagerStart()) { PRINT_ERR("No drivers need load by hdf manager!"); } dprintf("DeviceManagerStart end ...\n"); #endif net_init(); #ifdef LOSCFG_PLATFORM_ROOTFS dprintf("OsMountRootfs start ...\n"); if (LOS_GetCmdLine()) { dprintf("get cmdline error!\n"); } if (LOS_ParseBootargs()) { dprintf("parse bootargs error!\n"); } if (OsMountRootfs()) { dprintf("mount rootfs error!\n"); } dprintf("OsMountRootfs end ...\n"); #endif dprintf("Before PLATFORM_UART ...\n"); #ifdef LOSCFG_DRIVERS_HDF_PLATFORM_UART if (virtual_serial_init(TTY_DEVICE) != 0) { PRINT_ERR("virtual_serial_init failed"); } if (system_console_init(SERIAL) != 0) { PRINT_ERR("system_console_init failed\n"); } #endif dprintf("After PLATFORM_UART ...\n"); if (OsUserInitProcess()) { PRINT_ERR("Create user init process failed!\n"); return; } dprintf("cat log shell end\n"); return; } ...
板级系统移植
SoC 芯片平台 HDF 驱动移植
驱动适配相关文件放置在 device/soc/st/common/platform
中,所有的驱动都是通过 HDF
机制加载,本章节以 GPIO 驱动适配为例进行详细说明。
-
在
//device/soc/st/common/platform/gpio/BUILD.gn
文件中,描述了 stm32mp1xxgpio
驱动的编译适配。如下:module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO) --- 如果打开HDF的GPIO配置开关,才进行如下编译。 module_name = get_path_info(rebase_path("."), "name") hdf_driver("hdf_gpio") { sources = [ "stm32mp1_gpio.c" ] ---gpio驱动源文件。 include_dirs = [ ---依赖的.h路径。 "." , "../stm32mp1xx_hal/STM32MP1xx_HAL_Driver/Inc", ] }
-
在
//device/soc/st/common/platform/gpio/stm32mp1_gpio.c
文件中,描述了 stm32mp1xxgpio
驱动的源码适配。
首先,按照OpenHarmony
的HDF
驱动框架加载驱动基本适配框架,如下:struct HdfDriverEntry g_GpioDriverEntry = { .moduleVersion = 1, .moduleName = "HDF_PLATFORM_GPIO", .Bind = GpioDriverBind, .Init = GpioDriverInit, .Release = GpioDriverRelease, }; HDF_INIT(g_GpioDriverEntry); --- 通过HDF_INIT 加载GPIO驱动。
-
在//device/soc/st/stm32mp1xx/sdk_liteos/hdf_config/gpio 中添加 gpio 硬件描述信息文件 gpio_config.hcs,在该文件中添加驱动私有配置信息。
root { platform { gpio_config { controller_0x50002000 { match_attr = "st_stm32mp1_gpio"; groupNum = 11; bitNum = 16; gpioRegBase = 0x50002000; gpioRegStep = 0x1000; irqRegBase = 0x5000D000; irqRegStep = 0x400; } } } }
-
配置产品加载驱动,产品的所有设备信息被定义在源码文件//vendor/bearpi/bearpi_hm_micro/hdf_config/device_info/device_info.hcs 中。
平台驱动请添加到 platform 的 host 中。说明:
moduleName 要与驱动文件中定义的相同,deviceMatchAttr 要与驱动私有配置信息文件 gpio_config.hcs 中定义 match_attr 的相同。root { ... platform :: host { device_gpio :: device { device0 :: deviceNode { policy = 2; priority = 10; permission = 0644; moduleName = "HDF_PLATFORM_GPIO_MANAGER"; serviceName = "HDF_PLATFORM_GPIO_MANAGER"; } device1 :: deviceNode { policy = 0; priority = 10; permission = 0644; moduleName = "HDF_PLATFORM_GPIO"; serviceName = "HDF_PLATFORM_GPIO"; deviceMatchAttr = "st_stm32mp1_gpio"; } } } }
-
完善驱动代码,gpio_config.hcs 的配置信息会在 GpioDriverInit 中加载。
static int32_t GpioDriverInit(struct HdfDeviceObject *device) { int32_t ret; struct Mp1xxGpioCntlr *stm32gpio = &g_Mp1xxGpioCntlr; dprintf("%s: Enter", __func__); if (device == NULL || device->property == NULL) { HDF_LOGE("%s: device or property NULL!", __func__); return HDF_ERR_INVALID_OBJECT; } //获取属性数据 ret = Mp1xxGpioReadDrs(stm32gpio, device->property); if (ret != HDF_SUCCESS) { HDF_LOGE("%s: get gpio device resource fail:%d", __func__, ret); return ret; } ... }
OpenHarmony 子系统适配
OpenHarmony
子系统适配只需要在 config.json
中增加对应子系统和部件,这样编译系统会将该部件纳入编译目标中。
启动恢复子系统适配
启动恢复子系统需要适配 bootstrap_lite
、syspara_lite
、appspawn_lite
、init
四个部件。请在 vendor/bearpi/bearpi_hm_micro/config.json
中新增对应的配置选项。
{
"subsystem": "startup",
"components": [
{ "component": "syspara_lite", "features":[] },
{ "component": "bootstrap_lite", "features":[] },
{ "component": "appspawn_lite", "features":[] },
{ "component": "init", "features":[] }
]
},
系统启动时会根据//vendor/bearpi/bearpi_hm_micro/init_configs 中的启动配置来启动系统。
DFX 子系统适配
进行 DFX
子系统适配需要添加 hilog_featured_lite
、hidumper_lite
部件,直接在 config.json
文件配置即可。
{
"subsystem": "hiviewdfx",
"components": [
{ "component": "hilog_featured_lite", "features":[] },
{ "component": "hidumper_lite", "features":[] }
]
},
系统服务管理子系统适配
进行系统服务管理子系统适配需要添加 samgr_lite
、safwk_lite
、dmsfwk_lite
三个部件,直接在 config.json
配置即可。
{
"subsystem": "distributed_schedule",
"components": [
{ "component": "samgr_lite", "features":[] },
{ "component": "safwk_lite", "features":[] },
{ "component": "dmsfwk_lite", "features":[] }
]
},
安全子系统适配
进行安全子系统适配需要添加 permission_lite
、appverify
、device_auth
、huks
四个部件,直接在 config.json
配置即可。
{
"subsystem": "security",
"components": [
{ "component": "permission_lite", "features":[] },
{ "component": "appverify", "features":[] },
{ "component": "device_auth", "features":[] },
{ "component": "huks", "features":
[
"huks_config_file = \"hks_config_small.h\""
]
}
]
},
公共基础库子系统适配
进行公共基础库子系统适配需要添加 kv_store
、os_dump
两个部件,直接在 config.json
配置即可。
{
"subsystem": "utils",
"components": [
{ "component": "kv_store", "features":[] },
{ "component": "os_dump", "features":[] }
]
},
图形子系统适配
进行图形子系统适配需要添加 graphic_utils
部件,直接在 config.json
配置即可。
{
"subsystem": "graphic",
"components": [
{ "component": "graphic_utils",
"features": [ "enable_ohos_graphic_utils_product_config = true"
]
},
{ "component": "graphic_hals", "features":[] },
{ "component": "ui", "features":[ "enable_graphic_font = true","enable_video_component=false"] },
{ "component": "surface", "features":[] },
{ "component": "wms", "features":[] }
]
},
graphic
配置文件见 //vendor/bearpi/bearpi_hm_micro/graphic_config/product_graphic_lite_config.h
。
ArkUI 开发框架子系统适配
进行 ArkUI 开发框架子系统适配需要添加 ace_engine_lite
部件,直接在 config.json
配置即可。
{
"subsystem": "arkui",
"components": [
{
"component": "ace_engine_lite",
"features": [
"enable_ohos_ace_engine_lite_product_config = true"
]
}
]
},
ace_engine_lite
部件配置文件见 //vendor/bearpi/bearpi_hm_micro/ace_lite_config/product_acelite_config.h
。
元能力子系统适配
进行元能力子系统适配需要添加 aafwk_lite
部件,直接在 config.json
配置即可。
{
"subsystem": "aafwk",
"components": [
{
"component": "aafwk_lite",
"features": [
"enable_ohos_appexecfwk_feature_ability = true" --- 支持FA特性,即包含图形能力。
]
}
]
},
包管理子系统适配
进行包管理子系统适配需要添加 appexecfwk_lite
部件,直接在 config.json
配置即可。
{
"subsystem": "appexecfwk",
"components": [
{
"component": "appexecfwk_lite"
}
]
},
最后
有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙(HarmonyOS NEXT)最新学习路线
-
HarmonOS基础技能
- HarmonOS就业必备技能
- HarmonOS多媒体技术
- 鸿蒙NaPi组件进阶
- HarmonOS高级技能
- 初识HarmonOS内核
- 实战就业级设备开发
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开发入门教学视频》
《鸿蒙生态应用开发V2.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
- ArkTS语言
- 安装DevEco Studio
- 运用你的第一个ArkTS应用
- ArkUI声明式UI开发
- .……
《鸿蒙开发进阶》
- Stage模型入门
- 网络管理
- 数据管理
- 电话服务
- 分布式应用开发
- 通知与窗口管理
- 多媒体技术
- 安全技能
- 任务管理
- WebGL
- 国际化开发
- 应用测试
- DFX面向未来设计
- 鸿蒙系统移植和裁剪定制
- ……
《鸿蒙进阶实战》
- ArkTS实践
- UIAbility应用
- 网络案例
- ……
获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。