从零开始学习 sg200x 多核开发之 sophpi 编译生成 fip.bin 流程梳理
本文主要介绍 sophpi 编译生成 fip.bin 流程。
1、编译前准备
sophpi 的基本编译流程如下:
$ source build/cvisetup.sh
$ defconfig sg2002_wevb_riscv64_sd
$ clean_all
$ build_all
$ pack_burn_image
注:
- 需要在 bash 下运行
- clean_all 非必要可以不执行。
生成的固件位置: install/soc_sg2002_wevb_riscv64_sd/milkv-duo.img
。build_milkv.sh 也是一步一步调用这些函数。
build/cvisetup.sh
通过软链接,链接到 build/envsetup_soc.sh
,相关的编译命令都在这个文件中。
在 build/envsetup_soc.sh
文件中,定义了一些后续编译会用到的变量,如:
- TOP_DIR=$(gettop)
- BUILD_PATH=“$TOP_DIR/build”
2、编译入口
总的编译命令,可以不调用 clean_all
函数,不然每次都要全编译。
function clean_all()
{clean_ubootclean_opensbiclean_rtos[[ "$ATF_SRC" == y ]] && clean_atfclean_kernelclean_ramdiskclean_3rd_partyif [ "$TPU_REL" = 1 ]; thenclean_ive_sdkclean_ivs_sdkclean_tpu_sdkclean_tdl_sdkclean_cnv_sdkficlean_middlewareclean_osdrv
}
重点看一下 build_all
函数,位于 build/envsetup_soc.sh
文件中
function build_all()
{(build_uboot || return $?build_kernel || return $?build_ramboot || return $?build_osdrv || return $?build_3rd_party || return $?build_middleware || return $?if [ "$TPU_REL" = 1 ]; thenbuild_tpu_sdk || return $?build_ive_sdk || return $?build_ivs_sdk || return $?build_tdl_sdk || return $?fipack_cfg || return $?pack_rootfs || return $?pack_data || return $?pack_system || return $?copy_tools || return $?pack_upgrade || return $?
)}
根据上面函数,先调用 build_uboot
函数。
3、uboot编译
build_uboot
函数在 build/milkvsetup.sh 文件中定义
function build_uboot()
{(print_notice "Run ${FUNCNAME[0]}() function"_build_uboot_env_build_opensbi_env_link_uboot_logocd "$BUILD_PATH" || returnmake u-boot || return "$?"
)}
- 查看 build/Makefile 文件中 203 行 u-boot 依赖 u-boot-dep
u-boot: u-boot-dep
继续找 u-boot-dep 。。。(文件真多啊。。。)
根据 build/.config 中定义了 CONFIG_FIP_V2=y
找到 build/Makefile
文件
ifeq (${CONFIG_FIP_V1},y)
include scripts/fip_v1.mk
else ifeq (${CONFIG_FIP_V2},y)
include scripts/fip_v2.mk
else
$(error no fip version)
endif
flp_v2.mk
u-boot-dep: fsbl-build ${OUTPUT_DIR}/elf$(call print_target)
ifeq ($(call qstrip,${CONFIG_ARCH}),riscv)${Q}cp ${OPENSBI_PATH}/build/platform/generic/firmware/fw_payload.bin ${OUTPUT_DIR}/fw_payload_uboot.bin${Q}cp ${OPENSBI_PATH}/build/platform/generic/firmware/fw_payload.elf ${OUTPUT_DIR}/elf/fw_payload_uboot.elf
endif
- u-boot-dep 又依赖 fsbl-build
fsbl-build 定义在 scripts/fip_v2.mk 文件
ifeq ($(call qstrip,${CONFIG_ARCH}),riscv)
fsbl-build: opensbi
endif
ifeq (${CONFIG_ENABLE_FREERTOS},y)
fsbl-build: rtos
fsbl%: export BLCP_2ND_PATH=${FREERTOS_PATH}/cvitek/install/bin/cvirtos.bin
fsbl%: export RTOS_DUMP_PRINT_ENABLE=$(CONFIG_ENABLE_RTOS_DUMP_PRINT)
fsbl%: export RTOS_DUMP_PRINT_SZ_IDX=$(CONFIG_DUMP_PRINT_SZ_IDX)
fsbl%: export RTOS_FAST_IMAGE_TYPE=${CONFIG_FAST_IMAGE_TYPE}
fsbl%: export RTOS_ENABLE_FREERTOS=${CONFIG_ENABLE_FREERTOS}
endif
fsbl%: export FSBL_SECURE_BOOT_SUPPORT=${CONFIG_FSBL_SECURE_BOOT_SUPPORT}
fsbl%: export ARCH=$(call qstrip,${CONFIG_ARCH})
fsbl%: export OD_CLK_SEL=${CONFIG_OD_CLK_SEL}
fsbl%: export VC_CLK_OVERDRIVE=${CONFIG_VC_CLK_OVERDRIVE}
fsbl%: export SUSPEND=${CONFIG_SUSPEND}
fsbl%: export TPU_PERF_MODE=$(shell if [ "${CONFIG_CHIP_cv1812cp}" = "y" ] || [ "${CONFIG_CHIP_sg2002}" = "y" ] || [ "${CONFIG_CHIP_cv1812cpa}" = "y" ]; then echo "y";else echo "n";fi)
fsbl%: export BUILD_BOOT0=${CONFIG_ENABLE_BOOT0}
fsbl%: export BUILD_FASTBOOT0=${CONFIG_ENABLE_FASTBOOT0}
fsbl%: export STORAGE=${STORAGE_TYPE}ifeq (${CONFIG_ENABLE_BOOT0},y)
fsbl-build: u-boot-build memory-map$(call print_target)${Q}mkdir -p ${FSBL_PATH}/build${Q}ln -snrf -t ${FSBL_PATH}/build ${CVI_BOARD_MEMMAP_H_PATH}${Q}$(MAKE) -j${NPROC} -C ${FSBL_PATH} O=${FSBL_OUTPUT_PATH}${Q}cp ${FSBL_OUTPUT_PATH}/boot0 ${OUTPUT_DIR}/
else
fsbl-build: u-boot-build memory-map$(call print_target)${Q}mkdir -p ${FSBL_PATH}/build${Q}ln -snrf -t ${FSBL_PATH}/build ${CVI_BOARD_MEMMAP_H_PATH}${Q}$(MAKE) -j${NPROC} -C ${FSBL_PATH} O=${FSBL_OUTPUT_PATH} BLCP_2ND_PATH=${BLCP_2ND_PATH} \LOADER_2ND_PATH=${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/u-boot-raw.bin${Q}cp ${FSBL_OUTPUT_PATH}/fip.bin ${OUTPUT_DIR}/
ifeq (${CONFIG_UBOOT_SPL_CUSTOM},y)${Q}$(MAKE) -C ${FSBL_PATH} clean O=${FSBL_OUTPUT_PATH}${Q}$(MAKE) -j${NPROC} -C ${FSBL_PATH} O=${FSBL_OUTPUT_PATH} BLCP_2ND_PATH=${BLCP_2ND_PATH} \CONFIG_SKIP_UBOOT=$(CONFIG_SKIP_UBOOT) LOADER_2ND_PATH=${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/spl/u-boot-spl-raw.bin${Q}cp ${FSBL_OUTPUT_PATH}/fip.bin ${OUTPUT_DIR}/fip_spl.bin
else${Q}cp ${FSBL_OUTPUT_PATH}/fip.bin ${OUTPUT_DIR}/fip_spl.bin
endif
endif
又依赖 opensbi
opensbi: export CROSS_COMPILE=$(CONFIG_CROSS_COMPILE_SDK)
opensbi: u-boot-build$(call print_target)${Q}$(MAKE) -j${NPROC} -C ${OPENSBI_PATH} PLATFORM=generic \FW_PAYLOAD_PATH=${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/u-boot-raw.bin \FW_FDT_PATH=${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/arch/riscv/dts/${CHIP}_${BOARD}.dtb
又依赖 u-boot-build, build/Makefile中定义了 u-boot-build,所以会先执行 u-boot-build
u-boot-build: memory-map
u-boot-build: u-boot-dts
u-boot-build: ${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER} ${UBOOT_CVIPART_DEP} ${UBOOT_OUTPUT_CONFIG_PATH}$(call print_target)${Q}ln -snrf ${CVI_BOARD_MEMMAP_H_PATH} ${UBOOT_PATH}/include/${Q}rm -f ${UBOOT_CVI_BOARD_INIT_PATH}${Q}ln -s ${BUILD_PATH}/boards/${CHIP_ARCH_L}/${PROJECT_FULLNAME}/u-boot/cvi_board_init.c ${UBOOT_CVI_BOARD_INIT_PATH}${Q}rm -f ${UBOOT_CVITEK_PATH}${Q}ln -s ${BUILD_PATH}/boards/${CHIP_ARCH_L}/${PROJECT_FULLNAME}/u-boot/cvitek.h ${UBOOT_CVITEK_PATH}${Q}$(MAKE) -j${NPROC} -C ${UBOOT_PATH} olddefconfig${Q}$(MAKE) -j${NPROC} -C ${UBOOT_PATH} all${Q}cat ${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/u-boot.bin > ${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/u-boot-raw.bin
ifeq (${CONFIG_UBOOT_SPL_CUSTOM},y)${Q}cat ${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/spl/u-boot-spl.bin > ${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/spl/u-boot-spl-raw.bin
endif
依赖 memory-map, build/scripts/mmap.mk 中定义了 memory-map
.PHONY: memory-mapCVI_BOARD_MEMMAP_H_PATH := ${BUILD_PATH}/output/${PROJECT_FULLNAME}/cvi_board_memmap.h
CVI_BOARD_MEMMAP_CONF_PATH := ${BUILD_PATH}/output/${PROJECT_FULLNAME}/cvi_board_memmap.conf
CVI_BOARD_MEMMAP_LD_PATH:= ${BUILD_PATH}/output/${PROJECT_FULLNAME}/cvi_board_memmap.ldBOARD_MMAP_PATH := ${BORAD_FOLDER_PATH}/memmap.py
MMAP_CONV_PY := ${BUILD_PATH}/scripts/mmap_conv.py${CVI_BOARD_MEMMAP_H_PATH}: ${BOARD_MMAP_PATH} ${MMAP_CONV_PY}$(call print_target)mkdir -p $(dir $@)@${MMAP_CONV_PY} --type h $< $@${CVI_BOARD_MEMMAP_CONF_PATH}: ${BOARD_MMAP_PATH} ${MMAP_CONV_PY}$(call print_target)@mkdir -p $(dir $@)@${MMAP_CONV_PY} --type conf $< $@${CVI_BOARD_MEMMAP_LD_PATH}: ${BOARD_MMAP_PATH} ${MMAP_CONV_PY}$(call print_target)@mkdir -p $(dir $@)@${MMAP_CONV_PY} --type ld $< $@ifeq ($(wildcard ${BOARD_MMAP_PATH}),)
memory-map:
else
memory-map: ${CVI_BOARD_MEMMAP_H_PATH} ${CVI_BOARD_MEMMAP_CONF_PATH} ${CVI_BOARD_MEMMAP_LD_PATH}
endif
该脚本会自动生成 cvi_board_memmap.h
, cvi_board_memmap.conf
, cvi_board_memmap.ld
三个文件。
然后依赖 u-boot-dts
u-boot-dts:$(call print_target)
ifeq ($(UBOOT_SRC), u-boot-2021.10)
# U-boot doesn't has arch/arm64
ifeq ($(ARCH), arm64)${Q}find ${BUILD_PATH}/boards/${CHIP_ARCH_L} \\( -path "*linux/*.dts*" -o -path "*dts_${ARCH}/*.dts*" \) \-exec cp {} ${UBOOT_PATH}/arch/arm/dts/ \;${Q}find ${DTS_DEFATUL_PATHS} -name *.dts* -exec cp {} ${UBOOT_PATH}/arch/arm/dts/ \;
else${Q}find ${BUILD_PATH}/boards/${CHIP_ARCH_L} \\( -path "*linux/*.dts*" -o -path "*dts_${ARCH}/*.dts*" \) \-exec cp {} ${UBOOT_PATH}/arch/${ARCH}/dts/ \;${Q}find ${DTS_DEFATUL_PATHS} -name *.dts* -exec cp {} ${UBOOT_PATH}/arch/${ARCH}/dts/ \;
endif
endif
最终执行的命令为:
find sophpi/build/boards/cv181x \\( -path "*linux/*.dts*" -o -path "*dts_riscv/*.dts*" \) \-exec cp {} sophpi/u-boot-2021.10/arch/riscv/dts/ \;
find sophpi/build/boards/default/dts/cv181x sophpi/build/boards/default/dts/cv181x_riscv -name *.dts* -exec cp {} sophpi/u-boot-2021.10/arch/riscv/dts/ \;
在 sophpi/u-boot-2021.10/arch/riscv/dts
目录下执行 tree
命令,查看相关设备树文件。我们理论上用的是 sg2002 相关的 sg2002_wevb_riscv64_sd.dts
这个文件。
$ tree
.
├── ae350_32.dts
├── ae350_64.dts
├── ae350-u-boot.dtsi
├── binman.dtsi
├── cv1810c_wdmb_0006a_spinor.dts
├── cv1810c_wevb_0006a_spinand.dts
├── cv1810c_wevb_0006a_spinor.dts
├── cv1810h_wevb_0007a_spinor.dts
├── cv1811c_wdmb_0006a_spinor.dts
├── cv1811c_wevb_0006a_emmc.dts
├── cv1811c_wevb_0006a_spinand.dts
├── cv1811c_wevb_0006a_spinor.dts
├── cv1811h_wevb_0007a_emmc.dts
├── cv1811h_wevb_0007a_spinand.dts
├── cv1811h_wevb_0007a_spinor.dts
├── cv1812cp_sophpi_duo_sd.dts
├── cv1812cp_wevb_0006a_emmc.dts
├── cv1812cp_wevb_0006a_spinand.dts
├── cv1812cp_wevb_0006a_spinor.dts
├── cv1812h_wevb_0007a_emmc.dts
├── cv1812h_wevb_0007a_emmc_huashan.dts
├── cv1812h_wevb_0007a_spinand.dts
├── cv1812h_wevb_0007a_spinand_huashan.dts
├── cv1812h_wevb_0007a_spinor.dts
├── cv1812h_wevb_0007a_spinor_huashan.dts
├── cv1813h_wevb_0007a_emmc.dts
├── cv1813h_wevb_0007a_spinand.dts
├── cv1813h_wevb_0007a_spinor.dts
├── cv181x_asic_bga.dtsi
├── cv181x_asic_emmc.dtsi
├── cv181x_asic_qfn.dtsi
├── cv181x_asic_sd.dtsi
├── cv181x_asic_spinand.dtsi
├── cv181x_asic_spinor.dtsi
├── cv181x_base.dtsi
├── cv181x_base_riscv.dtsi
├── cv181x_default_memmap.dtsi
├── fu540-c000.dtsi
├── fu540-c000-u-boot.dtsi
├── fu540-hifive-unleashed-a00-ddr.dtsi
├── fu740-c000.dtsi
├── fu740-c000-u-boot.dtsi
├── fu740-hifive-unmatched-a00-ddr.dtsi
├── hifive-unleashed-a00.dts
├── hifive-unleashed-a00-u-boot.dtsi
├── hifive-unmatched-a00.dts
├── hifive-unmatched-a00-u-boot.dtsi
├── k210.dtsi
├── k210-maix-bit.dts
├── Makefile
├── microchip-mpfs-icicle-kit.dts
├── microchip-mpfs-icicle-kit-u-boot.dtsi
├── openpiton-riscv64.dts
├── qemu-virt.dts
├── sg2000_wevb_riscv64_sd.dts
└── sg2002_wevb_riscv64_sd.dts
- 执行到这里,才真正开始编译 u-boot,主要是以下几行命令
${Q}$(MAKE) -j${NPROC} -C ${UBOOT_PATH} olddefconfig${Q}$(MAKE) -j${NPROC} -C ${UBOOT_PATH} all${Q}cat ${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/u-boot.bin > ${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/u-boot-raw.bin
最终产物在 sophpi/u-boot-2021.10/build/sg2002_wevb_riscv64_sd/u-boot-raw.bin
4、opensbi 编译
有了 u-boot 之后,开始编译 opensbi
为了兼容不同的运行需求,OpenSBI 支持三种类型的 Firmware,分别为:
- dynamic:从上一级 Boot Stage 获取下一级 Boot Stage 的入口信息,以 struct fw_dynamic_info 结构体通过 a2 寄存器传递。
- jump:假设下一级 Boot Stage Entry 为固定地址,直接跳转过去运行。
- payload:在 jump 的基础上,直接打包进来下一级 Boot Stage 的 Binary。下一级通常是 Bootloader 或 OS,比如 U-Boot,Linux。
相关编译脚本位置: build/scripts/fip_v2.mk
opensbi: export CROSS_COMPILE=$(CONFIG_CROSS_COMPILE_SDK)
opensbi: u-boot-build$(call print_target)${Q}$(MAKE) -j${NPROC} -C ${OPENSBI_PATH} PLATFORM=generic \FW_PAYLOAD_PATH=${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/u-boot-raw.bin \FW_FDT_PATH=${UBOOT_PATH}/${UBOOT_OUTPUT_FOLDER}/arch/riscv/dts/${CHIP}_${BOARD}.dtb
根据以上脚本获知,sophpi 上采用的是 payload 模式,payload 文件为 u-boot-raw.bin,就是上面我们编译出来的文件。
FW_FDT_PATH 为设备树路径,为 sophpi/u-boot-2021.10/build/sg2002_wevb_riscv64_sd/arch/riscv/dts/sg2002_wevb_riscv64_sd.dtb
编译完成后, 产物在 sophpi/opensbi/build/platform/generic/firmware
目录下。
5、fsbl编译
编译完了u-boot 和 opensbi,继续往回推,来到了 fsbl-build。(中间还有一个 rtos 编译,暂时略过先)。
FSBL 是 First Stage Boot Loader 的缩写。
fsbl-build: u-boot-build memory-map$(call print_target)${Q}mkdir -p ${FSBL_PATH}/build${Q}ln -snrf -t ${FSBL_PATH}/build ${CVI_BOARD_MEMMAP_H_PATH}${Q}$(MAKE) -j${NPROC} -C ${FSBL_PATH} O=${FSBL_OUTPUT_PATH}${Q}cp ${FSBL_OUTPUT_PATH}/boot0 ${OUTPUT_DIR}/
最终执行的编译命令为 :
make -j8 -C sophpi/fsbl O=sophpi/fsbl/build/sg2002_wevb_riscv64_sd BLCP_2ND_PATH=sophpi/freertos/cvitek/install/bin/cvirtos.bin \LOADER_2ND_PATH=sophpi/u-boot-2021.10/build/sg2002_wevb_riscv64_sd/u-boot-raw.bin
主要来看看 fsbl 编译流程,从 fsbl/Makefile 文件开始
all: fip bl2 blmacrosinclude ${MAKE_HELPERS_DIRECTORY}fip.mk
依次找到 fip 在 fsbl/make_helpers/fip.mk 文件
gen-chip-conf:$(print_target)${Q}mkdir -p '${BUILD_PLAT}'${Q}./plat/${CHIP_ARCH}/chip_conf.py ${CHIP_CONF_PATH}macro_to_env = ${NM} '${BLMACROS_ELF}' | awk '/DEF_${1}/ { rc = 1; print "${1}=0x" $$1 } END { exit !rc }' >> ${BUILD_PLAT}/blmacros.envblmacros-env: blmacros$(print_target)${Q}> ${BUILD_PLAT}/blmacros.env # clear .env first${Q}$(call macro_to_env,MONITOR_RUNADDR)${Q}$(call macro_to_env,BLCP_2ND_RUNADDR)
ifeq (${BUILD_BOOT0},y)
$(eval $(call add_define,ENABLE_BOOT0))
fip: fip_boot0
else
fip: fip-all
endiffip-dep: bl2 blmacros-env gen-chip-conffip_boot0: fip-dep$(print_target)${Q}echo " [GEN] boot0"${Q}. ${BUILD_PLAT}/blmacros.env && \${FIPTOOL} -v genfip \'${BUILD_PLAT}/boot0' \--MONITOR_RUNADDR="$${MONITOR_RUNADDR}" \--BLCP_2ND_RUNADDR="$${BLCP_2ND_RUNADDR}" \--CHIP_CONF='${CHIP_CONF_PATH}' \--NOR_INFO='${NOR_INFO}' \--NAND_INFO='${NAND_INFO}'\--BL2='${BUILD_PLAT}/bl2.bin' \--BLCP_IMG_RUNADDR=${BLCP_IMG_RUNADDR} \--BLCP_PARAM_LOADADDR=${BLCP_PARAM_LOADADDR} \--BLCP=${BLCP_PATH} \--DDR_PARAM='${DDR_PARAM_TEST_PATH}'${Q}echo " [LS] " $$(ls -l '${BUILD_PLAT}/boot0')${Q}cp ${BUILD_PLAT}/boot0 ${OUTPUT_DIR}fip-simple: fip-dep$(print_target)${Q}echo " [GEN] fip.bin"${Q}${FIPTOOL} -v genfip \'${BUILD_PLAT}/fip.bin' \--CHIP_CONF='${CHIP_CONF_PATH}' \--NOR_INFO='${NOR_INFO}' \--NAND_INFO='${NAND_INFO}'\--BL2='${BUILD_PLAT}/bl2.bin'${Q}echo " [LS] " $$(ls -l '${BUILD_PLAT}/fip.bin')
通过一堆复杂的操作。。。生成了一个 bl2.bin 文件。(正常情况下我们开发者也不会去修改这个玩意。。。)
主要关心 fip-all 这个操作,用于生成 fip.bin 文件。
6、fip.bin文件合成
查阅官方有限的资料,获知 fip.bin 为内含 bootloader+uboot 的文件
为啥要这么干?官方的文档里面是这么说的:
由于原生 u-boot 编译出 u-boot.bin 无法直接刻录到 FLASH 中。我们采取 ARM Trusted Firmware Design 中的 Firmware Image Package (FIP) 方式,将 uboot.bin 封装在 FIP.bin 里面。
https://doc.sophgo.com/cvitek-develop-docs/master/docs_latest_release/CV180x_CV181x/zh/01.software/BSP/U-boot_Porting_Development_Guide/build/html/3_U-boot_Transplant.html
通过 chatgpt 查询 fip 后得知:
FIP(Flexible Image Processor)文件是指存储在ARM架构的处理器设备上的固件映像文件。它主要用于引导和配置设备。FIP文件通常包含以下内容:
- Trusted Firmware-A(TF-A):TF-A 是 ARM 架构设备上的一个开源的可信固件。它负责设备的引导、安全检查和启动加载程序的执行。
- U-Boot:U-Boot 是一个开源的引导加载程序(bootloader),用于启动设备。它提供了引导设备的功能,并提供了配置和管理设备硬件的选项。
- ARM Trusted Firmware(ATF):ATF 是一组用于安全引导的固件,用于验证和启动设备上的其他软件组件(如操作系统)。
- 其他组件:FIP 文件还可以包含其他固件组件,如设备树(Device Tree)文件、TEE 固件(如 OP-TEE)、加密密钥和配置参数等。
FIP 文件在 ARM 架构设备上很常见,它们提供了引导和初始化处理器的必要组件。这些文件由设备制造商提供,并根据特定设备、硬件配置和需求进行定制。
按照前面的分析,fip.bin 在 fsbl 最后阶段合成
fip-all: fip-dep$(print_target)${Q}echo " [GEN] fip.bin"${Q}. ${BUILD_PLAT}/blmacros.env && \${FIPTOOL} -v genfip \'${BUILD_PLAT}/fip.bin' \--MONITOR_RUNADDR="$${MONITOR_RUNADDR}" \--BLCP_2ND_RUNADDR="$${BLCP_2ND_RUNADDR}" \--CHIP_CONF='${CHIP_CONF_PATH}' \--NOR_INFO='${NOR_INFO}' \--NAND_INFO='${NAND_INFO}'\--BL2='${BUILD_PLAT}/bl2.bin' \--BLCP_IMG_RUNADDR=${BLCP_IMG_RUNADDR} \--BLCP_PARAM_LOADADDR=${BLCP_PARAM_LOADADDR} \--BLCP=${BLCP_PATH} \--DDR_PARAM='${DDR_PARAM_TEST_PATH}' \--BLCP_2ND='${BLCP_2ND_PATH}' \--MONITOR='${MONITOR_PATH}' \--LOADER_2ND='${LOADER_2ND_PATH}' \--compress='${FIP_COMPRESS}'${Q}echo " [LS] " $$(ls -l '${BUILD_PLAT}/fip.bin')
转换成实际执行命令为:
. sophpi/fsbl/build/sg2002_wevb_riscv64_sd/blmacros.env && \
./plat/cv180x/fiptool.py -v genfip \'sophpi/fsbl/build/sg2002_wevb_riscv64_sd/fip.bin' \--MONITOR_RUNADDR="${MONITOR_RUNADDR}" \--BLCP_2ND_RUNADDR="${BLCP_2ND_RUNADDR}" \--CHIP_CONF='sophpi/fsbl/build/sg2002_wevb_riscv64_sd/chip_conf.bin' \--NOR_INFO='FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' \--NAND_INFO='00000000'\--BL2='sophpi/fsbl/build/sg2002_wevb_riscv64_sd/bl2.bin' \--BLCP_IMG_RUNADDR=0x05200200 \--BLCP_PARAM_LOADADDR=0 \--BLCP=test/empty.bin \--DDR_PARAM='test/cv181x/ddr_param.bin' \--BLCP_2ND='sophpi/freertos/cvitek/install/bin/cvirtos.bin' \--MONITOR='../opensbi/build/platform/generic/firmware/fw_dynamic.bin' \--LOADER_2ND='sophpi/u-boot-2021.10/build/sg2002_wevb_riscv64_sd/u-boot-raw.bin' \--compress='lzma'
相关文章:
从零开始学习 sg200x 多核开发之 sophpi 编译生成 fip.bin 流程梳理
本文主要介绍 sophpi 编译生成 fip.bin 流程。 1、编译前准备 sophpi 的基本编译流程如下: $ source build/cvisetup.sh $ defconfig sg2002_wevb_riscv64_sd $ clean_all $ build_all $ pack_burn_image注: 需要在 bash 下运行clean_all 非必要可以不…...

python--在服务器上面创建conda环境
今天刚开始使用服务器的时候使用上面的公共环境发现老师缺少模块, [guoyupingcins195 ~]$ conda --version Traceback (most recent call last): File "/home/miniconda3/bin/conda", line 12, in <module> from conda.cli import main Fil…...

day15 python(3)——python基础(完结!!)
【没有所谓的运气🍬,只有绝对的努力✊】 目录 1、函数 1.1 函数传参中的拆包 1.2 匿名函数的定义 1.3 匿名函数练习 1.4 匿名函数应用——列表中的字典排序 2、面向对象 OOP 2.1 面向对象介绍 2.2 类和对象 2.3 类的构成和设计 2.4 面向对象代码…...
/:087启动游戏时提示丢失”d3dx···.dll””VCOMP···.dll”
/:087启动游戏时提示丢失”d3dx.dll””VCOMP.dll”或遇到应用程序无法正常启动(0xc000007b)和游戏有图像没有声音等情况。 主要是因为系统缺少大型游戏/软件运行的必备组件,这些组件有DirectX,Visual C2010,2012&…...
利用PHP和phpSpider进行图片爬取及下载
利用PHP和phpSpider进行图片爬取及下载,可以遵循以下步骤。phpSpider是一个开源的PHP爬虫框架,它可以帮助你轻松地抓取网页内容。以下是一个基本的步骤指南: 1. 安装phpSpider 首先,你需要确保你已经安装了Composer(…...
企业架构划分探讨:业务架构与IT架构的利与弊
在企业架构(EA)的江湖里,大家一直致力于如何把企业的复杂性简化成有条有理的架构蓝图。有人选择把企业架构分成业务架构和IT架构,而IT架构又进一步细分为应用架构、数据架构和技术架构。但一提到这种划分方式,总有人跳…...

Java设计模式 —— 【结构型模式】桥接模式详解
前言 现在有一个需求,需要创建不同的图形,并且每个图形都有可能会有不同的颜色。 首先我们看看用继承来实现: 我们可以发现有很多的类,假如我们再增加一个形状或再增加一种颜色,就需要创建更多的类。 试想…...

MySQL学习之DDL操作
目录 数据库的操作 创建 查看 选择 删除 修改 数据类型 表的创建 表的修改 表的约束 主键 PRIMARY KEY 唯一性约束 UNIQUE 非空约束 NOT NULL 外键约束 约束小结 索引 索引分类 常规索引 主键索引 唯一索引 外键索引 优点 缺点 视图 创建 删除 修改…...

游戏AI实现-寻路算法(A*)
A*(A-star)是一种图遍历和寻路算法,由于其完整性、最优性和最佳效率,它被用于计算机科学的许多领域。给定一个加权图、一个源节点和一个目标节点,该算法将找到从源到目标的最短路径(相对于给定的权重&#…...

spring学习(spring的IoC思想、spring容器、spring配置文件、依赖注入(DI)、BeanProxy机制(AOP))
目录 一、spring-IoC。 (1)spring框架。(诞生原因及核心思想) 1、为什么叫框架? 2、spring框架诞生的技术背景。 (2)控制反转(IoC)。 (3)spring的Bean工厂和IoC容器。 &a…...

谁说C比C++快?
看到这个问题,我我得说:这事儿没有那么简单。 1. 先把最大的误区打破 "C永远比C快" —— 某位1990年代的程序员 这种说法就像"自行车永远比汽车省油"一样荒谬。我们来看个例子: // C风格 char* str (char*)malloc(100…...

GEE+本地XGboot分类
GEE本地XGboot分类 我想做提取耕地提取,想到了一篇董金玮老师的一篇论文,这个论文是先提取的耕地,再做作物分类,耕地的提取代码是开源的。 但这个代码直接在云端上进行分类,GEE会爆内存,因此我准备把数据下…...
OpenCV相机标定与3D重建(24)计算两个二维点集之间的最佳仿射变换矩阵(2x3)函数estimateAffine2D()的使用
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 计算两个二维点集之间的最优仿射变换,它计算 [ x y ] [ a 11 a 12 a 21 a 22 ] [ X Y ] [ b 1 b 2 ] \begin{bmatrix} x\\ y\\ \en…...
UIP协议栈 TCP通信客户端 服务端,UDP单播 广播通信 example
文章目录 1. TCP通信 客户端(关键配置)2. TCP 服务端配置3. UDP 点播通信4. UDP 广播通信5. UIP_UDP_APPCALL 里边的处理example6. TCP数据处理 ,UIP_APPCALL调用的函数 UIP_APPCALL TCP的数据都在这个宏定义的函数里进行数据处理的 UDP 数据…...
【NoSQL系列】为什么要使用Redis?
第一次知道Redis是以前准备面试的时候,只知道是用来缓存数据的。随着这几年的工作,对软件的认识从盲人摸象到睁眼看世界。 在常用的软件架构评价模型中,性能、可用性、安全性和可维护性是常见的评价属性,客户总希望系统响应又快有…...

MySQL Explain 分析SQL语句性能
一、EXPLAIN简介 使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈。 (1) 通过EXPLAIN,我们可以分析出以下结果: 表的读取顺序数据读取…...

IIS部署程序https是访问出现403或ERR_HTTP2_PROTOCOL_ERROR
一、说明 在windows server 2016中的IIS程序池里部署一套系统,通过https访问站点,同时考虑到安全问题以及防攻击等行为,就用上了WAF云盾功能,能有效的抵挡部分攻击,加强网站的安全性和健壮性。 应用系统一直能够正常…...

学技术学英文:代码中的锁:悲观锁和乐观锁
本文导读: 1. 举例说明加锁的场景: 多线程并发情况下有资源竞争的时候,如果不加锁,会出现数据错误,举例说明: 业务需求:账户余额>取款金额,才能取钱。 时间线 两人共有账户 …...
青少年编程与数学 02-004 Go语言Web编程 02课题、依赖管理
青少年编程与数学 02-004 Go语言Web编程 02课题、依赖管理 课题摘要:一、项目结构各目录说明: 二、依赖项三、依赖管理任务四、依赖管理步骤1. 初始化Go Modules项目2. 添加依赖3. 指定依赖版本4. 更新依赖5. 清理未使用的依赖6. 离线工作7. 模块隔离8. 可重现构建 …...
MyBatis写法汇总
Mybatis写法汇总 1. 批量操作 1.1 批量插入 <insert id"batchInsert" parameterType"java.util.List">INSERT INTO user (username, password, create_time) VALUES<foreach collection"list" item"item" separator"…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...

【开发技术】.Net使用FFmpeg视频特定帧上绘制内容
目录 一、目的 二、解决方案 2.1 什么是FFmpeg 2.2 FFmpeg主要功能 2.3 使用Xabe.FFmpeg调用FFmpeg功能 2.4 使用 FFmpeg 的 drawbox 滤镜来绘制 ROI 三、总结 一、目的 当前市场上有很多目标检测智能识别的相关算法,当前调用一个医疗行业的AI识别算法后返回…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...

视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...