Linux內(nèi)核增加HDF驅(qū)動(dòng)子系統(tǒng)
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
前言
HDF驅(qū)動(dòng)子系統(tǒng)是OpenHarmony重要的特色功能之一,其主要的功能是實(shí)現(xiàn)驅(qū)動(dòng)程序在多內(nèi)核多平臺(tái)的物聯(lián)網(wǎng)環(huán)境,實(shí)現(xiàn)一次驅(qū)動(dòng)開(kāi)發(fā),多端部署。之前移植OHOS3.0使用了傳統(tǒng)的linux驅(qū)動(dòng),比較遺憾,今天嘗試將HDF驅(qū)動(dòng)子系統(tǒng)加入編譯框架。開(kāi)始前先了解幾個(gè)名詞。
HCS(HDF Configuration Source)是 HDF 驅(qū)動(dòng)框架的配置描述源碼,JSON存儲(chǔ)。
HC-GEN(HDF Configuration Generator)是 HCS 配置轉(zhuǎn)換工具,可以將 HDF 配置文件HCS轉(zhuǎn)換為二進(jìn)制HCB。
HCB(HDF Configuration Binary)二進(jìn)制文件,驅(qū)動(dòng)可使用 HDF 框架提供的配置解析接口獲取配置。
內(nèi)核打補(bǔ)丁
如何在內(nèi)核加入HDF驅(qū)動(dòng),linux內(nèi)核下主要實(shí)現(xiàn)是下面兩個(gè)目錄:
drivers\adapter\khdf\linux 和 drivers\framework
這兩個(gè)目錄是通過(guò)鏈接的方式加入到內(nèi)核編譯的,流程如下:
kernel\linux\build\kernel.mk:75
- $(hide) cd $(KERNEL_SRC_TMP_PATH) && patch -p1 < $(HDF_PATCH_FILE) && patch -p1 < $(DEVICE_PATCH_FILE)
可以參考3516的HDF補(bǔ)丁:kernel\linux\patches\linux-5.10\hi3516dv300_patch\hdf.patch
- patching file drivers/Kconfig
- patching file drivers/Makefile
- patching file drivers/hdf/Makefile
- patching symbolic link drivers/hdf/framework
- patching symbolic link drivers/hdf/khdf
- patching symbolic link include/hdf
- # 添加到linux內(nèi)核的補(bǔ)丁
- drivers/hdf/framework -> /drivers/framework/ # 驅(qū)動(dòng)子系統(tǒng)驅(qū)動(dòng)框架、配置管理、配置解析、驅(qū)動(dòng)通用框架模型、硬件通用平臺(tái)能力接口等
- drivers/hdf/khdf -> /drivers/adapter/khdf/linux/ # 在linux內(nèi)核中部署OpenHarmony驅(qū)動(dòng)框架
- drivers/hdf/Makefile # 由hdf.patch提供
- include/hdf -> /drivers/framework/include/ # 驅(qū)動(dòng)框架對(duì)外提供能力的頭文件
內(nèi)核配置
只是打上補(bǔ)丁還不行,還得在內(nèi)核的編譯配置文件中加入HDF選項(xiàng)。最開(kāi)始的做法就是參考3516的配置選擇,但是發(fā)現(xiàn)有些配置會(huì)導(dǎo)致編譯失敗。測(cè)試發(fā)現(xiàn)下面的配置是可以編譯成功的。
- [*] Enable HDF manager
- (2) Set HDF support platform
- [*] Enable HDF platform driver
- [*] Enable HDF platform mipi dsi driver
- [*] Enable HDF platform gpio driver
- [*] Enable HDF platform i2c driver
- [*] Enable HDF platform watchdog driver
- [*] hi35xx pwm driver
- [*] Enable HDF platform pwm driver
- [*] Enable HDF platform uart driver
- [ ] Enable HDF platform sdio driver
- [ ] Enable HDF platform emmc driver
- [*] Enable HDF platform mmc driver
- [*] Enable HDF platform spi driver
- [*] Enable HDF platform rtc driver
- [*] Enable HDF linux test
- [*] Enable HDF Display driver
- [ ] Enable HDF Lcdkit driver
- [*] Enable HDF Icn9700 driver
- [ ] Enable HDF St7789 driver
- [*] Enable HDF input driver
- [*] Enable HDF tp 5P5 GT911 driver
- [*] Enable HDF tp 2P35 FT6236 driver
- [ ] Enable HDF wifi
- [ ] Enable HDF Bluetooth
- [*] Enable HDF sensor driver
- [ ] Enable HDF accel sensor driver
- [ ] Enable HDF gyro sensor driver
- [ ] Enable HDF barometer sensor driver
- [ ] Enable HDF hall sensor driver
- [*] Enable HDF storage driver
- [ ] Enable HDF USB PNP Notify driver
- [ ] Enable F_GENERIC driver
- [ ] Enable HDF Audio driver
- [*] Enable HDF vibrator driver
- [*] Enable HDF linear vibrator driver
- [ ] Enable HDF dsoftbus driver
- CONFIG_DRIVERS_HDF=y
- CONFIG_HDF_SUPPORT_LEVEL=2
- CONFIG_DRIVERS_HDF_PLATFORM=y
- CONFIG_DRIVERS_HDF_PLATFORM_MIPI_DSI=y
- CONFIG_DRIVERS_HDF_PLATFORM_GPIO=y
- CONFIG_DRIVERS_HDF_PLATFORM_I2C=y
- CONFIG_DRIVERS_HDF_PLATFORM_WATCHDOG=y
- CONFIG_PWM_HI35XX=y
- CONFIG_DRIVERS_HDF_PLATFORM_PWM=y
- CONFIG_DRIVERS_HDF_PLATFORM_UART=y
- # CONFIG_DRIVERS_HDF_PLATFORM_SDIO is not set
- # CONFIG_DRIVERS_HDF_PLATFORM_EMMC is not set
- CONFIG_DRIVERS_HDF_PLATFORM_MMC=y
- CONFIG_DRIVERS_HDF_PLATFORM_SPI=y
- CONFIG_DRIVERS_HDF_PLATFORM_RTC=y
- CONFIG_DRIVERS_HDF_TEST=y
- CONFIG_DRIVERS_HDF_DISP=y
- # CONFIG_DRIVERS_HDF_LCDKIT is not set
- CONFIG_DRIVERS_HDF_LCD_ICN9700=y
- # CONFIG_DRIVERS_HDF_LCD_ST7789 is not set
- CONFIG_DRIVERS_HDF_INPUT=y
- CONFIG_DRIVERS_HDF_TP_5P5_GT911=y
- CONFIG_DRIVERS_HDF_TP_2P35_FT6236=y
- # CONFIG_DRIVERS_HDF_WIFI is not set
- # CONFIG_DRIVERS_HDF_BT is not set
- CONFIG_DRIVERS_HDF_SENSOR=y
- # CONFIG_DRIVERS_HDF_SENSOR_ACCEL is not set
- # CONFIG_DRIVERS_HDF_SENSOR_GYRO is not set
- # CONFIG_DRIVERS_HDF_SENSOR_BAROMETER is not set
- # CONFIG_DRIVERS_HDF_SENSOR_HALL is not set
- CONFIG_DRIVERS_HDF_STORAGE=y
- # CONFIG_DRIVERS_HDF_USB_PNP_NOTIFY is not set
- # CONFIG_DRIVERS_HDF_USB_F_GENERIC is not set
- # CONFIG_DRIVERS_HDF_AUDIO is not set
- CONFIG_DRIVERS_HDF_VIBRATOR=y
- CONFIG_DRIVERS_HDF_VIBRATOR_LINEAR=y
- # CONFIG_DRIVERS_HDF_DSOFTBUS is not set
- # end of Device Drivers
[*] Enable HDF linux test 是需要設(shè)置的,如果沒(méi)有設(shè)置CONFIG_DRIVERS_HDF_TEST,目錄結(jié)構(gòu)就出問(wèn)題了,會(huì)報(bào)這樣的錯(cuò)誤。
- drivers/hdf/khdf/Makefile:22: PRODUCT_PATH=vendor/raspberrypi/RPI4B
- scripts/Makefile.build:44: drivers/hdf/khdf/../../../../vendor/raspberrypi/RPI4B/hdf_config/Makefile: No such file or directory
- make[5]: *** No rule to make target 'drivers/hdf/khdf/../../../../vendor/raspberrypi/RPI4B/hdf_config/Makefile'. Stop.
- CC [M] drivers/net/wireless/mac80211_hwsim.o
- make[4]: *** [scripts/Makefile.build:497: drivers/hdf/khdf/../../../../vendor/raspberrypi/RPI4B/hdf_config] Error 2
- make[3]: *** [scripts/Makefile.build:497: drivers/hdf/khdf] Error 2
- make[2]: *** [scripts/Makefile.build:497: drivers/hdf] Error 2
- make[2]: *** Waiting for unfinished jobs....
下面3個(gè)選項(xiàng)要關(guān)閉,不然會(huì)報(bào)下面的錯(cuò)誤。
[ ] Enable HDF platform sdio driver
[ ] Enable HDF platform emmc driver
[ ] Enable HDF wifi
- drivers/../../../../../../drivers/adapter/khdf/linux/platform/sdio/sdio_adapter.o: In function `Hi35xxLinuxSdioRescan':
- sdio_adapter.c:(.text+0x20): undefined reference to `hisi_sdio_rescan'
- sdio_adapter.c:(.text+0x34): undefined reference to `himci_get_mmc_host'
- drivers/../../../../../../drivers/adapter/khdf/linux/platform/sdio/sdio_adapter.o: In function `Hi35xxLinuxSdioFindFunc':
- sdio_adapter.c:(.text+0xc84): undefined reference to `himci_get_mmc_host'
- sdio_adapter.c:(.text+0xc9c): undefined reference to `himci_get_mmc_host'
- sdio_adapter.c:(.text+0xcb4): undefined reference to `himci_get_mmc_host'
- drivers/../../../../../../drivers/adapter/khdf/linux/platform/emmc/emmc_adapter.o: In function `Hi35xxLinuxEmmcBind':
- emmc_adapter.c:(.text+0x214): undefined reference to `himci_get_mmc_host'
- drivers/../../../../../../device/hisilicon/drivers/wifi/driver/hi3881/oal/oal_sdio_host.o: In function `sdio_card_detect_change':
- oal_sdio_host.c:(.text+0x2ce8): undefined reference to `hisi_sdio_rescan'
- make[1]: *** [Makefile:1179: vmlinux] Error 1
- make[1]: Leaving directory '/home/liangzili/ohos/out/KERNEL_OBJ/kernel/src_tmp/linux-5.10'
- make: *** [kernel.mk:80: /home/liangzili/ohos/out/KERNEL_OBJ/kernel/src_tmp/linux-5.10/arch/arm/boot/zImage] Error 2
- ninja: build stopped: subcommand failed.
編譯過(guò)程
為了方便測(cè)試可以單獨(dú)進(jìn)行內(nèi)核編譯,比如我的編譯命令是這樣的。
- ./build.sh --product-name RPI4B --ccache --build-target raspberrypi_products
可以分析下HDF這部分的編譯過(guò)程。
linux-5.10\drivers\hdf\Makefile,hdf.patch會(huì)添加這個(gè)Makefile,將khdf文件夾加入編譯。
- obj-$(CONFIG_DRIVERS_HDF) += khdf/
linux-5.10\drivers\hdf\khdf\Makefile
- export HDF_ROOT := drivers/hdf
- obj-$(CONFIG_DRIVERS_HDF) += osal/
- obj-$(CONFIG_DRIVERS_HDF) += network/
- obj-$(CONFIG_DRIVERS_HDF) += config/
- SUPPORT_LEVEL_STD_H := $(shell [ "$(CONFIG_HDF_SUPPORT_LEVEL)" -ge 2 ] && echo true)
- $(warning PRODUCT_PATH=$(PRODUCT_PATH)) # 會(huì)檢查PRODUCT_PATH變量
- ifeq ($(PRODUCT_PATH),)
- $(error PRODUCT_PATH not)
- endif
- # 這里有條注釋指明了*.hcs配置文件的存放路徑
- # for L2+, hcs config should in vendor/product_company/product_name/config/khdf
- ifeq ($(SUPPORT_LEVEL_STD_H), true)
- SUB_DIR:=khdf/
- endif
- # HDF test的配置會(huì)使hcs目錄結(jié)構(gòu)不一樣,我當(dāng)時(shí)沒(méi)有設(shè)置CONFIG_DRIVERS_HDF_TEST就掉這個(gè)坑里了。
- ifeq ($(CONFIG_DRIVERS_HDF), y)
- ifeq ($(CONFIG_DRIVERS_HDF_TEST), y)
- obj-$(CONFIG_DRIVERS_HDF) += ../../../../$(PRODUCT_PATH)/hdf_config/$(SUB_DIR)/hdf_test/
- obj-$(CONFIG_DRIVERS_HDF) += test/
- else
- obj-$(CONFIG_DRIVERS_HDF) += ../../../../$(PRODUCT_PATH)/hdf_config/$(SUB_DIR)
- endif
- endif
- # ... 后面按照配置添加一些編譯目錄 ...
drivers\adapter\khdf\linux\Makefile:會(huì)調(diào)用 obj-(CONFIG_DRIVERS_HDF) += ../../../../(CONFIGDRIVERSHDF)+=../../../../(PRODUCT_PATH)/hdf_config/$(SUB_DIR)/hdf_test/ 這是OHOS3.0默認(rèn)的HCS文件存放路徑。官方的注釋也說(shuō)明了,所以將設(shè)備對(duì)應(yīng)的*.hcs存放到 vendor\raspberrypi\RPI4B\hdf_config\khdf 文件夾,參考 3516 的 vendor\hisilicon\Hi3516DV300\hdf_config\khdf\hdf.hcs 就可了。
- #include "device_info/device_info.hcs"
- #include "platform/i2c_config.hcs"
- #include "platform/hi35xx_watchdog_config.hcs"
- #include "platform/hi35xx_pwm_config.hcs"
- #include "platform/hi35xx_uart_config.hcs"
- #include "platform/sdio_config.hcs"
- #include "platform/emmc_config.hcs"
- #include "platform/hi35xx_spi_config.hcs"
- #include "input/input_config.hcs"
- #include "wifi/wlan_platform.hcs"
- #include "wifi/wlan_chip_hi3881.hcs"
- #include "sensor/sensor_config.hcs"
- #include "audio/audio_config.hcs"
- #include "audio/codec_config.hcs"
- #include "audio/dai_config.hcs"
- #include "audio/dma_config.hcs"
- #include "audio/dsp_config.hcs"
- #include "vibrator/vibrator_config.hcs"
- #include "vibrator/linear_vibrator_config.hcs"
- #include "lcd/lcd_config.hcs"
- root {
- module = "hisilicon,hi35xx_chip";
- }
參考 3516 的 vendor\hisilicon\Hi3516DV300\hdf_config\khdf\Makefile
其中:PRODUCT_PATH環(huán)境變量的來(lái)源:kernel/linux/build/kernel_module_build.sh:42:export PRODUCT_PATH=$4
- ifeq ($(LOCAL_HCS_ROOT),)
- LOCAL_HCS_ROOT := $(PRODUCT_PATH)
- endif
- SOURCE_ROOT:=$(abspath ../../../../../)
- HC_GEN_DIR := $(abspath $(SOURCE_ROOT)/drivers/framework/tools/hc-gen)
- HC_GEN := $(HC_GEN_DIR)/build/hc-gen
- LOCAL_HCS_ROOT := $(abspath $(dir $(realpath $(lastword $(MAKEFILE_LIST)))))
- HCS_DIR := $(LOCAL_HCS_ROOT)
- ifneq ($(TARGET_BOARD_PLATFORM),)
- HCS_DIR := $(LOCAL_HCS_ROOT)/$(TARGET_BOARD_PLATFORM)
- else
- ifneq ($(CONFIG_ARCH_HI3516DV300),)
- HCS_DIR := $(LOCAL_HCS_ROOT)
- endif
- ifneq ($(CONFIG_ARCH_HI3518EV300),)
- HCS_DIR := $(LOCAL_HCS_ROOT)
- endif
- endif
- $(info HCS_DIR = $(HCS_DIR))
- HCB_FLAGS := -b -i -a
- HCS_OBJ := hdf_hcs_hex.o
- HCS_OBJ_SRC := $(subst .o,.c,$(notdir $(HCS_OBJ)))
- CONFIG_GEN_HEX_SRC := $(addprefix $(LOCAL_HCS_ROOT)/, $(HCS_OBJ_SRC))
- CONFIG_HCS_SRC := $(subst _hcs_hex.o,.hcs,$(addprefix $(HCS_DIR)/, $(HCS_OBJ)))
- $(obj)/$(HCS_OBJ): $(CONFIG_GEN_HEX_SRC)
- $(Q)$(CC) $(c_flags) -c -o $@ $<
- $(Q)rm -f $<
- $(CONFIG_GEN_HEX_SRC): $(LOCAL_HCS_ROOT)/%_hcs_hex.c: $(HCS_DIR)/%.hcs | $(HC_GEN)
- $(Q)echo gen hdf built-in config
- $(Q)if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
- $(Q)$(HC_GEN) $(HCB_FLAGS) -o $(subst _hex.c,,$(@)) $<
- $(CONFIG_GEN_SRCS): $(CONFIG_OUT_DIR)%.c: $(HCS_DIR)/%.hcs | $(HC_GEN)
- $(Q)echo gen hdf driver config
- $(Q)if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi
- $(Q)$(HC_GEN) -t -o $@ $<
- $(HC_GEN):
- $(HIDE)make -C $(HC_GEN_DIR)
- obj-$(CONFIG_DRIVERS_HDF) += $(HCS_OBJ)
查看結(jié)果
編譯完成后,可以上傳內(nèi)核鏡像到開(kāi)發(fā)板,來(lái)查看HDF驅(qū)動(dòng)框架是否啟動(dòng)成功。
加入HDF前:
- # ls dev/
- __parameters__ hwrng tty1 tty28 tty46 tty7
- __trigger__ input tty10 tty29 tty47 tty8
- autofs kmsg tty11 tty3 tty48 tty9
- binder linux,cma tty12 tty30 tty49 ttyAMA0
- block loop-control tty13 tty31 tty5 ttyS0
- bus mem tty14 tty32 tty50 ttyprintk
- cachefiles memcg tty15 tty33 tty51 unix
- char null tty16 tty34 tty52 urandom
- console port tty17 tty35 tty53 vchiq
- cpuctl ptmx tty18 tty36 tty54 vcs
- cpuset pts tty19 tty37 tty55 vcs1
- dri random tty2 tty38 tty56 vcsa
- fd rawctl tty20 tty39 tty57 vcsa1
- freezer snd tty21 tty4 tty58 vcsu
- fscklogs stderr tty22 tty40 tty59 vcsu1
- full stdin tty23 tty41 tty6 vga_arbiter
- gpiochip0 stdout tty24 tty42 tty60 vndbinder
- gpiochip1 system tty25 tty43 tty61 watchdog
- graphics tty tty26 tty44 tty62 watchdog0
- hwbinder tty0 tty27 tty45 tty63 zero
加入HDF后:
- # ls dev/
- HDF_PLATFORM_I2C_MANAGER loop-control tty24 tty54
- HDF_PLATFORM_UART_1 mem tty25 tty55
- HDF_TEST memcg tty26 tty56
- I2C_TEST null tty27 tty57
- __parameters__ port tty28 tty58
- __trigger__ ptmx tty29 tty59
- autofs pts tty3 tty6
- binder random tty30 tty60
- block rawctl tty31 tty61
- bus sample_service tty32 tty62
- cachefiles snd tty33 tty63
- char stderr tty34 tty7
- console stdin tty35 tty8
- cpuctl stdout tty36 tty9
- cpuset system tty37 ttyAMA0
- dev_mgr tty tty38 ttyS0
- dri tty0 tty39 ttyprintk
- fd tty1 tty4 unix
- freezer tty10 tty40 urandom
- fscklogs tty11 tty41 vchiq
- full tty12 tty42 vcs
- gpiochip0 tty13 tty43 vcs1
- gpiochip1 tty14 tty44 vcsa
- graphics tty15 tty45 vcsa1
- hdf_bl tty16 tty46 vcsu
- hdf_input_host tty17 tty47 vcsu1
- hdf_misc_vibrator tty18 tty48 vga_arbiter
- hdf_sensor_manager_ap tty19 tty49 vndbinder
- hwbinder tty2 tty5 watchdog
- hwrng tty20 tty50 watchdog0
- input tty21 tty51 zero
- kmsg tty22 tty52
- linux,cma tty23 tty53
基本算是啟動(dòng)成功了,接下來(lái)考慮打算用HDF的方式添加一下設(shè)備。來(lái)驗(yàn)證HDF驅(qū)動(dòng)框架是否運(yùn)轉(zhuǎn)正常。
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)