【嵌入式Linux驱动学习】Day1-Day2 全流程梳理:环境搭建→U-Boot→内核→根文件系统→驱动基础

本文整理了嵌入式Linux驱动学习前两日的完整内容,从最基础的虚拟机双网卡环境搭建,到TFTP/NFS服务配置、交叉编译工具链,再到U-Boot编译烧录、内核裁剪、BusyBox根文件系统构建,最后梳理驱动核心基础知识点。全程结合实操步骤与核心概念,既能跟着步骤复现环境,也能快速回顾核心理论,适合嵌入式入门学习者参考。

文章目录

  • 前言
  • 一、基础环境搭建:嵌入式开发的"基建"部分
    • [1.1 双网卡网络配置:兼顾上网与开发板通信](#1.1 双网卡网络配置:兼顾上网与开发板通信)
    • [1.2 apt-get软件源配置](#1.2 apt-get软件源配置)
    • [1.3 minicom串口终端配置](#1.3 minicom串口终端配置)
    • [1.4 TFTP服务器配置](#1.4 TFTP服务器配置)
    • [1.5 NFS服务器配置](#1.5 NFS服务器配置)
    • [1.6 交叉编译工具链配置](#1.6 交叉编译工具链配置)
  • [二、开发启动方案:SD卡U-Boot + TFTP内核 + NFS根文件系统](#二、开发启动方案:SD卡U-Boot + TFTP内核 + NFS根文件系统)
    • [2.1 整体流程](#2.1 整体流程)
    • [2.2 U-Boot环境变量配置](#2.2 U-Boot环境变量配置)
  • [三、U-Boot 深入理解与实操](#三、U-Boot 深入理解与实操)
    • [3.1 U-Boot核心定位](#3.1 U-Boot核心定位)
    • [3.2 核心功能](#3.2 核心功能)
    • [3.3 U-Boot启动流程(两级架构)](#3.3 U-Boot启动流程(两级架构))
    • [3.4 U-Boot编译实操](#3.4 U-Boot编译实操)
    • [3.5 常用命令分类](#3.5 常用命令分类)
    • [3.6 核心环境变量详解](#3.6 核心环境变量详解)
  • 四、Linux内核编译与裁剪
    • [4.1 内核概述](#4.1 内核概述)
    • [4.2 编译步骤](#4.2 编译步骤)
    • [4.3 编译产物与部署](#4.3 编译产物与部署)
  • [五、BusyBox 构建根文件系统](#五、BusyBox 构建根文件系统)
    • [5.1 根文件系统的作用](#5.1 根文件系统的作用)
    • [5.2 BusyBox方案特点](#5.2 BusyBox方案特点)
    • [5.3 构建步骤](#5.3 构建步骤)
    • [5.4 功能验证](#5.4 功能验证)
  • 六、Linux驱动基础核心知识点
    • [6.1 驱动本质与三大分类](#6.1 驱动本质与三大分类)
    • [6.2 内核模块:驱动的载体](#6.2 内核模块:驱动的载体)
    • [6.3 字符设备驱动核心框架](#6.3 字符设备驱动核心框架)
    • [6.4 bus-device-driver驱动模型](#6.4 bus-device-driver驱动模型)
    • [6.5 设备树(Device Tree)](#6.5 设备树(Device Tree))
    • [6.6 中断处理机制](#6.6 中断处理机制)
    • [6.7 驱动核心设计思想](#6.7 驱动核心设计思想)
  • 总结

一、基础环境搭建:嵌入式开发的"基建"部分

环境搭建是嵌入式开发的第一步,核心目标是让Ubuntu虚拟机同时具备「访问公网下载软件」和「与开发板通信提供服务」的能力,同时配齐开发所需的各类工具。

1.1 双网卡网络配置:兼顾上网与开发板通信

为什么需要双网卡

嵌入式开发中,Ubuntu需要一个网卡直连开发板,提供TFTP文件传输、NFS目录共享服务;同时还需要另一个网卡访问公网,用于下载软件、更新源码。单网卡无法同时满足两个场景,因此采用双网卡方案。

两种虚拟机网络模式对比
模式 原理 优势 局限性 适用场景
桥接模式 Ubuntu作为独立主机存在,拥有真实局域网IP 可作为服务器被其他设备访问,网络独立 拨号网络下可能无法获取公网IP 与开发板通信、提供服务
NAT模式 Windows为主机虚拟网卡,Ubuntu共享Windows的网络 配置简单,Windows能上网Ubuntu就能上网 虚拟IP无法作为服务器被外部访问 Ubuntu访问公网
双网卡组网方案
  • 网卡1(NAT模式) :负责Ubuntu访问公网,网段默认192.168.78.0
  • 网卡2(桥接模式) :桥接到电脑有线网卡,负责与开发板直连通信,静态IP设为192.168.1.100
详细配置步骤
  1. 虚拟机添加双网卡 VMware中添加两个网络适配器,分别设置为NAT模式、桥接模式(桥接到物理有线网卡)。

  2. Ubuntu内配置IP地址 先通过ifconfig查看两个网卡名称(如ens33为NAT网卡,ens36为桥接网卡),编辑网络配置文件:

    复制代码
    sudo vim /etc/network/interfaces

    配置NAT网卡自动获取IP,桥接网卡设置静态IP:

    复制代码
    auto ens33
    iface ens33 inet dhcp
    auto ens36
    iface ens36 inet static
    address 192.168.1.100
    netmask 255.255.255.0
  3. 修复默认路由(关键坑点) 默认路由必须指向NAT网卡才能正常上网,桥接网卡仅负责192.168.1.0网段通信:

    复制代码
    sudo route delete default
    sudo route add default gw 192.168.78.2 ens33
  4. 路由配置开机自启 创建systemd服务实现开机自动配置路由,避免每次重启重复操作:

    复制代码
    sudo vim /etc/systemd/system/custom-route.service

    写入服务配置:

    复制代码
    [Unit]
    Description=Custom Route Configuration
    After=network.target
    [Service]
    Type=oneshot
    ExecStart=/sbin/route delete default
    ExecStart=/sbin/route add default gw 192.168.78.2 ens33
    RemainAfterExit=yes
    [Install]
    WantedBy=multi-user.target

    启用服务:

    复制代码
    sudo systemctl daemon-reload
    sudo systemctl enable custom-route.service
    sudo systemctl start custom-route.service
  5. 双网卡转发(可选:开发板上网) 如果需要开发板通过Ubuntu访问公网,开启IP转发并配置MASQUERADE:

    复制代码
    sudo echo "1" > /proc/sys/net/ipv4/ip_forward
    sudo iptables -t nat -A POSTROUTING -o ens33 -j MASQUERADE

    同样可以写入上述开机自启服务,实现重启生效。

验证测试
复制代码
# 测试公网连通性
ping www.baidu.com
# 测试开发板连通性
ping 192.168.1.50

1.2 apt-get软件源配置

apt-get是Ubuntu的软件包管理工具,能自动解决软件依赖,配置国内源可大幅提升下载速度。

  1. 将软件源替换为阿里云镜像源

  2. 更新软件源:

    复制代码
    sudo apt-get autoclean
    sudo apt-get update
    sudo apt-get install -f
  3. 常用命令:

    • 安装软件:sudo apt-get install 软件名
    • 卸载软件:sudo apt-get remove 软件名

1.3 minicom串口终端配置

嵌入式开发中,通过串口与开发板交互、查看启动日志、输入命令,minicom是Ubuntu下常用的串口终端工具。

  1. 安装:

    复制代码
    sudo apt-get install minicom
  2. 首次配置:

    复制代码
    sudo minicom -s

    选择Serial port setup,设置串口设备、波特率115200、8N1。

  3. 常用操作:

    • 启动:sudo minicom
    • 退出:Ctrl + A 再按 Q,选择Yes退出

1.4 TFTP服务器配置

TFTP是嵌入式开发中最常用的网络文件传输工具,开发板可以直接通过网络从Ubuntu下载内核、设备树等文件。

  1. 安装服务端与客户端:

    复制代码
    sudo apt-get install tftpd-hpa tftp
  2. 编辑配置文件,指定共享目录:

    复制代码
    sudo vim /etc/default/tftpd-hpa

    设置TFTP_DIRECTORY为共享目录路径,如/home/linux/tftpboot。

  3. 创建共享目录并设置权限:

    复制代码
    mkdir /home/linux/tftpboot
    chmod 0777 /home/linux/tftpboot
  4. 重启服务:

    复制代码
    sudo service tftpd-hpa restart
  5. 功能测试:分别测试上传、下载功能,确认服务正常。

1.5 NFS服务器配置

NFS是网络文件共享协议,将Ubuntu的目录共享给开发板挂载,修改代码后编译完成直接放到共享目录,开发板就能立即运行,无需反复烧录,大幅提升开发效率。

  1. 安装NFS服务:

    复制代码
    sudo apt-get install nfs-kernel-server
  2. 编辑配置文件/etc/exports,添加共享目录配置:

    复制代码
    /home/linux/nfs/rootfs * rw sync no_subtree_check no_root_squash
    • *:允许所有客户端访问
    • rw:读写权限
    • no_root_squash:客户端root用户拥有服务端root权限
  3. 创建共享目录并设置权限:

    复制代码
    sudo mkdir -p /home/linux/nfs/rootfs
    sudo chmod 0777 /home/linux/nfs/rootfs
  4. 重启服务:

    复制代码
    sudo service nfs-kernel-server restart
  5. 挂载测试:

    复制代码
    # 查看可挂载目录
    sudo showmount -e
    # 本地挂载测试
    sudo mount -t nfs -o nolock,rw 192.168.1.100:/home/linux/nfs/rootfs /mnt

1.6 交叉编译工具链配置

什么是交叉编译

在x86架构的Ubuntu上,编译出能在ARM架构开发板上运行的程序,这个过程叫交叉编译,对应的工具就是交叉编译工具链。

配置步骤
  1. 解压工具链到指定目录,如/home/linux/tools/opt/

  2. 添加环境变量到~/.bashrc:

    复制代码
    export PATH=$PATH:/home/linux/tools/opt/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin
  3. 重启终端或重新加载配置,验证安装:

    复制代码
    arm-linux-gnueabihf-gcc -v

    输出版本号即为配置成功,其中hf表示支持硬件浮点指令。

二、开发启动方案:SD卡U-Boot + TFTP内核 + NFS根文件系统

这是嵌入式开发阶段的标准启动方案,优势在于修改内核、驱动、应用后,无需烧录到开发板存储,直接在Ubuntu更新文件,开发板重启就能加载最新版本,调试效率极高。

2.1 整体流程

  1. 开发板从SD卡启动U-Boot,完成硬件初始化
  2. U-Boot通过TFTP从Ubuntu下载内核镜像zImage和设备树.dtb到内存
  3. U-Boot向内核传递启动参数,跳转执行内核
  4. 内核启动后,通过NFS挂载Ubuntu上的根文件系统
  5. 进入Linux命令行,完成系统启动

2.2 U-Boot环境变量配置

在U-Boot串口终端依次配置以下参数,saveenv保存到SD卡持久化:

复制代码
# 网络基础参数
setenv ipaddr 192.168.1.50
setenv ethaddr 00:04:9f:04:d2:35
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.100
saveenv
自动启动命令:倒计时结束自动下载内核+设备树并启动
setenv bootcmd 'tftp 80800000 zImage;tftp 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000'
saveenv
内核启动参数:指定控制台、根文件系统为NFS、IP配置
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.255.0::eth0:off'
saveenv

配置完成后输入boot或重启开发板,即可自动完成从TFTP下载、NFS挂载的完整启动流程。

三、U-Boot 深入理解与实操

3.1 U-Boot核心定位

U-Boot(Universal Boot Loader)是嵌入式领域最主流的开源引导加载程序,是开发板上电后第一个运行的程序,地位等同于PC的「BIOS+启动引导器」。

  • 本质:裸机程序,直接运行在硬件之上,不依赖操作系统
  • 核心使命:硬件初始化、加载并启动Linux内核、提供底层调试工具

3.2 核心功能

  1. 硬件底层初始化:初始化CPU时钟、DDR内存、串口、以太网、SD/EMMC控制器等核心外设
  2. 引导Linux内核:读取内核镜像与设备树到内存,传递启动参数,跳转执行内核
  3. 环境变量管理:支持配置参数持久化存储,掉电不丢失
  4. 调试工具集:提供内存读写、网络调试、存储烧录等丰富的串口命令
  5. 多启动介质支持:支持SD卡、EMMC、网络、USB等多种启动方式

3.3 U-Boot启动流程(两级架构)

  1. BL1(ROM Boot):芯片出厂固化在ROM中,上电自动执行,加载第二阶段程序到片内RAM
  2. SPL(BL2):U-Boot精简版,负责初始化DDR内存,再加载完整U-Boot到DDR运行
  3. U-Boot正文:完整功能版本,完成外设初始化、倒计时等待、命令行交互、引导内核

3.4 U-Boot编译实操

  1. 安装依赖库:

    复制代码
    sudo apt-get install libncurses5-dev
  2. 解压源码并进入目录,执行编译:

    复制代码
    # 清理旧编译
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
    # 加载板级配置
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_alientek_emmc_defconfig
    # 编译
    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16
  3. 编译产物:顶层目录生成u-boot.imx镜像文件,可烧录到SD卡或EMMC。

3.5 常用命令分类

类别 常用命令 功能
环境变量 printenv/setenv/saveenv 查看、修改、保存环境变量
内存操作 md/mw/cp/cmp 内存读取、写入、拷贝、比较
网络操作 ping/tftp/nfs 网络连通测试、TFTP下载、NFS加载
MMC操作 mmc dev/mmc read/mmc write/mmc part 切换设备、读写、查看分区
启动命令 bootz/bootm/boot/go 启动zImage/uImage、执行bootcmd、跳转地址

3.6 核心环境变量详解

  • bootcmd:自动启动命令,U-Boot倒计时结束后自动执行,定义了内核加载与启动的完整流程
  • bootargs:传递给Linux内核的启动参数,包含控制台配置、根文件系统类型与路径、网络配置等,是内核启动的关键参数

四、Linux内核编译与裁剪

4.1 内核概述

Linux内核是操作系统的核心,负责进程调度、内存管理、硬件驱动、文件系统、网络协议等核心功能。嵌入式开发中需要根据硬件平台裁剪配置内核,生成适配的镜像文件。

4.2 编译步骤

  1. 安装依赖工具:

    复制代码
    sudo apt-get install lzop
  2. 解压内核源码并进入目录:

    复制代码
    # 清理旧编译
    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

4.3 编译产物与部署

编译完成后生成两个关键文件:

  • 内核镜像:arch/arm/boot/zImage
  • 设备树文件:arch/arm/boot/dts/imx6ull-alientek-emmc.dtb

将两个文件拷贝到TFTP共享目录,开发板启动时就会自动下载最新版本:

复制代码
cp arch/arm/boot/zImage ~/tftpboot/
cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb ~/tftpboot/

五、BusyBox 构建根文件系统

5.1 根文件系统的作用

根文件系统是Linux内核启动后挂载的第一个文件系统,包含系统命令、库文件、配置文件、设备节点等,是用户空间运行的基础。嵌入式常用BusyBox构建轻量根文件系统,体积小、易定制。

5.2 BusyBox方案特点

BusyBox被称为"嵌入式Linux的瑞士军刀",将大量Linux命令和工具整合到一个二进制文件中,支持静态编译,占用空间极小,非常适合嵌入式场景。

5.3 构建步骤

  1. 解压BusyBox源码,修改Makefile指定交叉编译器:

    复制代码
    CROSS_COMPILE ?= arm-linux-gnueabihf-
    ARCH ?= arm
  2. 配置BusyBox:

    复制代码
    make defconfig
    make menuconfig

    关键配置:开启Build static binary静态编译,避免依赖动态库。

  3. 编译并安装到指定目录:

    复制代码
    make
    make install CONFIG_PREFIX=/home/linux/nfs/rootfs
  4. 拷贝依赖库文件 将交叉工具链中的libc库、动态库拷贝到根文件系统的lib和usr/lib目录,确保程序能正常运行。

  5. 创建必要目录

    复制代码
    mkdir dev proc mnt sys tmp root lib/modules
  6. 完善系统配置文件

    • /etc/init.d/rcS:系统启动脚本,配置环境变量、挂载文件系统、启动mdev
    • /etc/fstab:文件系统挂载表,定义proc、tmpfs、sysfs等特殊文件系统
    • /etc/inittab:init进程配置,定义系统启动、重启、关机对应的动作

5.4 功能验证

将构建好的根文件系统放到NFS共享目录,开发板通过NFS挂载启动,能正常进入命令行、运行程序,即为构建成功。

六、Linux驱动基础核心知识点

6.1 驱动本质与三大分类

驱动是运行在内核态的代码,是硬件与用户程序之间的桥梁,向下管理硬件,向上提供标准操作接口。

  • 字符设备:按字节流顺序访问,如串口、LED、按键,是最基础的驱动类型
  • 块设备:以数据块为单位随机访问,如SD卡、硬盘,用于存储场景
  • 网络设备:面向数据包收发,不对应普通文件节点,如网卡

6.2 内核模块:驱动的载体

内核模块是可以动态加载卸载的代码段,无需重新编译内核,是Linux驱动的标准开发形式。

  • 四大要素:module_init入口、module_exit出口、MODULE_LICENSE许可证、辅助描述信息
  • 操作命令:insmod加载、rmmod卸载、lsmod查看已加载模块
  • 进阶特性:模块参数动态传参、EXPORT_SYMBOL符号导出跨模块调用

6.3 字符设备驱动核心框架

  1. 两个核心结构体:
    • struct cdev:内核抽象字符设备的结构体
    • struct file_operations:操作函数表,封装open、read、write、ioctl等接口
  2. 设备号:主设备号(标识驱动类型)+ 次设备号(标识不同设备实例),支持静态申请和动态分配
  3. 核心流程:分配设备号 → 初始化cdev并绑定操作函数 → 注册到内核
  4. 空间交互:通过copy_from_user和copy_to_user完成内核与用户空间的数据拷贝

6.4 bus-device-driver驱动模型

核心思想是硬件描述与驱动逻辑分离,通过总线统一管理匹配,实现一个驱动适配多个同类硬件。

  • 总线(bus):管理者,负责设备与驱动的匹配绑定
  • 设备(device):描述硬件资源信息
  • 驱动(driver):实现通用驱动逻辑
  • Platform平台总线:专为SoC片上外设设计的虚拟总线,是嵌入式最常用的驱动框架

6.5 设备树(Device Tree)

将硬件配置信息从驱动代码中剥离,用独立的.dts树形文件描述硬件,驱动只实现通用逻辑,通过解析设备树获取硬件参数,实现驱动通用化、跨板适配。

  • 核心属性:compatible(匹配标识)、reg(寄存器地址)、interrupts(中断配置)、status(设备状态)
  • 驱动通过of_系列函数解析设备树节点属性

6.6 中断处理机制

采用顶半部+底半部分层设计,平衡中断响应速度与处理耗时:

  • 顶半部:中断触发后立即执行,只做紧急操作,运行在中断上下文,不可睡眠
  • 底半部:延后执行耗时逻辑,主流实现有tasklet(软中断,不可睡眠)和工作队列(内核线程,可睡眠)

6.7 驱动核心设计思想

  1. 分层思想:通用逻辑向上抽取复用,硬件差异向下适配
  2. 分离思想:硬件信息与驱动代码分离,一套驱动适配多硬件
  3. 面向对象思想:用结构体封装属性与方法,模拟面向对象编程

以上就是嵌入式驱动前两日的全部学习内容,从底层环境搭建到系统启动全流程,再到驱动核心理论,形成了完整的入门知识体系。后续会继续深入字符设备驱动、platform总线、设备树驱动等内容的学习与实操。

相关推荐
我命由我123451 小时前
Photoshop - Photoshop 使用简单的选择工具
学习·职场和发展·产品运营·求职招聘·职场发展·学习方法·photoshop
UIU1141 小时前
头文件可以防什么错?运用头文件做声明
c++·学习·c#
我命由我123451 小时前
Photoshop - Photoshop 使用工具
学习·职场和发展·产品运营·求职招聘·职场发展·产品经理·学习方法
YonyouHRSaaS1 小时前
从安全、信创、运维三方面看,人力资源管理系统哪种部署方式更适合企业HR?
运维·安全·hr系统·人力资源管理系统·hr saas·人事管理系统
外收内放1 小时前
Python基础语法练习题(53-54)
python·学习
by209992 小时前
list:迭代器与资源管理实现的综合叙述(下)
数据结构·c++·笔记·list
欣欣之王来了2 小时前
Python入门:Jupyter Notebook安装与使用指南
学习·架构·面向对象·项目·python教程
倔强的石头1062 小时前
【Linux指南】动静态库系列(十二):库工程发布与错误排查:从能跑到可维护
linux·运维·服务器
JWASX2 小时前
Java 转 go 学习 - kitex(2)
学习·golang