1. 课程导论与工程背景

1.1 SPI总线在嵌入式系统中的核心地位

串行外设接口(Serial Peripheral Interface,SPI)是嵌入式系统中最广泛使用的高速同步串行通信协议之一。与I²C和UART相比,SPI以全双工、主从架构和极低协议开销著称,特别适合传感器、ADC/DAC、显示驱动、存储器等需要高数据吞吐量的外设连接。

SPI总线关键特性: 全双工通信、主从架构、无地址帧(通过片选线CS选择从设备)、时钟频率可达数十MHz、硬件流控简单。

下表对比了嵌入式系统中三大主流串行总线协议的核心差异:

特性 SPI I²C UART
通信模式 全双工 半双工 全双工
信号线数量 4(SCLK、MOSI、MISO、CS) 2(SCL、SDA) 2(TX、RX)
从设备选择 独立片选线(硬件) 7/10位地址(软件) 点对点
最大时钟频率 典型10~80 MHz 典型100 kHz~3.4 MHz 典型115.2 kbps~数Mbps
协议开销 极低 中等(ACK/NACK、地址帧) 低(起始/停止位)
多从设备支持 是(每设备独立CS) 是(总线仲裁) 否(需额外硬件)
典型应用 传感器、ADC、LCD、Flash EEPROM、温湿度传感器、RTC GPS、蓝牙模块、调试串口
工程经验: 在需要连续高速数据流(如加速度计以10 kHz采样率输出三轴数据)的场景中,SPI是唯一能同时满足带宽和实时性要求的串行总线。I²C的时钟拉伸和ACK机制会引入不可预测的延迟。

下图展示了SPI总线在典型嵌入式系统中的连接拓扑:

SPI总线在嵌入式系统中的典型拓扑 主控制器 (SoC / MCU) SPI Master 传感器 A 加速度计 SPI Slave 传感器 B 陀螺仪 SPI Slave 传感器 C 磁力计 SPI Slave SCLK MOSI MISO CS0 CS1 CS2 SPI总线特点 • 全双工:MOSI与MISO同时传输 • 主控时钟:SCLK由Master产生 • 片选独立:每个Slave独占CS线 • 无地址帧:硬件选择从设备 • 速率高:典型10~80 MHz

1.2 传感器适配工程的核心挑战

在嵌入式Linux系统中,将物理传感器通过SPI总线接入内核并实现可靠的数据采集,远不止是“连接几根线、写一个驱动”那么简单。工程实践中,开发者面临以下系统性挑战:

  1. 硬件时序差异: 不同传感器厂商对SPI时钟极性(CPOL)、时钟相位(CPHA)、数据位序(MSB/LSB first)的要求各不相同,配置错误将导致数据完全错乱。
  2. 寄存器映射多样性: 每个传感器都有独特的寄存器地址空间、读写协议、多字节传输顺序(大端/小端)以及状态机控制流程。
  3. 中断与数据就绪信号: 传感器通常通过GPIO中断通知数据就绪,驱动需要协调SPI传输与中断处理,避免数据丢失或重复读取。
  4. 电源管理与功耗优化: 电池供电设备要求驱动在数据采集间隙将传感器置于低功耗模式,并通过SPI命令精确控制唤醒/休眠状态。
  5. 并发访问与数据一致性: 多个用户空间进程(如传感器融合算法、日志记录)可能同时访问同一传感器,驱动必须保证SPI传输的原子性和数据缓冲区的完整性。
  6. 内核态与用户态数据传递: 如何高效地将SPI采集的原始数据从内核驱动传递到用户空间应用程序,涉及字符设备、输入子系统、IIO子系统等多种架构选择。
常见陷阱: 许多初学者在编写SPI传感器驱动时,只关注“能读到数据”,而忽略了时序容差和错误恢复。当传感器在高温或电磁干扰环境下工作时,SPI传输可能发生位错误,驱动必须具备重试机制和错误校验能力,否则系统会出现随机数据跳变。

下表总结了传感器适配过程中不同层面的典型问题与应对策略:

层面 典型问题 工程应对策略
硬件接口 SPI模式不匹配、电平不兼容 查阅数据手册确认CPOL/CPHA,使用电平转换器
寄存器协议 多字节顺序错误、保留位未处理 严格按手册实现读写函数,使用位域结构体
中断处理 中断丢失、数据竞争 使用自旋锁保护共享缓冲区,采用bottom half机制
电源管理 传感器持续耗电、唤醒延迟 实现suspend/resume回调,使用自动休眠定时器
数据路径 用户态读取延迟高、CPU占用大 采用IIO内核框架的triggered buffer模式
调试验证 无法确认SPI时序是否正确 使用逻辑分析仪抓取SCLK/MOSI/MISO波形

1.3 课程目标与学习路径

本课程旨在培养学员从零开始,在Linux内核中为SPI传感器编写高质量设备驱动的工程能力。课程覆盖从硬件协议分析、驱动框架选择、内核编程实现到用户空间验证的完整闭环。

课程核心目标:
  • 掌握Linux SPI子系统架构(spi_master、spi_device、spi_driver)及核心API。
  • 能够独立分析传感器数据手册,提取驱动开发所需的时序、寄存器、中断等关键信息。
  • 熟练使用Linux内核的IIO(Industrial I/O)框架开发传感器驱动。
  • 具备驱动调试、性能优化和电源管理工程实践能力。

下图展示了本课程30章内容的递进学习路径:

课程学习路径与知识体系 阶段一:基础筑基 第1~6章 SPI协议 / 内核模块 / 设备树 / 字符设备 阶段二:核心框架 第7~14章 SPI子系统 / IIO框架 / 中断与同步 / 缓冲区 阶段三:实战驱动 第15~22章 加速度计 / 陀螺仪 / 磁力计 / 环境传感器 阶段四:进阶优化 第23~27章 电源管理 / DMA传输 / 调试与性能分析 阶段五:工程交付 第28~30章 驱动测试 / 文档 / 内核主线提交实践 学习建议 • 每章完成后完成配套实验 • 使用QEMU + 开发板双环境 • 善用printk与ftrace调试

1.4 课程预备知识与工程环境

为获得最佳学习效果,学员应具备以下基础:

  • C语言编程: 指针、内存管理、位运算、链表操作。
  • Linux基础: 文件系统、进程管理、命令行操作。
  • 嵌入式基础: GPIO、中断、时钟树的基本概念。
  • 硬件基础: 能够阅读芯片数据手册的时序图和寄存器表。
推荐实验环境:
  • 主机:Ubuntu 22.04 LTS 或更新版本
  • 交叉编译工具链:arm-linux-gnueabihf- 或 aarch64-linux-gnu-
  • 目标板:Raspberry Pi 3/4 或 BeagleBone Black(均内置SPI控制器)
  • 逻辑分析仪:Saleae Logic 8 或兼容设备(用于SPI时序验证)
  • 传感器模块:ADXL345(加速度计)、MPU9250(九轴)、BME280(环境)

本课程所有驱动代码均基于Linux内核版本 6.1 LTS 进行开发和测试,该版本具有长期支持且SPI/IIO子系统接口稳定。学员可在此基础上适配其他内核版本。

1.5 本章小结