一、移植
根据硬件平台的差异,将代码进行少量的修改,修改过后的代码在目标平台上运行起来
移植还需要考虑硬件环境,驱动只需要考虑内核的环境
二、移植内容
1、移植Uboot
uboot属于bootloader的一种,还有其他的bootloader,如:arm-boot、red-boot、uboot、pmon、uefi
bootloader是系统上电之后执行的第一个系统软件,负责初始化硬件,负责加载引导操作系统。
2、移植Linux内核
1)获取Linux内核源码
2)板子上操作系统与不上操作系统的区别
优点:可以更容易的实现较为复杂的业务逻辑
缺点:硬件的成本很高
3)Linux内核的核心功能
【1】进程间通信
管道:命名管道、匿名管道
[a]通信方式
匿名管道:半双工的,同一时刻数据只能使用一种方式流动,用于有亲缘关系的进程间通信
命名管道:支持双向通信,允许非亲缘关系的进程间通信(包括亲缘关系)
[b]通信方式
匿名管道:pipe(2)
命名管道:mkfifo(2)
[c]存在形式
匿名管道:不是文件,是kernel中的一段buffer
命名管道:是文件,在linux文件系统中以p表示
[d]生命周期
匿名管道:当调用pipe(2)时创建,当调用进程结束时,pipe被销毁了
命名管道:当调用mkfifo(2)时创建,当调用进程结束时,fifo文件依然存在
SYS V IPC:消息队列、共享内存、信号量
【2】进程间的管理
给当前进程分配多少个时间片,给当前进程分配多少内存
【3】虚拟文件子系统
【4】网络子系统
【5】内存管理子系统
早期的内核版本:2.6版本(Red Hat4)
开发板中使用的内存版本是3.4版本
企业中使用最多的是4.19、5.10
3、移植根文件系统
1号进程[init]对应的程序就是根文件系统
根文件系统里面包含一些命令,例如
ls、cd、touch、rm。。。
我们可以通过busybox工具制作根文件系统,它已经集成了上述命令。
4、总结
移植三大系统软件,包括:
|--------------|----------------------|-------------------------------------------------|
| 【1】移植uboot | 对应固件工程师(固化到硬件里的软件程序) | 例如:ESP8266WiFi模块,内部集成了TCP/UDP协议栈,是由乐鑫公司固件工程师实现的 |
| 【2】移植Linux内核 | 对应Linux内核工程师 | |
| 【3】移植根文件系统 | 对应系统集成开发工程师 | |
5、目标
【1】熟悉uboot的源码,掌握uboot的编译方式
【2】掌握Linux源码的框架结构,掌握Linux内核裁剪方式,掌握Linux内核编译过程
【3】掌握根文件系统镜像的制作
三、开发板烧写
擦除emmc,并对其进行分区
1、实验前准备
【1】uboot
【2】Linux内核
【3】根文件系统的镜像
2、新建一个实验文件夹
mkdir s5p6818
3、将所需文件拷贝至实验文件
cp ubootpak.bin ~/s5p6818/
cp fastboot/uImage ~/s5p6818/
cp fastboot/rootfs_ext4.img ~/s5p6818/
4、查看各文件大小,便于分区
1)查看uboot(引导内核)
du -h ubootbinpak.bin
看到ubootpak.bin只有336K,不到1Mb,可以在emmc开头位置分1Mb的空间给uboot
2)查看uImage(内核)
du -h uImage
看到uImage有5.2Mb,但我们将来需要裁剪,并且还要添加很多的驱动模块,所以给内核分大一些,分64Mb
3)查看rootfs(根文件系统)
du -h rootfs_ext4.img
看到rootfs有100Mb,我们给它分大一些,比如800Mb
5、关于EMMC的分区
三星公司对于第二启动设备(EMMC)的分区有一个指定的命名
第一分区:mmcblk0p1
第二分区:mmcblk0p2
第三分区:mmcblk0p3
注意:
我们在烧录的时候,需要按照扇区进行烧写,1扇区=512byte
因为EMMC是一个硬盘,是一个块设备,需要用字节进行操作,需要按照扇区进行烧录
1】在擦除之前保证下位机可以ping通上位机
2】保证全过程开发板不断电
3】把SD卡拔掉
ps:如果失败,需要把之前的步骤重新来一遍
6、擦除emmc分区
mmc erase 0 0x100000
注释:
0:要擦除的起始块
0x100000:要擦出的字节数
7、对emmc进行分区
fdisk 2 3 0x100000:0x4000000 0x4100000:2f200000 0x33300000:0
注释:
2表示第二个启动设备(EMMC)
3表示分区个数
第一个参数表示每个分区的起始地址
第二个参数表示分区的字节大小
8、烧写uboot
1)上位机把ubootpak.bin拷贝到tftp共享目录
cp ubootpak.bin /tftpboot/
md5sum ubootpak.bin
md5sum /tftpboot/ubootpak.bin
//通过md5sum命令计算校验文件的MD5校验码,来确定是否拷贝成功
2)下位机下载uboot
tftp 0x48000000 ubootpak.bin
注意:
这是将ubootpak.bin通过tftp方式下载到了开发板的内存中,将来需要更新到EMMC中
下载了多少个字节,将来就更新多少个字节
3)下位机更新EMMC
update_mmc 2 2ndboot 0x48000000 0x200 0x53ba8
注释:
update_mmc:更新emmc命令
2:设备号
2ndboot:第二启动设备
0x48000000:从内存的0x48000000位置开始读取
0x200:从emmc的200个字节开始更新
0x53ba8:更新的字节数(下载了多少字节,就更新多少字节)
4)下位机的ip地址
烧写完之后,需要重新更改下位机的ip地址
setenv ipaddr 192.168.1.6
setenv serverip 192.168.1.8
saveenv
9、烧录uImage
1)上位机把uImage拷贝到tftp共享目录
cp uImage /tftpboot/
md5sum uImage
md5sum /tftpboot/uImage
//通过md5sum命令计算校验文件的MD5校验码,来确定是否拷贝成功
2)下位机下载uImage
tftp 0x48000000 uImage
注意:
这是将uImage通过tftp方式下载到了开发板的内存中,将来需要更新到EMMC中
下载了多少个字节,将来就更新多少个字节
3)下位机写emmc
mmc write 0x48000000 0x800 0x3000
注释:
mmc write:往emmc中写数据指令
0x48000000:从内存的0x48000000位置开始读取
0x800:从emmc的0x800个扇区的位置开始写
0x3000:要写的扇区数(可以比实际下载的大小大一些)
4)修改bootcmd环境变量
需要修改环境变量bootcmd,告诉uboot去哪里加载Linux内核
setenv bootcmd mmc read 0x48000000 0x800 0x3000\;bootm 0x48000000
注释:
mmc read:从硬盘读
0x48000000:读到内存的0x48000000地址中
0x800:从硬盘的第0x800扇区读
0x3000:连续读0x3000个扇区
\:连续符
bootm 48000000:自动从48000000位置启动内核
saveenv
a、烧录根文件系统
1)上位机把rootfs_ext4.img拷贝到tftp共享目录
cp rootfs_ext4.img /tftpboot/
md5sum rootfs_ext4.img
md5sum /tftpboot/rootfs_ext4.img
//通过md5sum命令计算校验文件的MD5校验码,来确定是否拷贝成功
2)下位机下载rootfs_ext4.img
tftp 0x48000000 rootfs_ext4.img
注意:
这是将rootfs_ext4.img通过tftp方式下载到了开发板的内存中,将来需要更新到EMMC中
下载了多少个字节,将来就更新多少个字节
3)下位机写emmc
mmc write 0x48000000 0x20800 0x32000
注释:
mmc write:往emmc中写数据指令
0x48000000:从内存的0x48000000位置开始读取
0x20800:从emmc的0x20800个扇区的位置开始写
0x32000:要写的扇区数(可以比实际下载的大小大一些)
4)修改bootargs环境变量
需要修改环境变量bootargs,告诉Linux内核去哪里挂载根文件系统,以什么样的方式挂载根文件系统
setenv bootargs root=/dev/mmcblk0p2 rootfstype=ext4 console=ttySAC0,115200 maxcpus=1 lcd=wy070ml tp=gslx680
注释:
root=/dev/mmcblk0p2:从EMMC的第二个分区找根文件系统
rootfstype=ext4:根文件系统的类型
console=ttySAC0,115200:用来设置控制终端
maxcpus=1:单CPU模式
lcd=wy070ml:指定LCD先视频的型号
tp=gslx680:指定TS触摸屏的型号
saveenv
四、通过nfs的方式挂载根文件系统
nfs的网络服务(Network File System)是由SUN公司研制的UNIX操作系统的表示层协议
|-------|--------|
| OSI | TCP/IP |
| 应用层 | 应用层 |
| 表示层 | 应用层 |
| 会话层 | 应用层 |
| 传输层 | 传输层 |
| 网络层 | 传输层 |
| 数据链路层 | 数据链路层 |
| 物理层 | 物理层 |
我们不把根文件系统放到开发板的EMMC中,而是将下位机的根文件系统部署在上位机中,这样做的好处:
【1】可以直接在上位机中修改下位机的根文件系统的内容
【2】不需要再重复的往下位机的EMMC中烧录根文件系统,延长EMMC的寿命
1、在PC机中配置nfs服务
sudo apt-get install nfs-kernel-server
sudo mkdir /nfs_share
sudo chmod 777 /nfs_share
tar -xvf rootfs_qt.tar.bz2 -C /nfs_share
/*修改nfs的配置文件*/
/*修改nfs的服务文件*/
2、修改nfs的配置文件
sudo vim /etc/exports
(在exports文件中直接添加内容)
/nfs_share/rootfs *(rw,sync,no_root_squash)
注释:
/nfs_share/rootfs 共享目录的绝对路径
* 所有ping通服务器的用户
rw 用户在访问时可读可写
sync 同步
no_root_squash 不会对于root用户降级
3、 修改nfs的服务文件
sudo vim /etc/default/nfs-kernel-server
(在文件中直接添加内容)
RPCNFSDOPTS="--nfs-version 2,3,4 --debug --syslog"
/*保存退出,重启nfs服务*/
sudo service nfs-kernel-server restart
/*关闭防火墙*/
sudo service ufw stop
4、 修改下位机的bootargs环境变量
setenv bootargs root=/dev/nfs
nfsroot=192.168.1.8:/nfs_share/rootfs ip=192.168.1.6:192.168.1.8:192.168.1.1:255.255.255.0
init=/linuxrc
console=ttySAC0,115200
maxcpus=1
lcd=wy070ml
tp=gslx680-linux
注释:
root=/dev/nfs:说明根文件系统不在本地,在网络上
nfsroot=192.168.1.8:/nfs_share/rootfs:说明根文件系统在nfs服务器上的具体位置
ip=192.168.1.6:192.168.1.8:192.168.1.1:255.255.255.0:设置根文件系统的ip信息
(本地ip,服务器ip,网关,子网掩码)
init=/linuxrc:执行init进程初始化文件
console=ttySAC0,115200:设置控制终端
maxcpus=1:单CPU模式
lcd=wy070ml:指定LCD显示屏的型号
tp=gslx680-linux:指定TS触摸屏的型号
5、总结
用户名:root
密码:123456
由于是挂载的根文件系统,所以PC机在/nfs_share目录中创建的文件,在开发板的根中可以找到;在开发板的根中创建的文件,在PC机的/nfs_share目录中可以找到;在实际的嵌入式开发中,这种方式经常会用到,很方便。