在嵌入式Linux开发领域,SPI作为一种常见的高速同步串行通信协议,被广泛用于连接各种传感器、存储芯片和显示模块。对于需要快速验证或简化开发流程的场景,直接通过用户空间访问SPI设备往往比编写完整的内核驱动更为便捷。这其中,Linux内核的spidev框架就扮演了关键角色。本文将深入探讨如何基于spidev,在Linux用户态实现对SPI接口的配置、测试与数据通信。

一、spidev框架简介
Linux内核的SPI子系统支持两种主要的访问模式:内核驱动开发和用户态直接访问。spidev框架的核心价值在于,它允许开发者绕过复杂的内核驱动编写工作,直接通过用户空间的文件操作接口来控制SPI外设。这为快速原型开发、调试以及某些轻量级应用提供了极大便利,其优势主要体现在以下几个方面:
- 无需深入内核驱动开发,降低了技术门槛。
- 支持全双工与半双工通信,可灵活配置多种SPI模式。
- 能够动态调整通信速率、数据位宽等关键参数。
- 完全兼容标准的Linux文件I/O操作(如
open、read、write、ioctl)。
二、硬件环回测试(MOSI/MISO短路)
在着手进行软件配置之前,强烈建议先通过一次简单的硬件环回测试来验证SPI物理链路的基本连通性。这个方法能有效排查如引脚虚焊、连接错误或电平不匹配等硬件层面的问题。
测试原理
将SPI总线上的MOSI(主机输出/从机输入)引脚与MISO(主机输入/从机输出)引脚用导线短接,这样就形成了一个物理上的数据回路。当主机通过MOSI引脚发送数据时,这些数据会直接“环回”到MISO引脚被主机接收。如果接收到的数据与发送的数据完全一致,则证明SPI总线的硬件连接是正常的,可以继续进行软件层的配置。
三、设备树与内核配置
要使Linux系统能够识别并支持通过spidev访问特定的SPI外设,需要进行两项核心的系统配置:启用内核的spidev支持 和 在设备树中正确描述SPI外设信息。
3.1 内核配置
首先需要确保内核编译时启用了对用户态SPI设备的支持。操作步骤如下:
- 进入你的Linux内核源代码目录。
- 执行
make menuconfig 命令打开内核配置菜单。
- 导航至
Device Drivers -> SPI support -> User mode SPI device driver support。
- 将该选项配置为
y(编译进内核)或 m(编译为可加载模块)。
- 保存配置,然后重新编译内核(或模块),并将新的内核镜像更新到你的开发板上。
3.2 设备树配置
设备树(Device Tree)用于向内核描述硬件信息。对于SPI外设,我们需要在其中明确SPI控制器、引脚复用、通信参数等。一个典型的spidev设备节点配置示例如下:
&spi4 {
pinctrl-names = "default", "sleep"; // 引脚状态配置(默认/休眠)
pinctrl-0 = <&spi4_pins_a>; // 默认状态引脚配置
pinctrl-1 = <&spi4_sleep_pins_a>; // 休眠状态引脚配置
status = "okay"; // 启用spi4控制器
spidev@0{
compatible = "rohm,dh2228fv"; // 兼容属性(支持spidev框架)
reg = <0>; // 从设备地址(对应SPI片选索引)
spi-max-frequency = <4000000>; // 最大通信速率4MHz
};
};
配置说明
pinctrl-names 与 pinctrl-0/1:指定SPI引脚在不同电源状态下的复用配置,需要与开发板的实际引脚定义保持一致。
reg = <0>:指定该SPI从设备的片选(Chip Select)索引号。如果系统中有多个SPI从设备挂载在同一控制器上,需要通过此参数来区分。
spi-max-frequency:根据你所连接外设的规格书进行调整,设定值不应超过SPI控制器和外设芯片双方支持的最大速率。
配置完成后,重新编译设备树(执行 make dtbs),并将生成的 .dtb 文件部署到开发板。
四、基于spidev_test的SPI单元测试
spidev_test 是Linux内核源码中自带的一个官方测试工具,它功能全面,支持全/半双工传输、速率与模式配置,是验证spidev接口是否正常工作的首选工具。
4.1 工具获取与编译
该工具的源码位于内核源码树的 tools/spi/ 目录下,文件名为 spidev_test.c。获取后,使用交叉编译工具链进行编译:
aarch64-linux-gnu-gcc spidev_test.c -o spidev_test
编译完成后,将生成的可执行文件 spidev_test 拷贝到你的开发板中即可。
4.2 核心选项说明
执行 ./spidev_test -h 可以查看所有可用选项。下表列出了核心参数:
| 类别 |
选项 |
功能描述 |
| 设备配置 |
-D/--device |
指定spidev设备节点(默认 /dev/spidev1.1) |
|
-s/--speed |
设置最大通信速率(单位:Hz) |
|
-d/--delay |
设置两次传输间的延迟(单位:微秒) |
| SPI模式 |
-H/--cpha |
配置时钟相位(CPHA) |
|
-O/--cpol |
配置时钟极性(CPOL) |
| 传输模式 |
-l/--loop |
启用环回模式(配合硬件短接使用) |
|
-t/--txonly |
仅发送模式(半双工) |
|
-r/--rxonly |
仅接收模式(半双工) |
| 数据配置 |
-b/--bpw |
设置每字的数据位宽(如8,16) |
|
-S/--size |
设置单次传输的数据长度 |
|
-I/--iter |
设置传输迭代次数 |
| 数据I/O |
-i/--input |
从指定文件读取发送数据(如 test.bin) |
|
-o/--output |
将接收数据输出到文件(如 results.bin) |
|
-p |
直接指定要发送的原始数据(如 "1234\xde\xad") |
| 辅助功能 |
-v/--verbose |
启用详细模式,打印收发缓冲区数据 |
4.3 32字节全双工环回测试
结合前文所述的硬件环回(MOSI与MISO短接)配置,我们可以执行以下命令进行测试:
./spidev_test -D /dev/spidev0.0 -v -l
命令解析
-D /dev/spidev0.0:指定要测试的SPI设备节点。请根据你设备树中的实际配置进行调整,可以通过 ls /dev/spidev* 命令查看系统中存在的节点。
-v:启用详细输出模式,这样我们就能看到具体发送和接收的数据内容。
-l:启用软件环回模式。注意,此处的环回模式需要与硬件的物理短接配合才能生效。
预期输出
如果一切配置正确,你将看到类似以下的输出,其中发送(TX)和接收(RX)的数据缓冲区内容完全一致:
spi mode: 0x0
bits per word: 8
max speed: 500000 Hz (500 KHz)
TX | FF FF FF FF FF FF 40 00 00 00 00 95 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF F0 0D | ......@....
.................. .
RX | FF FF FF FF FF FF 40 00 00 00 00 95 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF F0 0D | ......@....
.................. .
TX与RX数据一致,即证明从软件配置到硬件连接的整个SPI通路工作正常。
4.4 注意事项
在实际使用 spidev_test 或编写自己的应用程序时,有几点需要特别注意:
- 速率适配:工具默认使用500KHz的速率。如果你的SPI控制器时钟源或分频配置不支持此速率,需要使用
-s 选项指定一个合法的值,例如 -s 4000000 表示4MHz。
- 模式匹配:不同的SPI外设可能工作在不同的模式(由CPOL和CPHA组合定义)。如果外设要求模式1、2或3,你需要使用
-O(设置CPOL)和 -H(设置CPHA)选项进行匹配。
- 数据位宽:默认数据位宽是8位/字。如果外设支持16位或其它位宽传输,需要使用
-b 选项指定,例如 -b 16。
总结
通过spidev框架在Linux用户态操作SPI接口,是一种高效且灵活的开发方式,特别适合前期验证、快速原型开发以及不需要复杂内核交互的应用。整个过程围绕 内核配置、设备树描述 和 用户空间工具测试 三个核心步骤展开。掌握这个方法,能让你在嵌入式Linux开发中,更加游刃有余地应对各种SPI外设。希望这篇结合了硬件环回测试与spidev_test工具使用的指南,能为你带来切实的帮助。如果你想深入探讨更多关于嵌入式开发或系统内核的底层知识,欢迎在云栈社区与其他开发者一起交流学习。