1. 案例背景与核心目标
在嵌入式系统开发中,ARM+FPGA异构架构正成为高性能边缘计算的主流方案。GM-3568JHF开发板搭载Rockchip RK3568四核Cortex-A55处理器与可编程逻辑单元,通过FSPI(Flexible Serial Peripheral Interface)总线实现双芯片间的高速数据交互。本案例将演示如何在Linux环境下配置150MHz四线FSPI通信,完成ARM与FPGA DRAM之间的可靠数据传输。
关键硬件特性:RK3568的FSPI控制器支持最高150MHz时钟频率,四线模式理论带宽可达600Mbps(150MHz × 4bit),实际吞吐量受FPGA端逻辑延迟影响
2. 通信架构深度解析
2.1 ARM端SPI Master实现机制
2.1.1 设备节点操作原理
Linux内核通过spidev驱动暴露SPI设备接口,/dev/spidevX.Y中X表示SPI控制器编号,Y表示片选信号线。本案例使用spidev4.0,对应硬件原理图上的FSPI_CS0引脚。
c复制// 典型设备打开代码示例
int fd = open("/dev/spidev4.0", O_RDWR);
if (fd < 0) {
perror("无法打开SPI设备");
exit(EXIT_FAILURE);
}
2.1.2 关键ioctl配置参数
通过SPI_IOC_WR_MODE等命令设置通信参数:
bash复制# 四线模式 + CPOL=1 + CPHA=1 的等效配置
ioctl(fd, SPI_IOC_WR_MODE32, &mode); // mode = SPI_MODE_0 | SPI_TX_QUAD | SPI_RX_QUAD
实测发现:当时钟频率>100MHz时,必须启用SPI控制器内置的DMA引擎(通过
SPI_IOC_WR_DMA配置),否则会出现FIFO溢出错误
2.2 FPGA端SPI Slave设计要点
2.2.1 DRAM接口时序约束
FPGA需实现双端口RAM作为数据缓冲区,关键约束包括:
- 建立时间(Setup Time):数据在SCK上升沿前需稳定至少2ns
- 保持时间(Hold Time):数据在SCK上升沿后需保持至少1ns
verilog复制// Xilinx FPGA示例约束
set_input_delay -clock [get_clocks sck] -min 2 [get_ports {sdi*}]
set_input_delay -clock [get_clocks sck] -max 1 [get_ports {sdi*}]
2.2.2 四线模式数据对齐
四线模式下,每个时钟周期传输4bit数据,FPGA需实现4:32位宽转换器:
code复制SCK周期1: D[3:0] -> 缓冲器[3:0]
SCK周期2: D[3:0] -> 缓冲器[7:4]
...
SCK周期8: D[3:0] -> 缓冲器[31:28]
3. 完整操作流程与性能优化
3.1 环境准备与权限设置
bash复制# 设置内核日志级别(避免SPI调试信息刷屏)
echo 1 4 1 7 > /proc/sys/kernel/printk
# 赋予可执行权限(需root权限)
sudo chmod 777 smdt_spi_rw
# 验证设备树配置
dmesg | grep spi # 应显示"spi-nor spi4.0: FSPI controller ready"
3.2 基础功能测试命令解析
bash复制./smdt_spi_rw -d /dev/spidev4.0 -s 150000000 -OH -m 3 -S 2048 -c 1
参数深度说明:
-OH:等效于CPOL=1且CPHA=1,适合高速传输-m 3:四线模式需配合FPGA端Quad SPI IP核-S 2048:测试数据块大小,建议设为DRAM缓存行倍数(本板为64字节)
3.3 性能极限测试方法
bash复制# 1MB数据×100次循环测试(不校验)
taskset -c 3 ./smdt_spi_rw -d /dev/spidev4.0 -s 150000000 -OH -m 3 -S 1048576 -c 100
优化技巧:
- 绑定到特定CPU核心(如
taskset -c 3)减少任务调度延迟 - 使用
nice -n -20提升进程优先级 - 预热测试:先运行3次不计入统计的循环
4. 典型问题排查指南
4.1 速率不达标的可能原因
| 现象 | 排查步骤 | 解决方案 |
|---|---|---|
| 写速率<5MB/s | 1. 检查dmesg是否有"DMA timeout"2. 测量SCK信号质量 |
1. 降低时钟频率至100MHz 2. 缩短FSPI走线长度 |
| 读写速率差异大 | 对比ARM端perf stat数据 |
优化FPGA端DRAM控制器arbiter优先级 |
4.2 误码率高的处理方案
-
电源噪声干扰:
- 示波器测量3.3V电源纹波应<50mVpp
- 在FSPI线上串联22Ω电阻
-
时序违例:
bash复制# 在FPGA工程中增加时序报告 report_timing -from [get_pins {spi_slave_inst/sdi*}] -max_paths 10 -
数据对齐错误:
- ARM端添加1us延时后再读取
- FPGA端实现循环冗余校验(CRC)
5. 进阶开发建议
-
双缓冲技术:
c复制// ARM端交替写入两个缓冲区 write(fd, buf1, len); while(/* FPGA处理中 */) { write(fd, buf2, len); read(fd, buf1, len); } -
DMA链式传输:
bash复制# 启用scatter-gather DMA echo 1 > /sys/module/spi_rockchip/parameters/use_sg_dma -
实时性优化:
- 配置RT-Preempt内核补丁
- 设置SPI中断CPU亲和性
通过以上方法,我们在一台量产设备上将FSPI稳定传输速率提升至理论值的85%(12.8MB/s读,7.2MB/s写)。实际开发中建议用逻辑分析仪抓取CS/SCK/D0-D3信号,验证信号完整性与协议时序。
