Linux驱动开发(1)——系统移植

imx6ull开发板cortex-A7系列上有多种外部存储模块:

  • SD 卡:外置可插拔存储,存放代码,多用于裸机程序烧录与调试
  • eMMC(8G):板载固化式存储芯片,内部集成 NAND 闪存与控制单元,容量大、稳定性强,用于存放Linux系统与用户数据;
  • DDR 内存(512M):高速运行内存,负责系统与程序运行时的数据临时缓存,断电数据自动丢失,是嵌入式系统运行的核心临时存储介质。

在裸机开发阶段,我们通过 SD 卡启动实现硬件的基础控制,但这种方式无法高效管理 eMMC、DDR 等板载存储,也不支持复杂的系统调度。为了充分利用硬件资源、实现多任务运行与标准化外设控制,需要学习 Linux 驱动开发,通过驱动程序完成硬件抽象与系统对接,让嵌入式系统真正走向实用化与工程化。

一、系统移植概念

inux系统想要移植到开发板上,我们需要移植三部分:U-Boot(bootloader)、zImage(内核镜 像)、rootfs(文件系统),我们需要将其烧写到开发板的存储器中,这个过程称为系统移植。

  • uboot:一段加载引导系统启动的裸机代码。其核心功能是为操作系统内核的启动提供硬件初始化、镜像加载及参数传递等支持。
  • zImage(80800000):内核镜像文件。内核可以理解为一个软件,具备管理处理器、内存管理、硬件设备管理、进程调度、网络通信等功能。
  • .dtb(83000000):设备树文件。描述硬件设备信息,从内核中独立分出的设备文件。
  • rootfs:文件系统。用户层与内核层交互、对文件系统管理和操作。

1. Linux系统烧写

uboot烧写到SD卡 + zImage通过tftp下载 + rootfs通过nfs挂载

1.1 操作方式

将uboot烧录到SD卡上,并设置为SD卡启动,开发板上电即可启动uboot, 然后将zImage放入到tftp管理目录,通过tftp下载zImage和设备树文件到DDR中,并加载内核,最后将 文件系统设置在nfs服务器上,内核挂载nfs服务器的文件系统,启动Linux系统。

这样做的目的在于每次下载的zImage和dts设备树文件都是最新裁剪出来的,减少了烧录固化的时间,并且文件系统也是最新版本的,适合用于开发时使用。

1.2 双网卡设置

Ubuntu需要一个网卡与开发板连接,用来实现基于网络的tftp(文件传输)及nfs(目录共享)服务功能,我们需要设置双网卡来实现既能上网又能与开发板通信的效果。

  • NAT模式:window有IP地址,ubuntu作为windows上的一个软件是虚拟地址。
  • 桥接模式:windows和ubuntu各有一个独立的IP地址。
  • 有线网卡工作在桥接模式,因为它需要作为开发板的服务器,提供 TFTP 和 NFS 服务。
  • 无线网卡工作中NAT模式,与路由器连接用于上网。

2. 内核编译及裁剪

内核编译及裁剪通过make menuconfig图形化配置界面实现,本质是通过宏定义控制驱动的编译方式,通过配置宏开关,可保留必要功能、剔除无用组件,实现内核精简与定制化。

  • <*> 表示静态加载(obj-y),驱动编译进内核镜像 zImage,开机自动加载;
  • <M> 表示动态加载(obj-m),驱动编译为 .ko 模块文件,需手动加载;
  • 不选择表示不编译,对应功能被裁剪,不参与内核构建。

3. busybox制作文件系统

采用busybox构建根文件系统,其特点是易于构建简单的根文件系统,而且文件系统占用空间小。

1)./etc/inittab文件,该文件指定启动后一些代码的运行方式。

复制代码
#etc/inittab
#指定系统启动时要执行的脚本文件
::sysinit:/etc/init.d/rcS
#终端启动时要执行的脚本文件
console::askfirst:-/bin/sh
#重启时要执行的脚本文件
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
#关闭时要执行的脚本文件
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

2)./etc/init.d/rcS文件,该文件是一个shell脚本,Linux内核启动后需要启动的一些服务都可以通过该脚本进行配置。

复制代码
#!/bin/sh

#环境变量
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
#库路径
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
#导出,使后续子进程继承环境变量
export PATH LD_LIBRARY_PATH

#去执行/etc/fstab,将每个文件系统进行挂载
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts

#支持热插拔
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s

**3)./etc/fstab文件,**将内核的分区挂载在应用层,可在应用层查看内核的文件信息。

复制代码
#<file system>  <mount point>   <type>  <options>   <dump>  <pass>
proc            /proc           proc    defaults    0       0
tmpfs           /tmp            tmpfs   defaults    0       0   
sysfs           /sys            sysfs   defaults    0       0

4. 系统启动流程

bootROM阶段

  • 上电后,芯片从0x0地址加载BootROM代码:这是芯片出厂内置的固件,负责初始化基本硬件并检测启动模式。
  • BootROM在芯片内部RAM(128K)中执行:由于此时DDR尚未初始化,因此BootROM代码在片内RAM中运行,完成芯片校验和启动方式判断。
  • 根据启动模式定位U-Boot镜像:选择SD卡启动,BootROM会从SD卡读取u-boot.imx文件(uboot.bin + DCD数据头)。
  • 将U-Boot搬运至DDR并跳转执行:BootROM初始化DDR后,将u-boot.imx从存储介质复制到DDR中,并跳转至U-Boot入口地址,由U-Boot接管后续启动流程。

uboot阶段

  • 重新设置异常向量表,执行reset复位异常
  • 关闭MMU、dcache、看门狗,打开icache
  • 对硬件设备初始化
  • 进入人机交互,倒计时结束未交互则执行bootcmd加载内核

内核阶段

  • 解析设备树文件
  • 启动内核(内存管理、多任务管理、进程间通信、网络通信、文件系统管理)
  • 根据uboot中的bootargs挂载文件系统,如果没有文件系统会内核恐慌

文件系统阶段

  • 内核启动完成后自动拉起init 进程,接管系统上层管理;
  • init 读取/etc/inittab配置文件,确定系统开机执行规则;
  • 自动运行/etc/init.d/rcS初始化脚本,完成网络、设备、环境等基础配置;
  • 解析/etc/fstab挂载配置文件,自动完成 SD 卡、eMMC 等存储设备要挂载到哪个文件夹;
  • 最后启动串口终端,提供人机交互命令行界面,完成整个 Linux 系统启动。
相关推荐
PH = 72 小时前
OverlayFS联合文件系统使用示例
java·linux·服务器
AC赳赳老秦2 小时前
OpenClaw进阶技巧:批量修改文件内容、替换关键词,解放双手
java·linux·人工智能·python·算法·测试用例·openclaw
志栋智能2 小时前
超自动化巡检:解锁运维数据的深层价值
运维·服务器·数据库·自动化
Joseph Cooper3 小时前
STM32MP157 Linux驱动学习笔记(四):典型总线与设备模型(SPI/USB)
linux·stm32·学习
坚持就完事了3 小时前
Linux中的mv命令
linux·运维·服务器
SongYuLong的博客3 小时前
Claude Code安装配置(Linux)
linux·运维·服务器
linux修理工3 小时前
禁用 Windows 跳转列表和最近文档跟踪的注册表修改
运维
栈低来信4 小时前
kernel信号量源码分析
linux
AC赳赳老秦4 小时前
OpenClaw权限管理实操:团队共享Agent,设置操作权限,保障数据安全
服务器·开发语言·前端·javascript·excel·deepseek·openclaw