1.嵌入式系统启动过程
嵌入式系统启动过程是指从系统通电开始,经过一系列的步骤,使嵌入式处理器由复位状态进入到操作系统和程序可以正常运行的状态。启动过程如下图五个步骤:
- 第1步:运行固件
固件(Firmware)是一种常被写入ROM中的程序代码,它控制设备的基本操作和功能。不同设备的固件,其功能不同,如路由器、打印机、电视机顶盒等的固件是连接硬件和软件的桥梁,确保硬件能够正确运行并响应软件发出的指令个人计算机的固件,即BIOS,初始化CPU、内存、显卡、键盘和鼠标等硬件并检查硬件是否硬件是否正常,应道操作系统加载;嵌入式系统的固件用于设置基本任务和将引导加载程序加载到内存中,并跳转到引导加载程序在内存中的起始位置。固件是生产商在设备制造过程中被写入ROM中,不可修改。
特别说明:某些嵌入式系统没有此过程,直接从引导加载程序开始运行。
- 第2步:运行引导加载程序
引导加载程序(Bootloader)是始化硬件、设置内存和将操作系统内核映像从外存里加载到内存中的程序代码。Bootloader由设备生产商提供或从互联网上下载,经过处理后,移植到设备的外存里。
- 第3步:运行操作系统内核
操作系统内核(简称内核或kernel)是初始化内存、设备驱动、中断服务程序、网络堆栈等硬件的程序代码。内核由设备生产商提供或从互联网上下载。
- 第4步:挂载根文件系统
根文件系统(rootfs)是构成系统启动和运行所需文件和目录的程序代码。
rootfs的作用:
提供文件和目录组织:使得用户和应用程序能够方便地访问和管理存储在系统中的文件和目录。
启动初始化:根文件系统包含了系统启动所需的各种文件,如内核映像、初始化脚本(如init脚本或Systemd)以及设备文件等。
- 第5步:启动系统进程
根文件系统挂载完成后,会启动第一个进程,即init进程,其进程编号为1,是其它进程的父进程。init进程在启动后会继续启动其他系统进程和服务,从而为系统提供完整的功能。
- 第6步:执行应用程序
上面五步执行完成后,嵌入式系统就启动成功了。用户就可以执行应用程序了。
2.S5P6818开发板启动过程
本章节结合S5P6818开发板详述嵌入式系统启动的过程。S5P6818开发板启动过程如下图:
- 第①步:运行固件
S5P6818开发板上电后,首选运行iROM内的固件,此固件会初始化PLL、时钟和堆栈以及设置看门狗等基础任务,然后选择外存(S5P6818开发板的外存有eMMC、USB1、USB2、USB3、SD0、SD1等,从中选择一个外存),并从选中的外存中将Bootloader加载到iRAM中、最后跳转到Bootloader在iRAM的起始位置。此阶段称为BL0。
- 第②步:运行引导加载程序
此步骤分为两个阶段:BL1和BL2。对于S5P6818开发板在第①步实际加载到iRAM中的Bootloader只有部分代码,通常是Bootloader前16KB代码,加载并跳转完成后,运行此部分代码,此部分代码会初始化DDR3、关闭缓存、设置栈等基础任务,和将剩余的Bootloader代码加载到DDR3中,并跳转到剩余的Bootloader代码在DDR3的起始位置。此阶段称为BL1。
BL1运行完成后,运行DDR3中剩余的Bootloader代码,此部分代码会初始化外部设备、检测系统内存映射、为内核设置启动参数等,和将内核加载到DDR3中,并跳转到内核在DDR3的起始位置。此阶段称为BL2。
特别说明:并不是所有嵌入式系统都分为BL1和BL2两个阶段,而是一个阶段就可以完成这两个阶段的工作,那么在第①步就会将全部的Bootloader代码加载到内存中。只有一个阶段被称为单阶段,多于一个阶段被称为多阶段。多阶段的优点:能够提供更复杂的功能,及有更好的可读性和移植性。
- 第③步:运行操作系统内核
内核初始化内存、设备驱动、中断服务程序、网络堆栈等。
- 第④步:挂载根文件系统
内核初始化完成后,将rootfs加载到DDR3中,并跳转到rootfs在DDR3的起始位置。加载并跳转完成后,运行rootfs,rootfs会创建使用户和应用程序能够方便访问和管理的文件和目录以及初始化脚本和设备文件等。
- 第⑤步和第⑥步的描述同“嵌入式系统启动过程”章节相同
3.Bootloader种类
Bootloader是严重地依赖于硬件而实现的,特别是嵌入式系统。因此,在嵌入式系统里建立一个通用的Bootloader几乎是不可能的,不同处理器架构和板级设备的嵌入式系统使用不同的Bootloader。Bootloader种类如下表:
种类 | 描述 |
---|---|
U-Boot | U-Boot是由PPCBoot、ARMboot和其他一些arch的Loader合并而成的一个开源Bootloader。它支持多种处理器架构,如ARM、X86、PowerPC、MIPS等。 |
Redboot | Redboot是由Redhat公司发布的一个开源Bootloader。它支持多种处理器架构,如ARM、X86、PowerPC、MIPS、MN10300、Renesas SHx、v850等。 |
ARMboot | ARMboot是专为ARM处理器架构设计的一个开源Bootloader。2002年ARMboot终止了维护。 |
vivi | vivi是由韩国mizi公司发布的一个Bootlader,适用于ARM9处理器架构。 |
U-Boot适用于S5P6818开发板,后续会结合U-Boot对嵌入式系统介绍
4.U-Boot移植
4.1.获取U-Boot源码
获取U-Boot源码的方法有两种:官网下载和从设备厂家获取。
- 官网下载
官网下载地址:点击下载
不建议通过此种方法获取U-Boot。因为,从官网下载U-Boot源码是一个通用的、未经特定硬件平台定制的版本。不同的嵌入式系统板级设备具有不同的硬件配置、接口和特性,因此需要对U-Boot源码进行定制和修改,以适应特定硬件平台的需求。
- 从设备厂家获取
建议通过此种方法获取U-Boot。因为,设备厂家提供的U-Boot源码是经过设备厂家定制和修改的,特别适合本家的设备。适用于S5P6818开发板的源码链接地址: (此链接的U-Boot也是设备厂家提供的)或从设备厂家获取。后续会将此种方法获取的U-Boot移植到S5P6818开发板。
4.2.U-Boot源码目录介绍
目录 | 描述 |
---|---|
api | 这个目录里包含的API是U-Boot本身使用的,与嵌入式系统的硬件无关,通常是演示测试的代码。 |
arch | 这个目录存放了与CPU架构相关的文件和代码。每个子目录对应一个特定的CPU架构,如arm、x86、powerpc等,在这些子目录中,你可以找到与架构相关的启动代码、中断处理、时钟设置等。可对不需要的子目录可删除,只保留需要的目录,如针对S5P6818开发板只保留arm子目录即可。 |
board | 这个目录包含了与开发板相关的文件和代码。每个子目录都对应一个特定的开发板或评估板,其中包含了该板的初始化代码、硬件配置、外设驱动等。同“arch”目录一样,只保留需要的目录。在U-Boot源码中,没有针对S5P6818开发板的文件,需要开发板厂家提供。 |
common | 这个目录存放了U-Boot支持的通用命令的代码。每个命令通常对应一个文件。 |
disk | 这个目录包含了与磁盘相关的代码,如分区表、文件系统等。 |
doc | 这是U-Boot的文档目录,其中包含了U-Boot的介绍、使用手册、开发指南等文档。 |
drivers | 这个目录包含了U-Boot支持的各种设备的驱动程序,如串口、以太网、USB、I2C、SPI等。 |
dts | 这个目录存放了设备树源文件(.dts文件),用于描述硬件的结构和配置。 |
examples | 这个目录包含了一些示例代码,用于演示U-Boot的功能和用法。 |
fs | 这个目录包含了U-Boot支持的文件系统的代码,如FAT、JFFS2等。 |
include | 这个目录包含了U-Boot所需的各种头文件,如公共定义、架构相关定义、板级相关定义等。 |
lib | 这个目录存放了与架构相关的库文件,如汇编程序、启动代码等。 |
Licenses | 这个目录包含了U-Boot源码的许可证文件。 |
net | 这个目录包含了与网络相关的代码,如TCP/IP协议栈、BOOTP/DHCP协议等。 |
post | 这个目录包含了上电自检相关的代码。 |
scripts | 这个目录包含了一些用于生成配置文件、编译U-Boot等任务的脚本文件。 |
test | 这个目录包含了一些用于测试U-Boot功能和性能的测试代码和工具。 |
tools | 这个目录包含了一些用于开发U-Boot的辅助工具,如二进制文件转换工具、镜像生成工具等。 |
4.3.U-Boot编译
U-Boot编译是指将U-Boot源码编译成机器语言,即二进制代码。由于设备厂家会对U-Boot的源码进行修改和配置,因此针对不同厂家的设备,编译U-Boot源码的过程会有差异。U-Boot源码的编译过程一般会由设备厂家提供,本教程不讲解U-Boot编译。
编译完成后,会生成一个二进制的ubootpak.bin镜像。
4.4.U-Boot烧写
烧写是指将二进制代买写入到目标设备存储介质中的过程。U-Boot烧写是将ubootpak.bin镜像烧写到eMMC中,以便在设备启动时加载到iRAM和DDR3中并运行。
- 第1步:在Ubuntu上执行sudo apt-get install android-tools-fastboot命令以安装fastboot驱动
- 第2步:使用Micro USB数据线链接开发板的OTG USB接口和电脑上安装的Ubuntu
- 第3步:启动开发板,在uboot三秒倒计时时按下空格键进入uboot模式
- 第4步:在开发板的uboot模式下输入fastboot命令进入fastboot模式
- 第5步:输入fastboot命令后,Ubuntu会弹出如下图弹窗,选择“链接到虚拟机”并点击“确定”按钮
- 第6步:在Ubuntu上进入ubootpak.bin所在目录,输入fastboot flash ubootpak ubootpak.bin命令进行烧写
- 第7步:烧写成功后,在开发板的fastboot模式下可以看到“Flash : ubootpak – DONE”提示。按Ctrl+C退出fastboot模式,进入uboot模式,然后输入reset命令以重启开发板
4.5.U-Boot命令介绍
4.5.1.查看U-Boot命令
- 查看U-Boot支持的命令
启动开发板,在uboot三秒倒计时按下空格键进入uboot模式,然后输入help命令,即可查看U-Boot所有的命令。如下图:
- 查看某个U-Boot命令的详细用法
用法:help <command name>。<command name>为命令名称。示例如下图:
4.5.2.U-Boot命令分类
分类 | 命令 | 描述 |
---|---|---|
基础命令 | help | 显示命令的用法 |
version | 显示U-Boot的版本信息 | |
bdinfo | 显示板卡信息 | |
reset | 重启系统 | |
sleep | 使U-Boot延迟执行一段时间 | |
test | 执行一些简单的自检程序 | |
环境变量操作命令 | printenv | 打印环境变量的值 |
setenv | 设置环境变量的值 | |
saveenv | 保存环境变量的更改 | |
内存操作命令 | md | 显示内存内容 |
mw | 修改内存内容 | |
cp | 在内存中复制数据块 | |
cmp | 比较内存区域的内容 | |
crc32 | 计算内存区域的CRC32校验和 | |
网络命令 | ping | 发送ICMP ECHO_REQUEST到网络主机 |
dhcp | 通过DHCP获取IP地址 | |
tftpboot | 过TFTP协议从网络服务器下载文件 | |
nfs | 通过NFS协议挂载网络文件系统 | |
httpd | 启动一个简单的HTTP服务器 | |
存储命令 | mmc | 操作MMC/SD/eMMC存储设备 |
nand | 操作NAND闪存设备 | |
ubi | 操作UBI | |
ubifs | 操作UBIFS文件系统 | |
fatload | 用于从外部存储设备(如 USB 闪存驱动器、SD 卡等)加载数据到内存中 | |
fatls | 用于查询 FAT 格式设备的目录和文件信息 | |
fatinfo | 用于查询指定 MMC 设备分区的文件系统信息 | |
ext2load | 用于从EXT2格式的设备中加载文件到内存中 | |
ext2ls | 用于列出EXT2格式设备的目录和文件信息 | |
ext4load | 用于从EXT4格式的设备中加载文件到内存中 | |
ext4ls | 用于列出EXT4格式设备的目录和文件信息 | |
引导加载命令 | bootm | 从内存引导内核映像 |
bootp | 通过BOOTP/DHCP协议获取网络引导信息 | |
bootz | 引导zImage格式的内核映像 | |
go | 跳转到指定地址执行代码 | |
Flash内存操作命令 | base | 用于设置或显示操作的基地址 |
erase | 用于擦除Flash内存的一个或多个区块 | |
protect | 用于设置Flash内存区域的写保护状态。写保护的区域将无法被擦除或写入新数据 | |
unprotect | 移除Flash内存区域的写保 |