Skip to the content.

U-Boot add TI board

1. Overview

SPL 和 U-Boot 共享共同的代码库. 将自定义板添加到 U-Boot 时, 建议从在某些方面类似于自定义硬件设计的 TI EVM 开始, 例如在 DDR (内存类型和大小) 、MMC (使用哪个模块) 领域 、是否连接了 eMMC 或者是否正在使用 SD 卡) 、网络设置 (连接的 PHY 的类型和数量) 以及 UART 设置 (哪个 UART 旨在用于控制台目的?) . 就本操作方法文档而言, 我们将该 EVM 称为”Originating TI EVM”.

对于定制 AM437x 板, 许多人的设计基于 AM437x 通用 EVMAM437x 入门套件. 对于这里的讨论, 我们假设 AM437x 通用 EVM 作为我们的起点, 但是相同的概念也适用于从不同的基础平台开始的板端口. 新板将像其他现有板集成到 U-Boot 中一样干净地集成.

2. 将对新板的支持集成到 U-Boot 树中

添加支持基本上是通过克隆、剥离和扁平化 TI EVM 板支持来完成的, 同时将生成的文件集成到 U-Boot 构建流程中, 从而生成自定义 defconfig、自定义板特定头文件、自定义顶级文件 宣传新板名称的设备树文件, 以及用于平台设置 (例如 DDR 和 pinmux) 的一组自定义板文件. 一旦建立了这种扁平化基线并验证了其可以成功构建并在原始平台上运行, 下一步就是执行实际的定制工作.

2.1. 通过克隆和扁平化 TI EVM 支持创建初始基线

这些步骤包括在板端口过程中需要替换的各种占位符, 如下所示:

Placeholder Usage
用大写字母标识您的自定义板的名称. 它将用作与您的主板关联的新 U-Boot CONFIG 符号的名称, 允许自定义各种构建和运行时方面.
以小写字母标识您的自定义板的名称. 用于在 U-Boot 源树层次结构中建立自定义板平台文件, 并作为板特定文件名的一部分等.
贵公司的名称. 用于在 U-Boot 源树层次结构中建立一个文件夹, 其中包含 的板特定文件作为板端口的一部分.

创建初始基线的步骤:

  1. 建立自定义板特定的 CONFIG 选项, 可用于识别自定义硬件并相应地直接代码和构建流程.

    • 将 arch/arm/mach-omap2/am33xx/Kconfig 中的整个配置 TARGET_AM43XX_EVM 部分克隆到名为 config TARGET_AM43XX_ 的新部分.

    • 将新克隆部分中的配置 TARGET_AM43XX_ 选项描述从 bool "Support am43xx_evm"更新为 bool "Support am43xx_".

    • 同样, 更新新克隆部分的帮助描述, 以反映它适用于自定义板.

    • 从新部分中删除选择的 TI_I2C_BOARD_DETECT 条目. 在大多数情况下, 我们不需要或不希望自定义板具有此功能, 因为我们将围绕我们的特定平台定制解决方案, 所以让我们立即删除它.

    • 将源” board///Kconfig "添加到包含位于 arch/arm/mach-omap2/Kconfig 中的源位置的部分.

  2. 将板文件复制并更新到新文件夹.

    • 将所有文件从 board/ti/am43xx/ 复制到名为 board// 的新文件夹.

    • 根据需要删除 (或更新) README 和 MAINTAINERS 文件 (如果存在) .

    • 从 board.c 中删除 #include “../common/board_detect.h”.

    • 从 board.c 中删除 #ifdef TI_I2C_BOARD_DETECT 和 #endif 之间的代码.

    • 返工并删除 board.c、board.h 和 mux.c 中所有与板检测相关的代码, 仅保留并压平支持自定义板所基于的实际平台所需的部分. 原始的 board.c、board.h 和 mux.c 文件的编写方式使得它们支持多种不同的板以及给定板的不同版本, 所有这些都具有自己的板特定功能集, 包括但不限于 DDR 配置、pinmux、器件操作点/速度以及其他外设初始化代码. 通过遵循由于各种 board_is_*() 函数调用而执行的代码路径来进行返工. 例如, 要扁平化平台代码并将其定制为当前发布的 AM437x GP EVM 硬件版本, 假设 board_is_evm() 评估为 true, 所有其他 board_is_*() 函数评估为 false, 并相应地简化平台代码.

    • 编辑 board///Kconfig, 如下所示.

      • 将 TARGET_AM43XX_EVM 更新为 TARGET_AM43XX_.

      • 将配置 SYS_BOARD 下的默认”am43xx”更新为默认”".

      • 将配置 SYS_VENDOR 下的默认”ti”更新为默认”".

      • 将配置 SYS_CONFIG_NAME 下的默认”am43xx_evm”更新为默认”am43xx_".

  3. 复制并更新板特定的头文件.

    • 将 include/configs/am43xx_evm.h 复制到新文件 include/configs/am43xx_.h.

    • 删除#define CONFIG_ENV_EEPROM_IS_ON_I2C、#define CONFIG_SYS_I2C_EEPROM_ADDR、#define CONFIG_SYS_I2C_EEPROM_ADDR_LEN 定义, 因为我们通常不想使用外部 EEPROM 进行配置存储, 而是希望使用启动介质.

    • 将通过 CONFIG_EXTRA_ENV_SETTINGS 进行的 findfdt U-Boot 环境变量定义更新为硬编码用于引导 Linux 内核的板特定 DTB 文件”findfdt=setenv fdtfile am437x-.dtb\0".

    • 请记住, 当尝试使用此配置引导系统时, 在这种情况下, 您必须提供名为 am437x-.dtb 的内核 DTB 文件. 不提供此文件可能会导致基于 ENV 的 U-Boot 加载期间出现无提示故障, 并且内核无法启动.

  4. 复制并更新顶级设备树文件并集成到构建过程中.

    • 将 arch/arm/dts/am437x-gp-evm.dts 复制到 arch/arm/dts/am437x-.dts.

    • 编辑 arch/arm/dts/am437x-.dts 并使用自定义的、特定于板的字符串更新模型节点.

    • 编辑 arch/arm/dts/am437x-.dts 以包含隐式包含的 am437x-gp-evm-u-boot.dtsi 文件中的内容.

    Note

    许多 TI 板还附带 U-Boot 特定设备树包含文件, 其基本名称与主设备树文件相同, 但以 -u-boot.dtsi 结尾, 该文件由 U-Boot 的设备树构建过程隐式包含. 例如, 在 arch/arm/dts/am437x-gp-evm.dts 的情况下, 隐式包含的文件称为 arch/arm/dts/am437x-gp-evm-u-boot.dtsi. 建议简单地从此类包含文件中获取内容并将其添加到板的主设备树文件中, 从而提供更简单且更易于管理的活动配置视图.

    • 编辑 arch/arm/dts/Makefile 将 am437x-.dtb 添加到 dtb-$(CONFIG_AM43XX) 构建目标.
  5. 复制并更新 U-Boot defconfig 文件.

    • 将 configs/am43xx_evm_defconfig 复制到 configs/am43xx__defconfig.

    • 按如下方式编辑 configs/am43xx__defconfig.

      • 在 CONFIG_AM43XX=y 下面添加 CONFIG_TARGET_AM43XX_=y.

      • 更新 CONFIG_DEFAULT_DEVICE_TREE=”am437x-".

      • 删除 CONFIG_OF_LIST 条目.

此时, 初始基线已完成, 我们应该有一个自定义板, 该板将在板端口所基于的平台 (TI EVM) 上运行. 现在要完成此步骤, 请执行以下操作:

  1. 使用通常的流程构建我们的自定义板端口, 首先构建新创建的 defconfig 文件, 然后执行 SPL 和 U-Boot 的实际构建. 修复您可能遇到的任何构建错误并重新构建, 直到构建干净地执行, 没有任何构建警告.确保 toolchain path 已正确设置.
$ make ARCH=arm CROSS_COMPILE='arm-linux-gnueabihf-' mrproper
$ make ARCH=arm CROSS_COMPILE='arm-linux-gnueabihf-' <device>_<myboard>_defconfig
$ make ARCH=arm CROSS_COMPILE='arm-linux-gnueabihf-'
  1. 将新添加的文件检入 Git 以建立已知良好的检查点.

2.2. 定制新建立的基线以支持实际的目标平台

下一步, 我们希望创建一个可用于启动开发板的初始尝试的最小配置. 一旦基础知识发挥作用, 它将成为逐步构建设置的良好基础, 以完全支持定制板的所有所需功能. 请注意, 在第一次尝试中一切顺利的机会相当低, 因此通常会采用迭代方法, 包括进行更改、确保它们构建、将它们签入 Git 源代码树 (以便可以跟踪、理解更改并记录更改) . 如果需要更容易地恢复) , 并在硬件上对其进行测试, 直到实现完全工作且功能齐全的板端口.

U-Boot 使用相同的代码库为 SPL 和 U-Boot 本身构建映像. 当您使用不同的源文件和头文件时, 请注意某些语句如何包装在 #ifdef CONFIG_SPL … #endif 语句预处理器宏中, 这意味着包含的部分仅适用并在构建 SPL 时进行构建. 同样, 当您在 Kconfig 中遇到以 CONFIG_SPL_* 开头的配置符号时 工具 (意思是 make […] menuconfig) , 在 U-Boot 树中的实际 Kconfig 文件 (在这种情况下省略前导 CONFIG_ 前缀) 中, 或在任何源文件和 Makefile 文件中, 这意味着某个功能或 部分仅激活或适用于 SPL.

Note

使用 Kconfig 工具中的搜索功能可以快速找到下面讨论的各种 CONFIG_* 选项. 按”/”键可以激活搜索.

Note

设备树文件中进行的任何 pinmux 设置均不适用且不被 U-Boot 使用. 之所以存在这些文件, 是因为 U-Boot 设备树文件通常是 Linux 设备树文件的副本, 因为这可以简化保持这些文件同步的过程. 但这并不意味着 pinmux 等所有条目都适用于 U-Boot.

CONFIG_DEBUG_UART_BASE=0x44e09000
CONFIG_DEBUG_UART_CLOCK=48000000
CONFIG_DEBUG_UART=y
CONFIG_DEBUG_UART_OMAP=y
CONFIG_DEBUG_UART_SHIFT=2
CONFIG_DEBUG_UART_ANNOUNCE=y

Note

早期 (调试) UART 的建议设置包括 CONFIG_DEBUG_UART_ANNOUNCE=y, 这会在大多数/任何 SoC 和外设配置发生之前, 在 SPL 启动流程的早期阶段输出 . 启用此功能是在主板启动期间看到某种"早期生命迹象"的好方法, 让人们相信启动过程的基本原理正在工作, 即 ROM 启动加载程序从所需的启动介质加载 SPL 和 SPL 开始执行.

现在进行自定义后, 生成的 SPL/U-Boot 不应再在原始 TI EVM 上运行, 而是在自定义硬件上运行. 我们现在应该能够在新板的硬件启动上下文中尝试自定义硬件平台的初始启动. 目标应该是进入 U-Boot 提示符.

2.3. 建立对目标平台的全面支持

一旦我们到达 U-Boot 提示符, 我们就可以专注于 (重新) 向 U-Boot 添加我们可能需要更全面地支持我们的自定义系统的任何功能, 然后转向引导 Linux 内核. 建议一一添加功能, 同时使用 Git 跟踪任何更改并在添加功能时在实际硬件上测试/验证功能, 直到添加并集成所有所需功能.

定制步骤可能涉及但不限于添加…

添加功能时, 通常最好分析 U-Boot 中已存在的使用相同 TI SoC 的其他板, 然后将功能移植到我们自己的板文件、板特定头文件和 defconfig 中.

要识别 U-Boot 中哪些其他板使用相同的 SoC, 请使用以下命令:

git grep CONFIG_AM43XX=y

检查最新的上游 U-Boot 树 是否有可能已经可用的其他板也很有帮助. 然而, 在将代码向后移植到 TI SDK 的 U-Boot 部分时必须小心, 以考虑所有必需的依赖项和可能影响特定功能的更改.

3. U-Boot 启动调试技巧

进行 U-Boot 板移植通常是一个迭代过程, 涉及一定量的调试和故障排除, 尤其是在与 TI EVM 存在很大差异的定制硬件平台上. 下面的列表提供了一些在调试和 U-Boot 启动过程中可能会有所帮助的想法.

printf("%s: %d:\n", __func__, __LINE__);
dtc -I dtb spl/u-boot-spl.dtb
dtc -I dtb u-boot.dtb