目录
一、Uboot 是什么,为什么要移植
在嵌入式系统的世界里,Uboot 可是个相当关键的角色,它的全称为 Universal Boot Loader,即通用引导加载程序 ,遵循 GPL(General Public License)开源协议。我们可以把它类比为电脑的 BIOS,当我们按下电脑电源键,BIOS 就开始工作,进行硬件自检、初始化等操作,然后引导操作系统启动。Uboot 在嵌入式系统中的作用与之类似,当嵌入式设备通电后,Uboot 首先运行,它负责初始化硬件设备,比如设置 CPU 的工作频率、初始化内存、配置串口等,为后续操作系统内核的启动做好充分准备。
举个例子,在一个基于 ARM 架构的嵌入式开发板中,Uboot 会在系统启动时,先初始化开发板上的 SDRAM,让其能够正常工作,为后续加载操作系统内核提供稳定的内存空间;同时,它还会初始化串口,这样我们就可以通过串口与开发板进行交互,查看启动信息、调试程序等。
那么为什么要进行 Uboot 的移植呢?不同的嵌入式硬件平台,其硬件架构、处理器型号、外设配置等都可能存在差异。比如,一款采用 STM32 处理器的开发板和一款采用英伟达 Jetson 系列芯片的开发板,它们的硬件组成和特性大不相同。而 Uboot 的原始版本并不能直接适配所有的硬件平台,这就需要我们进行移植工作,让 Uboot 能够适应特定的硬件环境,从而实现对不同硬件平台的支持,成功引导操作系统内核启动。
掌握 Uboot 移植技能对于嵌入式开发人员来说至关重要。在实际的嵌入式项目开发中,我们常常会遇到各种各样的硬件平台,只有熟练掌握 Uboot 移植,才能快速让系统在新的硬件上稳定运行,缩短开发周期,提高开发效率 。无论是开发智能穿戴设备、工业控制模块,还是智能家居产品,Uboot 移植都是嵌入式开发过程中不可或缺的一环。
二、前期准备工作
(一)硬件平台了解
在进行 Uboot 移植之前,深入了解目标硬件平台的架构和特性是首要任务。这就好比我们要建造一座房子,必须先了解土地的状况、地形特点等。了解硬件平台,我们需要查阅芯片手册和原理图等关键资料。芯片手册是芯片厂商提供的关于芯片详细信息的文档,它包含了芯片的功能描述、寄存器配置、电气特性等重要内容。以常见的 STM32 芯片手册为例,我们可以从中了解到芯片的内核架构,是 Cortex-M 系列的哪一款内核,以及芯片所包含的各种外设,如定时器、串口、SPI 接口等的详细信息,包括它们的工作模式、寄存器地址等。
原理图则展示了硬件电路板上各个元器件之间的连接关系,就像一幅地图,告诉我们各个硬件模块是如何协同工作的。通过分析原理图,我们可以确定内存芯片的型号和容量,以及它与 CPU 之间的连接方式,这对于 Uboot 初始化内存至关重要。例如,在一款基于 ARM Cortex-A9 架构的开发板原理图中,我们能看到 SDRAM 芯片通过地址总线、数据总线和控制总线与 CPU 相连,并且明确了它们之间的信号连接关系,这为我们在移植 Uboot 时正确配置内存控制器提供了关键依据。
以友善之臂的 Nanopi Neo 开发板为例,它采用的是全志 H3 芯片,这是一款基于 ARM Cortex-A7 架构的四核处理器。通过查阅全志 H3 的芯片手册,我们了解到它内部集成了丰富的外设,如千兆以太网控制器、USB 2.0 接口、SPI 接口、I2C 接口等。再结合 Nanopi Neo 的原理图,我们可以清晰地看到各个外设与处理器之间的连接方式,以及电源电路、复位电路等关键部分的设计。这些信息对于我们后续在该开发板上移植 Uboot 非常重要,比如在 Uboot 中配置以太网驱动时,就需要根据芯片手册和原理图中的信息,正确设置以太网控制器的寄存器,以实现网络功能。了解硬件平台的资源和特性,能让我们在移植 Uboot 时更有针对性地进行配置和优化,确保 Uboot 能够充分发挥硬件的性能 。
(二)软件工具准备
交叉编译工具链:交叉编译工具链是在进行 Uboot 移植时必不可少的工具,它的作用是在一种计算机平台上生成能在另一种不同平台上运行的可执行代码 。比如我们通常在 PC 机(x86 架构)上进行开发,但目标硬件平台可能是基于 ARM 架构的嵌入式开发板,这时候就需要交叉编译工具链将我们编写的 Uboot 源代码编译成适合 ARM 平台运行的二进制文件。选择交叉编译工具链时,要根据目标硬件平台的架构来确定,如针对 ARM 架构,常见的有 arm-linux-gnueabi-gcc、arm-linux-gnueabihf-gcc 等。如果目标平台是 32 位的 ARMv7 及以下版本,且需要支持硬件浮点运算,那么 arm-linux-gnueabihf-gcc 就是一个合适的选择;如果是 64 位的 ARMv8-A 及更高版本架构,则可以选择 aarch64-linux-gnu-gcc。
以在 Ubuntu 系统上安装 arm-linux-gnueabihf-gcc 交叉编译工具链为例,我们可以使用以下命令:
sudo apt-get update
sudo apt-get install gcc-arm-linux-gnueabihf
安装完成后,还需要配置环境变量,将交叉编译工具链的路径添加到系统的 PATH 变量中,这样在命令行中就可以直接使用该工具链。例如,假设交叉编译工具链安装在/usr/bin/目录下,我们可以在~/.bashrc文件中添加以下内容:
export PATH=$PATH:/usr/bin/
然后执行source ~/.bashrc使配置生效。
TFTP、NFS 等辅助工具:TFTP(Trivial File Transfer Protocol)即简单文件传输协议,它主要用于在网络上进行简单的文件传输。在 Uboot 移植过程中,我们可以通过 TFTP 服务器将编译好的 Uboot 镜像文件、内核镜像文件等下载到开发板的内存中,方便进行调试和启动测试。搭建 TFTP 服务器,以在 Ubuntu 系统上搭建为例,我们可以按照以下步骤进行:
-
安装 TFTP 软件包,执行命令:sudo apt-get install tftp-hpa tftpd-hpa,其中tftp-hpa是客户端,tftpd-hpa是服务器端。
-
创建 TFTP 服务器的工作目录,比如mkdir ~/tftpboot,并设置该目录的权限为可读写执行,命令为:sudo chmod 777 ~/tftpboot。
-
配置 TFTP 服务器,编辑/etc/default/tftpd-hpa文件,将TFTP_DIRECTORY的值修改为我们创建的工作目录路径,例如:TFTP_DIRECTORY="/home/yourusername/tftpboot",同时确保TFTP_OPTIONS="-l -c -s" ,其中-l表示使用inetd服务来启动 TFTP 服务器,-c表示允许客户端创建文件,-s表示指定服务器的根目录为我们创建的工作目录。
-
重启 TFTP 服务,执行命令:sudo service tftpd-hpa restart 。
NFS(Network File System)即网络文件系统,它允许网络中的计算机之间通过 TCP/IP 网络共享文件和目录。在 Uboot 移植和嵌入式开发中,NFS 常用于将开发主机上的文件系统挂载到开发板上,这样在开发板上就可以直接访问主机上的文件,方便进行程序调试、文件读写等操作 。在 Ubuntu 系统上搭建 NFS 服务器的步骤如下:
-
安装 NFS 服务器软件包,执行命令:sudo apt-get install nfs-kernel-server。
-
配置 NFS 共享目录,编辑/etc/exports文件,添加需要共享的目录以及允许访问的客户端主机,例如:/home/yourusername/nfsroot *(rw,sync,no_root_squash),其中/home/yourusername/nfsroot是要共享的目录,*表示允许所有主机访问,rw表示可读写权限,sync表示数据同步写入内存和硬盘,no_root_squash表示客户端使用 root 用户访问时,拥有和服务器 root 用户相同的权限。
-
创建 NFS 共享目录,如mkdir /home/yourusername/nfsroot 。
-
重启 NFS 服务,执行命令:sudo /etc/init.d/nfs-kernel-server restart 。
-
测试 NFS 服务器,在客户端主机上执行命令:mount -t nfs 服务器IP:/home/yourusername/nfsroot /mnt,如果挂载成功,就可以在/mnt目录下访问服务器上共享的文件了。