[u-boot 2020.07] README

挖坑,难填!

# SPDX-License-Identifier: GPL-2.0+
#
# © Copyright 2000 - 2013
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.

摘要:

   该目录包含U-Boot的源代码,U-Boot是基于PowerPC,ARM,MIPS和其他几个处理器的嵌入式板的引导加载程序,可以安装在引导ROM中,并用于初始化和测试硬件或下载并运行应用程序代码。

   U-Boot的开发与Linux密切相关:源代码的某些部分起源于Linux源代码树,我们有一些共同的头文件,并且已做出特殊规定来支持Linux映像的引导。

   为了使该软件易于配置和扩展,已经进行了一些注意。 例如,所有监视命令都使用相同的调用接口实现,因此添加新命令非常容易。 此外,您可以动态地加载和运行它,而不是向监视器永久添加很少使用的代码(例如,硬件测试实用程序)。

状态:

   通常,Makefile中存在配置选项的所有板均已进行了某种程度的测试,可以视为“正常”。 实际上,其中许多用于生产系统。

   如有问题,请参阅CHANGELOG文件以查找谁贡献了特定端口。 此外,在整个U-Boot源中散布着各种MAINTAINERS文件,用于标识负责各种板和子系统的人员或公司。

   注意:自2010年8月起,实际的U-Boot源代码树中不再有CHANGELOG文件。 但是,可以使用以下命令动态创建它:make CHANGELOG

在哪里获得帮助:

   如果您对U-Boot有任何疑问,问题或贡献,请通过 u-boot@lists.denx.de 向U-Boot邮件列表发送一条消息。 邮件列表上还有以前的流量存档-请在询问常见问题之前搜索存档。

请参阅 http://lists.denx.de/pipermail/u-boothttp://dir.gmane.org/gmane.comp.boot-loaders.u-boot

在哪里获取源代码:

The U-Boot source code is maintained in the Git repository at git://www.denx.de/git/u-boot.git ; you can browse it online at http://www.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=summary

The “snapshot” links on this page allow you to download tarballs of any version you might be interested in. Official releases are also available for FTP download from the ftp://ftp.denx.de/pub/u-boot/ directory.

Pre-built (and tested) images are available from ftp://ftp.denx.de/pub/u-boot/images/

我们来自哪里:

名称和拼写:

   该项目的“正式”名称是“ Das U-Boot”。 所有书面文本(文档,源文件中的注释等)均应使用拼写“ U-Boot”。 例:

  • This is the README file for the U-Boot project.

文件名等应基于字符串“ u-boot”。 例如:

  • include/asm-ppc/u-boot.h

  • #include <asm/u-boot.h>

变量名称,预处理器常量等应基于字符串“ u_boot”或基于“ U_BOOT”。 例:

  • U_BOOT_VERSION  u_boot_logo
  • IH_OS_U_BOOT   u_boot_hush_start

版本控制:

   从2008年10月的发行版开始,发行版的名称已从没有更深含义的数字发行版编号更改为基于时间戳的编号。 常规发行版的名称由发行日期的日历年和月份组成。 其他字段(如果存在)在“稳定的”维护树中指示候选版本或错误修复版本。

Examples:
	U-Boot v2009.11	    - Release November 2009
	U-Boot v2009.11.1   - Release 1 in version November 2009 stable tree
	U-Boot v2010.09-rc1 - Release candidate 1 for September 2010 release

目录层次结构:

/arch			Architecture specific files
  /arc			Files generic to ARC architecture
  /arm			Files generic to ARM architecture
  /m68k			Files generic to m68k architecture
  /microblaze	Files generic to microblaze architecture
  /mips			Files generic to MIPS architecture
  /nds32		Files generic to NDS32 architecture
  /nios2		Files generic to Altera NIOS2 architecture
  /openrisc		Files generic to OpenRISC architecture
  /powerpc		Files generic to PowerPC architecture
  /riscv		Files generic to RISC-V architecture
  /sandbox		Files generic to HW-independent "sandbox"
  /sh			Files generic to SH architecture
  /x86			Files generic to x86 architecture
/api			Machine/arch independent API for external apps
/board			Board dependent files
/cmd			U-Boot commands functions
/common			Misc architecture independent functions
/configs		Board default configuration files
/disk			Code for disk drive partition handling
/doc			Documentation (don't expect too much)
/drivers		Commonly used device drivers
/dts			Contains Makefile for building internal U-Boot fdt.
/examples		Example code for standalone applications, etc.
/fs				Filesystem code (cramfs, ext2, jffs2, etc.)
/include		Header Files
/lib			Library routines generic to all architectures
/Licenses		Various license files
/net			Networking code
/post			Power On Self Test
/scripts		Various build scripts and Makefiles
/test			Various unit test files
/tools			Tools to build S-Record or U-Boot images, etc.

软件配置:

   配置通常使用C预处理程序定义完成; 其基本原理是尽可能避免死代码。

有两类配置变量:

  • _OPTIONS_ 配置:
    这些可由用户选择,并且名称以CONFIG_开头。
  • _SETTINGS_ 配置:
    这些取决于硬件等。如果您不知道自己在做什么,则不应该介入其中。 它们的名称以CONFIG_SYS_开头。

   以前,所有配置都是手动完成的,包括创建符号链接和手动编辑配置文件。 最近,U-Boot添加了Linux内核使用的Kbuild基础结构,允许您使用“ make menuconfig”命令来配置构建。

处理器架构和板类型的选择:

   对于所有受支持的板,都有可用的默认配置。 只需键入“ make <board_name> _defconfig”。

Example: For a TQM823L module type:

	cd u-boot
	make TQM823L_defconfig

   注意:如果您正在寻找某个板子的默认配置文件,您肯定曾经在其中,但是现在丢失了,请检查文件 doc / README.scrapyard 中不再支持的板子的列表。

沙盒环境(Sandbox):

   可以使用“沙盒”板在本地构建U-Boot以在Linux主机上运行。 这允许在本机平台上进行不是特定于主板或体系结构的功能开发。 沙箱还用于运行U-Boot的某些测试。

See doc/arch/index.rst for more details.

Board 初始化流程:

   这是电路板的预期启动流程。 这应该同时适用于SPL和U-Boot正确(即它们都遵循相同的规则)。

注意:“ SPL”代表“辅助程序加载程序(Secondary Program Loader)”,此文件稍后将对此进行详细说明。

   目前,SPL大多使用单独的代码路径,但是每个函数的功能名称和角色都相同。 某些板或体系结构可能不符合此要求。 至少大多数使用CONFIG_SPL_FRAMEWORK的ARM板都符合此要求。

1. start.S

   boot 通常从特定于体系结构(并且可能特定于CPU)的start.S文件开始,例如:

  • arch/arm/cpu/armv7/start.S
  • arch/powerpc/cpu/mpc83xx/start.S
  • arch/mips/cpu/start.S

and so on. 从这里开始,调用了三个函数。 这些功能的目的和局限性如下所述。

2. lowlevel_init()

  • 目的:允许执行到达 board_init_f() 的最基本且必须的初始化。
  • 没有 global_data 或 BSS
  • 没有堆栈(ARMv7可能有一个堆栈,但是很快就会被删除)
  • 不得设置 SDRAM 或使用控制台
  • 必须只做最少的工作,以允许执行继续到 board_init_f()
  • this is almost never needed
  • 从此函数正常返回

3. board_init_f()

  • 目的:设置机器以准备运行 board_init_r():即 SDRAM 和串行 UART
  • 可用 global_data
  • 堆栈位于 SRAM 中
  • BSS 不可用,因此您不能使用全局/静态变量,只能使用堆栈变量和global_data

Non-SPL-specific notes:

  • 调用 dram_init() 设置DRAM。 如果已经在SPL中完成,则无法执行任何操作

SPL-specific notes:

  • 您可以根据需要使用自己的版本重写整个 board_init_f() 函数。
  • preloader_console_init() can be called here in extremis.
  • 应该设置SDRAM,以及使UART工作所需的所有东西。
  • 这些不需要清除 BSS,将由 crt0.S 完成。
  • for specific scenarios on certain architectures an early BSS can be made available (via CONFIG_SPL_EARLY_BSS by moving the clearing of BSS prior to entering board_init_f()) but doing so is discouraged. Instead it is strongly recommended to architect any code changes or additions such to not depend on the availability of BSS during board_init_f() as indicated in other sections of this README to maintain compatibility and consistency across the entire code base.
  • 必须从此函数正常返回(不要直接调用 board_init_r() )

此处清除了BSS。 对于SPL,如果定义了 CONFIG_SPL_STACK_R,则此时将堆栈和 global_data 重定位到 CONFIG_SPL_STACK_R_ADDR 之下。 对于非SPL,U-Boot被重定位以在内存顶部运行。

setup_reloc() 重定位 global_data 。

4. board_init_r()

  • 目的:主要执行,通用代码
  • 可用 global_data
  • 可用 SDRAM
  • BSS可用,可以使用所有静态/全局变量
  • 执行最终继续到 main_loop()

Non-SPL-specific notes:

  • U-Boot重定位到内存的顶部,并且现在从那里开始运行。

SPL-specific notes:

  • 如果定义了CONFIG_SPL_STACK_R并且CONFIG_SPL_STACK_R_ADDR指向SDRAM,则堆栈可选地位于SDRAM中
  • 可以在这里调用 preloader_console_init() -通常是通过选择 CONFIG_SPL_BOARD_INIT 然后提供包含该调用的 spl_board_init() 函数来完成的
  • 加载 U-Boot 或(在falcon模式下)Linux

配置选项:

   配置取决于板卡和CPU类型的组合。 所有这些信息都保存在配置文件include / configs / <board_name> .h中。

Example: For a TQM823L module, all configuration settings are in “include/configs/TQM823L.h”.

   许多选项的名称与相应的Linux内核配置选项完全相同。 目的是使构建配置工具更容易-稍后。

ARM平台总线类型(CCI):

CoreLink缓存一致性互连(CCI)是ARM BUS,可在两个多核CPU群集之间提供完全的缓存一致性,并为设备和I / O主设备提供I / O一致性。
CONFIG_SYS_FSL_HAS_CCI400
定义用于具有缓存一致性互连CCN-400的SoC
CONFIG_SYS_FSL_HAS_CCN504
定义用于具有缓存一致性互连CCN-504的SoC

The following options need to be configured:

Board initialization settings:

Configuration Settings:

Low Level (hardware related) configuration options:

Freescale QE/FMAN Firmware Support:

Freescale Layerscape Management Complex Firmware Support:

Freescale Layerscape Debug Server Support:

可复制的构建

   为了实现可复制的构建,必须将U-Boot构建过程中使用的时间戳设置为固定值。

   这是使用SOURCE_DATE_EPOCH环境变量完成的。 SOURCE_DATE_EPOCH将在构建主机的外壳上设置,而不是作为U-Boot的配置选项或U-Boot中的环境变量。

   SOURCE_DATE_EPOCH应该设置为自该时期以来的秒数(以UTC为单位)。

Building the Software:

   构建U-Boot已在多个本机构建环境和许多不同的交叉环境中进行了测试。 当然,我们不能在所有(可能已过时)的版本中支持交叉开发工具的所有可能的现有版本。 如果出现工具链问题,我们建议使用ELDK(请参阅 http://www.denx.de/wiki/DULG/ELDK),该工具已广泛用于构建和测试U-Boot。

   如果您不使用本机环境,则假定您的路径中具有GNU交叉编译工具。 在这种情况下,必须在外壳程序中设置环境变量CROSS_COMPILE。 请注意,无需更改Makefile或任何其他源文件。 例如,在4xx CPU上使用ELDK,请输入:

$ CROSS_COMPILE=ppc_4xx-
$ export CROSS_COMPILE

   U-Boot旨在易于构建。 安装源后,必须为一种特定的板类型配置U-Boot。 通过键入以下内容来完成:

  • make NAME_defconfig

   其中“ NAME_defconfig”是现有配置之一的名称; 有关支持的名称,请参见 configs / * _ defconfig

   注意:对于某些板,可能存在特殊的配置名称; 检查董事会供应商是否提供了其他信息; 例如,TQM823L 系统不带(标准)或带LCD支持。 您可以在选择配置时选择此类其他“功能”。

  make TQM823L_defconfig
- will configure for a plain TQM823L, i. e. no LCD support

  make TQM823L_LCD_defconfig
- will configure for a TQM823L with U-Boot console on LCD

   最后,输入“ make all”,然后您应该会得到一些可以工作的U-Boot映像,以下载到/安装在系统上:

  • “u-boot.bin” is a raw binary image
  • “u-boot” is an image in ELF binary format
  • “u-boot.srec” is in Motorola S-Record format

   默认情况下,构建是在本地执行的,并且对象保存在源目录中。 可以使用以下两种方法之一来更改此行为并将U-Boot构建到某个外部目录:

  1. 在make命令行调用中添加 O=
make O=/tmp/build distclean
make O=/tmp/build NAME_defconfig
make O=/tmp/build all
  1. 将环境变量 KBUILD_OUTPUT 设置为指向所需位置:
export KBUILD_OUTPUT=/tmp/build
make distclean
make NAME_defconfig
make all

注意,命令行 O= 设置将覆盖 KBUILD_OUTPUT 环境变量。

   通过设置相应的环境变量KCPPFLAGS,KAFLAGS和KCFLAGS,可以将用户特定的CPPFLAGS,AFLAGS和CFLAGS传递给编译器。 例如,将所有编译器警告视为错误:

  • make KCFLAGS=-Werror

   请注意,Makefiles假定您正在使用GNU make,因此例如在NetBSD上,您可能需要使用“ gmake”而不是本机的“ make”。

   如果目录中没有你的系统板,但是你需要将 U-Boot 移植到你的硬件平台上。为了完成这个目标,请遵循以下步骤:

  1. 创建一个新目录来保存您的主板特定代码。 添加您需要的任何文件。 在您的板目录中,至少需要“ Makefile”和“ <board> .c”。
  2. 为您的电路板创建一个新的配置文件“ include / configs / <board> .h”。
  3. 如果要将U-Boot移植到新CPU,则还要创建一个新目录来保存您的CPU特定代码。 添加您需要的任何文件。
  4. 用您的新名称运行“ make <board> _defconfig”。
  5. 键入“ make”,您应该得到一个可以正常工作的“ u-boot.srec”文件,该文件将被安装在目标系统上。
  6. 调试并解决可能出现的任何问题。[当然,最后一步比听起来要难得多。]

测试移植到新硬件而为U-Boot作的修改:

   如果您已经修改了U-Boot源(例如添加了新板或对新设备的支持,新CPU等),则应向其他开发人员提供反馈。 反馈通常采用“补丁”的形式,即与特定(最新的官方版本或git存储库中最新的)U-Boot源版本的上下文差异。

   但是在提交此类补丁之前,请确认您所做的修改没有破坏现有代码。 至少要确保所有受支持的板都能在没有任何编译器警告的情况下进行编译。 为此,只需运行buildman脚本(tools / buildman / buildman),它将为所有支持的系统配置和构建U-Boot。 请注意,这将需要一段时间。 请参阅buildman自述文件,或运行’buildman -H’以获取文档。

See also “U-Boot Porting Guide” below.

监视命令-概述:

go	- start application at address 'addr'
run	- run commands in an environment variable
bootm	- boot application image from memory
bootp	- boot image via network using BootP/TFTP protocol
bootz   - boot zImage from memory
tftpboot- boot image via network using TFTP protocol
	       and env variables "ipaddr" and "serverip"
	       (and eventually "gatewayip")
tftpput - upload a file via network using TFTP protocol
rarpboot- boot image via network using RARP/TFTP protocol
diskboot- boot from IDE devicebootd   - boot default, i.e., run 'bootcmd'
loads	- load S-Record file over serial line
loadb	- load binary file over serial line (kermit mode)
md	- memory display
mm	- memory modify (auto-incrementing)
nm	- memory modify (constant address)
mw	- memory write (fill)
cp	- memory copy
cmp	- memory compare
crc32	- checksum calculation
i2c	- I2C sub-system
sspi	- SPI utility commands
base	- print or set address offset
printenv- print environment variables
setenv	- set environment variables
saveenv - save environment variables to persistent storage
protect - enable or disable FLASH write protection
erase	- erase FLASH memory
flinfo	- print FLASH memory information
nand	- NAND memory operations (see doc/README.nand)
bdinfo	- print Board Info structure
iminfo	- print header information for application image
coninfo - print console devices and informations
ide	- IDE sub-system
loop	- infinite loop on address range
loopw	- infinite write loop on address range
mtest	- simple RAM test
icache	- enable or disable instruction cache
dcache	- enable or disable data cache
reset	- Perform RESET of the CPU
echo	- echo args to console
version - print monitor version
help	- print online help
?	- alias for 'help'

监视命令-详细说明:

TODO.

For now: just type "help ".

环境变量:

   U-Boot支持使用环境变量进行用户配置,可以通过将其保存到闪存中来使其持久化。

   使用“ setenv”设置环境变量,使用“ printenv”打印,然后使用“ saveenv”保存到Flash。 使用不带值的“ setenv”可用于从环境中删除变量。 只要不保存环境,您就在使用内存中副本。 万一包含环境的Flash区域被意外擦除,则提供默认环境。

   可以使用环境变量来设置一些配置选项。

环境变量列表(很可能不完整):

baudrate - see CONFIG_BAUDRATE

bootdelay - see CONFIG_BOOTDELAY

bootcmd - see CONFIG_BOOTCOMMAND

bootargs - 引导RTOS映像时的引导参数

bootfile - 用TFTP加载的映像名称

bootm_low - 可以限制bootm命令中可用于 image 处理的内存范围。 该变量以十六进制数形式给出,并定义了bootm命令允许使用的最低地址。 另请参见“ bootm_size”环境变量。 “ bootm_low”定义的地址也是Linux内核的初始内存映射的基础-请参见CONFIG_SYS_BOOTMAPSZ和bootm_mapsize的描述。

bootm_mapsize - Linux内核的初始内存映射的大小。 该变量以十六进制数形式给出,它定义了从基地址bootm_low开始的内存区域的大小,Linux内核在早期引导期间可以访问该区域。 如果未设置,则将CONFIG_SYS_BOOTMAPSZ用作默认值(如果已定义),否则使用bootm_size。

bootm_size - 可以限制bootm命令中可用于 image 处理的内存范围。 该变量以十六进制数形式给出,并定义了bootm命令允许使用的区域的大小。 另请参见“ bootm_low”环境变量。

bootstopkeysha256, bootdelaykey, bootstopkey - See README.autoboot

updatefile - 软件更新文件在TFTP服务器上的位置,由自动软件更新功能使用。 请参阅doc / README.update中的文档以获取更多详细信息。

autoload - 如果设置为“ no”(以“ n”开头的任何字符串),则“ bootp”将仅从BOOTP服务器加载以执行配置查找,但不会尝试使用TFTP加载任何图像

autostart - 如果设置为“是”,使用“ bootp”,“ rarpboot”,“ tftpboot”或“ diskboot”命令加载的映像将自动启动(通过内部调用“ bootm”)
如果设置为“ no”,则传递给“ bootm”命令的独立映像将被复制到加载地址(并最终被解压缩),但不会启动。 这可用于加载和解压缩任意数据。

fdt_high - TODO

   以下映像位置变量包含引导中使用的映像的位置。 “image”列给出了图像的作用,而不是环境变量名称。 其他列是环境变量名称。 “文件名”给出了TFTP服务器上文件的名称,“ RAM地址”给出了映像将被加载到的RAM中的位置,“闪存位置”给出了NOR闪存中的图像地址或NAND闪存中的偏移量。

   注意-不必为所有电路板都定义这些变量,某些电路板当前将其他变量用于这些目的,而某些电路板将这些变量用于其他目的。

ImageFile NameRAM AddressFlash Location
u-bootu-bootu-boot_addr_ru-boot_addr
Linux kernelbootfilekernel_addr_rkernel_addr
device tree blobfdtfilefdt_addr_rfdt_addr
ramdiskramdiskfileramdisk_addr_rramdisk_addr

   网络引导命令(“ bootp”和“ rarpboot”)可能会使用以下环境变量并自动更新这些变量,具体取决于引导服务器提供的信息:

  bootfile	- see above
  dnsip		- IP address of your Domain Name Server
  dnsip2	- IP address of your secondary Domain Name Server
  gatewayip	- IP address of the Gateway (Router) to use
  hostname	- Target hostname
  ipaddr	- see above
  netmask	- Subnet Mask
  rootpath	- Pathname of the root filesystem on the NFS server
  serverip	- see above

两个特殊的环境变量

  • serial# - 包含硬件标识信息,例如类型字符串和/或序列号
  • ethaddr - 以太网地址

这些变量只能设置一次(通常在电路板制造过程中)。 一旦设置了这些变量,U-Boot便拒绝删除或覆盖这些变量。

其他特殊环境变量:

  • ver - 包含使用“ version”命令打印的U-Boot版本字符串。 该变量是只读的(请参见CONFIG_VERSION_VARIABLE)。

请注意,对某些配置参数的更改可能仅在下次启动后生效(是的,就像Windoze:-一样)。

环境变量的回调函数:

   对于某些环境变量,更改其值时,u-boot的行为需要更改。 此功能允许将函数与任意变量关联。 在创建,覆盖或删除时,回调将为发生某些副作用或拒绝更改提供机会。

   使用您的开发板或驱动程序代码中的U_BOOT_ENV_CALLBACK宏命名回调并将其与函数关联。

   这些回调以两种方式之一与变量关联。 可以通过在板配置中将CONFIG_ENV_CALLBACK_LIST_STATIC定义为定义关联列表的字符串来添加静态列表。 该列表必须采用以下格式:

entry = variable_name[:callback_name]
list = entry[,list]

   如果未指定回调名称,则删除该回调。 列表中的任何地方都允许有空格。

   也可以通过使用上面相同的列表格式定义“ .callbacks”变量来关联回调。 “ .callbacks”中的任何关联都将覆盖静态列表中的任何关联。 您可以将CONFIG_ENV_CALLBACK_LIST_DEFAULT定义为列表(字符串),以在默认或嵌入式环境中定义“ .callbacks”环境变量。

   如果定义了CONFIG_REGEX,则上面的variable_name将作为正则表达式求值。 这允许将多个变量连接到同一回调,而无需明确列出所有变量。

回调函数的签名为:

int callback(const char *name, const char *value, enum env_op op, int flags)
  • name - 更改的环境变量
  • value - 环境变量的新值
  • op - 操作(创建,覆盖或删除)
  • flags - 环境变量的属性更改,请参见include / search.h中的标志H_*

如果接受变量更改,则返回值为0,否则为1。

命令行解析:

   U-Boot提供了两种不同的命令行解析器:旧的“简单”解析器和功能更强大的 “hush” shell:

1. 旧的,简单的命令行解析器:

  • 支持环境变量(通过setenv / saveenv命令)
  • 一行上的多个命令,以’;'分隔
  • 使用“ … $ {name} …”语法的变量替换
  • 特殊字符(’$’,’;’)可以通过以’'为前缀进行转义,
    例如:setenv bootcmd bootm \${address}
  • 您也可以通过将单引号引起来来转义文本,例如:
setenv addip 'setenv bootargs $bootargs ip=$ipaddr:$serverip:$gatewayip:$netmask:$hostname::off'

2. Hush shell:

  • 类似于Bourne Shell,具有类似的控制结构
    if…then…else…fi, for…do…done; while…do…done,
    until…do…done, …
  • 支持环境(“global”)变量(通过setenv / saveenv命令)和本地外壳变量(通过标准 shell 语法“name=value”); 只有环境变量可以与“ run”命令一起使用

3. 通用规则:

  1. 如果命令行(或由“ run”命令执行的环境变量)包含多个用分号分隔的命令,而其中一个命令失败,则其余命令将始终执行。
  2. 如果您通过一次运行调用来执行多个变量(即,以一系列变量作为参数调用run),则任何失败的命令都将导致“运行”终止,即。 e。 其余变量不执行。

冗余以太网接口注意事项:

   有些板带有冗余的以太网接口。 U-Boot支持此类配置,并能够在需要时自动选择“工作”界面。 MAC分配工作如下:

   网络接口编号为eth0,eth1,eth2,…相应的MAC地址可以在环境中存储为“ ethaddr”(=> eth0),“ eth1addr”(=> eth1),“ eth2addr”,…

   如果网络接口存储了一些有效的MAC地址(例如,在SROM中),则在环境中没有相应设置的情况下,它将用作默认地址; 如果设置了相应的环境变量,它将覆盖卡中的设置,环境变量的值将用作默认地址; 这意味着:

  • 如果SROM具有有效的MAC地址,并且环境中没有地址,则使用SROM的地址。
  • 如果SROM中没有有效地址,并且环境中存在定义,那么将使用环境变量中的值。
  • 如果SROM和环境都包含MAC地址,并且两个地址相同,则使用此MAC地址。
  • 如果SROM和环境都包含MAC地址,并且地址不同,则使用环境中的值并打印警告。
  • 如果SROM或环境都不包含MAC地址,则会引发错误。 如果定义了CONFIG_NET_RANDOM_ETHADDR,则在这种情况下,将使用本地分配的随机MAC。

   如果以太网驱动程序实现了“ write_hwaddr”功能,则在初始化过程中会将有效的MAC地址编程到硬件中。 可以通过设置适当的’ethmacskip’环境变量来跳过此操作。 命名约定如下:
"ethmacskip" (=>eth0), "eth1macskip" (=>eth1) etc.

Image Formats:

   U-Boot能够以两种格式引导(并对其执行其他辅助操作)image:

1. New uImage format (FIT)

   基于扁平化图像树-FIT的灵活而强大的格式(类似于扁平化设备树)。 它允许使用具有多个组件(几个内核,ramdisk等)的映像,其内容受SHA1,MD5或CRC32保护。 在doc / uImage.FIT目录中找到更多详细信息。

2. Old uImage format

   旧的 uImage 格式基于二进制文件,该文件基本上可以是任何文件,并带有特殊的标头。 有关详细信息,请参见include / image.h中的定义; 标题基本上定义了以下image属性:

  • 目标操作系统(针对OpenBSD,NetBSD,FreeBSD,4.4BSD,Linux,SVR4,Esix,Solaris,Irix,SCO,Dell,NCR,VxWorks,LynxOS,pSOS,QNX,RTEMS,INTEGRITY的设置;当前支持:Linux,NetBSD, VxWorks,QNX,RTEMS,LynxOS,INTEGRITY)。
  • 目标CPU体系结构(针对Alpha,ARM,Intel x86,IA64,MIPS,NDS32,Nios II,PowerPC,IBM S390,SuperH,Sparc,Sparc 64位的规定;当前受支持:ARM,Intel x86,MIPS,NDS32,Nios II, PowerPC)。
  • 压缩类型(未压缩,gzip,bzip2)
  • Load Address
  • Entry Point
  • Image Name
  • Image Timestamp

   标头由特殊的魔术数字标记,并且标头和image的数据部分均通过CRC32校验和进行保护,以防止损坏。

Linux Support:

   尽管U-Boot应该轻松支持任何OS或独立应用程序,但在设计U-Boot时始终将重点放在Linux上。

   到目前为止,U-Boot包含许多功能,这些功能已成为Linux内核中某些特殊的“引导程序”代码的一部分。 而且,要使用的任何“初始”映像都不再是一个大Linux映像的一部分; 相反,内核和“ initrd”是单独的映像。 此实现有几个目的:

  • 相同的功能可用于其他操作系统或独立应用程序(例如:使用压缩映像来减少闪存占用空间)
  • 移植新的Linux内核版本变得容易得多,因为许多底层的,与硬件相关的工作都是由U-Boot完成的
  • 现在可以将同一Linux内核映像与不同的“初始”映像一起使用; 当然,这也意味着可以使用相同的“ initrd”运行不同的内核映像。 这使测试更加容易(只需在“ initrd”中更改文件,就不必构建新的“ zImage.initrd” Linux映像)。 而且,现在可以更轻松地对该软件进行现场升级。

Linux HOWTO:

1. 将Linux移植到基于U-Boot的系统:

   U-Boot无法避免您进行所有必要的修改来配置Linux设备驱动程序以与目标硬件一起使用(不,我们不打算为Linux提供完整的虚拟机接口:-)。

   但是现在您可以忽略所有引导加载程序代码(在arch / powerpc / mbxboot中)。

   只要确保您的计算机专用头文件(例如include / asm-ppc / tqm8xx.h)包含与我们在include / asm- /u-boot.h中定义的Board Information结构相同的定义, 确保您对IMAP_ADDR的定义使用与CONFIG_SYS_IMMR中的U-Boot配置相同的值。

   请注意,U-Boot现在具有一个驱动程序模型,这是驱动程序的统一模型。 如果要添加新的驱动程序,请将其放入驱动程序模型中。 如果没有可用的uclass,建议您创建一个。 请参阅doc / driver-model。

2. 配置Linux内核:

   对U-Boot没有特定要求。 确保您的目标系统具有一些根设备(初始ramdisk,NFS)。

3. Building a Linux Image:

   对于U-Boot,不使用“ zImage”或“ bzImage”之类的“常规”构建目标。 如果您使用最新的内核源,则将存在一个新的构建目标“ uImage”,该目标将自动构建U-Boot可用的uImage。 大多数较早的内核还支持“ pImage”目标,该目标是为我们的前一个项目PPCBoot引入的,并使用100%兼容的格式。

Example:

	make TQM850L_defconfig
	make oldconfig
	make dep
	make uImage

   “ uImage”构建目标使用一种特殊的工具(在’tools / mkimage’中)来封装带有标题信息,CRC32校验和等的压缩Linux内核映像,以用于U-Boot。 这就是我们正在做的:

  • 构建标准的“ vmlinux”内核映像(ELF二进制格式):
  • 将内核转换为原始二进制映像:
	${CROSS_COMPILE}-objcopy -O binary \
				 -R .note -R .comment \
				 -S vmlinux linux.bin
  • 压缩二进制图像:
    gzip -9 linux.bin
  • 打包U-Boot的压缩二进制映像:
	mkimage -A ppc -O linux -T kernel -C gzip \
		-a 0 -e 0 -n "Linux Kernel Image" \
		-d linux.bin.gz uImage

   “ mkimage”工具还可用于创建与U-Boot一起使用的ramdisk映像,该映像可以与Linux内核映像分开,也可以合并为一个文件。 “ mkimage”使用64字节的标头封装图像,标头包含有关目标体系结构,操作系统,图像类型,压缩方法,入口点,时间戳,CRC32校验和等信息。

   可以通过两种方式调用“ mkimage”:验证现有图像并打印标题信息,或构建新 image。

  1. 在第一种形式(带有“ -l”选项)中,mkimage列出了现有U-Boot映像的标题中包含的信息; 这包括校验和验证:
	tools/mkimage -l image
	  -l ==> list image header information
  1. 第二种形式(带有“ -d”选项)用于从“数据文件”构建 U-boot image,该文件用作 image 有效负载:
	tools/mkimage -A arch -O os -T type -C comp -a addr -e ep \
		      -n name -d data_file image
	  -A ==> set architecture to 'arch'
	  -O ==> set operating system to 'os'
	  -T ==> set image type to 'type'
	  -C ==> set compression type 'comp'
	  -a ==> set load address to 'addr' (hex)
	  -e ==> set entry point to 'ep' (hex)
	  -n ==> set image name to 'name'
	  -d ==> use image data from 'datafile'

   现在,用于PowerPC系统的所有Linux内核都使用相同的加载地址(0x00000000),但是入口点地址取决于内核版本:

  • 2.2.x kernels have the entry point at 0x0000000C,
  • 2.3.x and later kernels have the entry point at 0x00000000.

因此,构建U-Boot映像的典型调用为

	-> tools/mkimage -n '2.4.4 kernel for TQM850L' \
	> -A ppc -O linux -T kernel -C gzip -a 0 -e 0 \
	> -d /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux.gz \
	> examples/uImage.TQM850L
	Image Name:   2.4.4 kernel for TQM850L
	Created:      Wed Jul 19 02:34:59 2000
	Image Type:   PowerPC Linux Kernel Image (gzip compressed)
	Data Size:    335725 Bytes = 327.86 kB = 0.32 MB
	Load Address: 0x00000000
	Entry Point:  0x00000000

要验证 image 的内容(或检查是否损坏):

	-> tools/mkimage -l examples/uImage.TQM850L
	Image Name:   2.4.4 kernel for TQM850L
	Created:      Wed Jul 19 02:34:59 2000
	Image Type:   PowerPC Linux Kernel Image (gzip compressed)
	Data Size:    335725 Bytes = 327.86 kB = 0.32 MB
	Load Address: 0x00000000
	Entry Point:  0x00000000

   注意:对于启动时间很关键的嵌入式系统,您可以以内存换取速度并安装UNCOMPRESSED映像:这在Flash中需要更多空间,但由于不需要解压缩,因此启动速度要快得多:

	-> gunzip /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux.gz
	-> tools/mkimage -n '2.4.4 kernel for TQM850L' \
	> -A ppc -O linux -T kernel -C none -a 0 -e 0 \
	> -d /opt/elsk/ppc_8xx/usr/src/linux-2.4.4/arch/powerpc/coffboot/vmlinux \
	> examples/uImage.TQM850L-uncompressed
	Image Name:   2.4.4 kernel for TQM850L
	Created:      Wed Jul 19 02:34:59 2000
	Image Type:   PowerPC Linux Kernel Image (uncompressed)
	Data Size:    792160 Bytes = 773.59 kB = 0.76 MB
	Load Address: 0x00000000
	Entry Point:  0x00000000

   类似地,当内核打算使用初始ramdisk时,可以从ramdisk.image.gz文件构建U-Boot映像:

	-> tools/mkimage -n 'Simple Ramdisk Image' \
	> -A ppc -O linux -T ramdisk -C gzip \
	> -d /LinuxPPC/images/SIMPLE-ramdisk.image.gz examples/simple-initrd
	Image Name:   Simple Ramdisk Image
	Created:      Wed Jan 12 14:01:50 2000
	Image Type:   PowerPC Linux RAMDisk Image (gzip compressed)
	Data Size:    566530 Bytes = 553.25 kB = 0.54 MB
	Load Address: 0x00000000
	Entry Point:  0x00000000

   “ dumpimage”是用于分解由mkimage构建的图像的工具。 它的“ -i”选项执行mkimage第二种形式的相反操作(“ -d”选项)。 给定由mkimage构建的图像,dumpimage从图像中提取“数据文件”:

	tools/dumpimage -i image -T type -p position data_file
	  -i ==> extract from the 'image' a specific 'data_file'
	  -T ==> set image type to 'type'
	  -p ==> 'position' (starting at 0) of the 'data_file' inside the 'image'

4. Installing a Linux Image:

   要通过串行(控制台)界面下载U-Boot映像,必须将映像转换为S-Record格式:

objcopy -I binary -O srec examples/image examples/image.srec

   'objcopy’无法理解U-Boot映像头中的信息,因此生成的S-Record文件将相对于地址0x00000000。 要将其加载到给定地址,您需要使用“ loads”命令将目标地址指定为“ offset”参数。

示例:将映像安装到地址0x40100000(在TQM8xxL上位于第一个Flash库中):

	=> erase 40100000 401FFFFF

	.......... done
	Erased 8 sectors

	=> loads 40100000
	## Ready for S-Record download ...
	~>examples/image.srec
	1 2 3 4 5 6 7 8 9 10 11 12 13 ...
	...
	15989 15990 15991 15992
	[file transfer complete]
	[connected]
	## Start Addr = 0x00000000

您可以使用“ iminfo”命令检查下载是否成功; 这包括校验和验证,因此您可以确定没有发生数据损坏:

	=> imi 40100000

	## Checking Image at 40100000 ...
	   Image Name:	 2.2.13 for initrd on TQM850L
	   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
	   Data Size:	 335725 Bytes = 327 kB = 0 MB
	   Load Address: 00000000
	   Entry Point:	 0000000c
	   Verifying Checksum ... OK

5. Boot Linux:

   “ bootm”命令用于引导存储在内存(RAM或闪存)中的应用程序。 如果是Linux内核映像,则将“ bootargs”环境变量的内容作为参数传递给内核。 您可以使用“ printenv”和“ setenv”命令检查和修改此变量:

	=> printenv bootargs
	bootargs=root=/dev/ram

	=> setenv bootargs root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2

	=> printenv bootargs
	bootargs=root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2

	=> bootm 40020000
	## Booting Linux kernel at 40020000 ...
	   Image Name:	 2.2.13 for NFS on TQM850L
	   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
	   Data Size:	 381681 Bytes = 372 kB = 0 MB
	   Load Address: 00000000
	   Entry Point:	 0000000c
	   Verifying Checksum ... OK
	   Uncompressing Kernel Image ... OK
	Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:35:17 MEST 2000
	Boot arguments: root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
	time_init: decrementer frequency = 187500000/60
	Calibrating delay loop... 49.77 BogoMIPS
	Memory: 15208k available (700k kernel code, 444k data, 32k init) [c0000000,c1000000]
	...

   如果要使用初始RAM磁盘引导Linux内核,请将内核和initrd映像(PPBCOOT格式!)的内存地址都传递给“ bootm”命令:

	=> imi 40100000 40200000

	## Checking Image at 40100000 ...
	   Image Name:	 2.2.13 for initrd on TQM850L
	   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
	   Data Size:	 335725 Bytes = 327 kB = 0 MB
	   Load Address: 00000000
	   Entry Point:	 0000000c
	   Verifying Checksum ... OK

	## Checking Image at 40200000 ...
	   Image Name:	 Simple Ramdisk Image
	   Image Type:	 PowerPC Linux RAMDisk Image (gzip compressed)
	   Data Size:	 566530 Bytes = 553 kB = 0 MB
	   Load Address: 00000000
	   Entry Point:	 00000000
	   Verifying Checksum ... OK

	=> bootm 40100000 40200000
	## Booting Linux kernel at 40100000 ...
	   Image Name:	 2.2.13 for initrd on TQM850L
	   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
	   Data Size:	 335725 Bytes = 327 kB = 0 MB
	   Load Address: 00000000
	   Entry Point:	 0000000c
	   Verifying Checksum ... OK
	   Uncompressing Kernel Image ... OK
	## Loading RAMDisk Image at 40200000 ...
	   Image Name:	 Simple Ramdisk Image
	   Image Type:	 PowerPC Linux RAMDisk Image (gzip compressed)
	   Data Size:	 566530 Bytes = 553 kB = 0 MB
	   Load Address: 00000000
	   Entry Point:	 00000000
	   Verifying Checksum ... OK
	   Loading Ramdisk ... OK
	Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:32:08 MEST 2000
	Boot arguments: root=/dev/ram
	time_init: decrementer frequency = 187500000/60
	Calibrating delay loop... 49.77 BogoMIPS
	...
	RAMDISK: Compressed image found at block 0
	VFS: Mounted root (ext2 filesystem).

	bash#

6. 启动Linux并传递一个平面设备树:

   首先,必须使用适当的定义来编译U-Boot。 有关更深入的说明,请参见上面标题为“ Linux内核接口”的部分。 以下是如何启动内核并传递更新的平面设备树的示例:

=> print oftaddr
oftaddr=0x300000
=> print oft
oft=oftrees/mpc8540ads.dtb
=> tftp $oftaddr $oft
Speed: 1000, full duplex
Using TSEC0 device
TFTP from server 192.168.1.1; our IP address is 192.168.1.101
Filename 'oftrees/mpc8540ads.dtb'.
Load address: 0x300000
Loading: #
done
Bytes transferred = 4106 (100a hex)
=> tftp $loadaddr $bootfile
Speed: 1000, full duplex
Using TSEC0 device
TFTP from server 192.168.1.1; our IP address is 192.168.1.2
Filename 'uImage'.
Load address: 0x200000
Loading:############
done
Bytes transferred = 1029407 (fb51f hex)
=> print loadaddr
loadaddr=200000
=> print oftaddr
oftaddr=0x300000
=> bootm $loadaddr - $oftaddr
## Booting image at 00200000 ...
   Image Name:	 Linux-2.6.17-dirty
   Image Type:	 PowerPC Linux Kernel Image (gzip compressed)
   Data Size:	 1029343 Bytes = 1005.2 kB
   Load Address: 00000000
   Entry Point:	 00000000
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
Booting using flat device tree at 0x300000
Using MPC85xx ADS machine description
Memory CAM mapping: CAM0=256Mb, CAM1=256Mb, CAM2=0Mb residual: 0Mb
[snip]

7. More About U-Boot Image Types:

TODO

8. Booting the Linux zImage:

   在某些平台上,可以启动Linux zImage。 这是使用“ bootz”命令完成的。 “ bootz”命令的语法与“ bootm”命令的语法相同。

   注意,定义CONFIG_SUPPORT_RAW_INITRD允许用户向内核提供原始的initrd映像。 语法略有不同,initrd的地址必须以其大小增加,格式如下:“ :”。

Standalone HOWTO:

   U-Boot的功能之一是可以动态加载和运行“独立”应用程序,这些应用程序可以使用U-Boot的某些资源,例如控制台I / O功能或中断服务。

来源中包含两个简单的示例:

1. “Hello World” Demo:

   “ examples / hello_world.c”包含一个小的“ Hello World”演示应用程序; 构建U-Boot时会自动编译该文件。 它配置为在地址0x00040004上运行,因此您可以像这样玩它:

	=> loads
	## Ready for S-Record download ...
	~>examples/hello_world.srec
	1 2 3 4 5 6 7 8 9 10 11 ...
	[file transfer complete]
	[connected]
	## Start Addr = 0x00040004

	=> go 40004 Hello World! This is a test.
	## Starting application at 0x00040004 ...
	Hello World
	argc = 7
	argv[0] = "40004"
	argv[1] = "Hello"
	argv[2] = "World!"
	argv[3] = "This"
	argv[4] = "is"
	argv[5] = "a"
	argv[6] = "test."
	argv[7] = "<NULL>"
	Hit any key to exit ...

	## Application terminated, rc = 0x0

2. interrupt

   可以在“ examples / timer.c”中找到另一个示例,该示例演示了如何使用U-Boot代码注册CPM中断处理程序。 此处,将CPM计时器设置为每秒产生一次中断。 中断服务程序很简单,只是打印一个“。”。 角色,但这只是一个演示程序。 可以通过以下键控制该应用程序:

	? - print current values og the CPM Timer registers
	b - enable interrupts and start timer
	e - stop timer and disable interrupts
	q - quit application

	=> loads
	## Ready for S-Record download ...
	~>examples/timer.srec
	1 2 3 4 5 6 7 8 9 10 11 ...
	[file transfer complete]
	[connected]
	## Start Addr = 0x00040004

	=> go 40004
	## Starting application at 0x00040004 ...
	TIMERS=0xfff00980
	Using timer 1
	  tgcr @ 0xfff00980, tmr @ 0xfff00990, trr @ 0xfff00994, tcr @ 0xfff00998, tcn @ 0xfff0099c, ter @ 0xfff009b0

Hit 'b':
	[q, b, e, ?] Set interval 1000000 us
	Enabling timer
Hit '?':
	[q, b, e, ?] ........
	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0xef6, ter=0x0
Hit '?':
	[q, b, e, ?] .
	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x2ad4, ter=0x0
Hit '?':
	[q, b, e, ?] .
	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x1efc, ter=0x0
Hit '?':
	[q, b, e, ?] .
	tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x169d, ter=0x0
Hit 'e':
	[q, b, e, ?] ...Stopping timer
Hit 'q':
	[q, b, e, ?] ## Application terminated, rc = 0x0

Minicom warning:

   随着时间的流逝,许多人报告了尝试使用“ minicom”终端仿真程序进行串行下载时遇到的问题。 我(wd)认为minicom坏了,建议不要使用它。 在Unix下,我建议将C-Kermit用于一般用途(尤其是用于kermit二进制协议下载(“ loadb”命令),并使用“ cu”用于S-Record下载(“ loads”命令)。请参阅 http://www.denx.de/wiki/view/DULG/SystemSetup#Section_4.3 寻求有关kermit的帮助。

   但是,如果绝对要使用它,请尝试将此配置添加到“文件传输协议”部分:

	   Name	   Program			Name U/D FullScr IO-Red. Multi
	X  kermit  /usr/bin/kermit -i -l %l -s	 Y    U	   Y	   N	  N
	Y  kermit  /usr/bin/kermit -i -l %l -r	 N    D	   Y	   N	  N

NetBSD Notes:

   从0.9.2版开始,U-Boot作为主机(构建U-Boot)和目标系统(引导NetBSD / mpc8xx)都支持NetBSD。

   建筑需要一个交叉的环境; 众所周知,它可以通过交叉powerpc-netbsd-1.3软件包在NetBSD / i386上运行(由于Makefile与BSD make不兼容,因此您还需要gmake)。 请注意,cross-powerpc软件包不安装包含文件。 由于缺少<machine / ansi.h>,尝试构建U-Boot将会失败。 此文件必须手动安装和修补:

	# cd /usr/pkg/cross/powerpc-netbsd/include
	# mkdir powerpc
	# ln -s powerpc machine
	# cp /usr/src/sys/arch/powerpc/include/ansi.h powerpc/ansi.h
	# ${EDIT} powerpc/ansi.h	## must remove __va_list, _BSD_VA_LIST

   由于本机和U-Boot包含文件之间的不兼容性,本机版本“不起作用”。

   引导假定引导的映像(的第一部分)是第二阶段加载程序,该加载程序依次加载然后调用内核。 加载程序源将最终出现在NetBSD源树中(可能在 sys/arc/mpc8xx/stand/u-boot_stage2/ 中); 同时,请参见ftp://ftp.denx.de/pub/u-boot/ppcboot_stage2.tar.gz

Implementation Internals:

   以下内容并非旨在完整描述每个实施细节。 但是,这应该有助于了解U-Boot的内部工作原理,并使其更容易移植到自定义硬件上。

1. Initial Stack, Global Data:

   U-Boot的实现非常复杂,因为U-Boot开始会用完ROM(闪存),通常无法访问系统RAM(因为尚未初始化内存控制器)。 这意味着我们没有可写的Data或BSS段,并且BSS没有初始化为零。 为了使C环境完全正常运行,我们必须至少分配一个最小的堆栈。 对此的实现选项由所使用的CPU定义和限制:某些CPU型号提供片上存储器(例如MPC8xx和MPC826x处理器上的IMMR区域),在其他(部分)数据缓存中,其锁定为(mis-) 用作内存等

克里斯·哈里南(Chris Hallinan)在U-Boot邮件列表中很好地总结了这些问题:

Subject: RE: [U-Boot-Users] RE: More On Memory Bank x (nothingness)?
From: “Chris Hallinan” <clh@net1plus.com>
Date: Mon, 10 Feb 2003 16:43:46 -0500 (22:43 MET)

   伙计们,如果我错了,请纠正我,但是我的理解是这样的:将DCACHE用作Stack等的初始RAM,不需要任何物理RAM来备份缓存。 聪明之处在于,在设置SDRAM控制器之前,将缓存用作必需存储的临时供应。 详细信息已超出此列表的范围,但是您可以通过研究缓存体系结构以及体系结构和特定于处理器的手册中的操作来了解其工作原理。

   OCM是片上存储器,我相信405GP具有4K。 对于系统设计人员来说,另一种选择是在SDRAM可用之前用作初始堆栈/ RAM区域。 两种选择都应该适合您。 如果您的电路板设计人员没有将CS 4用于某些会在初次启动时引起您痛苦的事情,那么使用CS 4应该没问题! 它经常不使用。

   CONFIG_SYS_INIT_RAM_ADDR应该位于不会干扰处理器/主板/系统设计的地方。 您可以在核桃.h中的任何最新u-boot发行版中找到的默认值都可以使用。 我将其设置为大于您的SDRAM模块的值。 如果您有64MB SDRAM模块,请将其设置为400_0000以上。 只要确保您的董事会没有任何资源可以响应该地址! start.S中的代码已经存在了一段时间,当您正确配置后,它应该可以正常工作。

-Chris Hallinan
DS4.COM, Inc.

   必须记住这一点,因为它会对初始化过程的C代码产生一些影响:

  • 初始化的全局数据(数据段)是只读的。 不要尝试写它。
  • 完全不要使用任何未初始化的全局数据(或隐式初始化为零数据-BSS段)-这是未定义的,稍后会执行初始化(在移至RAM时)。
  • 堆栈空间非常有限。 避免大数据缓冲区或类似的事情。

   仅将堆栈作为可写内存限制意味着我们无法使用常规的全局数据在代码之间共享信息。 但是事实证明,通过使所有功能都可以使用全局数据结构(gd_t),可以大大简化U-Boot的实现。 我们可以将指向此数据的指针作为所有函数的参数传递,但这会使代码膨胀。 取而代之的是,我们使用GCC编译器的功能(全局寄存器变量)来共享数据:我们将指向全局数据的指针(gd)放入我们为此保留的寄存器中。

   当出于这种目的选择寄存器时,我们会受到当前架构的相关(E)ABI规范以及GCC实施的限制。


On ARM, the following registers are used:

	R0:		function argument word/integer result
	R1-R3:	function argument word
	R9:		platform specific
	R10:	stack limit (used only if stack checking is enabled)
	R11:	argument (frame) pointer
	R12:	temporary workspace
	R13:	stack pointer
	R14:	link register
	R15:	program counter

    ==> U-Boot will use R9 to hold a pointer to the global data

    Note: on ARM, only R_ARM_RELATIVE relocations are supported.

Other TODO

2. Memory Management:

   U-Boot在系统状态下运行并使用物理地址,即MMU既不用于地址映射也不用于内存保护。

   使用内存控制器将可用内存映射到固定地址。 在此过程中,即使每种存储类型都由几个物理存储体组成,也会为每种存储类型(闪存,SDRAM,SRAM)形成一个连续的块。

   U-Boot安装在第一个Flash bank的前128 kB中(在TQM8xxL模块上,这是范围0x40000000 … 0x4001FFFF)。 在启动并调整DRAM的大小并对其进行初始化之后,代码会将其自身重新定位到DRAM的高端。 在U-Boot代码的正下方,保留了一些内存供malloc()使用[请参见CONFIG_SYS_MALLOC_LEN配置设置]。 在其下,放置具有全局董事会信息数据的结构,然后是堆栈(向下增长)。

   此外,某些异常处理程序代码被复制到DRAM的低8 kB(0x00000000 … 0x00001FFF)。

   因此,具有16 MB DRAM的典型内存配置如下所示:

	0x0000 0000	Exception Vector code
	      :
	0x0000 1FFF
	0x0000 2000	Free for Application Use
	      :
	      :

	      :
	      :
	0x00FB FF20	Monitor Stack (Growing downward)
	0x00FB FFAC	Board Info Data and permanent copy of global data
	0x00FC 0000	Malloc Arena
	      :
	0x00FD FFFF
	0x00FE 0000	RAM Copy of Monitor Code
	...		eventually: LCD or video framebuffer
	...		eventually: pRAM (Protected RAM - unchanged by reset)
	0x00FF FFFF	[End of RAM]

3. System Initialization:

   在重置配置中,U-Boot从重置入口点开始(在大多数PowerPC系统上,地址为0x00000100)。 由于CS0#的重置配置,因此它是板载闪存的镜像。 为了能够重新映射存储器,U-Boot随后跳至其链接地址。 为了能够在C中实现初始化代码,在内部双端口RAM(如果提供类似功能的CPU)或数据的锁定部分中设置了一个(小!)初始堆栈。
缓存。 之后,U-Boot初始化CPU内核,缓存和SIU。

   接下来,使用初步映射来映射所有(潜在)可用的存储体。 例如,我们将它们放在512 MB边界上(0x20000000的倍数:0x00000000和0x20000000上的SDRAM,0x40000000和0x60000000上的Flash,0x80000000上的SRAM)。 然后,对UPM A进行编程以进行SDRAM访问。 使用临时配置,将运行简单的内存测试,以确定SDRAM存储区的大小。

   如果有多个SDRAM存储区,并且存储区的大小不同,则首先映射最大的存储区。 对于相等的大小,将首先映射第一个存储区(CS2#)。 第一个映射始终是针对地址0x00000000的,后面紧跟着任何其他存储区以创建从0开始的连续存储器。

   然后,监视器将自身安装在SDRAM区域的高端,并分配内存以供malloc()和全局Board Info数据使用; 同样,将异常向量代码复制到低RAM页面中,并建立最终堆栈。

   只有在此重定位之后,您才能拥有“正常”的C环境。 直到您受到多种方式的限制,主要是因为您是从ROM运行,并且因为必须将代码重定位到RAM中的新地址。

4. U-Boot移植指南:

[Based on messages by Jerry Van Baren in the U-Boot-Users mailing list, October 2002]

int main(int argc, char *argv[])
{
	sighandler_t no_more_time;

	signal(SIGALRM, no_more_time);
	alarm(PROJECT_DEADLINE - toSec (3 * WEEK));

	if (available_money > available_manpower) {
		Pay consultant to port U-Boot;
		return 0;
	}

	Download latest U-Boot source;

	Subscribe to u-boot mailing list;

	if (clueless)
		email("Hi, I am new to U-Boot, how do I get started?");

	while (learning) {
		Read the README file in the top level directory;
		Read http://www.denx.de/twiki/bin/view/DULG/Manual;
		Read applicable doc/README.*;
		Read the source, Luke;
		/* find . -name "*.[chS]" | xargs grep -i <keyword> */
	}

	if (available_money > toLocalCurrency ($2500))
		Buy a BDI3000;
	else
		Add a lot of aggravation and time;

	if (a similar board exists) {	/* hopefully... */
		cp -a board/<similar> board/<myboard>
		cp include/configs/<similar>.h include/configs/<myboard>.h
	} else {
		Create your own board support subdirectory;
		Create your own board include/configs/<myboard>.h file;
	}
	Edit new board/<myboard> files
	Edit new include/configs/<myboard>.h

	while (!accepted) {
		while (!running) {
			do {
				Add / modify source code;
			} until (compiles);
			Debug;
			if (clueless)
				email("Hi, I am having problems...");
		}
		Send patch file to the U-Boot email list;
		if (reasonable critiques)
			Incorporate improvements from email list code review;
		else
			Defend code as written;
	}

	return 0;
}

void no_more_time (int sig)
{
      hire_a_guru();
}

可能在 while (learning) 是死循环吧? :)

5. Coding Standards:

6. Submitting Patches:

   

   

   

   

   

   

   

   

   

   

   

   

   

   

   

   

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值