Skip to content

wdfk-prog/U-boot-Study

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

31 Commits
 
 
 
 
 
 
 
 

Repository files navigation

[toc]

art-pi构建命令

export CROSS_COMPILE=arm-none-eabi- ARCH=arm
make stm32h750-art-pi_defconfig
make menuconfig
	> Boot options        (console=ttySTM0,115200 root=/dev/ram loglevel=8) Boot arguments
	> Device Drivers > Serial drivers        (115200) Default baudrate
u-boot-v2021.07\arch\arm\dts\stm32h750i-art-pi.dts
	chosen {
		bootargs = "root=/dev/ram";
		stdout-path = "serial0:2000000n8";
	};
	chosen {
		bootargs = "root=/dev/ram";
		stdout-path = "serial0:115200n8";
	};
make -j 12

F4 构建命令

export CROSS_COMPILE=arm-none-eabi- ARCH=arm
make stm32f429-discovery_defconfig
arch/arm/dts/stm32f429-disco.dts
make -j 12

Makefile

功能

V=1 显示完成命令输出

  • V=1:告诉 make 显示完成的命令输出。这对于调试构建过程非常有用,因为它可以显示构建过程中执行的所有命令。
  • 没有设置 V 时,make 默认不显示命令输出。
  • 其中 Q = @,@用于抑制命令的输出
# make V=1 显示完成命令输出
ifeq ("$(origin V)", "command line")	#获取V是否输入
  KBUILD_VERBOSE = $(V)	# KBUILD_VERBOSE = 1
endif
ifndef KBUILD_VERBOSE	# 如果没有输入V,则KBUILD_VERBOSE = 0
  KBUILD_VERBOSE = 0
endif

ifeq ($(KBUILD_VERBOSE),1)	# 如果KBUILD_VERBOSE = 1,则显示完成命令输出
  quiet =
  Q =
else	# 否则不显示完成命令输出
  quiet=quiet_
  Q = @
endif

-s 静默模式

  • -s:告诉 make 进入静默模式。在静默模式下,make 不会显示构建过程中执行的命令。
  • 设置 quiet变量为 silent_,这样就可以在构建过程中使用 $(quiet)前缀来隐藏命令的输出。
ifneq ($(filter 4.%,$(MAKE_VERSION)),)	# make-4
ifneq ($(filter %s ,$(firstword x$(MAKEFLAGS))),)
  quiet=silent_
endif
else					# make-3.8x
ifneq ($(filter s% -s%,$(MAKEFLAGS)),)
  quiet=silent_
endif
endif

O= 输出目录

make CROSS_COMPILE=arm-none-eabi- ARCH=arm -j3 O=output/
  • 使用 KBUILD_SRC设置输出目录。使用 O变量设置输出目录,如果 O变量没有设置,则使用 KBUILD_SRC变量设置输出目录。
ifeq ($(KBUILD_SRC),)
    ifeq ("$(origin O)", "command line")
    KBUILD_OUTPUT := $(O)
endif

C=1 启用静态检查

  • 使用 'make C=1' 来启用仅检查重新编译的文件。
  • 使用 'make C=2' 来启用对 所有 源文件的检查,无论它们是否被重新编译。

M = 构建的外部模块的目录

  • 使用 make M=dir 指定要构建的外部模块的目录
  • 旧语法 make ...SUBDIRS=$PWD 仍受支持
  • 设置环境变量KBUILD_EXTMOD优先

cc-option CC编译器选项测试检查

# output 目录进行以下测试
# 如果 KBUILD_EXTMOD 被定义,则使用其第一个值作为临时输出目录;否则,TMPOUT 为空。
TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)

# try-run
# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
# 退出代码选择选项。“$$TMP” 可以用作临时文件,并会自动清理。
# 针对 U-Boot 进行了修改:防止 cc-option 留下 .*.su 文件

# set -e 确保在命令失败时立即退出。
# 定义了三个临时文件,分别用于存储编译输出和中间文件。$$$$ 用于生成唯一的文件名。
# 执行编译命令 $(1),并根据其退出状态选择输出。如果编译成功,输出 $(2);否则,输出 $(3)。
# 删除临时文件,确保不会留下多余的文件。
try-run = $(shell set -e;		\
    TMP="$(TMPOUT).$$$$.tmp";	\
    TMPO="$(TMPOUT).$$$$.o";	\
    TMPSU="$(TMPOUT).$$$$.su";	\
    if ($(1)) >/dev/null 2>&1;	\
    then echo "$(2)";		\
    else echo "$(3)";		\
    fi;				\
    rm -f "$$TMP" "$$TMPO" "$$TMPSU")

# __cc-option
# Usage: MY_CFLAGS += $(call __cc-option,$(CC),$(MY_CFLAGS),-march=winchip-c6,-march=i586)
# $(1) 表示编译器命令(如 $(CC))。
# $(2) 表示已有的编译标志。
# $(3) 表示要测试的编译选项。
# $(4) 表示备用选项。
# 宏会尝试编译一个空的 C 文件 null,并将输出重定向到临时文件 $$TMP。如果编译成功,则返回 $(3),否则返回 $(4)
__cc-option = $(call try-run,\
    $(1) -Werror $(2) $(3) -c -x c /dev/null -o "$$TMP",$(3),$(4))

# cc-option
# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
# 编译器CC 编译条件KBUILD_CPPFLAGS KBUILD_CFLAGS 成功返回$(1) 失败返回$(2)
cc-option = $(call __cc-option, $(CC),\
    $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS),$(1),$(2))

scripts 用于构建脚本的工具

Kconfig 相关的功能

  • Kconfig 是一个配置文件,用于定义内核的配置选项。它使用一种类似于 C 语言的语法,包含一系列配置选项和依赖关系。Kconfig 文件通常由 Kconfig 工具解析,生成配置文件(.config)。
config          - 使用行定向程序更新当前配置
nconfig         - 使用基于 ncurses 菜单的程序更新当前配置
menuconfig      - 使用基于菜单的程序更新当前配置
xconfig         - 使用基于 Qt 前端的程序更新当前配置
gconfig         - 使用基于 GTK+ 前端的程序更新当前配置
oldconfig       - 使用提供的 .config 作为基础更新当前配置
localmodconfig  - 更新当前配置,禁用未加载的模块
localyesconfig  - 更新当前配置,将本地模块转换为核心
defconfig       - 使用 ARCH 提供的默认配置创建新配置
savedefconfig   - 将当前配置保存为 ./defconfig(最小配置)
allnoconfig     - 创建一个所有选项都回答为 no 的新配置
allyesconfig    - 创建一个所有选项都接受为 yes 的新配置
allmodconfig    - 创建一个尽可能选择模块的新配置
alldefconfig    - 创建一个所有符号都设置为默认值的新配置
randconfig      - 创建一个所有选项都随机回答的新配置
listnewconfig   - 列出新选项
olddefconfig    - 与 oldconfig 相同,但将新符号设置为默认值而不提示
testconfig      - 运行 Kconfig 单元测试(需要 python3 和 pytest)
  • 强制使用需修改Kconfig文件
mainmenu "U-Boot $(UBOOTVERSION) Configuration"
srctree := .
CC = $(CROSS_COMPILE)gcc

config 使用行定向程序更新当前配置

  • 通过命令 ./scripts/kconfig/conf --oldaskconfig Kconfig运行

  • 运行的是命令行版本的配置工具,用于解析Kconfig文件并生成配置文件。

*
* U-Boot  Configuration
*
*
* Compiler: 
*
Architecture select
  1. ARC architecture (ARC)
> 2. ARM architecture (ARM)
  3. M68000 architecture (M68K)
  4. MicroBlaze architecture (MICROBLAZE)
  5. MIPS architecture (MIPS)
  6. Nios II architecture (NIOS2)
  7. PowerPC architecture (PPC)
  8. RISC-V architecture (RISCV)
  9. Sandbox (SANDBOX)
  10. SuperH architecture (SH)
  11. x86 architecture (X86)
  12. Xtensa architecture (XTENSA)
choice[1-12?]: 2
*
* Skipping low level initialization functions
*
Skip calls to certain low level initialization functions (SKIP_LOWLEVEL_INIT) [N/y/?] N
Skip call to lowlevel_init during early boot ONLY (SKIP_LOWLEVEL_INIT_ONLY) [N/y/?] N
*
* ARM architecture
*
ARM GICV2 driver (DRIVER_GICV2) [N/y/?] N
ARM GICV3 ITS (GIC_V3_ITS) [N/y/?] N
ARM GICV3 GIC600 SUPPORT (GICV3_SUPPORT_GIC600) [N/y/?] N
Do not enable icache (SYS_ICACHE_OFF) [N/y/?] N
Do not enable dcache (SYS_DCACHE_OFF) [N/y/?] N
CP15 based cache enabling support (SYS_ARM_CACHE_CP15) [N/y/?] N
MMU-based Paged Memory Management Support (SYS_ARM_MMU) [N/y/?] N
Use the ARM v7 PMSA Compliant MPU (SYS_ARM_MPU) [Y/?] y
Select the ARM data write cache policy
> 1. Write-back (WB) (SYS_ARM_CACHE_WRITEBACK)
  2. Write-through (WT) (SYS_ARM_CACHE_WRITETHROUGH)
  3. Write allocation (WA) (SYS_ARM_CACHE_WRITEALLOC)
choice[1-3?]: 0
Select the ARM data write cache policy
> 1. Write-back (WB) (SYS_ARM_CACHE_WRITEBACK)
  2. Write-through (WT) (SYS_ARM_CACHE_WRITETHROUGH)
  3. Write allocation (WA) (SYS_ARM_CACHE_WRITEALLOC)
choice[1-3?]: 1
Enable ARCH_CPU_INIT (ARCH_CPU_INIT) [N/y/?] n
Build U-Boot using the Thumb instruction set (SYS_THUMB_BUILD) [Y/?] y

ARM PL310 L2 cache controller (SYS_L2_PL310) [N/y/?] n
ARM PL310 L2 cache controller in SPL (SPL_SYS_L2_PL310) [N/y/?] ^C

embedsky@ubuntu:~/share/u-boot$ ./scripts/kconfig/conf --oldaskconfig Kconfig 
  • 用法
--listnewconfig         列出新的选项
--oldaskconfig          使用行定向程序开始新的配置
--oldconfig             使用提供的 .config 文件作为基础更新配置
--syncconfig            类似于 oldconfig,但生成的配置文件位于 include/{generated/,config/}
--olddefconfig          与 oldconfig 相同,但将新符号设置为默认值
--defconfig <file>      使用 <file> 中定义的默认值创建新的配置
--savedefconfig <file>  将当前最小配置保存到 <file>
--allnoconfig           创建一个所有选项都回答为 no 的新配置
--allyesconfig          创建一个所有选项都回答为 yes 的新配置
--allmodconfig          创建一个所有选项都回答为 mod 的新配置
--alldefconfig          创建一个所有符号都设置为默认值的新配置
--randconfig            创建一个所有选项都随机回答的新配置
  • 代码解析
int main(int ac, char **av)
{
    const char *progname = av[0];
    int opt;
    const char *name, *defconfig_file = NULL /* gcc uninit */;
    struct stat tmpstat;
    int no_conf_write = 0;

    tty_stdio = isatty(0) && isatty(1); //判断标准输入输出是否指向终端
  //从命令行获取短选项-s参数或者long_opts结构体的选项
  // 执行对应配置操作
  while ((opt = getopt_long(ac, av, "s", long_opts, NULL)) != -1) {
    //如果存在-s参数,则设置消息输出回调为空,即不输出消息
    if (opt == 's') {
      conf_set_message_callback(NULL);
      continue;
        }
  }
  //如果 ac 等于 optind,则表示没有提供额外的命令行参数,即没有提供配置文件
  if (ac == optind) {
        fprintf(stderr, "%s: Kconfig file missing\n", av[0]);
        conf_usage(progname);
        exit(1);
    }
  //获取配置文件
  name = av[optind];
    //执行配置操作
  //通过scripts/kconfig/zconf.y 使用 bison -d zconf.y 生成 zconf.tab.c
  //这里会需要进行用户配置
  conf _parse(name);
  //执行配置操作


    re turn 0;
}

menuconfig 使用基于菜单的程序更新当前配置

  • 通过命令 ./scripts/kconfig/mconf Kconfig 运行
  • 运行的是menuconfig的配置工具,使用基于菜单的程序更新当前配置
embedsky@ubuntu:~/share/u-boot$ ./scripts/kconfig/mconf Kconfig 
.config:37:warning: symbol value '' invalid for ENV_OFFSET
.config:38:warning: symbol value '' invalid for ENV_SECT_SIZE
.config:47:warning: symbol value '' invalid for TPL_STACK
.config:52:warning: symbol value '' invalid for SYS_LOAD_ADDR
.config:57:warning: symbol value '' invalid for PRE_CON_BUF_ADDR
.config:108:warning: symbol value '' invalid for BOARD_SIZE_LIMIT
.config:116:warning: symbol value '' invalid for SYS_MONITOR_BASE
.config:827:warning: symbol value '' invalid for SYS_SATA_MAX_DEVICE

WARNING: unmet direct dependencies detected for NPCM_OTP
  Depends on [n]: ARM [=n] && ARCH_NPCM [=n]
  Selected by [y]:
  - NPCM_AES [=y]
Your display is too small to run Menuconfig!
It m ust be at least 19 lines by 80 columns.
 

WAING: unmet direct dependencies detected for NPCM_OTP
 Dpends on [n]: ARM [=n] && ARCH_NPCM [=n]
 S lected by [y]:
- NP CM_AES [=y]



 configuration changes were NOT saved.

`


建说明



执 make xxx_defconfig`时,会执行conf可执行文件的编译
后执 `./scripts/kconfig/conf --defconfig=generated_defconfig Kconfig`命令,生成配置文件

`ma

kefile
# scripts/kcon fig/Makefile  
  

 %defconfig: $(obj)/conf
    $(Q)$(CPP) -nostdinc -P -I $(srctree) -undef -x assembler-with-cpp $(srctree)/arch/$(SRCARCH)/configs/$@ -o generated_defconfig
    $(Q)$< $(silent) --defconfig=generated_defconfig $(Kconfig)
  • 展开为
arm-none-eabi-gcc -E -nostdinc -P -I . -undef -x assembler-with-cpp ./arch/../configs/stm32h750-art-pi_defconfig -o generated_defconfig
nfig/conf  --defconfig=generated_defconfig Kconfig

构建流程

Ubootb编译第一步通常是执行make xxx_config

  • 在编译指定顶层目录生成.c onfig文件,这种方式要求厂商 提供一个基础的xxx_config文件(通常来说开发者不会通过执行make menuconfig从零开始配置,这个工作过量太大了)。

  • 查看编译流程时,优先查看 xxx:这类可执行目标;如果make 没有带目标时,则优先查看第一个目标,因为是执行的这个目标;从头开始查看,需要注意查看 include是否引入的 xxx:

  • 这里的目标是 xxx_config:,即 %config:

# 定义了一个模式规则,匹配所有以 config 结尾的目标
%config: scripts_basic outputmakefile FORCE
	$(Q)$(MAKE) $(build)=scripts/kconfig $@
  • %config 还会依赖于 scripts_basicoutputmakefileFORCE是一个空目标,用于强制执行规则。

build变量的定义

  • 观察顶层makefile
# 我们需要一些通用定义(不要尝试重新制作文件)。
# 里面定义了$(build)
scripts/Kbuild.include: ;
include scripts/Kbuild.include
  • 在scripts/Kbuild.include 中定义:
###

# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
# Usage:
# $(Q)$(MAKE) $(build)=dir
build := -f $(srctree)/scripts/Makefile.build obj

编译scripts_basic 生成fixep

outputmakefile 生成Makefile

执行scripts/kconfig Makefile

编译生成conf

执行conf --defconfig=generated_defconfig Kconfig

include/config/auto.conf、 include/config/auto.conf.cmd、 include/generated/autoconf.h

Ubootb编译 执行make 操作

shell 命令

GNU C

objdump 工具

反汇编 -d

objdump -d start.o
  • 更多的详细信息,可以使用 -S 选项,它会将源代码和反汇编代码一起显示

  • 问题:

    1. objdump: can't disassemble for architecture UNKNOWN!
    • 出现这个错误可能是因为 objdump 工具无法识别目标文件的架构。你可以尝试显式指定架构来解决这个问题。
    objdump -d -m arm start.o
    • 使用file命令查看文件类型
      $file start.o
      arch/arm/cpu/armv7m/start.o: ELF 32-bit LSB relocatable, ARM, EABI5 version 1 (SYSV), with debug_info, not stripped
    • 使用objdump -i查看支持的架构
    • 根据你的架构 armv7m,使用arm-none-eabi-objdump

查看段信息 -h

显示段内容 -s

反汇编指定的段 -j

Bison && Flex

map分析

流程分析

U-BOOT 配置

U-boot 分类

arch

boot

cmd

common

dm

env

fdt

include

lib

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published