arm系统移植

发布于:2025-07-01 ⋅ 阅读:(25) ⋅ 点赞:(0)

1. 流程

在SD卡内烧写uboot,然后设置开发板,通过tftp把uimage和exynos.dtb下载到开发板,通过nfs挂载根文件系统。即可以在开发板上先启动uboot,然后在模拟linux环境。或者可以自由制作uboot和rootfs根文件系统。

2. 概念

2.1 设备树

Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写。引入了设备树之后,驱动代码只负责处理驱动的逻辑,而关于设备的具体信息存放到设备树文件中,这样,如果只是硬件接口信息的变化而没有驱动逻辑的变化,驱动开发者只需要修改设备树文件信息,不需要改写驱动代码。比如在ARM Linux内,一个.dts(device tree source)文件对应一个ARM的machine,一般放置在内核的"arch/arm/boot/dts/“目录内,比如exynos4412参考板的板级设备树文件就是"arch/arm/boot/dts/exynos4412-origen.dts”。这个文件可以通过$make dtbs命令编译成二进制的.dtb文件供内核驱动使用。

2.2 根文件系统

根文件系统(root filesystem)是运行Linux系统所必须的各种工具软件、库文件、脚本、配置文件的一种特殊的文件目录结构。Linux内核要启动后要挂载一个文件系统才能运行。

2.3 文件说明

1.uImage : 编译好的Linux内核文件,它是专门给u-boot提供的,u-boot是用来引导linux的一个系统。

2.exynos4412-itop-elite.dtb:编译好的设备树文件,设备树中描述了硬件信息,如LED信息,网卡信息DM9606等等。

3.rootfs.tar.gz : 这是文件系统,Linux内核要运行必须挂载一个文件系统。

3. 交叉编译链

3.1 作用

ubuntu为x86环境,交叉编译链的作用是在x86的环境下模拟通过arm编译。

3.2 在linux下配置

  1. gcc-arm-8.3.tar.gz 放到 /opt目录下
sudo mv gcc-arm-8.3.tar.gz /opt
  1. 解压
sudo tar zxvf gcc-arm-8.3.tar.gz
  1. 解压后在 /opt 目录下会出现
    gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf
  2. 编辑环境变量加载文件
sudo vim /etc/profile

#在文件尾部添加下面两行
export ARM_PATH=/opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin
export PATH=${PATH}:${ARM_PATH}
  1. 使 /etc/profile 生效: 在控制终端运行 source /etc/profile
  2. 测试交叉编译工具链有没有安装成功
在控制终端 输入 arm-linux-gnueabihf-gcc -v

7.若以上方法无法找到arm-linux-gnueabihf-gcc命令(可选)
vim ~/.bashrc .bashrc文件是在你的用户根目录下,即在/home/<用户名>目录下
在.bashrc末尾添加

export ARM_PATH=/opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin
export PATH=${PATH}:${ARM_PATH}

4. tftp

4.1 作用

(在这里的作用)把uimage和exynos.dtb下载到开发板

4.2 安装过程

1.安装tftp服务器及客户端

sudo apt-get install tftpd-hpa tftp-hpa

2.在 /home/[用户名]/路径下创建一个文件夹: tftpboot

mkdir ~/tftpboot

3.修改tftp的配置文件

sudo vi /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/[用户名]/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-c -s -l"  

4.重启tftp服务器

sudo systemctl restart tftpd-hpa.service

5.启动成功
在这里插入图片描述
6.上传/下载文件测试
<1>上传文件到tftp服务器
在任意一个目录新建一个文件a.txt,并向其中写入任意内容,然后执行下面的命令

tftp 127.0.0.1
tftp> put a.txt

tftp配置文件 sudo vi /etc/default/tftpd-hpa 中的OPTIONS里要加上-c,才能新建文件
修改 /home/[用户名]/tftpboot  文件夹权限为777

<2>开发板测试tftp服务器功能
从开发板上传文件到tftp服务器目录 :

tftp 192.168.101.242 -p -l new_file.txt

从tftp服务器目录下载文件到开发板 :

tftp 192.168.101.242 -g -r a.txt

测试从tftp服务器下载文件:

tftp 127.0.0.1
tftp> get a.txt 

将uImage 和 exynos4412-itop-elite.dtb放在tftp服务器的配置目录下,如tftpboot目录下。

5. nfs

5.1 作用

在linux运行起来后,挂载根文件系统。linux内核在运行时支持通过网络挂载另一网络地址上的文件系统。将pc机上的目录共享给开发板使用,提高开发效率。

5.2 安装过程

1.在/home/[用户名]/目录下创建一个文件夹nfs,将根文件系统的压缩包rootfs.tar.gz拷贝至/home/[用户名]/nfs目录下,然后解压。解压后生成一个目录rootfs,然后修改rootfs权限。

mkdir ~/nfs
cp rootfs.tar.gz ~/nfs
cd nfs
tar -zxvf rootfs.tar.gz
chmod 777 rootfs

2.重新安装nfs服务器

sudo apt-get install nfs-kernel-server

3.配置NFS服务器

sudo vim /etc/exports

在最末尾添加:
/home/[用户名]/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)
选项可以参考 man 5 exports (/etc/exports注释中提示的)

4.重启NFS服务器

sudo service nfs-kernel-server restart 

5.查看状态

$ sudo systemctl status nfs-kernel-server.service

6.进行挂载测试

sudo mkdir /mnt/root_nfs 
sudo mount -t nfs localhost:/home/[用户名]/nfs/rootfs /mnt/root_nfs
ls -l /mnt/root_nfs 

7.卸载对rootfs的挂载(可选)

sudo umount /mnt/root_nfs

6. 配置开发板

1.设置开发板的IP地址,开发板通过USB转串口连接到电脑,通过SecureCRT打开串口,输入以下命令:

 setenv ipaddr 192.168.xx.xx

2.设置服务器的IP地址,就是虚拟机的地址

setenv serverip 192.168.xx.xx

3.设置网关ip

setenv gatewayip 192.168.101.1

4.设置网络掩码

setenv netmask 255.255.255.0

5.设置开发板启动linux启动的环境变量,设置从nfs挂载根文件系统

setenv bootargs root=/dev/nfs nfsroot=192.168.107.10:/home/[用户名]/nfs/rootfs,proto=tcp,nfsvers=3 rw console=ttySAC2,115200n8 init=/linuxrc ip=192.168.107.100:192.168.107.10:192.168.107.1:255.255.255.0::eth0:o
//bootargs 中的ip参数解释
//bootargs参数由linux内核运行到最后挂载根文件系统时使用
root=/dev/nfs	//使用的网络文件系统
nfsroot=192.168.x.x   //为虚拟机服务器的ip
nfsroot=192.168.107.10:/home/wyl/nfs/rootfs	//其中/home/wyl/nfs/rootfs 是Ubuntu上rootfs的真实路径
ip=192.168.x.x:192.168.x.x:192.168.x.1 //第一个ip为开发的ip,第二个是虚拟机的ip, 第三个是网关

6.下载kernel到内存

tftpboot 40008000 uImage
tftpboot 42000000 exynos4412-itop-elite.dtb 

7.手动启动

bootm 40008000 - 42000000 

8.如果上面的测试通过的话,可以把2,3中的命令写到bootcmd环境变量中,以后重启就是自动执行

setenv bootcmd tftpboot 40008000 uImage\;tftpboot 42000000 exynos4412-itop-elite.dtb\;bootm 40008000 - 42000000
1. 切换到 u-boot 运行环境下,设置以下环境变量
setenv bootcmd tftpboot 40008000 uImage\;tftpboot 42000000 exynos4412-itop-elite.dtb\;bootm 40008000 - 42000000
再用 saveenv 命令保存u-boot下的环境变量,重启开发板,u-boot倒计时结束 后会自动启动linux

9.保存

saveenv

10.若开发板挂载根文件系统太慢,则可以在Ubuntu上 用ping命令,去ping开发板的IP地址。

7. linux下的uboot镜像烧写到SD卡中

7.1 生成uboot二进制文件,二进制文件就是裸机程序。

运行 uboot源码目录(uboot_itop4412_2017.11.tar.gz 或 jason412_uboot-2017.11)mkboot子目录下的脚本程序 build.sh,在uboot/mkboot目录下输入 ./build.sh 进行 uboot源码的编译,编译完成后,会生成两个文件,一个是itop4412-spl.bin,一个是u-boot.bin。

uboot的源码目录是指:jason412_uboot-2017.11目录
itop4412-spl.bin是在 uboot/spl目录下
u-boot.bin是在 uboot目录下

脚本程序build.sh会将itop4412-spl.bin文件和u-boot.bin拷贝到 uboot/mkboot目录下。

7.2 合成最终的uboot

通过命令 cat E4412_N.bl1.bin itop4412-spl.bin env.bin u-boot.bin > u-boot-iTOP-4412.bin

E4412_N.bl1.bin:三星提供的二进制文件。
itop4412-spl.bin :u-boot编译生成的。
env.bin :保存的环境变量。
u-boot.bin:编译uboot生成的。

通过命令cat E4412_N.bl1.bin itop4412-spl.bin env.bin u-boot.bin > u-boot-iTOP-4412.bin把三个二进制文件合成为一个最终的 u-boot-iTOP-4412.bin

7.3 通过dd命令把u-boot-iTOP-4412.bin烧写到SD卡中

sudo dd iflag=dsync oflag=dsync if=u-boot-iTOP-4412.bin of=/dev/sdb seek=1

解析:
sudo是超级用户权限
dd 是linux 的命令;
dsync 读写数据采用同步IO;所谓同步就是写入或读取磁盘会花费时间,同步就是等待读/写结束,阻塞式等待。
iflag=dsync 使用iflag来控制读取数据时的行为特征。
oflag=dsync 使用oflag来控制写入数据时的行为特征。
if: 输入的文件
of:输出到哪个设备文件(磁盘文件),of=/dev/sdb 其中的 /dev/sdb就代表SD卡

因此意思是:使用超级用户权限把u-boot-iTOP-4412.bin写入到磁盘sdb上,跳过该设备的第一个块(block)(每个block的大小为512B)

块(block):举例说明,内存是以字节为单位来访问的,块设备,如磁盘(flash,SD卡,emmc)是按照块大小为单位来访问的。块的大小可以理解 为内存中的一个存储单元。

磁盘设备的第一个块,存储有磁盘的一些重要信息,一定不能用dd命令去写。

8. 制作linux根文件系统

8.1 busybox

BusyBox 是一个轻量级的开源工具箱,官网地址是:http://www.busybox.net/,其中包含了许多标准的 Unix 工具,例如 sh、ls、cp、sed、awk、grep 等,同时它也支持大多数关键的系统功能,例如自启动、进程管理、启动脚本等等。

8.2 需要配置的软件环境

  • 安装arm交叉编译工具链 8.3.0
  • 在ubuntu中安装libncurses5-dev sudo apt install libncurses5-dev

8.3 配置busybox选项并编译

  1. 解压buxybox压缩包
tar -jxvf busybox-1.36.1.tar.bz2 //解压buxybox压缩包
cd busybox-1.36.1 //会在当前目录下解压为一个文件夹,进入
  1. 配置编译选项
make menuconfig ARCH=arm //弹出图形化界面

一般配置三个选项:

a)编译器前缀
Settings ---->
	(arm-linux-gnueabihf-) Cross compiler prefix //添加交叉编译链arm-linux-gnueabihf-

b)编译静态库
Settings ---->
	[*] Build static binary (no shared libs) 

c)安装目录
Settings ---->
	[*] ( ./_install) Destination path for 'make install'     //./install为rootfs安装的目录路径

d)保存后退出
  1. 编译
make ARCH=arm CROSS_COMPILE=arm-linux-guneabihf-

在 busybox-1.36.1目录下会生成一个busybox可执行文件。运行file busybox,如下:
$ file busybox 确认编译生成的是 ARM 平台的(显示为ELF 32-bit LSB executable, ARM)

  1. 安装
make install
  1. 做了什么
    至此通过busybox编译安装了根文件目录_install,即rootfs,现在要做的是将根文件目录放到nfs下

8.4 制作根文件系统

  1. 进入busybox install后的安装目录并创建所需目录
cd _install
mkdir dev etc mnt  proc var tmp sys root lib
  1. 将工具链中的库拷贝到_install/lib 目录下
cd lib

#从编译工具链中拷贝运行库到刚制作的根据文件系统的lib下
sudo cp -Parf /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/lib/*  ./
sudo cp -Parf /opt/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/*  ./
  1. 删除静态库和共享库(动态库)文件中的符号表以减小体积
#在 lib 目录下,删除掉静态库
rm *.a

#裁剪掉调试信息 
arm-linux-gnueabihf-strip ./*
  1. 查看lib目录大小
du -mh lib/

应该是7.0MB的大小左右

  1. 添加系统启动文件
cp -rf ~/nfs/rootfs/etc .

拷入成熟的参考配置,将linux内核能成功挂载的rootfs目录下的etc文件夹拷贝到新制作的rootfs目录下面。
a) 在etc下添加文件inittab,文件内容如下:

#this is run first except when booting in single-user mode.
::sysinit:/etc/init.d/rcS
# /bin/sh invocations on selected ttys
# Start an "askfirst" shell on the console (whatever that may be)
::respawn:-/bin/sh
# Stuff to do when restarting the init process
::restart:/sbin/init
# Stuff to do before rebooting
::ctrlaltdel:/sbin/reboot 

b) 在etc目录下创建init.d子目录,并在etc/init.d目录下添加rcS文件:

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
runlevel=S
prevlevel=N
umask 022
export PATH runlevel prevlevel
mount -a
echo /sbin/mdev>/proc/sys/kernel/hotplug
mdev -s
mount -o remount,rw /

c) 更改rcS的权限

chmod a+x _install/etc/init.d/rcS

d) 修改以可读可写方式挂载文件系统Readonly file system

vim  rootfs/etc/init.d/rcS

e) 在文件末尾添加以下内容

mount -o remount,rw /

f) 在etc下添加文件fstab,文件内容如下

#device     mount-point      type       options         dump     fsck order
proc	       /proc                proc       defaults             0               0
tmpfs        /tmp             tmpfs      defaults         0           0
sysfs          /sys              sysfs       defaults         0           0
tmpfs       /dev             tmpfs      defaults          0           0
  1. 支持挂载proc, sysfs, tmpfs文件的内核配置

这里我们挂载的文件系统有三个proc、sysfs和tmpfs。在内核中proc和sysfs默认都支持,而tmpfs是没有支持的,我们需要添加tmpfs的支持。
进入linux-4.14.12内核源码根目录,修改Linux内核配置并重新编译:

$ make menuconfig
File systems --->
	Pseudo filesystems --->
		[*] Tmpfs virtual memory file system support (former shm fs)
		[*] Tmpfs POSIX Access Control Lists

在Linux内核源码根目录下,重新编译内核

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- LOADADDR=0x40008000 uImage
  1. 在rootfs目录下的etc目录下添加profile文件,文件内容为
#!/bin/sh
export HOSTNAME=i4412
export USER=root
export HOME=root
export PS1="[$USER@$HOSTNAME \W]\# "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH  LD_LIBRARY_PATH

重要:新制作的文件系统尺寸若超出8M,删除不需要的库文件
9. 创建设备文件

在根文件系统的根目录执行以下命令

#在根文件系统的dev目录一创建一个console设备文件
sudo mknod dev/console c 5 1

#在根文件系统的dev目录一创建一个null设备文件
sudo mknod dev/null c 1 3
  1. 测试:看新的根文件系统能否正常挂载到开发板
#把原有的根文件系统备份一下
linux@linux:~/busybox-1.22.1  $ mv  ~/nfs/rootfs /nfs/rootfs.ok

把新的根文件系统拷贝过去(改名rootfs)
linux@linux:~/busybox-1.22.1$ sudo cp -arf _install  ~/nfs/rootfs
  1. 挂载成功

网站公告

今日签到

点亮在社区的每一天
去签到