深入解析Rockchip SFC驱动:SPI Flash传输流程与问题排查指南

电子说

1.4w人已加入

描述

在嵌入式系统中,SPI Flash凭借小巧、低功耗、高速的特性,广泛用于存储固件、配置参数等关键数据。Rockchip作为主流嵌入式SOC厂商,提供了专门的SFC(Serial Flash Controller)驱动(spi-rockchip-sfc.c),用于高效管理SPI Flash的读写传输。本文基于Linux内核驱动代码与Rockchip官方开发指南,深入拆解SFC驱动的核心流程、关键机制,并给出实用的问题排查方案,助力开发者快速定位问题。

一、SFC驱动核心功能概览

Rockchip SFC驱动是Linux内核级SPI内存设备驱动,专为Rockchip SOC(如RK3506、RV1126、RV1103等)设计,核心特性包括:

•支持SPI Nor Flash等串行存储设备,兼容摩托罗拉SPI协议;

•支持DMA传输(大数据场景)与FIFO轮询(小数据场景),降低CPU占用;

•集成DLL(Delay Line)延迟调优,保障高速传输(最高150MHz)稳定性;

•支持多片选(最多2路)、灵活的位宽配置(2/4/8位)与Dummy周期调整;

•完善的电源管理(Runtime PM + 系统休眠唤醒)。

适用场景:嵌入式系统中SPI Flash的固件升级、数据读写、配置存储等场景。

二、驱动核心流程深度解析

SFC驱动的工作流程可分为三大核心环节:驱动初始化(probe)数据传输(exec_mem_op)关键辅助机制(DLL调优、中断处理)

2.1 驱动初始化流程(probe函数)

probe是驱动的“启动入口”,负责申请硬件资源、初始化控制器状态,为后续传输做准备。

关键步骤拆解:

1.资源申请与结构体初始化

○分配SPI Master结构体,绑定设备私有数据(struct rockchip_sfc);

○映射SFC控制器寄存器地址(regbase),获取IO内存访问权限;

○申请时钟(hclk:AHB总线时钟,clk:SFC接口时钟)并使能;

○申请中断,注册中断处理函数(处理DMA传输完成事件)。

2.硬件配置初始化

○解析DTS配置(片选GPIO、复位GPIO、DMA开关、时钟频率等);

○初始化控制器:重置FSM(状态机)与FIFO(rockchip_sfc_reset),清除中断掩码(rockchip_sfc_irq_mask);

○读取控制器版本(rockchip_sfc_get_version),适配不同版本特性(如VER4+支持更大IO尺寸);

○配置最大IO传输长度(max_iosize)、DLL最大延迟单元(max_dll_cells)。

3.设备注册

○初始化DMA缓冲区(若启用),映射物理地址;

○注册SPI Master到内核,完成驱动加载。

初始化流程图:

SFC

2.2 数据传输核心流程(exec_mem_op函数)

这是驱动的“业务核心”,负责处理SPI Flash的读写、擦除等操作,支持DMA与FIFO轮询两种传输模式。

关键步骤拆解:

1.传输前准备

○运行时电源唤醒(pm_runtime_get_sync),确保控制器供电;

○调整传输参数(rockchip_sfc_adjust_op_work):解决“SFC不支持CMD后直接接Dummy周期”的硬件限制,将Dummy周期转为ADDR周期;

○激活片选(rockchip_sfc_set_cs_gpio):通过GPIO拉低对应片选,选中目标设备。

2.传输配置

○调用rockchip_sfc_xfer_setup配置控制器寄存器:

命令配置( opcode、命令位宽、DTR模式);

地址配置(地址长度、位宽、DTR模式);

Dummy周期配置(根据位宽调整,如8位总线需分2次传输);

数据配置(传输方向、位宽、长度)。

3.数据传输

○判定传输模式:数据长度≥64字节(SFC_DMA_TRANS_THRETHOLD)且对齐4字节→DMA传输;否则→FIFO轮询;

○DMA传输:初始化完成量(completion),启动DMA传输(rockchip_sfc_xfer_data_dma),等待中断触发完成;

○FIFO轮询:循环读写FIFO缓冲区(rockchip_sfc_write_fifo/read_fifo),直到数据传输完毕。

4.传输后清理

○等待控制器空闲(rockchip_sfc_xfer_done),避免总线冲突;

○释放片选(拉高三态);

○触发电源休眠(pm_runtime_put_autosuspend),降低功耗。

数据传输流程图:

SFC

2.3 关键辅助机制解析

(1)DLL延迟调优(保障高速传输稳定性)

当传输速率超过50MHz(SFC_DLL_THRESHOLD_RATE)时,信号传输延迟可能导致数据采样错误。驱动通过rockchip_sfc_delay_lines_tuning自动调整延迟线:

1.读取Flash ID作为参考基准;

2.遍历DLL延迟单元(dll_cells),找到稳定传输的有效区间;

3.取有效区间中点作为最优延迟值,写入SFC_DLL_CTRL0寄存器。

•若调优失败:自动降频到50MHz,确保传输可靠性。

(2)中断处理

仅用于DMA传输场景,中断处理函数(rockchip_sfc_irq_handler)逻辑简单:

1.读取原始中断状态寄存器(SFC_RISR);

2.若检测到DMA完成中断(SFC_RISR_DMA),触发完成量(complete(&sfc->cp));

3.清除中断标志(SFC_ICLR)。

(3)电源管理

•Runtime PM:传输时唤醒,闲置时休眠(默认2000ms延迟),降低待机功耗;

•系统休眠/唤醒:休眠时关闭时钟、保存寄存器状态;唤醒时恢复配置,重新初始化控制器。

三、常见问题排查指南

结合驱动代码与实际开发场景,总结以下高频问题的排查思路:

3.1 驱动加载失败(probe失败)

可能原因:

•寄存器地址映射失败(DTS中reg属性与硬件不匹配);

•时钟申请失败(DTS中clock-names或clocks配置错误);

•中断申请失败(中断号错误或被占用);

•GPIO配置错误(片选/复位GPIO未定义或引脚被占用)。

排查步骤:

1.查看内核日志:dmesg | grep rockchip-sfc,定位失败环节(如“Failed to get sfc interface clk”);

2.核对DTS配置:确保reg、clocks、interrupts、cs-gpios与SOC datasheet一致;

3.检查硬件资源:通过cat /proc/interrupts确认中断是否被占用,ls /sys/class/gpio确认GPIO是否可用。

3.2 传输无响应/超时

可能原因:

•片选未正确激活(GPIO方向错误或电平极性反转);

•FIFO读写超时(rockchip_sfc_wait_rxfifo_ready/wait_txfifo_ready返回-ETIMEDOUT);

•控制器未进入工作状态(SFC_SR寄存器显示忙碌但无数据传输);

•时钟未使能或频率配置错误。

排查步骤:

1.示波器抓波形:检查CLK、CS、MOSI/MISO引脚是否有信号输出(CS应拉低,CLK应有稳定频率);

2.打印寄存器状态:在超时处添加日志,打印SFC_SR(状态机)、SFC_FSR(FIFO状态),确认是否卡在校验或等待状态;

3.验证片选控制:手动触发片选GPIO电平切换(gpiod_set_value),观察引脚波形;

4.检查时钟:通过clk_get_rate(sfc->clk)打印实际时钟频率,确认与配置一致。

3.3 数据传输错误(CRC校验失败/数据错乱)

可能原因:

•位宽配置错误(驱动配置与Flash支持的位宽不匹配,如Flash支持4位但驱动配置8位);

•Dummy周期配置错误(未满足Flash datasheet要求的最小Dummy周期);

•DLL调优失败(高速传输时未找到稳定延迟值);

•相位选择错误(SFC_CTRL_PHASE_SEL_NEGETIVE配置与Flash SPI模式不匹配)。

排查步骤:

1.核对Flash参数:确认Flash支持的位宽、Dummy周期、SPI模式(CPHA/CPOL);

2.检查传输配置:在rockchip_sfc_xfer_setup中添加日志,打印ctrl、cmd、dummy_ext等寄存器值,与Flash要求对比;

3.关闭高速模式:临时将传输速率降至50MHz(规避DLL问题),测试是否恢复正常;

4.验证FIFO读写:小数据传输(如1字节)时,打印FIFO读写的数据,确认是否与预期一致。

3.4 传输速率不达标

可能原因:

•DMA未启用(大数据传输仍使用FIFO轮询,CPU占用高);

•DLL调优失败导致降频;

•时钟配置错误(如VER8+芯片未启用SCLK_X2_BYPASS,实际速率减半);

•电源管理策略:autosuspend延迟过短,频繁唤醒/休眠影响速率。

排查步骤:

1.确认DMA启用:检查DTS中是否未配置rockchip,sfc-no-dma,且传输长度≥64字节;

2.查看DLL调优日志:dmesg | grep dll training,确认是否调优成功(如“dll training success in 150MHz”);

3.调整时钟配置:VER8+芯片需在DTS中添加rockchip,sclk-x2-bypass,确保速率翻倍;

4.优化电源管理:增大autosuspend延迟(如rockchip,autosuspend-delay-ms = <5000>),减少休眠唤醒开销。

3.5 SPI无信号输出

可能原因:

•控制器未复位(SFC_RCVR_RESET未置位);

•中断掩码未清除(SFC_IMR全1,禁止所有中断);

•片选未激活(cs-gpios配置错误,未拉低);

•引脚复用配置错误(SPI引脚被配置为GPIO功能)。

排查步骤:

1.检查控制器复位:在probe函数中添加日志,确认rockchip_sfc_reset返回0(复位成功);

2.清除中断掩码:确认rockchip_sfc_irq_mask(sfc, 0xFFFFFFFF)已调用,后续按需解锁中断;

3.验证引脚复用:通过cat /sys/kernel/debug/pinctrl/pinctrl-soc/state查看SPI引脚是否配置为SPI功能;

4.手动激活片选:在传输前强制拉低片选GPIO,观察波形是否正常。

四、优化建议

1.启用DMA传输:对于≥64字节的大数据传输,务必启用DMA(默认启用,避免配置rockchip,sfc-no-dma),可降低CPU占用率至5%以下;

2.优化DLL调优:高速传输(>50MHz)时,确保Flash支持的延迟范围与驱动DLL参数匹配,必要时在DTS中配置rockchip,max-dll调整最大延迟单元;

3.合理配置PM延迟:根据业务场景调整rockchip,autosuspend-delay-ms(如工业场景设为5000ms,消费电子设为2000ms);

4.DTS配置规范:严格按照SOC datasheet配置reg、clocks、cs-gpios,避免“经验值”配置(如RK3506的SFC控制器地址为0xff190000)。

五、总结

Rockchip SFC驱动的核心设计围绕“高效传输”与“稳定性”,通过DMA、DLL调优、灵活的电源管理实现SPI Flash的高速可靠读写。排查问题时,需遵循“从驱动加载→硬件配置→传输流程”的顺序,结合内核日志、示波器波形、寄存器状态逐步定位根因。

建议开发者在调试前:

1.通读SOC datasheet,明确SFC控制器的寄存器定义与硬件限制;

2.参考Rockchip官方开发指南,确保DTS配置符合规范;

3.启用驱动调试日志(dev_dbg),通过dmesg输出关键流程信息。

通过本文的流程解析与排查指南,希望能帮助开发者快速掌握SFC驱动的核心逻辑,高效解决实际开发中的问题。如果需要进一步深入某个环节(如DLL调优原理、DMA缓冲区管理),欢迎在评论区留言交流!

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分