当前位置: 首页 > news >正文

驱动(二)Linux 系统移植、驱动开发框架

一、Linux 驱动基础

1. 驱动分类及核心特点

驱动类型数据处理方式典型应用场景关键特性
字符设备驱动按单个字符顺序读写串口、键盘、鼠标、LED支持open/read/write等基本文件操作,无缓存或简单缓存
块设备驱动按固定大小 “块”(通常 512 字节)读写硬盘、eMMC、SD 卡、U 盘支持随机访问,需缓存管理,通过文件系统间接访问
网络设备驱动按网络帧(数据包)传输以太网、WiFi、CAN 总线不依赖文件系统,需对接 TCP/IP、CAN 等协议栈,通过socket接口访问

2. 驱动编译的两种方式(静态 vs 动态)

驱动编译的核心差异在于是否将驱动集成到内核镜像,或以独立模块形式加载,具体流程和区别如下:

(1)静态编译(内置到内核)

核心逻辑:将驱动代码直接编译进 Linux 内核镜像(如zImage),内核启动时自动加载驱动。操作步骤

  1. 准备驱动代码:在 Linux 内核源码的对应目录(如drivers/char/)编写驱动文件(例:hello.c)。
  2. 修改 Kconfig:在驱动目录的Kconfig文件中新增配置项,用于menuconfig图形化选择,示例:

    kconfig

    config HELLO_DRIVERtristate "Hello World Character Driver"helpThis is a test character driver for Linux.
    
  3. 图形化配置:执行make ARCH=arm CROSS_COMPILE=xxx- menuconfig,在对应菜单中选中HELLO_DRIVER(勾选为*,表示静态编译)。
  4. 更新配置文件:选中后,内核会自动在.config文件中添加CONFIG_HELLO_DRIVER=yy表示静态内置)。
  5. 修改 Makefile:在驱动目录的Makefile中添加编译规则,将驱动文件关联到配置项:

    makefile

    obj-$(CONFIG_HELLO_DRIVER) += hello.o
    
  6. 编译内核:执行make ARCH=arm CROSS_COMPILE=xxx- all -jN,驱动会随内核一起生成到zImage中。
(2)动态编译(模块编译)

核心逻辑:驱动代码编译为独立的内核模块文件(.ko),不内置到内核,可在系统运行时动态加载 / 卸载。操作步骤

  1. 准备驱动代码:同静态编译,编写hello.c(需包含模块加载 / 卸载函数,如module_init()/module_exit())。
  2. 修改 Kconfig:同静态编译,配置项类型为tristate(支持静态 / 动态 / 不编译)。
  3. 图形化配置:执行make menuconfig,将HELLO_DRIVER设为M(表示动态模块),.config中会生成CONFIG_HELLO_DRIVER=m
  4. 修改 Makefile:同静态编译,编译规则不变(obj-$(CONFIG_XXX)自动适配m模式)。
  5. 编译模块:执行make ARCH=arm CROSS_COMPILE=xxx- modules,内核仅编译标记为M的驱动,生成hello.ko文件。
  6. 模块操作
    • 加载:insmod hello.ko(临时加载,重启失效)
    • 卸载:rmmod hello(需确保驱动未被使用)
    • 查看:lsmod(查看已加载的模块)

二、Linux 驱动工程搭建(目录划分规范)

为保证工程可维护性,建议按 “功能模块 + 通用文件” 划分目录,典型结构如下:

plaintext

hello_driver/          # 驱动工程根目录
├── doc/               # 文档目录:存放驱动说明、接口文档、测试报告
├── driver/            # 驱动核心代码目录
│   ├── hello/         # 具体驱动模块(如hello驱动)
│   │   ├── hello.c    # 驱动核心逻辑(初始化、文件操作、中断处理等)
│   │   ├── hello.h    # 驱动头文件(宏定义、结构体、函数声明)
│   │   ├── Kconfig    # 该模块的配置文件
│   │   └── Makefile   # 该模块的编译规则
│   └── common/        # 通用驱动组件(如GPIO封装、中断封装)
├── include/           # 全局头文件目录:存放工程通用头文件(如平台定义、工具函数声明)
├── test/              # 测试程序目录:存放驱动测试代码(如`test_hello.c`,用于验证驱动功能)
├── scripts/           # 脚本目录:存放编译脚本(如`build.sh`)、烧录脚本(如`load_driver.sh`)
├── Makefile           # 工程顶层Makefile:调用内核Makefile,指定交叉编译工具链、架构等
└── README.md          # 工程说明:编译步骤、测试方法、注意事项

三、Linux 系统移植与驱动核心问题(重点)

1. Linux 系统移植需要哪些文件?各文件作用?

Linux 系统移植的核心是构建 “Bootloader + 内核 + 根文件系统” 三部分,所需关键文件及作用如下:

组件关键文件 / 目录作用说明
Bootloader(以 UBoot 为例)U-Boot 源码目录、u-boot.bin1. 硬件初始化(如 CPU、内存、GPIO、时钟);2. 加载内核到内存;3. 传递启动参数(bootargs)给内核;4. 提供命令行交互(如烧录、分区管理)
Linux 内核zImage/uImage.config、设备树(*.dtb1. zImage:压缩后的内核镜像,是系统运行的核心;2. .config:内核配置文件,决定内核功能和驱动;3. *.dtb:设备树文件,描述硬件信息(如外设地址、中断号),替代传统的 “板级代码”
根文件系统rootfs目录(包含bin/sbin/etc等)1. 提供系统运行所需的文件和目录结构;2. 包含初始化脚本(如init)、系统命令(如ls/cd)、库文件(lib);3. 存储用户数据和应用程序
交叉编译工具链arm-linux-gnueabihf-gcc为 ARM 架构编译 UBoot、内核、根文件系统和驱动的工具集

2. Linux 系统的启动流程(从上电到应用运行)

完整启动流程分为 4 个阶段,按顺序如下:

  1. 硬件上电初始化(固化代码)上电后,CPU 先执行芯片内部固化的 “启动代码”(如 i.MX 的 ROM Code),完成最基础的硬件检查(如内存是否存在),然后从指定启动介质(如 eMMC、SD 卡)加载 Bootloader。

  2. Bootloader(UBoot)阶段

    • 初始化硬件:配置 CPU 时钟、内存控制器、GPIO、串口等(让硬件处于可工作状态)。
    • 加载内核和设备树:将存储介质中的zImage(内核)和*.dtb(设备树)加载到内存指定地址(如内核加载到0x80800000)。
    • 传递启动参数:通过bootargs将根文件系统路径、串口配置等参数传递给内核,然后跳转到内核入口地址,启动内核。
  3. Linux 内核阶段

    • 内核初始化:解压内核、初始化进程管理、内存管理、文件系统(如ext4)、驱动框架。
    • 设备树解析:解析*.dtb文件,识别硬件设备(如 UART、GPIO),并加载对应的驱动。
    • 启动 init 进程:内核初始化完成后,启动第一个用户空间进程init(PID=1),init进程负责后续的系统初始化。
  4. 根文件系统与用户空间阶段

    • init进程执行初始化脚本(如/etc/init.d/rcS):挂载其他分区(如/tmp)、启动网络服务、加载驱动模块、启动应用程序。
    • 进入用户交互:若配置了登录功能,会启动终端(如串口终端),等待用户登录,最终进入 Shell 命令行或自动启动应用。

3. UBoot 中bootcmdbootargs的含义?

(1)bootcmd:UBoot 的 “自动启动命令”
  • 作用:UBoot 启动后,若未手动打断(如按键盘按键),会自动执行bootcmd中定义的命令,用于加载内核和设备树。
  • 典型示例(针对 eMMC 启动):

    bash

    setenv bootcmd 'mmc dev 0; mmc read 0x80800000 0x1000 0x8000; mmc read 0x83000000 0x9000 0x1000; bootz 0x80800000 - 0x83000000'
    
    命令拆解:
    • mmc dev 0:选择第 0 个 eMMC 设备;
    • mmc read 0x80800000 0x1000 0x8000:将 eMMC 中地址0x1000开始、长度0x8000zImage读入内存0x80800000
    • mmc read 0x83000000 0x9000 0x1000:将 eMMC 中地址0x9000开始、长度0x1000的设备树(*.dtb)读入内存0x83000000
    • bootz 0x80800000 - 0x83000000:启动内核(bootz是压缩内核启动命令,-表示无 ramdisk,最后是设备树地址)。
(2)bootargs:UBoot 传递给 Linux 内核的 “启动参数”
  • 作用:内核启动时会解析bootargs,获取根文件系统路径、串口配置、硬件参数等,决定系统的运行方式。
  • 典型示例

    bash

    setenv bootargs 'console=ttymxc0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rw init=/linuxrc'
    
    参数拆解:
    • console=ttymxc0,115200:指定系统控制台为ttymxc0(第 1 个串口),波特率 115200;
    • root=/dev/mmcblk0p2:指定根文件系统位于mmcblk0p2(第 0 个 eMMC 的第 2 个分区);
    • rootfstype=ext4:根文件系统类型为ext4
    • rw:根文件系统以 “可读可写” 模式挂载;
    • init=/linuxrc:指定用户空间的第一个init进程路径为/linuxrc(通常是busybox的链接)。

4. UBoot 如何编译?UBoot 的功能?

(1)UBoot 编译步骤(以 ARM 架构为例)
  1. 准备交叉编译工具链:确保arm-linux-gnueabihf-gcc已安装并添加到PATH(可通过echo $PATH验证)。
  2. 获取 UBoot 源码:从官方(https://www.denx.de/wiki/U-Boot)或开发板厂商(如正点原子)获取适配的 UBoot 源码。
  3. 加载默认配置:执行厂商提供的板级配置文件(位于configs/目录),示例(正点原子 IMX6ULL 开发板):

    bash

    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_alientek_emmc_defconfig
    
  4. 图形化配置(可选):若需修改 UBoot 功能(如添加命令、支持外设),执行:

    bash

    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
    
  5. 编译 UBoot:指定并行任务数(-jN,N 为 CPU 核心数的 1-2 倍),加速编译:

    bash

    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
    
  6. 获取编译产物:编译完成后,在源码根目录生成u-boot.bin(UBoot 镜像,需烧录到启动介质)、u-boot.elf(调试用)等文件。
(2)UBoot 的核心功能

UBoot 的定位是 “硬件初始化与内核加载工具”,核心功能分为 5 类:

  1. 硬件初始化:上电后初始化 CPU、内存(DDR)、时钟、GPIO、串口、存储设备(eMMC/SD)等,为内核运行准备硬件环境。
  2. 内核加载与启动:从存储介质(eMMC、SD、U 盘、网络)加载内核(zImage)和设备树(*.dtb)到内存,传递bootargs后启动内核。
  3. 命令行交互:提供丰富的命令集,用于调试和管理,如:
    • 存储操作:mmc(eMMC/SD)、usb(U 盘)、nand(NAND Flash);
    • 内存操作:md(查看内存)、mw(修改内存)、cp(内存拷贝);
    • 网络操作:ping(网络测试)、tftp(从 TFTP 服务器下载文件);
    • 环境变量操作:setenv(设置环境变量)、saveenv(保存环境变量到存储介质)。
  4. 系统烧录:支持将 UBoot、内核、根文件系统烧录到 eMMC、NAND Flash 等存储设备(如mmc write命令)。
  5. 故障排查:提供串口打印、内存查看、硬件状态检测等功能,帮助定位硬件或系统启动问题。

5. 内核如何编译?如何裁剪?

(1)Linux 内核编译步骤(以 ARM 架构为例)
  1. 准备环境:安装交叉编译工具链(如arm-linux-gnueabihf-gcc)、内核源码(从https://www.kernel.org/或厂商获取)。
  2. 清理编译环境:若之前编译过,执行distclean彻底清理残留文件:

    bash

    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
    
  3. 加载默认配置:执行板级默认配置文件(位于arch/arm/configs/目录),示例:

    bash

    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig
    
  4. 图形化裁剪(可选):执行menuconfig调整内核配置(裁剪功能 / 驱动):

    bash

    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
    
  5. 编译内核:执行all编译内核镜像、设备树和模块(-jN加速):

    bash

    make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
    
  6. 获取产物
    • 内核镜像:arch/arm/boot/zImage(压缩内核,用于启动);
    • 设备树:arch/arm/boot/dts/xxx.dtb(xxx 为开发板对应的设备树文件名);
    • 驱动模块:若有动态编译的驱动,生成*.ko文件(位于对应驱动目录)。
(2)内核裁剪方法(通过menuconfig

内核裁剪的核心是 “保留必需功能,删除无用功能”,以减小内核体积、降低资源占用,步骤如下:

  1. 进入裁剪界面:执行make ARCH=arm CROSS_COMPILE=xxx- menuconfig,进入图形化配置界面。
  2. 裁剪原则
    • 移除无用硬件驱动:如无老旧硬件(软驱、并口)、特定网卡或声卡驱动,检查Device Drivers子菜单,禁用无关选项。
    • 精简文件系统支持:保留必需的文件系统(如ext4squashfs),移除BtrfsReiserFS等。
    • 禁用调试和性能分析:关闭Kernel hackingDebugging相关选项,禁用ProfilingTracers
    • 优化网络功能:移除不用的网络协议(如Amateur RadioIrDA),精简防火墙(Netfilter)规则,仅保留必需模块。
    • 模块化非核心功能:将不常用功能编译为模块(M),而非内置(Y),如某些文件系统或驱动。
  3. 使用搜索功能:在menuconfig界面中,可以通过按 “/” 键来进行全局搜索,快速定位到需要裁剪或配置的选项。
  4. 保存配置:完成裁剪后,按 “Esc” 键退出配置界面,选择保存配置,配置结果将保存到.config文件中。
http://www.dtcms.com/a/399316.html

相关文章:

  • LDPC码的BP译码算法(一)
  • mit6s081 lab6: copy of write fork
  • 【多尺度/局部-全局融合与优化 】涉及的工业异常检测论文摘要整理
  • CRI与容器运行时:从Kubelet到Container的最后一公里
  • cnu摄影网站chrome官网
  • 一篇了解 Git 使用方法
  • wordVSTO插件实现自动填充序号
  • 海口网站建设哪家专业灌南住房建设局网站
  • 若依框架 (Spring Boot 3) 集成 knife4j 实现 OpenAPI 文档增强
  • MySQL分库分表详解:从原理、策略到ShardingSphere中间件选型,避坑指南一篇就够了
  • Excel知识体系
  • 零基础网站建设入门到精通视频教《妻子》在线观看免费韩剧
  • AI 大模型驱动的开源知识库搭建系统 PandaWiki的网页挂件机器人教程
  • 甘露园网站建设wordpress文章页面区别
  • 网上做视频赚钱的网站有哪些企查查企业信息
  • 网站生成静态页面工具wordpress menu icons
  • [css] flex 布局设置文字不自动换行
  • Suno V5首发 – V5模型重磅来袭 —— AI 音乐创作进入全新纪元
  • 构建AI智能体:四十二、使用 Qwen-Agent Assistant 调用高德 API 实现天气查询
  • 网站用的服务器网站怎么维护更新
  • Metal - 2. 3D 模型深度解析
  • 做非经营网站需要营业执照莱芜在线沙总
  • 网站建设模板研究玉林市网站开发公司电话
  • 无线数传模块优化挖掘机工厂机械设备的远程监控通讯
  • 【最终章】-串口收发指令处理器-Verilog语法学习EP12
  • 嵌入模型与向量数据库
  • 白山商城网站建设昆明网站建设猫咪
  • git的在工作中使用的一些注意事项
  • 河北网站备案多久wordpress站点管理
  • 力扣300.最长递增子序列(经典dp)力扣375.猜数字II力扣.329矩阵最长的递增子序列力扣.33搜索旋转排序数组