Linux驱动-系统移植

结束了ARM架构的学习,现在开始Linux驱动模块的学习。首先是Linux系统移植,我们需要把Linux系统移植到硬件平台。今天从头到尾完整实操了整套流程:从理解Linux内核基础概念、搭建Ubuntu虚拟机开发环境,配置双网卡网络,使用烧写工具烧写U‑Boot,完成U‑Boot编译、Linux内核编译,用BusyBox制作根文件系统,学习Linux完整启动流程。

一、关于Linux系统

一、为什么要将Linux系统移植到硬件平台?

1.屏蔽底层不同的硬件平台,为上层应用提供统一接口,从而简化应用层的编程,使得应用软件具备通用性。

2.Linux操作系统的五大核心功能:

1.内存管理(文本区、数据区、堆区、栈区、内核、虚拟空间、物理地址空间、进程空间)

2.多任务管理(进程和线程、任务的调度)

3.进程间通信(管理、信号、消息队列)

4.文件系统管理

5.网络协议(通信栈)

3.Linux系统分为两层:

1.用户层:shell(c语言利用库函数及系统调用编写的一些功能命令)、库函数(对系统调用的封装)

2.内核层:五大功能

3.两者之间的交互方法:系统调用、信号、文件系统

二、如何移植Linux系统?

1.开发板启动方式:

1.USB启动(第一次启动、调试时使用USB启动)

2.SD卡启动(调试阶段使用SD卡启动) 选用这种方式完成Linux系统烧录

3.EMMC启动(出厂时固化已经调试好的代码)

4.Nand Flash启动(批量化生产)

2.Linux系统所需要烧录的文件:

1.uboot 在Linux内核启动前,为加载内核做准备的一段逻辑代码

2.zImage 压缩的内核镜像文件,Linux系统的五大功能

3.dtb文件 设备树文件(描述硬件资源)

4.rootfs文件系统 提供人机交换的一个系统

3.如何将Linux系统(4个镜像文件)烧录到SD卡上?

使用芯片原厂提供的烧录工具mfgtool完成烧录

1.windows工具烧录(mfgtool)

2.Ubuntu烧录(mksdboot.sh)

三、Linux系统如何在开发板上启动加载的?

1.BotROM阶段

1.上电启动执行,芯片执行0x0地址的一段BotRom代码,这段代码是由厂家出场时固化,不允许修改

2.BotROM可以利用片内128K的SRAM执行代码

3.做一些芯片校验工作后,根据拨码开关设置的启动方式在对应的位置找uboot的代码

4.如果设置SD卡启动,BotROM会找到SD卡中的uboot.imx文件,uboot.imx文件是由3部分组成(IVT、uboot.bin、DCD)组成

5.BotROM会根据IVT向量表记录的位置找到DCD数据,DCD中包含了对DDR初始化的寄存器及时钟配置

6.BotROM初始化根据DCD初始化DDR

7.将uboot.bin拷贝到DDR中

8.跳转执行uboot.bin,uboot.bin是一段裸机代码

2.uboot阶段

1.初始化相应的外设

2.找到zImage和DTB文件,并将它们加载到DDR中

3.启动zImage内核,将DTB文件及其文件系统以参数的形式传入内核中

3.zImage内核阶段

1.Linux内核五大功能

2.找到文件系统

4.rootfs文件系统

1.启动文件系统

2.启动shell

二、开发环境搭建:Ubuntu双网卡配置

想要实现模式三网络启动,虚拟机网络配置是第一步。给VMware虚拟机添加两块网卡,分工明确:

网卡1:NAT模式,用来让Ubuntu访问外网,执行apt下载各类软件包。

网卡2:桥接模式,网线直连IMX6ULL开发板,充当TFTP、NFS服务器;虚拟机静态IP设置192.168.1.100,开发板IP设置为192.168.1.50。

  1. 桥接模式网卡,一定要桥接到电脑有线网卡,如果桥接无线网卡,开发板网络大概率不通。
  2. 默认网关要交给NAT网卡,不能把网关设置到桥接网卡,否则Ubuntu无法访问互联网。这里我写了systemd开机自启服务,开机自动修改路由,保证同时可以访问外网,又可以和开发板通信。
  3. Windows系统防火墙尽量关闭,不然会出现ping丢包、网络访问异常。

网络调通之后,安装全套开发需要工具:

  1. 将apt软件源替换为阿里源,更新软件索引。
  2. 安装minicom串口工具,用来接收开发板串口输出日志。
  3. 安装tftpd‑hpaTFTP服务器、nfs‑kernel‑serverNFS服务器。
  4. 部署交叉编译工具链gcc‑linaro‑4.9.4,把工具链路径加入环境变量PATH。

TFTP服务器配置

修改配置文件/etc/default/tftpd‑hpa,指定共享目录/home/linux/tftpboot,zImage和dtb设备树文件放到这个目录,开发板就可以通过网络下载镜像。给目录开放权限,重启tftpd‑hpa服务。

NFS服务器配置

修改/etc/exports,配置根文件系统目录共享权限:

复制代码
/home/linux/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)

修改完成重启nfs‑kernel‑server服务。这个共享目录就是开发板挂载的根文件系统,在Ubuntu这边修改程序,开发板可以直接运行,不需要拷贝到板载存储。

三、U‑Boot编译与烧写

U‑Boot是整个系统的入口,先编译源码得到镜像文件。

shell 复制代码
# 清理历史编译产物
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
# 加载开发板默认配置
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig
# 编译
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16

编译结束生成u‑boot.imx镜像。

烧写操作:使用烧写工具在Windows下将U‑Boot烧写到SD卡。开发板拨码开关设置为SD卡启动,上电后打开minicom,就能看到U‑Boot打印信息,按下任意按键可以进入uboot命令交互行。

注意:烧写的时候虚拟机需要关闭,不能占用开发板的OTG设备,否则烧写工具识别不到硬件。

四、Linux内核编译

接下来编译Linux内核源码:

shell 复制代码
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16

编译完成得到两个核心产物:

  1. arch/arm/boot/zImage:Linux内核镜像,复制到tftpboot目录
  2. arch/arm/boot/dts/imx6ull‑alientek‑emmc.dtb:设备树文件,复制到tftpboot目录

五、BusyBox构建根文件系统rootfs

光有内核还不够,内核本身没有ls、cd这些用户命令,需要制作根文件系统。这里使用BusyBox来构建最小化根文件系统:

  1. 解压BusyBox源码,修改顶层Makefile,指定ARCH=arm,配置交叉编译器CROSS_COMPILE=arm‑linux‑gnueabihf‑。
  2. make defconfig加载默认配置,打开make menuconfig,取消静态编译选项。
  3. 执行make && make install CONFIG_PREFIX=/home/linux/nfs/rootfs,生成基础文件。
  4. 把交叉工具链里面的库文件拷贝到rootfs的lib目录,手动创建dev、proc、sys、tmp等必要文件夹。
  5. 编写系统启动相关配置文件:/etc/inittab、/etc/init.d/rcS、/etc/fstab,完成根文件系统搭建。

六、模式三网络启动配置

三种主流启动方式

模式一:全套系统烧写到SD卡,适用于刷机、系统恢复、量产测试。

模式二:全套系统烧写到板载EMMC,适用于产品成品,设备独立运行

模式三:SD卡启动U‑Boot,TFTP下载内核设备树,NFS挂载根文件系统。

模式三是嵌入式开发调试阶段非常好用的启动方式,不用反复烧录SD卡或者EMMC。只要修改内核、设备树或者应用程序,把文件放到Ubuntu对应的服务目录,重启开发板就能加载新版本镜像,省去频繁烧卡的时间,调试效率提升非常明显。

模式三工作逻辑:SD卡存放U‑Boot;上电运行U‑Boot,通过TFTP协议从Ubuntu服务器下载zImage内核和dtb设备树,加载到DDR内存;再通过NFS网络挂载Ubuntu主机上的rootfs作为根文件系统,完整启动Linux操作系统。

进入uboot命令行,配置环境变量:

shell 复制代码
setenv ipaddr 192.168.1.50          #开发板本地IP
setenv serverip 192.168.1.100      #Ubuntu服务器IP
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv ethaddr 00:04:9f:04:d2:35

# bootcmd:开机自动执行,tftp下载内核、设备树,bootz启动内核
setenv bootcmd 'tftp 80800000 zImage;tftp 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000'

# bootargs:内核启动参数,指定使用NFS作为根文件系统
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.100:/home/linux/nfs/rootfs,proto=tcp,nfsvers=3 rw ip=192.168.1.50:192.168.1.100:192.168.1.1:255.255.0::eth0:off'

saveenv    #保存环境变量,重启不丢失

配置完毕复位开发板,U‑Boot自动执行bootcmd,网络下载内核与设备树,挂载NFS根文件系统,串口成功进入Linux shell交互终端。

裸机开发是我们直接读写寄存器操作硬件,而进入Linux系统移植之后开发思路完全转变。U‑Boot、Linux内核已经帮我们处理了绝大部分底层硬件初始化工作,我们更多的工作集中在配置、裁剪、编译、调试。

相关推荐
根目录下的猫1 小时前
虚拟机复制过来运行时:“虚拟机使用的此版本,VMware Workstation 不支持的硬件版本。”错误解决办法,亲测可用
linux·运维·服务器·后端
涉密IT资质笔记1 小时前
2026 涉密资质三类硬性条件对照:军工 / 集成 / 印制参数矩阵与易错点
服务器·线性代数·矩阵·创业创新
yunwei371 小时前
eBPF 入门实践教程十七:编写 eBPF 程序统计随机/顺序磁盘 I/O
linux·后端·性能优化
帷幕落秋1 小时前
内存、虚拟内存与 OOM
linux·运维
dingdingfish1 小时前
TLPI 第41章 读书笔记:Fundamentals of Shared Libraries
linux·static·link·dynamic·library·tlpi
mengge.cloud1 小时前
Redis
运维·服务器·数据库·redis·缓存·云计算
Smoothcloud润云2 小时前
GPU服务器租用实例DNS与HTTPS下载排障实战
大数据·运维·服务器·人工智能·https·gpu算力
Apipi*2 小时前
30天速通Linux 第五章Linux 进程管理
linux·运维·服务器
杨云龙UP2 小时前
PostgreSQL 四种常见部署模式快速理解:单实例、流复制、repmgr、Patroni
linux·运维·数据库·postgresql·流复制·高可用ha