按照硬件进行层次划分为芯片架构层、片上系统层和单板层。从下向上依次进行包含关系,例如:
基于硬件结构划分层次图,OpenHarmony顶层目录结构设计如下,
.
├── device
│ ├── boards
│ │ └── <board_company>
│ └── soc
│ └── <soc_company>
├── drivers
├── kernel
└── vendor
└── <product_company>
└── <product_name>
因为OpenHarmony为一个复杂的操作系统,硬件(对应/device目录)与产品(对应/vendor目录)的代码采用多仓设计,每个仓库做到相互独立,提交代码的时候互不影响。
例如,海思提供3861的soc,润和与小熊派分别基于该soc来制作单板,那么目录规划为
.
└── device
├── boards
│ ├── neptune
│ └── bearpi
└── soc
└── hisilicon
/device/soc/<soc_company>需要基于SoC Family、SoC Series和SoC的分层架构原则来进行目录设计规划,其中分为驱动源码、硬件参数配置、软件特性配置、软件开发套件(SDK)这四个部分。
驱动源码设计
按照OpenHarmony驱动框架(HDF)设计,驱动主要包含两部分,平台驱动和器件驱动。平台驱动主要包括通常在SOC内的GPIO、I2C、SPI等;器件驱动则主要包含通常在SOC外的器件,如 LCD、TP、WLAN等。
考虑驱动源码的复用性,需要尽可能将源码放到drivers目录中,例如:PL011 UART, PL022 SPI, PL031 RTC,这些属于ARM架构的通用外设控制器IP(Intellectual Property,知识产权),它们在基于ARM架构的SoC中十分通用。
但是当前驱动框架的代码目录,如下代码框图所示,它不适合放平台驱动源码,因为所有类型的驱动框架都是平铺的,没有使用目录来隔开,这样当同类型的不同驱动源码实现也只能平铺在该目录下,会导致该目录十分臃肿。
.
├── drivers
│ ├── framework
│ │ ├── support
│ │ │ ├── platform
│ │ │ │ ├── include
│ │ │ │ ├── src
│ │ │ │ │ ├── common
│ │ │ │ │ ├── gpio_core.c
│ │ │ │ │ ├── gpio_if.c
│ │ │ │ │ ├── i2c_core.c
│ │ │ │ │ ├── i2c_if.c
目录优化为如下:
.
├── drivers
│ ├── framework
│ │ ├── support
│ │ │ ├── platform
│ │ │ │ ├── Kconfig.platform --- Kconfig.platform 为平台驱动开关配置选项,它包含不同类型的驱动Kconfig,例如gpio驱动Kconfig.gpio
│ │ │ │ ├── BUILD.gn --- 根据Kconfig.platform的配置结果来选择编译不同类型的驱动,例如选择gpio驱动,则deps += [ "gpio" ];另外需要需要将include目录作为public_configs暴露出去给外设驱动调用
│ │ │ │ ├── include --- 所有平台驱动框架的头文件
│ │ │ │ ├── common
│ │ │ │ ├── gpio
│ │ │ │ │ ├── gpio_core.c
│ │ │ │ │ ├── gpio_if.c
│ │ │ │ │ ├── gpio_pl061.c
│ │ │ │ │ ├── ……
│ │ │ │ │ ├── Kconfig.gpio --- Kconfig.gpio 用于选择gpio驱动的不同实现,例如配置HDF_PLATFORM_GPIO_PL061,以及pl061驱动的相关配置
│ │ │ │ │ └── BUILD.gn --- 根据Kconfig.gpio的结果来选择编译gpio驱动的源码,如果配置了HDF_PLATFORM_GPIO_PL061,则编译gpio_pl061.c
│ │ │ │ ├── i2c
如果HDF驱动框架还未支持该驱动框架的实现,或者驱动以二进制开源的形式实现,那么需要将该驱动放到 /device/soc/<soc_company>/drivers 目录下。该drivers的目录举例如下:
/device/soc/<soc_company>/drivers
├── BUILD.gn --- 根据Kconfig的配置结果来选择编译不同类型的驱动,例如选择cfiflash驱动,则deps += [ "cfiflash" ];另外需要需要将include目录作为public_configs暴露出去给外设驱动调用
├── Kconfig --- Kconfig.platform 为平台驱动开关配置选项,它包含不同类型的驱动Kconfig,例如cfiflash驱动Kconfig.cfiflash
├── include --- 所有驱动的对外头文件
├── cfiflash
│ ├── BUILD.gn --- 编译cfiflash驱动
│ ├── Kconfig.cfiflash --- 根据Kconfig.cfiflash来定义cfiflash驱动的相关配置
│ ├── cfiflash.c
│ ├── cfiflash_internal.h
│ └── hdf_cfi.c
├── spinor_flash
硬件参数配置设计
类似DTS(Device Tree Source),OpenHarmony设计了HCS(HDF Configuration Source),用于对硬件设备参数进行描述,SoC部分的hcs配置文件放到/device/soc/<soc_company>/hcs目录下。
/device/soc/<soc_company>/hcs
├── common
│ ├── armv7-m.hcs --- 不同SoC依赖的公共hcs配置,一般CPU、ARCH的hcs配置放在这儿,例如nvic和systick的hcs配置
├── series_1
│ ├── series_1.hcs --- SoC Series 1 的hcs配置,它包含CPU、ARCH的hcs配置
│ ├── series_1_soc_1.hcs --- SoC Series 1 中 SoC 1 的hcs配置,它包含 SoC Series 1 的hcs配置
│ └── series_1_soc_2.hcs --- SoC Series 1 中 SoC 2 的hcs配置,它包含 SoC Series 1 的hcs配置
├── series_2
注:因为大部分公司主要专注于一类SoC Family的设计,例如st公司的SoC Family为stm32,因此hcs目录下没有 <soc_family> 目录,而是直接以 <soc_series> 来划分目录。
与Linux内核的兼容性设计,
软件特性配置设计
软件特性配置采用Kconfig,具体实现采用Python语言的Kconfiglib,相比传统linux下的Kconfig实现,它能够兼容后者,并且具备更加灵活的路径包含和自定义实现特定解析功能等特性,基于这个前提来设计Kconfig的配置关系。
Kconfig分为可配置部分与默认配置部分(defconfig),可配置部分提供选择哪个SoC Family,哪个SoC Series,以及哪个SoC,而defconfig部分则对应如果选择了哪个SoC Family,则它拥有该SoC Family的哪些特性,类似的,对应SoC Series和SoC。注:SoC Family未提供选择,主要是以SoC Series进行选择。
/device/soc/<soc_company>/
├── Kconfig.soc --- 包含./*/Kconfig.soc文件,用来选择对应SOC_SERIES下的SOC_SERIES_X_SOC_X
├── Kconfig.defconfig --- 包含./*/Kconfig.defconfig.series文件,是该SoC总的默认配置定义
├── Kconfig.series --- 包含./*/Kconfig.series,用于选择对应的SOC_SERIES,这样也就确定了对应的ARCH、CPU等
├── series_1
│ ├── Kconfig.defconfig.series --- 如果定义了SOC_SERIES_1(通过可配置Kconfig来选择),则包含该series 1下所有soc的defconfig配置,并且配置SOC_SERIES为"series_1"
│ ├── Kconfig.defconfig.series_1_soc_1 --- 如果定义了SOC_SERIES_1_SOC_1(通过可配置Kconfig来选择),则配置SOC为"series_1_soc_1",还有NUM_IRQ等
│ ├── Kconfig.defconfig.series_1_soc_2
│ ├── Kconfig.series --- 配置SOC_SERIES_1是否打开,为Kconfig.defconfig.series提供选择结果,如果选择打开它,那么将ARCH、CPU等相关宏也定义
│ └── Kconfig.soc --- 配置选择该SOC_SERIES_1下需要打开哪个SOC,为Kconfig.defconfig.series_1_soc_x提供选择结果
├── series_2
SDK目录设计
SDK包含SoC厂商提供的软件开发套件,不同的SoC启动的流程有差异,主要体现在不同的SoC Series,不同的内核这两个维度。因此目录设计如下
/device/soc/<soc_company>/series_x
├── common --- 通用部分
├── linux --- linux内核适配
├── liteos_a --- liteos_a内核适配
├── soc.c --- 包含SoC启动部分适配
├── soc.h
├── Kconfig.sdk --- SDK功能配置开关
└── BUILD.gn --- 编译配置文件
/device/boards/<board_company>需要基于board、shields(可选)的分层架构原则来进行目录设计规划,其中分为驱动源码、硬件参数配置、软件特性配置、软件开发套件(SDK)这四个部分。
驱动源码设计
按照OpenHarmony驱动框架(HDF)设计,单板驱动主要覆盖器件驱动,按照HDF驱动框架目录设计,这部分的驱动应该放到如下目录:
//drivers/peripheral
├── audio --- 音频驱动
│ ├── chipsets
│ │ ├── hi3516dv300 --- hi3516dv300 驱动
│ │ ├── tfa9879 --- tfa9879 驱动
如果HDF驱动框架还未支持该驱动框架的实现,或者驱动以二进制开源的形式实现,那么需要将该驱动放到 /device/boards/<board_company>/drivers 目录下。该drivers的目录设计类似/device/soc/<soc_company>/drivers 目录。
硬件参数配置
board部分的hcs配置文件放到/device/soc/<soc_company>/hcs目录下
/device/boards/<board_company>/hcs
├── board_1.hcs --- board_1.hcs文件应该包含某个series_x_soc_x.hcs,并且能够对其进行overlay,还可以定制该board的hcs
├── board_2.hcs
软件特性配置
Kconfig分为可配置部分与默认配置部分(defconfig)
/device/boards/<board_company>/
├── board_1 --- 单板名
│ ├── Kconfig.board --- 用来选择board_1单板,它依赖某SOC_SERIES_X_SOC_X配置宏
│ ├── Kconfig.defconfig --- 用来配置board_1单板的默认配置参数
│ ├── board_1_defconfig --- board_1单板的默认配置参数,在执行Kconfig的时候会默认加载它,使其成为默认配置选项,同时xxx_defconfig也标记它是一个board目录,xxx表示单板,需要跟board_1这个目录名保持一致。
扩展板
/device/boards/<board_company>/shields
├── shield_1 --- 扩展板名
│ ├── Kconfig.shield --- 用来选择shield
│ ├── Kconfig.defconfig --- 用来配置shield的默认配置参数
│ ├── shield_1.overlay.hcs --- shield_1.overlay.hcs文件允许对board_1.hcs文件中node进行overlay,主要是满足扩展板的需求
软件开发套件(SDK)
SDK包含单板厂商提供的软件开发套件,主要体现在不同的内核这两个维度。因此目录设计如下
/device/soc/<soc_company>/board_x
├── common --- 通用部分
├── linux --- linux内核适配
├── liteos_a --- liteos_a内核适配
├── board.c --- 包含board的SDK代码
├── board.h
├── Kconfig.sdk --- SDK功能配置开关
└── BUILD.gn --- 编译配置文件
按照新目录的设计,需要编译构建进行相应的适配设计,整体上编译流程分为配置解析和编译构建两个阶段。
配置解析阶段分为:
编译构建阶段分为:
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。