TDA4VM 8.4 RTOS SDK 中 SBL 的编译流程解析与makefile 分析笔记

0. TDA4VM 8.4 RTOS SDK 中 SBL 的编译流程解析

当我们在PDK_INSTALL_DIR/packages/ti/build目录下执行下述命令,可以编译 ospi sbl:

make -j BOARD=j721e_evm CORE=mcu1_0 BUILD_PROFILE=release sbl_ospi_img

接下来我会以上述编译命令来详细讲述 SBL 编译过程,其他目标同样适用。
根据分析当前目录下的 makefile 文件,发现 sbl_ospi_img 依赖下面的规则编译:
在这里插入图片描述

除了生成 .xer5f 文件与生成 .tiimage 文件这步外,其余命令都未执行,上述图片中的命令可简化如下:

$(FINAL_PKG_LIST_ALL) $(FINAL_DUP_EXAMPLE_LIST):
	#编译生成 sbl_ospi_img_mcu1_0_release.xer5f 文件
	$(MAKE) -C $($@_PATH) $($@_MAKEFILE)
	#由 sbl_ospi_img_mcu1_0_release.xer5f 转换为 .bin 文件与 .tiimage 文件
	$(MAKE) -C $($@_PATH) $($@_MAKEFILE) sbl_imagegen

其中,$($@_MAKEFILE) 变量在 sbl_component.mk 文件中赋值,展开为-f$(PDK_SBL_COMP_PATH)/build/sbl_img.mk BOOTMODE=ospi SBL_USE_DMA=yes BUILD_HS=no , 如下图所示:
在这里插入图片描述

所以,.xer5f 可执行文件的生成,是通过 sbl_img.mk 文件生成的。

TI SDK 的可执行文件后缀名是 .xer5f 的原因

$(MAKERULEDIR)/platform.mk 文件中,定义了生成的目标文件,静态库文件,可执行文件,反汇编文件的通用后缀名,如下:
在这里插入图片描述

sbl_ospi_img 的 .xer5f 可执行文件的生成过程

根据上述知识,我们需要执行 sbl_img.mk 来生成 .xer5f 文件。
分析 sbl_img.mk, 发现 sbl_img.mk 包含了 $(MAKERULEDIR)/common.mk 来包含编译规则,如下:
在这里插入图片描述

而在 $(MAKERULEDIR)/common.mk 文件中,第一条规则(默认规则)如下:
在这里插入图片描述

(.xerf 文件就是通过默认规则实现的,别急,往下看)
我们发现默认规则 all 的依赖是 $(CORE)
那么继续,我们查找目标为 $(CORE) 的规则,同样在 $(MAKERULEDIR)/common.mk 存在如下规则:
在这里插入图片描述

(叮咚叮咚~,恭喜你,发现编译生成 .xer5f 文件的最终规则)
对规则的说明如下:

# Create dependencies list to ultimately create application executable binary
$(CORE) : $(OBJDIR) $(BINDIR) $(DEPDIR) $(CONFIGURO_DIR)
ifneq ($(words $(PKG_LIST)), 0)
	#编译生成依赖的静态库,但好像什么都做不了,所有依赖的库名字都在 $(PKG_LIST) 变量中
	$(MAKE) $($(APP_NAME)_MAKEFILE) $(PKG_LIST)
endif
	#编译生成 .xer5f 可执行文件,这个过程会链接依赖的静态库
	$(MAKE) $($(APP_NAME)_MAKEFILE) $(EXE_NAME)
编译依赖的静态库

编译依赖的静态库命令:

	#编译生成依赖的静态库,但好像什么都做不了,所有依赖的库名字都在 $(PKG_LIST) 变量中(作为作业,自己分析)
	$(MAKE) $($(APP_NAME)_MAKEFILE) $(PKG_LIST)

(虽然 makefile 是这么写了,但是,经过实际测试,就算我改了库的源代码,好像不会重新编译库)
sbl_img.mk中,会对 APP_NAME 变量赋值,如下:
在这里插入图片描述

所以 $($(APP_NAME)_MAKEFILE) 变量展开依旧是 -f$(PDK_SBL_COMP_PATH)/build/sbl_img.mk BOOTMODE=ospi SBL_USE_DMA=yes BUILD_HS=no
即再次执行 sbl_img.mk,不过这一次会指定目标为$(PKG_LIST)
$(MAKERULEDIR)/common.mk 中, $(PKG_LIST) 编译规则如下:
在这里插入图片描述

变量 $@_MAKEFILE 即为具体模块对应的 makefile 文件,比如 board 模块对应的 makefile 文件如下:
在这里插入图片描述

即规则可以写作如下(已 board 模块为例):

board : 
$(MAKE) -C $(PDK_BOARD_COMP_PATH) -f build/makefile.mk

通过编译上述规则,可以编译 board 模块。
但是经过实际测试,我改了 board 模块源代码,好像并没有重新编译 board 模块???

编译可执行文件命令

编译可执行文件命令:

	#编译生成 .xer5f 可执行文件,这个过程会链接依赖的静态库
	$(MAKE) $($(APP_NAME)_MAKEFILE) $(EXE_NAME)

sbl_img.mk中,对 APP_NAME 变量赋值 sbl_ospi_image, 所以 $($(APP_NAME)_MAKEFILE) 变量展开依旧是 -f$(PDK_SBL_COMP_PATH)/build/sbl_img.mk BOOTMODE=ospi SBL_USE_DMA=yes BUILD_HS=no
而对于 $(EXE_NAME) 的值,该变量在 rules_ti_cgt_arm.mk 中赋值:
在这里插入图片描述

该文件会以如下方式被 $(MAKERULEDIR)/common.mk 文件包含:
在这里插入图片描述

所以,在最后的源文件生成二进制目标文件以及二进制目标文件链接生成可执行文件都是在rules_ti_cgt_arm.mk 文件中执行的。
.xer5f可执行文件生成的规则如下:
在这里插入图片描述

.oer5f 二进制目标文件生成的规则如下:

所以,编译生成可执行文件主要是通过 rules_ti_cgt_arm.mk 的规则实现的,但源文件以及依赖的库文件都需要在上层 mk 文件中赋值。
在这里插入图片描述

.xer5f 文件生成 .tiimage 文件

回顾开头,也许你有些忘记了,通过如下命令,我们还需要将 .xer5f转换为.tiimage文件,如下:
在这里插入图片描述
命令简化如下:

	#由 sbl_ospi_img_mcu1_0_release.xer5f 转换为 .bin 文件与 .tiimage 文件
	$(MAKE) -C $($@_PATH) $($@_MAKEFILE) sbl_imagegen

参考 sbl_component.mk 文件,将变量展开,这条命令如下:

$(MAKE) -C $(PDK_SBL_COMP_PATH)/board/k3 -f$(PDK_SBL_COMP_PATH)/build/sbl_img.mk BOOTMODE=ospi SBL_USE_DMA=yes BUILD_HS=no sbl_imagegen

即,对 sbl_img.mk 执行 make, 目标为 sbl_imagegen
查看 sbl_img.mk 文件,在它包含的 $(MAKERULEDIR)/common.mk 文件中,sbl_imagegen 目标对应的规则如下:
在这里插入图片描述

该规则依赖 $(SBL_IMAGE_PATH), 该依赖对应的一个新的规则,如下:
在这里插入图片描述

同样, $(SBL_IMAGE_PATH) 依赖 $(SBL_BIN_FILE),该依赖同样对应一个新的规则,如下:
在这里插入图片描述

.xer5f 文件转换为 .bin 文件后,回到 $(SBL_IMAGE_PATH) 目标中,执行下列步骤生成 .tiimage 文件:
在这里插入图片描述
至此,大功告成(*^_^*)。
恭喜你看到了这里,这就是 sbl_ospi_img 整个的编译流程,TI RTOS SDK 的其余目标基本也基此流程。
我们可以在 /ti/boot/sbl/binary/j721e_evm/ospi/bin目录下查看生成的文件。
在这里插入图片描述

( •̀ ω •́ )y,撒花撒花~

1. makefile 中,如果一个变量存在多个值,如何让变量的值换行输出

makefile 可以使用命令

FINAL_LIB_LIST = csl_init csl_intc csl csl_utils_common csl_uart_console board

print_test :
	@$(ECHO) lib = $(foreach LIB,$(FINAL_LIB_LIST),""; echo "$(LIB)")

该命令可以让变量的值换行输出,结果如下:

root@ftcd-010:/mnt/d/ADC30/ti-processor-sdk-rtos-j784s4-evm-08_02_02_02/pdk_j784s4_08_02_02_04/packages/ti/build# make -s print_test
lib =
csl_init
csl_intc
csl
csl_utils_common
csl_uart_console
board

2.如果想让上一个的命令作用到下一个命令中,那么两个命令需要写在同一行

makefile 文件如下:

dirtest0:
	@cd /proc
	@pwd
	
dirtest1:
	@cd /proc; @pwd

只有 dirtest1 会正常输出路径名为:/proc

3. make -C 选项可以重新指定当前工作目录

makefile 文件中 -C 选项使用方式如下:

$(MAKE) -C $($@_PATH) $($@_MAKEFILE)

4.makefile 中命令包的定义

查询资料,makefile 中命令包都以 define 开始,以 endef 结束。
命令包可以用来创建规则。
下面创建了一个 CREATE_DEP_TARGETS 的命令包:

# 定义 CREATE_DEP_TARGETS 宏包,用于创建 _has_dep 目标的编译规则,define 开始的语句是 makefile 的命令包
# 所以这个命令包是根据 (target)_DEPENDS_ON 变量来执行的
define CREATE_DEP_TARGETS
ifneq ($($(1)_DEPENDS_ON),)	# 判断 (target)_DEPENDS_ON 变量是否存在,存在则执行
ifeq ($($(1)_DEPENDS_ON),$(filter $($(1)_DEPENDS_ON), $($(2))))	# 判断 (target)_DEPENDS_ON 是否也是一个单独目标,是则创建下面的规则
$(1)_has_dep: $($(1)_DEPENDS_ON)_has_dep
	+$(MAKE) -f $(PDK_INSTALL_PATH)/ti/build/makefile $(1)

$(2)_DEP_LIST += $($(1)_DEPENDS_ON) # 将 (target)_DEPENDS_ON 变量加入 _DEP_LIST 列表
else
#依赖的不是一个单独的目标,即 (target)_DEPENDS_ON 不是一个单独的模块,无依赖
$(1)_has_dep:	
	+$(MAKE) -f $(PDK_INSTALL_PATH)/ti/build/makefile $(1)	
endif
else
# (target)_DEPENDS_ON 不存在
$(1)_has_dep:
	+$(MAKE) -f $(PDK_INSTALL_PATH)/ti/build/makefile $(1)
endif
endef

5. makefile 中 call 函数与 eval 函数以及命令包

下面这篇文章讲得非常好,请仔细阅读:
makefile 中 call 函数与 eval 函数的讲解

函数“eval”是一个比较特殊的函数。使用它可以在Makefile中构造一个可变的规则结构关系(依赖关系链),其中可以使用其它变量和函数

结合第 4 点,示例如下:

# 对于所有可编译的目标,根据 <module>_component.mk 创建目标的依赖规则
$(foreach LIB,$(FINAL_LIB_LIST),$(eval $(call CREATE_DEP_TARGETS,$(LIB),FINAL_LIB_LIST)))
$(foreach APP_LIB,$(FINAL_APP_LIB_LIST),$(eval $(call CREATE_DEP_TARGETS,$(APP_LIB),FINAL_APP_LIB_LIST)))
$(foreach EXAMPLE,$(FINAL_EXAMPLE_LIST),$(eval $(call CREATE_DEP_TARGETS,$(EXAMPLE),FINAL_EXAMPLE_LIST)))
$(foreach DUP_EXAMPLE,$(FINAL_DUP_EXAMPLE_LIST),$(eval $(call CREATE_DEP_TARGETS,$(DUP_EXAMPLE),FINAL_DUP_EXAMPLE_LIST)))
$(foreach FIRM,$(FINAL_FIRM_LIST),$(eval $(call CREATE_DEP_TARGETS,$(FIRM),FINAL_FIRM_LIST)))
$(foreach UTIL,$(FINAL_UTILS_LIST_ALL),$(eval $(call CREATE_DEP_TARGETS,$(UTIL),FINAL_UTILS_LIST_ALL)))
  • 8
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值