目录
4.2EMMC加载Linux内核及rootfs -- 成品阶段(有sd卡)
4.3tftp加载Linux内核 nfs挂载rootfs --研发阶段
前言
1.嵌入式系统移植导学
1.1 移植的目的
不同架构的处理器指令集不兼容,即便是相同的处理器架构,板卡不同驱动代码也不兼容
Linux是一个通用的内核并不是为某一个特定的处理器架构或板卡设计的,所以从官方获取Linux源码后我们要先经过相应的配置使其与我们当前的硬件平台相匹配后才能进行编译和安装
1.2流程
流程: 配置 ===> 编译 ===>安装
windows和linux安装的对比:流程基本相同
1.3开发板启动过程
1.3.1 fs4412地址映射:
32个地址总线可以寻址4GB的内存空间,CPU自己使用了IGB,剩下3GB作为扩充内存使用
1.3.2 开发板启动过程
1. 开发板上电后首先运行SOC内部iROM中固化的代码(BL0),这段代码先对基本的软硬件环境(时钟等...)进行初始化,然后再检测拨码开关位置获取启动方式,然后再将对应存储器中的uboot搬移到内存,然后跳转到uboot运行。
2. uboot开始运行后首先对开发板上的软硬件环境做进一步初始化,然后将linux内核、设备树(dtb)、根文件系统(rootfs)从外部存储器(或网络)搬移到内存,然后跳转到linux运行。
3. linux开始运行后先对系统环境做初始化,当系统启动完成后,Linux再从内存中(或网络)挂载根文件系统。
1.3.3系统移植步骤
系统移植步骤
uboot移植
linux内核移植(包含设备树)
根文件系统移植
2.交叉开发环境搭建
有三步:
1.配置ubantu网络为桥接,可以连接局域网的其他硬件设备。
2.tftp服务器 掌握 tftp环境搭建的基本方法,能够在 uboot 中使用 tftp 下载文件
3.nfs服务器 掌握 nfs环境搭建的基本方法,能够在开发板上使用 nfs 挂载根文件系统
每次打开ubuntu都需要重启重启 tftp 服务,使配置生效sudo service tftpd-hpa restart重启 nfs 服务,使配置生效sudo service nfs-kernel-server restart
工作目录位置
进入到tftp服务器工作目录cd /tftpboot/进入到nfs服务器工作目录cd /opt/4412/rootfs/
3.uboot烧写与使用
3.1uboot模式
自启动模式
uboot启动后若没有用户介入,倒计时结束后会自动执行自启动环境变量(bootcmd)中设置的命令(一般作加载和启动内核)
交互模式
倒计时结束之前按下任意按键uboot会进入交互模式,交互模式下用户可输入uboot命令
3.2uboot帮助命令
help
查看uboot支持的所有命令
help 命令
查看当前命令的使用方法
3.3uboot环境变量命令
printenv
打印uboot中所有的环境变量
setenv
设置指定的环境变量(保存在RAM中)
setenv 环境变量 环境变量的值例子: setenv ipaddr 192.168.1.100
saveenv
保存所有环境变量到EMMC中
3.4uboot常用环境变量
ipaddr
uboot的IP地址serverip
服务器的IP地址(即ubuntu的IP)bootdelay
进入自启动模式之前倒计时的秒数
3.5uboot帮助命令
loadb
通过Kermit协议下载文件到指定的内存地址
loadb 地址
tftp
通过tftp协议下载文件到指定的内存地址
tftp 地址 文件名 --tftpboot可省略为tftp注:使用tftp之前要配置好网络及tftp服务器
3.6uboot存储器访问指令
mmc read
将EMMC中指定扇区中的内容读取到内存中指定的地址
mmc read <addr> <blk#> <cnt>
addr: 内存地址
blk#: EMMC中的扇区编号
cnt: 读取的扇区的个数例子: mmc read 0 0x40008000 0x800 0x1 --其中 0 代表mmc
mmc write
将内存中指定地址中的内容写入到EMMC中指定的扇区
mmc write <addr> <blk#> <cnt>例子: mmc write 0 0x41000000 0x800 0x1 --其中 0 代表mmc
3.7uboot自启动环境变量
bootcmd
自启动的环境变量
该环境变量可以设置成一到多个uboot命令的集合(若有多个使用\;分割)
自启动模式下uboot就会按照bootcmd中命令的顺序逐条执行eg:setenv + bootcmd 命令
setenv bootcmd tftp 40008000 interface.bin\;go 40008000
3.8实验4: SD 卡启动盘制作
![](https://img-blog.csdnimg.cn/ca92e17b2b2d40d48735e790cd5d37d2.png)
![](https://img-blog.csdnimg.cn/fcb8dd92e9f343ab91fc3693ca0cbeb9.png)
![](https://img-blog.csdnimg.cn/209f7588024745a089aa3dd2b99a9c0a.png)
4.Linux内核的安装与加载
4.1tftp加载Linux内核及rootfs
4.1.1uboot内核启动命令
bootm
启动指定内存地址上的Linux内核并为内核传递参数
bootm kernel-addr ramdisk-addr dtb-addr
注:
kernel-addr: 内核的下载地址
ramdisk-addr: 根文件系统的下载地址
dtb-addr: 设备树的下载地址
若不使用相应的地址,对应的位置写“-”
eg:
bootm 0x41000000 - 0x42000000
4.1.2uboot自启动参数环境变量
bootargs
--这是uboot启动时,通过bootm传递给linux的参数。对uboot没用,是linux用的
eg:
setenv bootargs root=/dev/nfs nfsroot=xxx.xxx.xxx.xxx:/opt/4412/rootfs
rw console=ttySAC2,115200 init=/linuxrc ip=***.***.***.***
注:
root 根文件系统类型(nfs)
nfsroot 网络文件系统路径(xxx.xxx.xxx.xxx:/opt/4412/rootfs)
rw 操作网络文件系统的权限(rw)
console 控制台(使用串口2,波特率115200)
init init进程的位置(/linuxrc)
ip linux启动后自身的IP(***.***.***.***)
4.1.3详细步骤:
1 、 将资料中“ Linux 内核镜像”目录下的“uImage”和“exynos4412-fs4412.dtb ”拷贝到 ubuntu 中 tftp 工作目录下 。
将资料中“根文件系统镜像”目录下的“ ramdisk ”也拷贝到 ubuntu 中 tftp 工作目录下 。修改这些文件的权限 :$ sudo chmod 777 /tftpboot/*
2 、 重 启 tftp 服务器$ sudo service tftpd-hpa restart
3 、 连接开发板与电脑,在 uboot 交互模式下,设置 uboot 的启动参数# setenv ipaddr ***.***.***.***# setenv serverip xxx.xxx.xxx.xxx# setenv bootcmd tftp 0x41000000 uImage\;tftp 0x42000000 exynos4412-fs4412.dtb\;tftp0x43000000 ramdisk.img\;bootm 0x41000000 0x43000000 0x42000000# setenv bootargs root=/dev/nfs nfsroot=xxx.xxx.xxx.xxx:/opt/4412/rootfs/ rwconsole=ttySAC2,115200 init=/linuxrc ip=***.***.***.***注 1 :xxx.xxx.xxx.xxx 为 ubuntu 主机的 ip ,***.***.***.*** 为开发板的 ip ,必须和 ubuntu主机的 ip 在同一个网段(根据自己电脑情况进行设置)注 2 :以上设置手动输入,命令粘贴可能会有中文符号设置完成后保存这些参数# saveenv
4 、 检查网络设置是否正确,使用网线连接开发板与电脑,然后给开发板重新上电,上电之后观察 uboot 是否能通过 tftp 加载和启动内核,启动时是否能挂载根文件系统(ext2 ),启动完成后在终端上输入 linux 下的 shell 命令测试是否正常![]()
4.2EMMC加载Linux内核及rootfs -- 成品阶段(有sd卡)
![](https://img-blog.csdnimg.cn/1172a98ce39d4cc08f026d45cdfc0d05.png)
![](https://img-blog.csdnimg.cn/472ab54d06a94fe6986aebad9f2fa2dc.png)
![](https://img-blog.csdnimg.cn/dd7b3a97a5464f8f97ce76689aaa0ef7.png)
4.3tftp加载Linux内核 nfs挂载rootfs --研发阶段
![](https://img-blog.csdnimg.cn/f395f03452f34a9db6cf5345c44131ec.png)
4.4EMMC加载uboot-- 成品阶段(无sd卡)
![](https://img-blog.csdnimg.cn/5f1fa90eaf22449c90ff3d3b54404630.png)
5.交叉编译工具链
5.1ELF文件格式
5.1.1编译原理
机器码(二进制)是处理器能直接识别的语言,不同的机器码代表不同的运算指令,处理器能够识别哪些机器码是由处理器的硬件设计所决定的,不同的处理器机器码不同,所以机器码不可移植
汇编语言是机器码的符号化,即汇编就是用一个符号来代替一条机器码,所以不同的处理器汇编也不一样,即汇编语言也不可移植
C语言在编译时我们可以使用不同的编译器将C源码编译成不同架构处理器的汇编,所以C语言可以移植
5.1.2gcc编译过程
5.1.3交叉编译
简单来说:程序的编译和运行不在同一台机器上
5.1.4交叉编译工具链
交叉编译工具链的获取:
1) 官网获取(不推荐,需要自己进行复杂配置与编译)
http://ftp.gnu.org/gnu/gcc/
2) BSP板级开发支持包(推荐)
samsung、全志...
交叉编译工具链的内容
1) 交叉编译工具
gcc/readelf/size/nm/strip/objcopy/objdump/addr2line
2) 库
ARM架构的库
5.2 ELF文件格式
5.2.1 ELF文件相关命令
file
file + 文件名 查看文件的详细信息
readelf
readelf -h + 文件名 列出elf文件的头部信息
readelf -a + 文件名 列出elf文件的所有信息
5.3 BIN文件格式
5.4交叉编译工具链常用工具
size 列出目标文件每一段的大小以及总体的大小
size + 文件名
nm 列出目标文件中的符号表(标示符)
nm + 文件名
strip 丢弃目标文件中的符号
strip + 文件名
注:对于嵌入式开发,这个命令很重要
objdump 从目标文件中显示信息
eg:
objdump -d + 文件名 将目标文件反汇编(机器码->汇编)
objcopy 对目标文件进行复制和转换
eg:
objcopy --gap-fill=0xff -O binary a.out a.bin
将目标文件转换为bin格式
6.uboot移植
6.1 uboot源码获取
uboot源码下载
http://www.denx.de/wiki/U-Boot/(不使用)
https://ftp.denx.de/pub/u-boot/
uboot版本命名
前期:uboot-1.2.3
现在:uboot-2008.01
uboot版本选择
支持对应的硬件平台
相对成熟的版本(资料多)
6.2 uboot特点
代码结构清晰
支持丰富的处理器与开发板,易于移植
支持丰富的用户命令
支持丰富的网络协议
支持丰富的文件系统
支持丰富的设备驱动
更新活跃、用户较多、资料丰富
开放源代码
较高的稳定性
不具有通用性(不同的处理器、开发板uboot不可通用)
6.3 uboot源码结构
平台相关代码
即与CPU架构或开发板硬件相关的源码,硬件的改动对应的代码也需要进行修改arch:与CPU架构相关的源代码
board:与开发板相关的源代码,包含各种官方评估板对应的源码
平台无关代码
api: 应用接口
common: uboot命令源码
disk: 对磁盘设备的支持
drivers: 设备驱动源码
fs: 对文件系统的支持
include: 头文件
lib: 库
net: 对网络协议的支持
post: 上电自检程序
... ...
配置文件、帮助文档、示例程序、工具等:
README: 说明文档
doc: 帮助文档
Makefile: 编译管理
CREDITS: 开发者
COPYING: 版权
examples: 示例程序
tools: 工具
... ...
6.4 uboot配置
1.指定当前使用的硬件平台
make <board_name>_config
注1:<board_name>为当前使用的开发板的名字
注2:执行该命令的前提是uboot源码支持该开发板
注3:该命令必须在uboot源码的顶层目录下执行
2.指定编译uboot源码使用的编译器
在uboot源码顶层目录下的Makefile中指定(CROSS_COMPILE变量)
6.5 uboo编译
1.编译uboot
make
注1:该命令必须在uboot源码的顶层目录下执行
注2:该命令执行后在uboot源码顶层目录下生成u-boot.bin
2.清除编译过程中生成的中间文件
make clean
make distclean
注1:该命令必须在uboot源码的顶层目录下执行
6.6 uboo移植
6.7 实验6 uboot移植
一般 制作开发板的公司会把适配好的uboot直接给出,可以直接使用,将uboot拷贝到SD卡或者硬盘即可。
7.Linux内核移植
7.1 Linux内核特点
代码结构清晰、模块化设计
支持丰富的硬件平台
较高的稳定性
轻量化及较强的裁剪性
开放源代码
更新活跃、用户较多、资料丰富
支持丰富的网络协议
... ...
7.2 Linux内核源码下载
https://www.kernel.org/
Linux内核版本命名
主版本号.次版本号.修订版本
Linux内核版本选择
支持对应的硬件平台
相对成熟的版本(资料多)
稳定版本(次版本号为偶数的版本一般都是稳定版)
7.3 Linux内核源码结构
平台相关代码
arch: 与CPU架构相关的源代码
平台无关代码
block:磁盘设备的支持 crypto:加密相关
drivers:设备驱动 firmware:固件
fs:文件系统 include:头文件
init:内核初始化 ipc:进程间通信
kernel:内核核心调度机制等 lib:库
mm:内存管理 net:网络协议
scripts:工具、脚本等 security:安全
usr:打包与压缩 virt:虚拟
帮助文档、示例程序、工具等
COPYING: 版权
CREDITS: 内核贡献者
README: 说明文档
Documentation: 帮助文档
Makefile: 编译管理
samples: 示例
tools: 工具
... ...
7.4Linux内核源码配置
指定处理器架构及编译工具
在Linux内核源码顶层目录下的Makefile中指定(ARCH、CROSS_COMPILE)
导入当前处理器的默认配置
make <soc_name>_defconfig
注1:soc_name为当前使用的处理器的名字
注2:内核源码的arch/arm/configs下对各个厂商的soc都有一个默认配置文件
执行该命令后就会将对应的配置文件中的信息导入到源码顶层目录下的.config
文件中CONFIG_xxx=y表示内核选中了该功能,内核编译时就会将该功能对应的
代码编译,内核的体积也会增大。#CONFIG_xxx is not set表示内核没有选中
该功能,内核编译时该功能对应的代码不会被编译,内核的体积也会减小。修改配置
默认配置只能保证内核拥有最基本的功能,我们需要根据自己的实际需求对内核做进一步的配置方法1:
直接修改.config文件(不推荐)
方法2:
make menuconfig
7.5 make menuconfig
[ ] 有两种状态
输入Y,显示“*”,内核中该功能被选中,相关代码会被编译进内核
输入N,显示“ ”,内核中该功能不被选中,相关代码不会被编译进内核
< > 有三种状态
输入Y,显示“*”,内核中该功能被选中,相关代码会被编译进内核
输入N,显示“ ”,内核中该功能不被选中,相关代码不会被编译进内核
输入M,显示“M”,内核中该功能被选为模块(被编译为独立的模块)注:使用make menuconfig配置的本质还是修改.config文件
7.6 Linux内核源码编译
内核编译(以下命令均在内核源码的顶层目录下执行)
make uImage
编译内核(编译选为“*”的选项到内核)
make modules
编译内核模块(编译选为“M”的选项为独立模块)
make dtbs
编译设备树(将设备树源文件dts编译为二进制文件dtb)
make clean
删除编译过程中产生的中间文件
7.7 实验七 Linux 内核移植
![](https://img-blog.csdnimg.cn/a21b48bdcac14277b0c3d32e58acdfc5.png)
![](https://img-blog.csdnimg.cn/333ea7e2a9004714a0d7ecdbd48153f3.png)
![](https://img-blog.csdnimg.cn/c8afe0492cb74cfba2591b0f5d72d4f9.png)
![](https://img-blog.csdnimg.cn/fe4982ce0644426484eb960e40288075.png)
![](https://img-blog.csdnimg.cn/3c886d43574a45318a60ac31e860be76.png)
![](https://img-blog.csdnimg.cn/daeedfbfff9546c88be28c01905c84e2.png)
![](https://img-blog.csdnimg.cn/cf2d3be8aa2e430a8e0200f196d5923f.png)
8.Linux设备驱动移植
8.1设备树
设备树
设备树是一种描述硬件信息的数据结构,Linux内核运行时可以通过设备树将硬件信息直接传递给Linux内核,而不再需要在Linux内核中包含大量的冗余编码
8.2设备树语法概述
设备树文件
dts 设备树源文件
dtsi 类似于头文件,包含一些公共的信息,可被其它设备树文件引用
dtb 编译后的设备树文件设备树语法
设备树的语法为树状结构,由一系列的节点和属性组成,根节点下包含子节点
子节点下还可以包含子节点,节点内部包含了对应设备的属性
8.3linux内核驱动移植流程
1.在make menuconfig界面中选中要安装的驱动
2.在设备树中添加/修改相应的设备信息
3.重新编译内核/设备树
8.4 实验八 网卡驱动移植
Device Drivers --->[*] Network device support --->[*]Ethernet driver support --->< * >DM9000 support
[*] Networking support --->Networking options --->< * > Packet socket< * > Unix domain sockets[ * ] TCP/IP networking[ * ]IP: kernel level autoconfiguration
File systems --->[*] Network File Systems --->< * > NFS client support< * >NFS client support for NFS version 3 (NEW)[ * ]NFS client support for the NFSv3 ACL protocol extension[ * ]Root file system on NFS
srom-cs1@5000000 {compatible = "simple-bus";#address-cells = <1>;#size-cells = <1>;reg = <0x5000000 0x1000000>;ranges;ethernet@5000000 {compatible = "davicom,dm9000";reg = <0x5000000 0x2 0x5000004 0x2>;interrupt-parent = <&gpx0>;interrupts = <6 4>;davicom,no-eeprom;mac-address = [00 0a 2d a6 55 a2];};};
if (card->ext_csd.rev > 7) {pr_err("%s: unrecognised EXT_CSD revision %d\n",mmc_hostname(card->host), card->ext_csd.rev);err = -EINVAL;goto out;}
#if 0if (card->ext_csd.rev > 7) {#elseif (card->ext_csd.rev > 8) {#endifpr_err("%s: unrecognised EXT_CSD revision %d\n",mmc_hostname(card->host), card->ext_csd.rev);err = -EINVAL;goto out;}
9.根文件系统
9.1根文件系统
根文件系统是内核启动后挂载的第一个文件系统系统引导程序会在根文件系统挂载后从中把一些基本的初始化脚本和服务等加载到内存中去运行
9.2根文件系统内容
bin shell命令(elf格式)(通过busybox编译生成)
dev 设备文件(内核启动后会将设备信息写入该目录)
etc 内核配置文件
lib 共享库(elf格式)(从交叉编译工具链中获取)
linuxrc 内核运行的第一个应用程序(通过busybox编译生成)
mnt 挂载目录(非必要)
proc 进程相关文件(内核启动后会将进程信息写入该目录)
root 超级用户家目录(非必要)
sbin 系统管理shell命令(elf格式)(通过busybox编译生成)
sys 驱动相关文件(内核启动后会将驱动信息写入该目录)
usr shell命令(elf格式)(通过busybox编译生成)
9.3BusyBox
BusyBox将很多常用的工具集成到一个很小的可执行文件中,为普通用户提供大多数常用的命令,BusyBox实现的命令都是精简版的,很多扩展都不支持。BusyBox被称为Linux工具里的瑞士军刀
BusyBox的获取
https://busybox.net/downloads/
9.4 实验九 根文件系统移植
![](https://img-blog.csdnimg.cn/74e3dd3f051348189df5e5bbd5fc923a.png)
![](https://img-blog.csdnimg.cn/37d8b1532c18471c8987beb83194c5cc.png)
![](https://img-blog.csdnimg.cn/feb0724067554f7586428fc24e09404d.png)
![](https://img-blog.csdnimg.cn/6d33e1f2addb409595b06608b35819b2.png)
![](https://img-blog.csdnimg.cn/6e7fadcea711448484898ebcf3965ac5.png)
![](https://img-blog.csdnimg.cn/e4fbfc7f65eb47b8b341c24d9d275a56.png)
![](https://img-blog.csdnimg.cn/4d685e3709824d3380df3c89aea1c8d3.png)