嵌入式Linux(Exynos 4412)笔记
一、系统移植课程导学
1. 计算机系统层次结构
1)计算机系统层次划分
- 三层架构:嵌入式系统作为计算机系统的分支,分为硬件层(最下层)、操作系统层(中间层)和应用程序层(最上层APP)
- 特殊性质:嵌入式系统是特殊的计算机系统,但同样遵循这三层架构
2)硬件层介绍及作用
- 组成要素:包括内存、CPU、硬盘等核心硬件,以及SOC内部的各种硬件接口控制器(如GPIO、PWM、I2C、ADC等)
- 核心功能:实现计算机与外界的数据/信号输入输出,是信息交互的物理基础
- 控制方式:通过寄存器配置直接控制硬件工作(无操作系统时)
3)操作系统层介绍及作用
- 双重作用:
- 向下管理:统一管理计算机系统的软硬件资源
- 向上服务:为应用程序提供API接口(函数调用)
- 设计哲学:"向下管理硬件,向上提供接口",应用程序无需了解底层实现细节
- 典型接口:如文件操作(open/close/read/write)、进程管理(fork/pthread_create)等
4)应用程序层(APP)介绍
- 开发特点:使用操作系统提供的API开发特定功能应用
- 优势体现:开发者只需关注功能实现,无需了解硬件细节(如文件存储位置、网络协议实现等)
- 典型示例:基于Linux系统的各类应用软件
2. 之前介绍复习
1)应用开发与顶层开发
- 本质特征:使用操作系统提供的API进行开发
- 课程示例:IO课程(文件操作函数)、并发程序(进程线程函数)、网络编程(socket函数)、数据库操作函数等
- 共同特点:都是教授操作系统提供的特定功能函数的使用方法
2)操作系统提供的API
- IO接口:open/close/read/write等文件操作函数
- 进程管理:fork/pthread_create等进程线程函数
- 网络通信:socket/listen/connect/accept等网络函数
- 开发范式:调用现成API而不关心底层实现(如TCP协议栈实现)
3)Linux操作系统的五大功能
- 进程管理:创建/调度/销毁进程的机制实现
- 内存管理:内存分配(malloc)/释放(free)及虚拟内存管理
- 网络协议:集成TCP/UDP/IP等协议栈实现
- 文件系统:磁盘/文件管理的底层实现(如ext4文件系统)
- 设备管理:硬件设备驱动管理(LED/ADC/屏幕等)
4)ARM课程的学习内容
- CPU原理:通过汇编语言理解程序执行机制
- 接口技术:I2C/UART/GPIO/ADC/RTC等硬件接口实验
- 学习目的:
- 理解处理器工作原理
- 掌握无系统时的硬件控制方法(直接寄存器配置)
- 为驱动开发打基础(系统下的硬件管理方式不同)
- 系统差异:
- 无系统:直接配置寄存器控制硬件
- 有系统:通过设备文件控制硬件(驱动开发范畴)
- 底层开发本质:开发操作系统本身,包括硬件管理模块的实现
3. 系统移植的意义
1)系统移植定义
- 核心任务:将Linux系统安装到基于ARM处理器的开发板上
- 应用场景:嵌入式设备(如机器人控制)需要轻量化的开发板运行系统,而非直接使用电脑
- 对比传统方式:之前ARM开发板无操作系统,只能运行基础C语言程序
2)系统移植的意义
- 功能限制:未装系统时无法调用任何系统函数(如IO操作、进程线程、网络通信等)
- 开发效率:所有功能需自行实现,仅能完成小型项目
- 移植优势:安装系统后可调用标准库函数,直接运行上层应用程序
- 典型示例:printf/sleep等基础函数在无系统时需要自行实现
4. 移植的目的
1)不同架构处理器指令集不兼容
- 架构差异:ARM与x86等不同架构CPU的汇编指令集完全不同(如除法指令支持)
- 内核实现:Linux内核包含大量汇编代码,需针对特定处理器架构编写
- 兼容问题:用ARM汇编编写的内核无法在x86平台运行,反之亦然
2)相同架构不同板卡驱动代码不兼容
- 外设差异:相同处理器(如三星4412)在不同开发板上外设连接方式不同
- 实例说明:LED可能连接GPX2-7或GPX2-6引脚,需修改寄存器配置代码
- 平台相关代码:驱动程序等与硬件直接交互的代码需随硬件变更而修改
3)Linux内核的通用性与配置需求
- 源码特性:官方提供的是通用内核源码,未针对特定硬件优化
- 获取方式:下载得到的是C/汇编源代码,需自行编译(区别于Windows镜像)
- 匹配需求:必须修改源码使其适配目标硬件平台(处理器架构+外设电路)
4)移植工作的核心:软硬件匹配
- 配置本质:修改内核源码中的平台相关代码(汇编指令+驱动程序)
- 工作流程:下载源码→配置适配→编译→安装
- 时间分配:80%时间用于配置适配,仅20%用于实际安装
- 医学类比:类似器官移植的血型匹配,需确保软硬件参数完全兼容
知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
嵌入式系统层次结构 | 计算机系统分为三层:硬件层(CPU、内存等)、操作系统层(管理硬件、提供API)、应用程序层(APP开发) | 操作系统的作用(向下管理硬件,向上提供接口) | ⭐⭐ |
应用开发 vs 底层开发 | 应用开发:调用操作系统API(如文件IO、进程线程函数);底层开发:开发操作系统本身(如硬件控制、寄存器配置) | 函数调用限制(无系统时无法调用标准库函数) | ⭐⭐⭐ |
系统移植的意义 | 将Linux系统安装到ARM开发板,使应用层程序可在开发板运行(解决无系统时编程局限性) | 为何需要移植(官方源码与硬件不匹配) | ⭐⭐⭐⭐ |
移植的核心工作 | 配置源码(匹配硬件平台)→ 编译 → 安装,重点在硬件与软件的适配(如寄存器配置、外设电路差异) | 平台相关代码(不同硬件需修改汇编/驱动代码) | ⭐⭐⭐⭐ |
课程特点 | 1. 实践性强(无需写代码,侧重配置与安装); 2. 需掌握汇编/C/Shell等语言基础; 3. 重方法轻细节(掌握移植流程而非研究源码) | 学习误区(过度关注Linux源码细节) | ⭐⭐⭐ |
移植流程示例 | 下载源码 → 配置(适配硬件)→ 编译 → 安装到开发板 | 关键步骤优先级(配置>编译>安装) | ⭐⭐⭐⭐ |
二、系统移植过程
1. Windows装机
1)系统安装前的准备
- 系统镜像: 相当于操作系统的压缩包或安装包,可以从系统之家等网站下载,是安装系统的必备文件
- U盘启动盘: 需要准备一个U盘并刷入引导程序(如老毛桃、大白菜),这类程序的功能是引导和安装系统镜像到电脑磁盘中
2)BIOS设置与启动方式
- BIOS本质: 基本输入输出系统(Basic Input Output System),是电脑出厂时固化在主板上的程序,不是操作系统
- 主要功能: 设置硬件参数(如CPU虚拟化功能开关),其中最重要的设置项是启动方式
- 启动方式选择: 决定电脑开机后首先运行哪个介质中的程序(U盘/硬盘/光驱),安装系统时需要设置为U盘启动
3)系统安装过程
- 关键步骤:
- 开机按特定键(F2/F10等)进入BIOS
- 设置U盘为第一启动项
- 重启后自动运行U盘中的引导程序(老毛桃等)
- 通过引导程序将系统镜像安装到硬盘
- 耗时说明: 系统文件复制安装是最耗时的环节,需要耐心等待完成
4)驱动程序的安装
- 驱动功能: 使硬件设备(显卡/网卡/声卡等)能够正常工作的软件程序
- 常见问题: 新装系统后可能出现硬件无法使用的情况(如不能上网、显示异常等)
- 解决方案:
- Windows自带部分通用驱动
- 需要手动安装特定硬件厂商提供的专用驱动
- 确保驱动版本与硬件型号匹配
5)应用程序的安装
- 系统分层:
- 底层:硬件设备
- 中间层:操作系统
- 上层:应用程序(如QQ/PS/视频软件等)
- 安装原则: 根据实际需求选择安装,如通讯、图像处理、影音娱乐等不同用途的应用
- 功能实现: 应用程序通过调用操作系统提供的API接口实现特定功能
2. Linux系统移植
1)准备工作
- 准备内容:
- Linux内核镜像: 类似于Windows系统安装包,是Linux系统的核心部分。
- SD卡启动盘: 用于存储引导程序,以便从SD卡启动并安装系统。这里使用的是SD卡而非U盘。
- 引导程序:
- U-Boot: 在嵌入式系统中常用的引导程序,用于引导和安装操作系统,类似于Windows下的老毛桃、大白菜等工具。
2)选择启动方式
- BIOS与BL0:
- BIOS: 电脑主板上的固化程序,用于设置启动方式等。需开机后进入BIOS界面选择。
- BL0: 开发板(如4412处理器)芯片内固化的代码,类似于BIOS,但设置方式不同。
- 拨码开关: 开发板上用于选择启动方式的开关,不同位置代表不同启动方式(如SD卡启动、eMMC启动等)。设置拨码开关需在断电情况下进行,上电后开发板会根据拨码开关的位置选择启动介质。
3)安装Linux系统
- 安装步骤:
- 拨码开关设置: 将拨码开关拨到SD卡启动位置。
- 上电: 开发板上电后,BL0代码会检测拨码开关位置,并执行SD卡中的程序。
- 运行U-Boot: SD卡中的U-Boot引导程序运行起来,通过U-Boot界面安装Linux内核镜像到开发板(如eMMC)。
4)安装驱动程序
- 驱动需求: Linux系统安装完成后,开发板上的部分硬件可能无法正常工作,因为Linux系统可能不包含这些硬件的驱动程序。
- 安装驱动: 需要手动安装对应硬件的Linux驱动程序,如网卡驱动、LED驱动等。
5)安装应用程序
- 应用程序安装: 根据需求在开发板上安装各种应用程序,实现特定功能。
3. Windows装机与Linux系统移植的比较
- 相似性: Linux系统移植的步骤与Windows装机过程类似,都包括准备系统镜像、选择启动方式、安装系统、安装驱动和应用程序等步骤。
- 差异性:
- 启动方式设置: Windows通过BIOS设置,Linux开发板通过拨码开关设置。
- 引导程序: Windows下可能使用老毛桃、大白菜等工具,Linux下则常用U-Boot。
- 移植工作: 在安装Linux系统之前,还需要对源代码进行配置和编译工作,使其适配特定的开发板。这是Linux系统移植中特有的步骤,Windows装机则不涉及。
知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
嵌入式系统移植概述 | 介绍嵌入式系统移植在课程体系中的位置及意义 | - | 低 |
课程目的 | 给开发板安装Linux系统,便于应用层程序移植 | - | 低 |
学习难点 | 涉及细节性实验,易迷失方向 | 实验细节与整体目的关联 | 中 |
系统移植内容 | 不仅安装Linux,还需安装uboot、文件系统等 | Linux与uboot等区别 | 中 |
系统移植宏观过程 | 回顾Windows装机过程,类比嵌入式Linux系统移植 | 类比理解 | 低 |
Windows装机准备 | 系统镜像、U盘启动盘(老毛桃等) | - | 低 |
BIOS设置 | 设置启动方式(U盘启动) | BIOS与启动方式 | 中 |
安装系统 | 通过引导程序安装系统镜像 | - | 低 |
驱动安装 | 安装网卡、显卡等驱动 | - | 低 |
应用程序安装 | 根据需求安装QQ、微信等APP | - | 低 |
嵌入式Linux系统移植准备 | Linux内核镜像、SD卡启动盘(uboot) | U盘与SD卡启动区别 | 中 |
BL0设置 | 通过拨码开关选择启动方式(SD卡启动) | BIOS与BL0设置方式 | 中 |
安装Linux系统 | 通过uboot安装Linux内核镜像 | uboot与老毛桃功能对比 | 中 |
驱动安装 | 安装LED、网卡等驱动 | Linux与Windows驱动区别 | 中 |
应用程序移植 | 移植IO、进程等代码到开发板 | - | 低 |
移植工作 | 配置、修改、编译Linux源代码 | 安装与移植的区别 | 高 |
三、开发板启动过程
1. 动态图解释开发板启动过程
1)Exynos 4412手册
- 地址映射表复习
- 芯片概述: Exynos 4412 SCP是一款32位RISC处理器,采用Cortex-A9架构,具有低功耗、高性能特点,内置128位总线架构和多种硬件加速器。
- 地址空间特性:
- 采用32位地址总线,寻址空间为
2322^{32}232
=4GB - 通过内存映射表将4GB空间划分为不同功能区域
- 采用32位地址总线,寻址空间为
- 地址映射表定义:
- 将CPU可访问的4GB空间按功能划分为不同区域
- 每个区域对应特定硬件资源(内存、寄存器等)
- 示例区域:0x00000000-0x00010000为iROM区域
- 关键区域划分:
- 0x00000000-0x00010000: 64KB iROM(内部只读存储器)
- 0x02000000-0x02010000: 64KB iRAM(内部随机存储器)
- 0x10000000-0x14000000: 特殊功能寄存器区
- 0x40000000-0xA0000000: 1.5GB 外部内存扩展区
- 0xA0000000-0xFFFFFFFF: 1.5GB 外部内存扩展区
- iROM详解
- 物理特性:
- 位于芯片内部,大小为64KB
- 地址范围:0x00000000-0x00010000
- 内容由三星预先烧录,不可修改
- 功能特性:
- 存储BL0(Boot Loader 0)程序
- CPU上电后PC寄存器默认值为0,首先执行iROM中的BL0
- 类比PC机的BIOS固件
- 物理特性:
- 其他关键区域
- iRAM区域:
- 地址:0x02000000-0x02060000
- 大小:256KB
- 芯片内部高速内存
- SFR区域:
- 地址:0x10000000-0x14000000
- 用于控制各类硬件外设的寄存器
- 包括GPIO、UART、I2C等控制器寄存器
- 外部内存区:
- 共3GB空间(0x40000000-0xFFFFFFFF)
- 通过内存控制器连接外部DRAM
- 实际开发板通常配置1GB物理内存
- iRAM区域:
- 地址映射原理
- 设计目的:
- 解决有限地址空间分配问题
- 实现不同类型存储器的统一寻址
- 隔离不同硬件资源的访问冲突
- 实现方式:
- 通过内存控制器实现地址解码
- 不同地址范围触发不同片选信号
- 示例:访问0x10000000自动选择SFR总线
- 设计目的:
2)开发板各组成部分作用解析
- iROM及固件BL0
- iROM特性:位于处理器内部,地址从
0x0000_00000x0000\_00000x0000_0000
开始,是芯片上电后最先执行的存储区域 - BL0功能:
- 固化在iROM中的初始引导程序
- 执行基本硬件初始化(时钟、内存等)
- 读取启动设备选择信号
- 负责将第二级引导程序加载到内存
- iROM特性:位于处理器内部,地址从
- 拨码开关及其作用
- 物理结构:开发板上有4位拨码开关(标号1-4),位于按键旁
- 核心功能:设置启动介质选择,不同组合对应不同启动方式:
OFF ON ONOFF\ ON\ ONOFF ON ON
:eMMC启动ON OFF OFFON\ OFF\ OFFON OFF OFF
:SD卡启动
- 配置参考:开发板丝印层提供状态对照表,明确各组合对应的启动方式
- 外扩内存条RAM
- 硬件配置:
- 4片256MB内存芯片组成1GB容量
- 位于主控芯片Exynos4412周围
- 地址分配:
- 物理地址范围:
0x4000_00000x4000\_00000x4000_0000
0x8000_00000x8000\_00000x8000_0000
- 芯片预留3GB扩展空间,实际只使用前1GB
0x8000_00000x8000\_00000x8000_0000
0xFFFF_FFFF0xFFFF\_FFFF0xFFFF_FFFF
保留未使用
- 物理地址范围:
- 硬件配置:
- SD卡的作用
- 系统移植用途:存储Uboot和Linux系统镜像
- 启动特性:
- 属于外存设备,程序需加载到内存执行
- 通过拨码开关选择SD卡启动模式
- BL0会检测到SD卡启动后自动加载其中程序
- eMMC的作用
- 硬件特性:
- 相当于电脑硬盘,位于核心板右下角
- 非易失性存储,断电数据不丢失
- 系统运行机制:
- 安装Linux系统的最终存储位置
- 系统运行时从eMMC加载到内存执行
- 包含三部分:Linux内核、设备树(dtb)、根文件系统
- 硬件特性:
3)开发板启动过程动态演示
- BL0阶段:
- 上电后首先执行iROM中的BL0
- 初始化基础硬件环境(时钟、内存控制器等)
- 读取拨码开关确定启动介质
- 将SD卡中的uboot复制到内存(SD卡启动时)
- Uboot阶段:
- 初始化更复杂的硬件环境(堆栈、网卡、串口等)
- 从eMMC加载三部分到内存:
- Linux内核
- 设备树(dtb) - 存储硬件配置信息
- 根文件系统 - Linux运行所需的文件集合
- Linux启动:
- 初始化系统环境
- 挂载根文件系统(将文件系统内容读入内存使用)
- 完成启动后进入正常工作状态
- 关键组件关系:
- 设备树(dtb):分离驱动代码与硬件信息,便于硬件变更
- 根文件系统:包含系统运行所需的配置文件、库文件等
- 三者关系:Linux内核 + 设备树 + 根文件系统 = 完整Linux系统
4)开发板启动过程总结
- BL0的执行与启动方式选择
- BL0执行机制:开发板上电后首先运行SOC内部iROM中固化的代码(BL0),这段代码先对基本的软硬件环境(时钟等)进行初始化
- 启动方式检测:BL0会检测拨码开关位置获取启动方式,根据拨码开关选择从SD卡或eMMC启动
- 程序加载原理:选择SD卡启动时,BL0会将SD卡中的uboot搬移到内存运行(外存程序需加载到内存才能执行)
- U-Boot的加载与运行
- 初始化工作:uboot运行后首先对开发板上的软硬件环境做进一步初始化,包括网卡初始化、串口初始化等
- 系统加载三步骤:
- 将Linux内核从外存搬到内存
- 将设备树(dtb)从外存搬到内存
- 将根文件系统(rootfs)从外存搬到内存
- 加载必要性:这三个组件在外存无法直接执行,必须通过uboot加载到内存才能运行
- Linux系统的加载与运行
- 运行顺序:uboot完成加载后结束运行,Linux开始接管系统
- 初始化过程:Linux首先对系统环境做初始化,包括基本的软硬件初始化
- 组件关系:Linux内核和设备树(dtb)共同组成完整的Linux系统
- 根文件系统的挂载
- 挂载时机:Linux初始化完成后才进行根文件系统挂载
- 挂载方式:
- 常规方式:从内存挂载(如实验演示)
- 常用方式:通过网络挂载(实际开发更常用)
- 功能作用:根文件系统包含Linux运行所需的各类文件
- 启动过程总结与实验说明
- 执行程序序列:
- iROM中的BL0
- uboot
- Linux内核+设备树
- 根文件系统
- 实验注意事项:实际实验中根文件系统通常通过网络挂载,与演示的内存挂载方式不同
- 执行程序序列:
5)系统移植步骤总结
- 移植必要性:要使开发板正常启动,必须预先安装四个组件
- 免移植组件:BL0是芯片固化的,无需移植
- 需移植组件:
- uboot移植(如移植到SD卡)
- Linux内核移植(包含设备树,移植到eMMC)
- 根文件系统移植(移植到eMMC)
- 移植顺序:与程序运行顺序保持一致
- uboot移植
- Linux内核+设备树移植
- 根文件系统移植
- 存储介质选择:不同组件可能安装在不同存储介质(SD卡/eMMC)
知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
开发板启动过程 | 上电后依次执行:BL0(固化在iROM)→ uboot(从SD卡加载)→ Linux内核+设备树(从eMMC加载)→ 挂载根文件系统 | BL0的自动执行机制与地址映射关系(零地址固定分配) | ⭐⭐⭐⭐ |
地址映射表 | 4412芯片的4GB地址空间划分:iROM(64K)、iRAM(256K)、寄存器区(1GB)、外扩内存预留区(15GB) | 外扩内存实际使用1GB(0x40000000-0x80000000),剩余地址未使用 | ⭐⭐⭐ |
uboot作用 | 1. 初始化基础硬件 2. 加载Linux内核+设备树到内存 3. 加载根文件系统到内存 | 设备树与内核的关系(必须同时加载) | ⭐⭐⭐⭐ |
根文件系统 | Linux运行时依赖的文件集合(非代码),需提前加载到内存供内核挂载 | 与普通文件系统的区别(挂载时机与用途) | ⭐⭐⭐ |
系统移植步骤 | 1. 移植uboot到SD卡 2. 移植Linux内核+设备树到eMMC 3. 移植根文件系统到eMMC | 移植顺序与启动流程的严格对应关系 | ⭐⭐⭐⭐ |
拨码开关配置 | 通过1234拨码组合选择启动方式(如SD卡启动:ON-OFF-OFF) | 不同开发板的拨码规则差异(需查丝印表格) | ⭐⭐ |
四、开发板启动过程(续)
1. BL0的初始化与拨码开关检测
- 执行顺序:开发板上电后首先执行固化在芯片内部iROM中的BL0程序
- BL0功能:
- 硬件初始化:对软硬件环境进行基本初始化
- 启动检测:检测拨码开关状态确定启动方式(如SD卡启动)
- 存储特性:BL0由三星公司固化在芯片内部,无需用户移植
2. BL0根据拨码开关加载程序
- 加载机制:
- 检测到SD卡启动方式后,BL0将SD卡中的U-Boot程序复制到内存
- 必要性:外存(SD卡)中的程序无法直接运行,必须加载到内存才能执行
- 内存特性:内存中的程序可直接被CPU运行,而外存程序需要先加载
3. U-Boot的启动与初始化
- 启动流程:
- BL0结束后U-Boot开始运行
- 同样先对软硬件环境进行基本初始化
- 加载内容:将外存中的Linux内核、设备树(dtb)和根文件系统(rootfs)加载到内存
4. U-Boot加载Linux内核与文件系统
- 加载必要性:
- 系统组件安装在外存(断电不丢失)
- 但运行必须加载到内存(CPU只能直接运行内存中的程序)
- 加载顺序:U-Boot依次加载内核→设备树→根文件系统到内存
5. Linux系统的启动与文件系统挂载
- 启动过程:
- Linux内核运行并进行初始化
- 成功启动后挂载根文件系统
- 完整系统:内核+文件系统共同构成可运行的完整Linux系统
6. 系统移植的步骤与顺序
- 移植组件:
- BL0(已固化,无需移植)
- U-Boot
- Linux内核
- 设备树
- 根文件系统
- 移植顺序:遵循代码运行顺序,先移植U-Boot
7. 移植的首要任务:安装U-Boot
- 首要工作:在SD卡中刷入U-Boot
- 后续目标:学会使用U-Boot进行系统引导
五、Boot loader
1. Boot loader的基本功能
- 定义:操作系统运行前执行的小段代码(非操作系统本身)
- 核心功能:
- 环境初始化:将软硬件环境初始化到适合操作系统运行的状态
- 系统引导:加载操作系统到内存(从外存到内存)
- 参数传递:为Linux内核准备并传递启动参数
- 命令执行:支持执行用户命令(类似shell命令)
- 与U-Boot关系:U-Boot是嵌入式Linux最常用的具体Bootloader实现
2. 常见的Bootloader
- 分类特点:
- 通用性:多数Bootloader针对特定平台或系统
- ARM支持:仅少数支持ARM架构(如U-Boot、RedBoot)
- 选择原因:
- 平台兼容:U-Boot支持多种架构(包括ARM)
- 系统兼容:专为Linux设计,非专用引导程序
- 行业标准:嵌入式开发领域最广泛使用的Bootloader
知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
BL0 功能 | 三星芯片固化的初始程序,负责硬件初始化、检测启动方式(如SD卡),并将外部存储器代码加载到内存 | BL0 与 uboot 的分工(BL0 仅加载 uboot,uboot 加载内核) | ⭐⭐ |
uboot 作用 | 1. 初始化软硬件环境; 2. 加载 Linux 内核、设备树、根文件系统到内存; 3. 向内核传递参数; 4. 支持用户命令 | 传参机制(类似函数调用前准备参数)与内存/外存运行差异 | ⭐⭐⭐ |
Linux 系统启动流程 | BL0 → uboot → 内核初始化 → 挂载根文件系统 | 各阶段依赖关系(如内核需依赖 uboot 加载) | ⭐⭐⭐⭐ |
Boot Loader 定义 | 统称引导加载程序(如 uboot),负责操作系统运行前的环境准备 | Boot Loader ≠ 操作系统(仅为操作系统运行做铺垫) | ⭐⭐ |
uboot 特殊性 | 嵌入式开发通用引导程序,支持 ARM 架构和 Linux 系统 | 与其他 Boot Loader(如 RedBoot)的兼容性对比 | ⭐⭐⭐ |
系统移植顺序 | 1. uboot → 2. Linux 内核 → 3. 设备树 → 4. 根文件系统 | BL0 无需移植(芯片固化) | ⭐⭐⭐⭐ |
六、SD卡启动盘制作
1. SD卡的存储结构
- 基本单位:SD卡以扇区(块)为单位存储数据,每个扇区大小为
512Byte512Byte512Byte,与内存的字节寻址方式不同
- 编号规则:所有扇区从0开始线性编号,类似内存地址的排列方式
1)SD卡以扇区为单位存储
- 与内存的区别:
- 内存:以字节为单位(8bit),每个字节有唯一地址(0,1,2...连续排列)
- SD卡:以扇区/块为单位(512Byte),在Linux系统中被称为块设备
- 类比说明:如同书本分页存储,每个扇区相当于书的一页,但每页固定为512字节容量
2)零扇区存储分区表
- 特殊用途:第0扇区专门存储分区表(类似书籍目录页),记录全部分区范围信息
- 分区表示例:如8G SD卡可分为:
- 第1-100扇区:分区1
- 第101-200扇区:分区2
- 保护机制:该扇区不可随意写入,否则会导致分区信息丢失
3)后续扇区可自定义分区和格式化
- 自由管理区域:第1扇区及之后的空间允许用户:
- 按需划分多个分区(类似电脑的C/D/E盘)
- 对各分区独立格式化
- 使用建议:可根据不同用途划分区域,如系统区、数据存储区等
4)SD卡启动与程序搬移
- 启动流程:
- 开发板选择SD卡启动模式
- 处理器执行固化在iROM中的BL0代码
- BL0自动从SD卡第1扇区开始搬移程序到内存
- 关键特性:BL0不会搬移第0扇区(分区表所在位置)
5)uboot应存储于第一扇区开始的空间
- 存储规范:
- uboot必须从第1扇区开始存储(约500KB大小)
- 实际占用连续多个扇区(如1000个扇区)
- 错误示例:
- 存于第0扇区 → 不被BL0读取
- 存于第100扇区 → 前99扇区内容缺失
- 剩余空间:uboot之后的空间可自由分区格式化,如:
- 存放系统镜像
- 作为数据存储区
2. 实验手册
1)实验环境
- Ubuntu系统:实验在Ubuntu系统下进行,需要将u-boot镜像文件拷贝到家目录下
- 开发板型号:使用FS4412实验平台进行uboot烧写验证
2)实验步骤
- u-boot镜像准备
- 文件获取:从资料中获取u-boot-fs4412.bin文件
- 拷贝操作:将镜像文件拷贝到Ubuntu家目录下
- 文件验证:通过ls命令确认文件已成功拷贝
- 实验步骤详解
- 制作空镜像
- dd命令:
- 功能:用于转换和复制文件
- 参数说明:
- if=/dev/zero:输入文件,生成全零内容
- of=zero.bin:输出文件名
- count=1:块数量,1块=512字节
- 执行命令:sudo dd if=/dev/zero of=zero.bin count=1
- 验证输出:显示"1+0 records in/out"表示成功
- dd命令:
- 追加uboot
- 合并原理:
- SD卡结构:第0扇区存储分区表,从第1扇区开始存放uboot
- 合并目的:在uboot前添加512字节空数据,确保烧写时uboot从第1扇区开始
- 执行命令:cat zero.bin u-boot-fs4412.bin > win-u-boot-fs4412.bin
- 验证方法:通过ls命令查看生成的新文件
- 合并原理:
- 制作1M空镜像
- 清除目的:擦除SD卡中原有数据
- 计算方法:
- 1块=512字节
- 2048块=1MB
- 执行命令:sudo dd if=/dev/zero of=clear.bin count=2048
- 验证大小:使用du -MH命令确认文件大小为1MB
- 拷贝文件
- 传输文件:
- win-u-boot-fs4412.bin
- clear.bin
- 传输方法:通过VMware共享文件夹或直接拖拽
- 传输文件:
- 插入SD卡
- 识别问题:
- 若Windows不识别,可能被Ubuntu占用
- 解决方法:在虚拟机可移动设备中断开SD卡连接
- 验证方法:在"此电脑"中查看SD卡盘符
- 识别问题:
- Win32DiskImager烧写
- 烧写步骤:
- 先烧写clear.bin清空SD卡
- 再烧写win-u-boot-fs4412.bin
- 工具使用:
- 选择镜像文件
- 选择SD卡设备
- 点击Write开始烧写
- 成功标志:显示"Write Successful"
- 烧写步骤:
- 拔出SD卡并验证
- 硬件操作:
- 将SD卡插入开发板
- 设置拨码开关为SD卡启动模式
- 验证方法:
- LED2灯点亮
- 串口终端显示uboot启动信息
- 常见问题:
- LED亮但终端无输出:检查串口连接
- 无任何反应:检查烧写过程和启动模式设置
- 硬件操作:
- 制作空镜像
知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
SD卡存储结构 | SD卡以扇区(块)为单位存储,每块512字节,编号从0开始;第0块存储分区表,类似硬盘分区信息 | 内存按字节寻址 vs SD卡按块寻址 | ⭐⭐ |
Uboot烧录原理 | BL0固件从SD卡第1块开始加载程序,需确保uboot镜像从第1块写入 | 烧录工具默认从第0块写入,需前置512字节空块对齐 | ⭐⭐⭐ |
镜像制作步骤 | 1. 生成512字节空镜像 2. 合并空镜像与uboot.bin 3. 擦除SD卡原有数据 4. 烧录合并后的镜像 | dd命令参数:if=/dev/zero(输入空数据)、count=2048(生成1MB文件) | ⭐⭐⭐⭐ |
开发板启动验证 | 拨码开关设为SD卡启动,串口终端显示uboot版本及硬件信息,LED2亮起为成功标志 | 串口无输出时检查接线/启动模式 | ⭐⭐ |
关键命令 | dd if=/dev/zero of=zero.bin count=1(生成空块); cat zero.bin uboot.bin > final.bin(镜像合并) | 输出重定向>与dd的of=参数区别 | ⭐⭐⭐ |
七、ubuntu的使用
Ubuntu的使用在系统移植课程中至关重要,后续将Linux系统安装到开发板或从外存加载到内存运行均需通过Ubuntu完成。Ubuntu的熟练程度直接影响系统移植工作的效率,因此本次课程内容为重点内容。
1.uboot模式
Uboot有两种工作模式:
- 自启动模式
- 交互模式
1) 自启动模式
自启动模式指Ubuntu启动后进入倒计时阶段,若未进行人为干预,倒计时结束后将自动执行自启动命令。自启动命令通常用于加载和启动Linux内核。
2) 交互模式
交互模式指在Ubuntu倒计时阶段人为干预(如按下Enter键),系统将停止加载Linux内核并停留在Ubuntu界面。交互模式下可输入并执行Ubuntu命令,类似于电脑开机时进入BIOS的操作逻辑。
2.uboot命令
1) 帮助命令
- 例题:查看uboot支持的所有命令
- help命令用于查看Ubuntu支持的所有命令,执行后系统将列出全部可用命令,例如bootm(加载内核)、cp(拷贝内存)、erase(擦除存储内容)等。
- help命令后接具体命令可查看其使用方法,例如输入help loadb将显示loadb命令的格式及参数说明,包括二进制文件下载地址和波特率设置。
2) 环境变量命令
- 打印环境变量命令
- printenv命令用于打印Ubuntu环境变量,包括波特率、网卡型号、IP地址、子网掩码等关键配置信息。
- 执行printenv后,系统输出环境变量列表,例如ipaddr= - - - 150表示当前IP地址,serverip表示服务器IP地址。
- setenv命令用于修改环境变量,格式为setenv [变量名] [新值],例如setenv ipaddr - - - 100可将IP地址修改为 - - - 100。
- 通过setenv ipaddr - - - 100修改IP地址后,需注意环境变量仅临时保存在内存中,断电后恢复默认值。若需永久保存,需将配置写入外存(如SD卡或eMMC)。
- setenv命令用于将环境变量保存至外部存储器。通过help命令可查看saveenv功能说明,该命令实现环境变量的持久化存储。
- 环境变量查看:执行printenv显示当前IP地址为 - 150
- 环境变量修改:通过setenv IPaddr - - - 100更新IP地址
- 环境变量保存:saveenv命令将修改后的环境变量写入MMC存储器
- 验证持久化:重启开发板后执行printenv确认IP地址永久变更为 - - - 100
3) 常用环境变量
printenv命令可列出全部环境变量,其中关键环境变量包括:
ipaddr
- ipaddr为开发板/U-Boot的IP地址配置项。必须与Ubuntu主机处于同一网段,若Ubuntu IP为 - - - x,则U-Boot需对应配置为 - - - x系列地址。
serverip
- serverip定义TFTP服务器地址。当U-Boot作为TFTP客户端从Ubuntu下载文件时,该变量必须设置为Ubuntu主机的实际IP地址。
bootdelay
- bootdelay控制自启动模式前的倒计时秒数(默认3秒)。通过setenv bootdelay 5及saveenv可修改为5秒,重启后倒计时变更为54321序列。该参数适用于调整系统启动等待时间。
八、uboot网络传输命令
1. loadb命令
- 功能:通过Kermit协议从串口下载二进制文件到指定内存地址
- 特点:
- 基于串口通信,速度较慢
- 常用于ARM开发环境
- 使用方法:
- 命令格式:loadb <内存地址>
- 示例:loadb 0x41000000 将文件下载到内存0x41000000处
1)tftp命令
- 功能:通过TFTP协议从网络服务器下载文件到指定内存地址
- 特点:
- 基于网络通信,速度比loadb快很多
- U-Boot内置支持,无需额外安装客户端
- 使用方法:
- 完整格式:tftp [loadAddress] [hostIPaddr:]bootfilename
- 简化格式:tftp <内存地址> <文件名>
- 示例:tftp 0x41000000 interface.bin
- 使用前的准备工作
- 网络配置要求:
- 必须使用桥接模式连接
- 开发板与服务器必须在同一网段
- 需要正确配置IP地址、子网掩码和网关
- 网络配置要求:
- 服务器端配置
- 必须安装TFTP服务器:
- Ubuntu安装命令:sudo apt-get install tftpd-hpa tftp-hpa
- 每次重启后需要启动服务:sudo service tftpd-hpa restart
- 工作目录:
- 默认在/tftpboot目录
- 下载文件必须放在此目录下
- 文件权限需设置为777:sudo chmod 777 <文件名>
- 必须安装TFTP服务器:
- 客户端配置
- 关键环境变量:
- ipaddr:开发板IP地址(必须与服务器同网段)
- serverip:TFTP服务器IP地址(必须与Ubuntu主机IP一致)
- netmask:子网掩码(通常255.255.255.0)
- gatewayip:网关地址
- 检查方法:
- 使用printenv命令查看当前环境变量
- 使用setenv和saveenv修改并保存配置
- 关键环境变量:
- 常见问题排查
- 网络连通性测试:
- 成功显示"host is alive",失败显示"is not alive"
- 使用ping命令测试:ping <服务器IP>
- 常见问题:
- 防火墙未关闭(需关闭Windows防火墙)
- 网卡选择错误(必须选择有线网卡)
- 网线未直连(开发板与电脑需直连)
- IP地址配置错误(必须同网段不同IP)
- 实际下载示例
- 下载步骤:
- 将测试文件放入/tftpboot目录
- 设置文件权限:sudo chmod 777 interface.bin
- 执行下载命令:tftp 0x40008000 interface.bin
- 运行程序:go 0x40008000
- 注意事项:
- 下载过程中"#"表示传输进度
- 超时会显示"T",需检查网络连接
- 下载完成后会显示传输字节数
- 下载步骤:
知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
Uboot网络通信支持 | Uboot环境变量包含网络相关配置(如IP address、server IP),说明其内置网络协议支持 | 区分环境变量作用(IP address为开发板IP,server IP为服务器IP) | ⭐⭐ |
TFTP协议原理 | 轻量级文件传输协议,用于开发板与服务器(如Ubuntu)间文件传输 | 需明确服务器需安装TFTP服务端,开发板通过Uboot内置客户端下载 | ⭐⭐⭐ |
TFTP命令使用 | 格式:tftp <内存地址> <文件名>(如tftp 0x41000 interface.bin) | 省略server IP时默认使用环境变量中的server IP值 | ⭐⭐⭐⭐ |
网络配置前提 | 1. 开发板与服务器需直连网线; 2. 确保Ubuntu桥接模式且选择有线网卡; 3. 关闭Windows防火墙 | 常见错误:桥接模式选错网卡或未关闭防火墙 | ⭐⭐⭐⭐⭐ |
TFTP服务器配置 | 1. Ubuntu安装tftpd-hpa服务; 2. 文件需放入/tftpboot目录并设置权限为777 | 每次重启需手动重启服务:sudo service tftpd-hpa restart | ⭐⭐⭐ |
故障排查步骤 | 1. ping测试网络连通性; 2. 检查环境变量server IP一致性; 3. 验证文件权限及服务状态 | 超时问题多因网络配置或服务未启动 | ⭐⭐⭐⭐ |
TFTP与Loadb对比 | TFTP:基于网卡,速度快; Loadb:基于串口,速度慢 | 优先使用TFTP传输大文件 | ⭐⭐ |
九、uboot的使用
1. 存储器访问命令
1)mmc read
- 功能:将EMMC中指定扇区的内容读取到内存指定地址
- 命令格式:mmc read <addr> <blk#> <cnt>
- addr:内存目标地址
- blk#:EMMC起始扇区编号(1扇区=512字节)
- cnt:读取的扇区数量
- 应用场景:系统移植时加载存储在EMMC中的程序到内存运行
- 操作示例:mmc read 0x40008000 0x800 0x1表示从EMMC的0x800扇区读取1个扇区数据到内存0x40008000地址
2)mmc write
- 功能:将内存指定地址的内容写入EMMC指定扇区
- 命令格式:mmc write <addr> <blk#> <cnt>
- addr:内存源地址
- blk#:EMMC目标起始扇区编号
- cnt:写入的扇区数量
- 设备选择:第一个参数0表示EMMC,1表示SD卡
- 实际应用:
- 写入前需通过tftp将文件下载到内存(如tftp 41000000 interface.bin)
- 典型命令:mmc write 0x41000000 0x800 0x1将内存0x41000000的1个扇区数据写入EMMC的0x800扇区
- 验证方法:断电重启后使用mmc read重新读取验证数据完整性
3)命令组合使用
- 完整工作流:
- 通过tftp下载文件到内存
- 使用mmc write写入EMMC
- 断电验证持久化存储
- 上电后使用mmc read加载到内存
- 通过go命令执行程序
- 系统移植应用:
- 安装Linux系统时写入EMMC
- 系统启动时从EMMC加载到内存
- 注意事项:
- 文件小于512字节仍需写入完整1个扇区
- 重要数据建议写入后立即验证读取
2. 自启动环境变量
1)bootcmd
bootcmd作用演示
bootcmd自动执行演示:
- 定义:bootcmd是uboot中一个重要的自启动环境变量,不是命令而是环境变量
- 功能:可以设置1到多个uboot命令的集合(多个命令用
\textbackslash;\textbackslash;\textbackslash;
分隔) - 执行机制:在自启动模式下,uboot会按bootcmd中命令的顺序逐条执行
- 典型应用:常用于设置自动下载和执行程序的命令序列
- 典型应用场景:
- 自动下载并执行程序:setenv bootcmd tftp 40008000 interface.bin$\textbackslash;$go 40008000
- 自动从eMMC读取并执行:setenv bootcmd mmc read 0 0x40008000 0x800 0x1$\textbackslash;$go 40008000
- 优势:实现开发板上电后自动完成程序加载和执行,无需人工干预
- 系统级应用:
- 可扩展用于自动加载和启动Linux系统
- 典型流程:加载内核→加载设备树→加载文件系统→启动内核
- 重要性:是系统移植和启动流程中的核心配置项
- 注意事项:
- 命令顺序必须符合执行逻辑
- 各命令参数需要根据实际硬件配置调整
- 错误配置可能导致系统无法正常启动
- 典型应用场景:
知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
MMC命令 | 用于读写外部存储器(如SD卡、eMMC)的命令集合,包含子命令(mmc read/mmc write/mmc erase等) | 参数含义:addr(内存地址)、block(存储块起始编号)、cnt(块数量) | ⭐⭐⭐ |
mmc read | 从外存读取数据到内存,示例:mmc read 0x40008000 0x800 0x1(从eMMC的0x800块读1块到内存0x40008000) | 易混淆点:第一个参数是目标内存地址,第二个是外存块编号 | ⭐⭐ |
mmc write | 将内存数据写入外存,示例:mmc write 0x40008000 0x800 0x1(将内存0x40008000的数据写入eMMC的0x800块) | 关键操作:需先通过tftp下载文件到内存再写入外存 | ⭐⭐⭐⭐ |
bootcmd环境变量 | 自启动命令集合,Uboot倒计时结束后自动执行其包含的命令(如tftp下载+go执行) | 语法规则:多条命令用\;分隔,如setenv bootcmd "tftp 0x40008000 test.bin\; go 0x40008000" | ⭐⭐⭐⭐ |
eMMC与SD卡操作 | 通过mmc命令的编号区分设备(如0为eMMC,1为SD卡) | 易错点:设备编号需与硬件实际连接匹配 | ⭐⭐ |
Uboot命令链 | 结合tftp+mmc write+mmc read+go实现程序固化与自启动 | 典型流程:下载→写入eMMC→重启后读取→执行 | ⭐⭐⭐⭐ |
十、通过tftp加载内核和根文件系统
1. 内核的安装与加载
1)通过tftp加载内核和根文件系统
- Linux内核镜像
- 核心文件:包含两个关键文件
- uImage:Linux系统的内核镜像文件,大小为2.87MB(3,019,120字节)
- exynos4412-fs4412.dtb:设备树文件,大小为34KB
- 内核镜像特性
- 轻量级优势:
- 嵌入式领域选择Linux的主要原因之一是其轻量级特性
- 相比安卓/Windows等大型系统,Linux内核仅2.87MB,适合资源有限的嵌入式设备
- 能在低配置硬件(如性能较弱的CPU/小内存)上流畅运行
- 轻量级优势:
- 设备树文件
- 功能说明:
- 后缀.dtb表示Device Tree Binary(设备树二进制文件)
- Linux系统运行时必需的文件,包含硬件配置信息
- 文件大小仅33.5KB,修改日期与内核镜像同步(2021/4/6)
- 功能说明:
- 文件部署流程
- 操作步骤:
- 进入Ubuntu的TFTP工作目录:/tftpboot
- 使用sudo mv命令移动两个文件到目标目录
- 验证结果:通过ls命令确认uImage和.dtb文件存在
- 注意事项:
- 需要root权限操作(使用sudo)
- 文件路径需完整指定(含文件名和扩展名)
- 操作步骤:
- 核心文件:包含两个关键文件
- 根文件系统镜像
- 文件准备与权限修改
- 文件拷贝要求:
- 需将Linux内核镜像目录下的"uImage"和"exynos4412-fs4412.dtb"拷贝至ubuntu的tftp工作目录
- 需将根文件系统镜像目录下的"ramdisk"同样拷贝至tftp工作目录
- 权限修改:
- 执行命令:$sudo chmod 777 /tftpboot/*
- 原因:保证后续实验顺利,避免因权限不足导致下载失败
- 注意:必须修改所有相关文件的权限为777(可读可写可执行)
- 操作验证:
- 使用ls命令确认目录下存在三个关键文件:
- exynos4412-fs4412.dtb
- ramdisk.img
- uImage
- 使用ls命令确认目录下存在三个关键文件:
- 文件拷贝要求:
- TFTP服务器重启
- 重启命令:
- $sudo service tftpd-hpa restart
- 注意事项:
- 每次重启Ubuntu后都必须重新启动TFTP服务
- 必须确保网络配置正确,桥接模式需连接到有线网卡
- 验证方法:检查虚拟机网络设置是否桥接到"Realtek PCIe GBE Family Controller"
- 重启命令:
- 开发板与电脑连接
- 硬件连接要求:
- 必须使用串口线和网线直连开发板与电脑
- 禁止通过路由器连接,必须直连
- 网线另一端必须连接电脑网口
- 交互模式进入:
- 连接后需进入uboot交互模式
- 使用SecureCRT等工具通过串口连接(如COM4)
- 硬件连接要求:
- uboot启动参数设置
- IP地址设置:
- 命令:# setenv ipaddr ***.***.***.***
- 关键要求:必须与Ubuntu服务器在同一网段
- 验证方法:在Ubuntu执行ifconfig查看IP(如192.168.1.200)
- 服务器IP设置:
- 命令:# setenv serverip xxx.xxx.xxx.xxx
- 必须设置为Ubuntu的IP地址(如192.168.1.200)
- 验证命令:printenv查看当前uboot参数
- 自启动环境变量:
- 命令:# setenv bootcmd tftp 0x41000000 uImage;tftp 0x42000000 exynos4412-fs4412.dtb;tftp 0x43000000 ramdisk.img;bootm 0x41000000 0x43000000 0x42000000
- 内存地址分配:
- 0x41000000:内核镜像(uImage)
- 0x42000000:设备树文件(dtb)
- 0x43000000:根文件系统(ramdisk)
- 执行顺序:先下载三个文件到指定内存地址,再通过bootm命令启动
- IP地址设置:
- 文件准备与权限修改
- 应用案例
- 设置bootcmd命令
- 启动目标:通过uboot将Linux内核镜像、设备树文件和根文件系统从Ubuntu的TFTP服务器加载到开发板内存并运行
- 关键文件:
- uImage:Linux内核镜像
- exynos4412-fs4412.dtb:设备树文件
- ramdisk.img:根文件系统镜像
- 内存地址规划:
- 0x41000000:存放Linux内核镜像(uImage)
- 0x42000000:存放设备树文件(exynos4412-fs4412.dtb)
- 0x43000000:存放根文件系统(ramdisk.img)
- 地址选择原则:
- 必须位于物理内存范围内(0x40000000-0x80000000)
- 各文件地址间隔16MB空间(0x42000000-0x41000000=16MB)
- 实际文件大小验证:
- uImage:2.9MB
- exynos4412-fs4412.dtb:36KB
- 远小于分配的16MB空间
- 内存映射关键点:
- 物理内存范围:0x40000000-0x80000000(共1GB)
- 保留区域:
- 0x40000000-0x41000000:用于uboot传参
- 0x80000000之后:未使用空间
- 地址分配原因:
- 避免与uboot及其参数区域冲突
- 保证足够的空间裕度
- 命令结构:
- bootm命令详解:
- 功能:启动Linux内核并传递参数
- 参数顺序:
- 内核地址(必需)
- 根文件系统地址(无则用"-")
- 设备树地址(无则用"-")
- 参数传递机制:告知内核各组件在内存中的位置
- 操作步骤:
- 设置bootcmd环境变量
- 使用saveenv保存配置
- 开发板重启后自动执行
- 注意事项:
- TFTP服务器需提前配置好文件
- 地址必须使用十六进制格式
- 各命令间用分号分隔
- 最后需要执行bootm启动内核
- 内存布局验证:
- 0x41000000-0x42000000:16MB空间存放2.9MB的uImage
- 0x42000000-0x43000000:16MB空间存放36KB的dtb文件
- 0x43000000-0x44000000:16MB空间存放根文件系统
- 冲突避免:
- 各文件有独立地址空间
- 与uboot参数区无重叠
- 预留足够空间裕度
- 设置bootcmd命令
- 设置自启动参数bootargs
- bootargs环境变量介绍
- 定义:bootargs是uboot中用于设置Linux系统启动参数的重要环境变量
- 作用:告诉内核文件系统和设备树的位置,使开发板能运行Linux系统
- 组成:包含根文件系统类型、网络文件系统路径、控制台设置等多项参数
- 设置bootargs参数
- 基本命令:setenv bootargs <参数列表>
- 参数格式:
- root=/dev/nfs:指定根文件系统类型为NFS
- nfsroot=<服务器IP>:<路径>:设置NFS服务器地址和工作目录
- rw:设置文件系统可读写权限
- console=ttySAC2,115200:指定控制台使用串口2,波特率115200
- init=/linuxrc:指定init进程位置
- ip=<开发板IP>:设置Linux启动后的IP地址
- bootargs参数详解
- 服务器IP:必须填写Ubuntu虚拟机的实际IP地址(如192.168.1.200)
- NFS路径:需对应Ubuntu中NFS服务的工作目录(如/opt/4412/rootfs)
- 开发板IP:必须与服务器在同一网段(如192.168.1.100)
- 保存设置:使用saveenv命令将参数永久保存到MMC中
- 验证方法:通过printenv命令检查bootargs参数是否设置正确
- 注意事项:
- 路径和IP地址需根据实际环境调整
- 参数之间用空格分隔
- 大小写敏感(如ttySAC2必须大写)
- 设置完成后必须执行保存操作
- bootargs环境变量介绍
2、实验后检查
1) 检查网络设置
- 关键步骤:
- 使用网线连接开发板与电脑
- 给开发板重新上电
- 观察uboot是否能通过tftp加载和启动内核
- 检查启动时是否能挂载根文件系统(ext2)
- 启动完成后在终端输入linux shell命令测试功能
- 注意事项:
- TFTP服务必须重启确保可用
- 需要验证IP地址设置正确性(包括server IP)
- 网络不通时可先执行ping命令测试连通性
2)重启开发板
- 环境变量:
- bootargs=console=ttySAC2,115200 init=/linuxrc ip=192.168.1.100
- bootcmd=tftp 0x41000000 uImage;tftp 0x42000000 exynos4412-fs4412.dtb;tftp 0x43000000 ramdisk.img;bootm 0x41000000 0x43000000 0x42000000
- ethaddr=11:22:33:44:55:66
- 硬件信息:
- CPU: Exynos4412@1000MHz
- DRAM: 1 GiB
- MMC容量: 14910 MB
3)下载文件与启动内核
- 下载流程:
- 下载uImage内核镜像到0x41000000地址(3019120字节,约2.9MiB)
- 下载设备树文件exynos4412-fs4412.dtb到0x42000000地址(34358字节)
- 下载ramdisk.img根文件系统到0x43000000地址(2544147字节,约2.4MiB)
- 传输速率:
- uImage下载速度:98.6 KiB/s
- 设备树文件下载速度:332 KiB/s
- 根文件系统下载速度:676.8 KiB/s
4) 开发板启动流程回顾
- 启动阶段:
- BL0阶段:
- 运行三星固化的iROM程序
- 检测拨码开关状态(当前为SD卡启动模式)
- 将SD卡第一个扇区的uboot搬移到内存
- Uboot阶段:
- 初始化软硬件环境
- 打印版本信息(U-Boot 2013.01)
- 显示CPU型号和频率(Exynos4412@1000MHz)
- 显示内存信息(DRAM: 1 GiB)
- 内核加载:
- 执行bootcmd中的四条命令
- 通过TFTP协议依次下载三个必要文件
- 使用bootm命令启动内核(0x41000000)
- BL0阶段:
- 校验过程:
- 对下载的每个文件进行校验和验证
- 显示各文件的加载地址和入口点
- 内核启动后显示版本信息(Linux version 3.14.0)
3、开发板启动过程
1) Linux内核启动
- 启动阶段划分:
- uboot阶段:在"Starting kernel..."打印前由uboot执行,负责加载内核镜像、设备树和ramdisk
- 内核阶段:启动信息显示Linux版本为3.14.0,基于ARMv7架构的Exynos4412处理器
- 关键初始化过程:
- CPU识别:检测到ARMv7四核处理器(CPU0-CPU3),主频1GHz
- 内存管理:总内存256528页,采用zone内存分配策略
- 设备树加载:从地址0x42000000加载扁平设备树(FDT)
- 命令行参数:包含NFS根文件系统挂载参数root=/dev/nfs nfsroot=192.168.1.200:/opt/4412/rootfs
- 驱动加载:
- 串口驱动:注册ttySAC0-3四个串口设备
- USB驱动:EHCI主机控制器初始化完成
- 网络协议栈:TCP/IP协议族注册,包含TCP cubic拥塞控制算法
- 根文件系统挂载:最终通过VFS挂载ext2格式的根文件系统,完成启动流程
2) 执行Linux命令
- 基本操作验证:
- 目录浏览:ls命令显示标准Linux目录结构(/bin, /etc, /dev等)
- 文件操作:支持touch test.txt创建文件,cd切换目录
- 命令提示符:显示为[root@farsight]#,表示root用户登录
- 终端优化:
- 通过session option调整终端配色方案,使目录(蓝色)与文件(白色)区分更明显
- 支持标准Linux命令如cat、echo等busybox精简版工具
- 典型目录内容:
- /bin:包含基础命令如ash、busybox、ls等
- /dev:设备文件目录
- /proc:内核与进程信息虚拟文件系统
- 注意:由于使用NFS根文件系统,实际存储位于服务器192.168.1.200的/opt/4412/rootfs路径
知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
Uboot环境变量 | boot cmd自启动环境变量的作用与设置方法 | 环境变量设置格式与内存地址计算 | ⭐⭐⭐⭐ |
Linux内核加载 | 通过TFTP协议加载uImage内核镜像到0x41000地址 | 内存空间分配计算与冲突避免 | ⭐⭐⭐⭐ |
设备树加载 | EXYNOS4412-fs4412.dtb设备树文件加载到0x42000地址 | 设备树文件大小校验(36KB) | ⭐⭐⭐ |
根文件系统加载 | RAMDISK镜像加载到0x43000地址 | NFS工作目录配置要求 | ⭐⭐⭐⭐ |
bootm命令 | 启动参数格式:bootm <内核地址> <根文件系统地址> <设备树地址> | 参数顺序不可颠倒 | ⭐⭐⭐⭐⭐ |
内存映射 | 4412芯片内存分布(0x40000000-0x80000000) | 实际可用内存1GB与地址空间规划 | ⭐⭐⭐⭐ |
启动流程 | BL0→Uboot→Linux内核的完整启动链条 | Start Kernel标志位识别 | ⭐⭐⭐⭐ |
文件权限设置 | chmod 777确保TFTP传输权限 | 服务器文件权限配置要点 | ⭐⭐ |
网络配置 | 开发板IP(192.168.1.100)与服务器IP(192.168.1.200)同网段验证 | 直连网线要求 | ⭐⭐⭐ |
实验验证 | 成功启动后Linux命令行操作验证 | 控制台主题设置技巧 | ⭐⭐ |
十一、通过EMMC加载内核和根文件系统
1. 给开发板上电并下载镜像
1)开发板上电与镜像下载
- 操作步骤:
- 给开发板重新上电
- 在uboot交互模式下进行操作
- 下载并安装镜像文件到EMMC存储器
- 注意事项:
- 需要连接网线和串口线
- 确保网络连接正常
2)TFTP命令下载内核镜像
- 命令格式:tftp <内存地址> <文件名>
- 示例:tftp 0x41000000 uImage
- 功能说明:
- 从Ubuntu系统下载Linux内核镜像(uImage)到开发板内存
- 内存地址0x41000000为镜像加载位置
- 执行过程:
- 网络传输速度约为314.5 KiB/s
- 传输完成后显示字节数:3019120 (2e1170 hex)
3)MMC命令写入内核镜像
- 命令格式:mmc write <设备号> <内存地址> <EMMC块号> <块数>
- 示例:mmc write 0 0x41000000 0x800 0x1734
- 参数说明:
- 设备号0表示EMMC存储器
- 内存地址0x41000000存放下载的uImage
- EMMC块号0x800(2048)为写入起始位置
- 块数0x1734(5940)为需要写入的块数
- 存储布局:
- 前2048块保留给uboot
- 内核镜像从2048块开始存储
4)计算内核镜像占用块数
- 计算方法:
- 使用du -mh uImage查看镜像大小为2.9MB
- 转换为字节数:
2.9×1024×1024=3040870.42.9 \times 1024 \times 1024 = 3040870.42.9×1024×1024=3040870.4
字节 - 计算块数:
3040870.4÷512≈59403040870.4 \div 512 \approx 59403040870.4÷512≈5940
块 - 转换为十六进制:5940 = 0x1734
- 注意事项:
- EMMC是块设备,每次操作以512字节为一块
- uboot命令默认使用十六进制数值
- 计算时要留出足够空间避免覆盖其他数据
2. 计算所占空间并写入EMMC
1)将内核镜像写入EMMC
- 内存地址分配:内核镜像下载到内存地址
0x41000000,该地址后续会被设备树覆盖但不会影响安装过程
- 空间计算:
- 内核镜像大小2.9MB(3019120字节)
- EMMC块大小512字节,共需5896.71875块(约0x1700块)
- 写入命令:
- 从EMMC块0x800开始写入0x2000块(足够存放内核)
- 空间占用:0x800到0x2800块区域存放uImage
2)下载设备树到内存
- 下载命令:
- 特性说明:
- 设备树文件较小(36KB)
- 会覆盖内存中原有内核镜像,但因已完成安装不影响后续操作
- 空间计算:
- 实际大小34358字节(0x8636)
- 需72块(十进制),换算十六进制为0x48块
3)将设备树写入EMMC
- 写入位置选择:必须避开内核镜像区域(0x2800之后)
- 写入命令:
- 实际占用:
- 起始块:0x2800
- 结束块:0x3000
- 实际只需0x48块,0x800为预留空间
4)下载根文件系统镜像到内存
- 镜像特性:
- 文件名为ramdisk.img
- 大小2.5MB(2544147字节)
- 下载命令:
5)将根文件系统镜像写入EMMC
- 写入位置:0x3000块开始
- 写入命令:
- 空间分配:
- 实际需要约0x1300块
- 分配0x2000块(到0x5000)留有充足余量
- 完整布局:
0x0000−0x0800:保留区(可后续存放uboot)
0x0800−0x2800:内核镜像
0x2800−0x3000:设备树
0x3000−0x5000:根文件系统
3. 修改uboot启动参数
1)修改uboot启动参数的原因
- 启动方式变更: 从原先通过TFTP从服务器下载镜像改为从EMMC本地加载镜像,提高启动效率
- 参数保存问题: 原设置可能因命令过长导致保存失败,需要调整格式
2)设置环境变量bootcmd
- 命令结构: 使用setenv bootcmd命令设置自启动环境变量
- 格式注意: 当命令过长时,建议用单引号将整个值括起来,如'mmc read...'
- 参数保存: 设置完成后必须执行saveenv保存参数
3)从EMMC加载Linux内核
- 命令格式: mmc read 0 0x41000000 0x800 0x2000
- 参数说明:
- 0: 表示EMMC设备号
- 0x41000000: 目标内存地址
- 0x800: 源扇区号(对应EMMC中的0x800扇区)
- 0x2000: 读取块数(与写入时保持一致)
4)从EMMC加载设备树
- 命令格式: mmc read 0 0x42000000 0x2800 0x800
- 关键参数:
- 0x42000000: 设备树内存地址(与内核地址区分)
- 0x2800: 设备树在EMMC中的存储位置
- 0x800: 设备树占用的块数
5)从EMMC加载根文件系统
- 命令格式: mmc read 0 0x43000000 0x3000 0x2000
- 地址分配:
- 0x43000000: 根文件系统专用内存地址
- 0x3000: 文件系统在EMMC中的起始扇区
- 0x2000: 文件系统大小(与写入时一致)
6)启动Linux内核
- 启动命令: bootm 0x41000000 0x43000000 0x42000000
- 参数顺序:
- 内核镜像地址(0x41000000)
- 根文件系统地址(0x43000000)
- 设备树地址(0x42000000)
7)保存设置
- 保存方法: 执行saveenv命令
- 常见问题: 当命令过长时保存可能失败
- 解决方案:
- 使用单引号包裹整个命令字符串
- 通过文本编辑器整理格式后再粘贴
- 确认保存后使用printenv检查设置
4. 开发板启动过程
1)EMMC加载Linux内核及rootfs
- 启动方式:通过EMMC存储介质加载Linux内核镜像、设备树和文件系统
- 启动命令:
- mmc read 0 0x41000000 0x800 0x2000:将uImage从EMMC读到内存
- mmc read 0 0x42000000 0x2800 0x800:将设备树从EMMC读到内存
- mmc read 0 0x43000000 0x3000 0x2000:将文件系统从EMMC读到内存
- bootm 0x41000000 0x43000000 0x42000000:启动内核
2)启动流程详解
- 内核加载:
- 读取Linux-3.14.0内核镜像,大小2.9MiB
- 加载地址:0x40008000
- 校验和验证通过
- ramdisk加载:
- 读取压缩的ramdisk镜像,大小2.4MiB
- 加载地址:0x00000000
- 设备树加载:
- 使用FDT(Flattened Device Tree) blob
- 地址:0x42000000
3)内核启动过程
- CPU初始化:
- 检测到4个ARMv7处理器核心
- 主频1000MHz
- 采用SMP对称多处理架构
- 内存管理:
- 总内存:1GiB
- 可用内存:1014372K/1032192K
- 设备初始化:
- 检测到USB 2.0控制器
- 初始化dm9000网卡
- 挂载ext2文件系统
4)网络配置参数
- 网络设置:
- ipaddr=192.168.1.100
- netmask=255.255.255.0
- gatewayip=192.168.1.1
- serverip=192.168.1.200
- 启动参数:
- bootargs=root=/dev/nfs nfsroot=192.168.1.200:/opt/4412/rootfs rw console=ttySAC2,115200 init=/linuxrc ip=192.168.1.100
- bootdelay=5:自动启动倒计时5秒
5)两种启动方式对比
- 网络启动:
- 适用于开发调试阶段
- 依赖网络环境
- 便于快速更新内核和文件系统
- EMMC启动:
- 适用于产品发布阶段
- 从本地存储加载
- 启动更稳定可靠
- 是项目定型的标准做法
知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
Linux系统加载方式 | 通过TFTP从服务器加载内核镜像、设备树、根文件系统到开发板内存 | 需配置TFTP服务器路径,依赖网络环境 | ⭐⭐⭐ |
EMMC本地加载方案 | 将内核镜像、设备树、根文件系统写入EMMC指定扇区,启动时通过mmc read加载到内存 | 扇区地址计算(如0x800起始存内核)、块大小换算(需按512字节/块转换) | ⭐⭐⭐⭐ |
Uboot命令操作 | tftp下载文件到内存 → mmc write写入EMMC → mmc read读取到内存 → bootm启动内核 | 地址冲突风险(如多次使用0x410000需覆盖前次内容) | ⭐⭐⭐ |
开发板存储布局 | EMMC分区规划:0x000-0x800预留 → 0x800-0x2800内核 → 0x2800-0x3000设备树 → 0x3000-0x5000根文件系统 | 空间预留逻辑(避免覆盖uboot或后续扩展区域) | ⭐⭐⭐⭐ |
产品化部署要点 | 脱离网络依赖,所有系统文件固化到EMMC,确保断电不丢失 | 扇区分配合理性(需兼容未来升级) | ⭐⭐⭐⭐ |
十二、通过tftp加载内核通过nfs挂载根文件系统
1. 根文件系统镜像目录复制解压
1)NFS挂载准备工作
- 文件选择:使用rootfs.tar而非ramdisk.img进行NFS共享,因为前者是原始文件集合,后者是单个镜像文件
- 目录配置:NFS工作目录已预先配置为/opt/4412/rootfs(实验三中完成)
- 文件差异:
- ramdisk.img:适用于直接烧写到EMMC或加载到内存的镜像文件
- rootfs.tar:包含原始文件结构的压缩包,更适合NFS共享
2)文件系统部署步骤
- 文件拷贝:
- 必须使用sudo权限操作根目录下的文件
- 源文件路径根据VMware共享文件夹位置可能变化
- 解压操作:
- 解压过程相当于在根目录创建新文件,需要管理员权限
- 解压后生成完整的Linux目录结构(bin、sbin、etc等)
- 清理操作:
- 压缩包删除为可选操作,不影响系统运行
- 保留压缩包可节省后续重新部署时间
3)U-Boot参数配置
- 启动命令:
- 通过TFTP协议加载内核(uImage)和设备树(.dtb)
- 0x41000000和0x42000000为内存加载地址
- 参数保存:
- 必须执行保存操作使配置永久生效
- 开发板重启后会保持这些启动参数
2. 修改uboot的启动参数
1)修改启动参数的原因
- 变更需求:由于系统启动方式发生改变,原启动参数不再适用,需要重新配置
- 参数作用:bootcmd参数控制uboot的自动启动流程,需要与当前NFS挂载方式匹配
2)连接串口线
- 连接方式:通过COM4串口线连接开发板
- 交互准备:连接后需等待进入uboot交互模式
3)打印环境变量
- 查看命令:使用printenv命令显示当前环境变量
- 关键参数:
- bootcmd=tftp 0x41000000 uImage;tftp 0x42000000 exynos4412-fs4412.dtb;bootm 0x41000000-0x42000000
- bootargs=root=/dev/nfs nfsroot=192.168.1.200:/opt/4412/rootfs rw console=ttySAC2,115200 init=/linux
4)设置新的启动参数
- 设置命令:
- 参数说明:
- 0x41000000:Linux内核镜像加载地址
- 0x42000000:设备树文件加载地址
- -:表示根文件系统不存储在内存中
- 保存操作:执行saveenv命令永久保存新参数
- 注意事项:
- 参数中的"-"两边必须有空格
- 不再需要下载根文件系统镜像到开发板
3. 重启nfs服务器
- 重启命令:sudo service nfs-kernel-server restart
- 验证方法:显示四个"OK"表示重启成功
- 必要性:每次Ubuntu重启后都需要执行此操作以确保NFS服务可用
4. 给开发板通电观察内核启动和挂载情况
1)通过tftp加载内核与设备树
- 启动流程:
- 开发板上电后通过TFTP协议从服务器(192.168.1.200)加载uImage内核文件到内存地址0x41000000
- 同时加载设备树文件exynos4412-fs4412.dtb到0x42000000地址
- 传输速度达到322.3 KiB/s,完成3019120字节(约2.9MB)的传输
- 关键参数:
- 开发板IP:192.168.1.100
- 服务器IP:192.168.1.200
- 内核加载地址:0x41000000
- 设备树加载地址:0x42000000
2)nfs挂载根文件系统
- 挂载过程:
- 内核启动后通过NFS协议挂载位于192.168.1.200:/opt/4412/rootfs的根文件系统
- 挂载成功后显示"VFS: Mounted root (nfs filesystem) on device 0:10"
- 释放未使用的内核内存228K
- 文件系统特点:
- 文件实际存储在Ubuntu主机,开发板通过网络访问
- 在Ubuntu创建/删除文件会实时反映在开发板(如test.c文件)
- 开发板执行命令如ls可直接看到共享目录内容
- 验证方法:
- 在Ubuntu的/opt/4412/rootfs目录下创建文件
- 开发板立即可见并可操作该文件
- 删除操作也会双向同步
3)交叉编译与程序执行
- 编译差异:
- Ubuntu默认gcc生成x86架构可执行文件(Intel 80386)
- 开发板需要arm-none-linux-gnueabi-gcc生成ARM架构可执行文件
- 执行验证:
- x86程序在开发板报"Exec format error"
- ARM程序在开发板可正常输出"Hello World"
- 开发优势:
- 省去每次下载程序到开发板的步骤
- 直接通过nfs共享可执行文件
- 保持Ubuntu的开发环境,使用交叉编译器生成目标平台程序
- 关键命令:
5. uboot自启动参数环境变量
- 文件准备:需将uImage内核镜像和设备树文件exynos4412-fs4412.dtb拷贝至ubuntu的tftp工作目录
- 权限设置:执行$sudo chmod 777 /tftpboot/*修改文件权限
- 服务器重启:通过$sudo service tftpd-hpa restart重启tftp服务
1)bootargs环境变量介绍
- 本质属性:是uboot传递给Linux内核的启动参数集合,uboot本身并不使用这些参数
- 核心功能:包含内核启动所需的挂载方式、文件系统路径、控制台配置等关键信息
- 传递机制:uboot执行bootm命令时会自动将bootargs内容传递给正在启动的Linux内核
2)bootargs参数设置格式
- 标准结构:采用参数名=参数值的键值对形式,多个参数间用空格分隔
- 典型示例:setenv bootargs root=/dev/nfs nfsroot=192.168.1.200:/opt/4412/rootfs rw console=ttySAC2,115200
- 参数验证:若参数设置错误会导致内核启动失败或卡死在挂载阶段
3)root参数与nfs挂载
- 挂载方式:root=/dev/nfs指定内核通过NFS网络文件系统挂载根文件系统
- 必要性:告知内核不使用本地存储设备,而是从网络服务器获取根文件系统
- 错误影响:若误设为本地设备路径会导致内核找不到有效文件系统而启动失败
4)nfsroot参数与网络文件系统路径
- 路径格式:nfsroot=<服务器IP>:<绝对路径>如nfsroot=192.168.1.200:/opt/4412/rootfs
- 精确匹配:必须与NFS服务器实际导出路径完全一致,包括大小写和符号
- 调试技巧:可通过在服务器执行showmount -e验证NFS共享路径是否正确
5)rw参数与文件读写权限
- 权限控制:rw表示开发板对服务器文件具有读写权限(对应ro为只读)
- 实际效果:允许在开发板直接修改服务器文件,如删除或创建新文件
- 开发优势:省去重复烧写步骤,实现"修改即生效"的高效开发模式
6)console参数与串口打印
- 设备指定:console=ttySAC2确定使用开发板的第二个串口作为控制台
- 波特率匹配:115200必须与实际硬件连接使用的波特率严格一致
- 调试技巧:若更改串口号(如改为ttySAC3),需同步调整物理串口线连接位置
7)ip参数与Linux启动IP
- 地址分配:ip=192.168.1.100设置内核启动后的默认IP地址
- 网络要求:必须与服务器IP处于同一网段且未被其他设备占用
- 验证方法:内核启动后执行ifconfig命令可查看生效的IP配置
知识小结
知识点 | 核心内容 | 考试重点/易混淆点 | 难度系数 |
Linux系统加载方式对比 | TFTP方式:将内核镜像、设备树文件、根文件系统镜像通过TFTP加载到开发板内存; eMMC方式:将系统文件安装到开发板外部存储器; TFTP+NFS方式:内核通过TFTP加载,根文件系统通过NFS网络共享 | 三种方式的应用场景差异: - TFTP适合开发调试阶段; - eMMC适合产品量产阶段; - TFTP+NFS是开发效率最高的方式 | ⭐⭐⭐ |
NFS网络文件系统原理 | 将Ubuntu中的根文件系统目录通过NFS共享给开发板,实现: - 开发板直接访问主机文件; - 实时同步修改(演示文件创建/删除双向同步); - 省去文件传输步骤 | NFS服务配置要点: - 必须设置正确的服务器IP和工作目录路径; - 每次Ubuntu重启需重启nfs服务 | ⭐⭐ |
交叉编译环境 | ARM架构程序开发流程: 1. 在x86主机编写代码; 2. 用arm-none-linux-gnueabi-gcc编译; 3. 直接在开发板执行 | 常见错误: - 使用x86编译器生成无法在ARM运行的程序; - 文件权限问题(需sudo操作) | ⭐⭐⭐⭐ |
u-boot环境变量解析 | bootargs参数详解: - root=/dev/nfs 指定NFS挂载方式; - nfsroot=192.168.1.200:/opt/4412/rootfs 设置服务器路径; - console=ttySAC2,115200 指定调试串口; - ip=192.168.1.100 设置开发板IP | 参数错误会导致: - 内核启动失败; - 文件系统挂载异常; - 串口无输出 | ⭐⭐⭐⭐ |
开发效率优化 | TFTP+NFS方案优势: - 避免频繁刷写eMMC; - 代码修改实时生效; - 支持完整的Linux系统调用; - 可直接运行主机编译的程序(需交叉编译) | 典型应用场景: - 驱动开发; - 系统移植; - 应用调试 | ⭐⭐ |