QSPI(四线串行外设接口,Quad Serial Peripheral Interface)控制器是 Qualcomm SoC 中实现的一种高速同步串行总线主控制器。它扩展了传统的 4 线 SPI 总线,支持最多四条双向数据线(IO0–IO3),在相同时钟频率下可实现标准 SPI 4 倍的吞吐量。
图:QSPI 总线信号接口
总线信号说明
| 信号 | 方向 | 说明 |
|---|
CLK | 输出 | 由 QSPI 主控制器生成的串行时钟。 |
CS_N | 输出 | 片选(低电平有效)。置位以选择第一个外设。在分段传输期间保持置位。 |
IO0 | 双向 | 数据线 0。 |
IO1 | 双向 | 数据线 1。 |
IO2 | 双向 | 数据线 2。 |
IO3 | 双向 | 数据线 3。 |
I/O 模式波形
图:QSPI I/O 模式波形:1 位、2 位和 4 位
QSPI 控制器内部架构
图:QSPI 控制器内部框图
QSPI 配置
Linux
本节介绍 QSPI 软件驱动的内核配置和设备树节点更改。
支持 QSPI 接口需要以下驱动内核配置。
QSPI 接口组件
本节介绍内核设备树节点及相关文档。
表:QSPI 接口:Linux
Linux 下使用 SPI-NOR 进行 QSPI 验证
这些验证可确认 QSPI 控制器在 Linux 上与符合 JEDEC 标准的 SPI-NOR 闪存设备正常协同工作。测试涵盖三个核心方面:验证硬件在启动时被正确检测和枚举、确认可以可靠地从闪存读取数据,以及确保擦除后写入操作能成功完成。在新板卡启动(bring-up)后或修改 QSPI 设备树配置后,请使用这些检查。
以下设备树代码片段启用 QSPI 控制器并将其绑定到 SPI-NOR 闪存设备:
1. 初始化与检测
这些测试确认 QSPI 控制器和 NOR 闪存在启动时被 Linux 正确识别,并且在尝试任何读写之前,所有闪存分区都可作为 MTD 设备使用。
| 测试说明 | 示例命令 | 预期结果 |
|---|
| 检查 QSPI 控制器在启动时成功启动,内核日志中无错误 | dmesg | grep -i spi | QSPI 控制器初始化无错误 |
| 通过从 sysfs 接口读取 JEDEC ID,确认 NOR 闪存芯片被识别 | cat /sys/class/mtd/mtd0/device/spi-nor/jedec_id | 检测到 NOR 闪存且 JEDEC ID 正确 |
| 确认内核报告的闪存总容量和擦除块布局与设备规格一致 | cat /proc/mtd | 闪存容量和擦除大小符合规格 |
| 确认所有闪存分区都可作为 /dev 下的 MTD 字符设备访问 | ls -l /dev/mtd* | 所有 MTD 设备和分区可见 |
2. 读操作
这些测试验证可以准确地从闪存读取数据,包括从闪存地址空间末尾读取以及在压力条件下重复读取等边界情况。
| 测试说明 | 示例命令 | 预期结果 |
|---|
| 从闪存起始位置读取一个 256 字节块,确认数据读取无错误 | dd if=/dev/mtd0 of=/tmp/read.bin bs=256 count=1 | 数据读取成功 |
| 从闪存最后 256 字节读取,确认不会发生越界访问或缓冲区溢出 | dd if=/dev/mtd0 of=/tmp/boundary.bin bs=1 count=256 skip=$((SIZE-256)) | 无边界溢出 |
| 执行 100 次连续的 4K 块读取循环,确认在重复访问下运行稳定且无错误 | for i in {1..100}; do echo "iter $i"; dd if=/dev/mtd0 of=/dev/null bs=4K count=10; done | 重复读取稳定 |
3. 写操作
这些测试确认擦除后可以正确地向闪存写入数据,包括多页写入和覆写场景,这些是固件更新流程中最常见的操作。
| 测试说明 | 示例命令 | 预期结果 |
|---|
| 擦除一个闪存扇区并写入测试模式,确认基本的单扇区写入功能 | flash_erase /dev/mtd0 0 1 && echo TEST > /tmp/t.bin && dd if=/tmp/t.bin of=/dev/mtd0 | 写入成功 |
| 写入跨多个页面的 16 KB 随机数据,确认驱动正确处理跨页边界的情况 | dd if=/dev/urandom of=/tmp/m.bin bs=4K count=4 && flashcp /tmp/m.bin /dev/mtd0 | 多页写入成功 |
| 擦除先前写入的扇区并重新写入,确认闪存在擦除后能正确接受新数据 | flash_erase /dev/mtd0 0 1 && flashcp /tmp/t.bin /dev/mtd0 | 新数据写入正确 |