在嵌入式系統(tǒng)中,SPI Flash憑借小巧、低功耗、高速的特性,廣泛用于存儲(chǔ)固件、配置參數(shù)等關(guān)鍵數(shù)據(jù)。Rockchip作為主流嵌入式SOC廠商,提供了專門的SFC(Serial Flash Controller)驅(qū)動(dòng)(spi-rockchip-sfc.c),用于高效管理SPI Flash的讀寫傳輸。本文基于Linux內(nèi)核驅(qū)動(dòng)代碼與Rockchip官方開發(fā)指南,深入拆解SFC驅(qū)動(dòng)的核心流程、關(guān)鍵機(jī)制,并給出實(shí)用的問題排查方案,助力開發(fā)者快速定位問題。
一、SFC驅(qū)動(dòng)核心功能概覽
Rockchip SFC驅(qū)動(dòng)是Linux內(nèi)核級(jí)SPI內(nèi)存設(shè)備驅(qū)動(dòng),專為Rockchip SOC(如RK3506、RV1126、RV1103等)設(shè)計(jì),核心特性包括:
?支持SPI Nor Flash等串行存儲(chǔ)設(shè)備,兼容摩托羅拉SPI協(xié)議;
?支持DMA傳輸(大數(shù)據(jù)場(chǎng)景)與FIFO輪詢(小數(shù)據(jù)場(chǎng)景),降低CPU占用;
?集成DLL(Delay Line)延遲調(diào)優(yōu),保障高速傳輸(最高150MHz)穩(wěn)定性;
?支持多片選(最多2路)、靈活的位寬配置(2/4/8位)與Dummy周期調(diào)整;
?完善的電源管理(Runtime PM +系統(tǒng)休眠喚醒)。
適用場(chǎng)景:嵌入式系統(tǒng)中SPI Flash的固件升級(jí)、數(shù)據(jù)讀寫、配置存儲(chǔ)等場(chǎng)景。
二、驅(qū)動(dòng)核心流程深度解析
SFC驅(qū)動(dòng)的工作流程可分為三大核心環(huán)節(jié):驅(qū)動(dòng)初始化(probe)、數(shù)據(jù)傳輸(exec_mem_op)、關(guān)鍵輔助機(jī)制(DLL調(diào)優(yōu)、中斷處理)。
2.1驅(qū)動(dòng)初始化流程(probe函數(shù))
probe是驅(qū)動(dòng)的“啟動(dòng)入口”,負(fù)責(zé)申請(qǐng)硬件資源、初始化控制器狀態(tài),為后續(xù)傳輸做準(zhǔn)備。
關(guān)鍵步驟拆解:
1.資源申請(qǐng)與結(jié)構(gòu)體初始化:
?分配SPI Master結(jié)構(gòu)體,綁定設(shè)備私有數(shù)據(jù)(struct rockchip_sfc);
?映射SFC控制器寄存器地址(regbase),獲取IO內(nèi)存訪問權(quán)限;
?申請(qǐng)時(shí)鐘(hclk:AHB總線時(shí)鐘,clk:SFC接口時(shí)鐘)并使能;
?申請(qǐng)中斷,注冊(cè)中斷處理函數(shù)(處理DMA傳輸完成事件)。
2.硬件配置初始化:
?解析DTS配置(片選GPIO、復(fù)位GPIO、DMA開關(guān)、時(shí)鐘頻率等);
?初始化控制器:重置FSM(狀態(tài)機(jī))與FIFO(rockchip_sfc_reset),清除中斷掩碼(rockchip_sfc_irq_mask);
?讀取控制器版本(rockchip_sfc_get_version),適配不同版本特性(如VER4+支持更大IO尺寸);
?配置最大IO傳輸長(zhǎng)度(max_iosize)、DLL最大延遲單元(max_dll_cells)。
3.設(shè)備注冊(cè):
?初始化DMA緩沖區(qū)(若啟用),映射物理地址;
?注冊(cè)SPI Master到內(nèi)核,完成驅(qū)動(dòng)加載。
初始化流程圖:

2.2數(shù)據(jù)傳輸核心流程(exec_mem_op函數(shù))
這是驅(qū)動(dòng)的“業(yè)務(wù)核心”,負(fù)責(zé)處理SPI Flash的讀寫、擦除等操作,支持DMA與FIFO輪詢兩種傳輸模式。
關(guān)鍵步驟拆解:
1.傳輸前準(zhǔn)備:
?運(yùn)行時(shí)電源喚醒(pm_runtime_get_sync),確保控制器供電;
?調(diào)整傳輸參數(shù)(rockchip_sfc_adjust_op_work):解決“SFC不支持CMD后直接接Dummy周期”的硬件限制,將Dummy周期轉(zhuǎn)為ADDR周期;
?激活片選(rockchip_sfc_set_cs_gpio):通過GPIO拉低對(duì)應(yīng)片選,選中目標(biāo)設(shè)備。
2.傳輸配置:
?調(diào)用rockchip_sfc_xfer_setup配置控制器寄存器:
命令配置(opcode、命令位寬、DTR模式);
地址配置(地址長(zhǎng)度、位寬、DTR模式);
Dummy周期配置(根據(jù)位寬調(diào)整,如8位總線需分2次傳輸);
數(shù)據(jù)配置(傳輸方向、位寬、長(zhǎng)度)。
3.數(shù)據(jù)傳輸:
?判定傳輸模式:數(shù)據(jù)長(zhǎng)度≥64字節(jié)(SFC_DMA_TRANS_THRETHOLD)且對(duì)齊4字節(jié)→DMA傳輸;否則→FIFO輪詢;
?DMA傳輸:初始化完成量(completion),啟動(dòng)DMA傳輸(rockchip_sfc_xfer_data_dma),等待中斷觸發(fā)完成;
?FIFO輪詢:循環(huán)讀寫FIFO緩沖區(qū)(rockchip_sfc_write_fifo/read_fifo),直到數(shù)據(jù)傳輸完畢。
4.傳輸后清理:
?等待控制器空閑(rockchip_sfc_xfer_done),避免總線沖突;
?釋放片選(拉高三態(tài));
?觸發(fā)電源休眠(pm_runtime_put_autosuspend),降低功耗。
數(shù)據(jù)傳輸流程圖:

2.3關(guān)鍵輔助機(jī)制解析
(1)DLL延遲調(diào)優(yōu)(保障高速傳輸穩(wěn)定性)
當(dāng)傳輸速率超過50MHz(SFC_DLL_THRESHOLD_RATE)時(shí),信號(hào)傳輸延遲可能導(dǎo)致數(shù)據(jù)采樣錯(cuò)誤。驅(qū)動(dòng)通過rockchip_sfc_delay_lines_tuning自動(dòng)調(diào)整延遲線:
1.讀取Flash ID作為參考基準(zhǔn);
2.遍歷DLL延遲單元(dll_cells),找到穩(wěn)定傳輸?shù)挠行^(qū)間;
3.取有效區(qū)間中點(diǎn)作為最優(yōu)延遲值,寫入SFC_DLL_CTRL0寄存器。
?若調(diào)優(yōu)失敗:自動(dòng)降頻到50MHz,確保傳輸可靠性。
(2)中斷處理
僅用于DMA傳輸場(chǎng)景,中斷處理函數(shù)(rockchip_sfc_irq_handler)邏輯簡(jiǎn)單:
1.讀取原始中斷狀態(tài)寄存器(SFC_RISR);
2.若檢測(cè)到DMA完成中斷(SFC_RISR_DMA),觸發(fā)完成量(complete(&sfc->cp));
3.清除中斷標(biāo)志(SFC_ICLR)。
(3)電源管理
?Runtime PM:傳輸時(shí)喚醒,閑置時(shí)休眠(默認(rèn)2000ms延遲),降低待機(jī)功耗;
?系統(tǒng)休眠/喚醒:休眠時(shí)關(guān)閉時(shí)鐘、保存寄存器狀態(tài);喚醒時(shí)恢復(fù)配置,重新初始化控制器。
三、常見問題排查指南
結(jié)合驅(qū)動(dòng)代碼與實(shí)際開發(fā)場(chǎng)景,總結(jié)以下高頻問題的排查思路:
3.1驅(qū)動(dòng)加載失敗(probe失敗)
可能原因:
?寄存器地址映射失敗(DTS中reg屬性與硬件不匹配);
?時(shí)鐘申請(qǐng)失敗(DTS中clock-names或clocks配置錯(cuò)誤);
?中斷申請(qǐng)失敗(中斷號(hào)錯(cuò)誤或被占用);
?GPIO配置錯(cuò)誤(片選/復(fù)位GPIO未定義或引腳被占用)。
排查步驟:
1.查看內(nèi)核日志:dmesg | grep rockchip-sfc,定位失敗環(huán)節(jié)(如“Failed to get sfc interface clk”);
2.核對(duì)DTS配置:確保reg、clocks、interrupts、cs-gpios與SOC datasheet一致;
3.檢查硬件資源:通過cat /proc/interrupts確認(rèn)中斷是否被占用,ls /sys/class/gpio確認(rèn)GPIO是否可用。
3.2傳輸無響應(yīng)/超時(shí)
可能原因:
?片選未正確激活(GPIO方向錯(cuò)誤或電平極性反轉(zhuǎn));
?FIFO讀寫超時(shí)(rockchip_sfc_wait_rxfifo_ready/wait_txfifo_ready返回-ETIMEDOUT);
?控制器未進(jìn)入工作狀態(tài)(SFC_SR寄存器顯示忙碌但無數(shù)據(jù)傳輸);
?時(shí)鐘未使能或頻率配置錯(cuò)誤。
排查步驟:
1.示波器抓波形:檢查CLK、CS、MOSI/MISO引腳是否有信號(hào)輸出(CS應(yīng)拉低,CLK應(yīng)有穩(wěn)定頻率);
2.打印寄存器狀態(tài):在超時(shí)處添加日志,打印SFC_SR(狀態(tài)機(jī))、SFC_FSR(FIFO狀態(tài)),確認(rèn)是否卡在校驗(yàn)或等待狀態(tài);
3.驗(yàn)證片選控制:手動(dòng)觸發(fā)片選GPIO電平切換(gpiod_set_value),觀察引腳波形;
4.檢查時(shí)鐘:通過clk_get_rate(sfc->clk)打印實(shí)際時(shí)鐘頻率,確認(rèn)與配置一致。
3.3數(shù)據(jù)傳輸錯(cuò)誤(CRC校驗(yàn)失敗/數(shù)據(jù)錯(cuò)亂)
可能原因:
?位寬配置錯(cuò)誤(驅(qū)動(dòng)配置與Flash支持的位寬不匹配,如Flash支持4位但驅(qū)動(dòng)配置8位);
?Dummy周期配置錯(cuò)誤(未滿足Flash datasheet要求的最小Dummy周期);
?DLL調(diào)優(yōu)失敗(高速傳輸時(shí)未找到穩(wěn)定延遲值);
?相位選擇錯(cuò)誤(SFC_CTRL_PHASE_SEL_NEGETIVE配置與Flash SPI模式不匹配)。
排查步驟:
1.核對(duì)Flash參數(shù):確認(rèn)Flash支持的位寬、Dummy周期、SPI模式(CPHA/CPOL);
2.檢查傳輸配置:在rockchip_sfc_xfer_setup中添加日志,打印ctrl、cmd、dummy_ext等寄存器值,與Flash要求對(duì)比;
3.關(guān)閉高速模式:臨時(shí)將傳輸速率降至50MHz(規(guī)避DLL問題),測(cè)試是否恢復(fù)正常;
4.驗(yàn)證FIFO讀寫:小數(shù)據(jù)傳輸(如1字節(jié))時(shí),打印FIFO讀寫的數(shù)據(jù),確認(rèn)是否與預(yù)期一致。
3.4傳輸速率不達(dá)標(biāo)
可能原因:
?DMA未啟用(大數(shù)據(jù)傳輸仍使用FIFO輪詢,CPU占用高);
?DLL調(diào)優(yōu)失敗導(dǎo)致降頻;
?時(shí)鐘配置錯(cuò)誤(如VER8+芯片未啟用SCLK_X2_BYPASS,實(shí)際速率減半);
?電源管理策略:autosuspend延遲過短,頻繁喚醒/休眠影響速率。
排查步驟:
1.確認(rèn)DMA啟用:檢查DTS中是否未配置rockchip,sfc-no-dma,且傳輸長(zhǎng)度≥64字節(jié);
2.查看DLL調(diào)優(yōu)日志:dmesg | grep dll training,確認(rèn)是否調(diào)優(yōu)成功(如“dll training success in 150MHz”);
3.調(diào)整時(shí)鐘配置:VER8+芯片需在DTS中添加rockchip,sclk-x2-bypass,確保速率翻倍;
4.優(yōu)化電源管理:增大autosuspend延遲(如rockchip,autosuspend-delay-ms = <5000>),減少休眠喚醒開銷。
3.5 SPI無信號(hào)輸出
可能原因:
?控制器未復(fù)位(SFC_RCVR_RESET未置位);
?中斷掩碼未清除(SFC_IMR全1,禁止所有中斷);
?片選未激活(cs-gpios配置錯(cuò)誤,未拉低);
?引腳復(fù)用配置錯(cuò)誤(SPI引腳被配置為GPIO功能)。
排查步驟:
1.檢查控制器復(fù)位:在probe函數(shù)中添加日志,確認(rèn)rockchip_sfc_reset返回0(復(fù)位成功);
2.清除中斷掩碼:確認(rèn)rockchip_sfc_irq_mask(sfc, 0xFFFFFFFF)已調(diào)用,后續(xù)按需解鎖中斷;
3.驗(yàn)證引腳復(fù)用:通過cat /sys/kernel/debug/pinctrl/pinctrl-soc/state查看SPI引腳是否配置為SPI功能;
4.手動(dòng)激活片選:在傳輸前強(qiáng)制拉低片選GPIO,觀察波形是否正常。
四、優(yōu)化建議
1.啟用DMA傳輸:對(duì)于≥64字節(jié)的大數(shù)據(jù)傳輸,務(wù)必啟用DMA(默認(rèn)啟用,避免配置rockchip,sfc-no-dma),可降低CPU占用率至5%以下;
2.優(yōu)化DLL調(diào)優(yōu):高速傳輸(>50MHz)時(shí),確保Flash支持的延遲范圍與驅(qū)動(dòng)DLL參數(shù)匹配,必要時(shí)在DTS中配置rockchip,max-dll調(diào)整最大延遲單元;
3.合理配置PM延遲:根據(jù)業(yè)務(wù)場(chǎng)景調(diào)整rockchip,autosuspend-delay-ms(如工業(yè)場(chǎng)景設(shè)為5000ms,消費(fèi)電子設(shè)為2000ms);
4.DTS配置規(guī)范:嚴(yán)格按照SOC datasheet配置reg、clocks、cs-gpios,避免“經(jīng)驗(yàn)值”配置(如RK3506的SFC控制器地址為0xff190000)。
五、總結(jié)
Rockchip SFC驅(qū)動(dòng)的核心設(shè)計(jì)圍繞“高效傳輸”與“穩(wěn)定性”,通過DMA、DLL調(diào)優(yōu)、靈活的電源管理實(shí)現(xiàn)SPI Flash的高速可靠讀寫。排查問題時(shí),需遵循“從驅(qū)動(dòng)加載→硬件配置→傳輸流程”的順序,結(jié)合內(nèi)核日志、示波器波形、寄存器狀態(tài)逐步定位根因。
建議開發(fā)者在調(diào)試前:
1.通讀SOC datasheet,明確SFC控制器的寄存器定義與硬件限制;
2.參考Rockchip官方開發(fā)指南,確保DTS配置符合規(guī)范;
3.啟用驅(qū)動(dòng)調(diào)試日志(dev_dbg),通過dmesg輸出關(guān)鍵流程信息。
通過本文的流程解析與排查指南,希望能幫助開發(fā)者快速掌握SFC驅(qū)動(dòng)的核心邏輯,高效解決實(shí)際開發(fā)中的問題。如果需要進(jìn)一步深入某個(gè)環(huán)節(jié)(如DLL調(diào)優(yōu)原理、DMA緩沖區(qū)管理),歡迎在評(píng)論區(qū)留言交流!
審核編輯 黃宇
-
SFC
+關(guān)注
關(guān)注
0文章
45瀏覽量
11669 -
Rockchip
+關(guān)注
關(guān)注
0文章
92瀏覽量
19577
發(fā)布評(píng)論請(qǐng)先 登錄
深入解析TPS61166:高效白光LED驅(qū)動(dòng)芯片的全方位應(yīng)用指南
SD NAND 為何不能存啟動(dòng)代碼,SPI NAND 與 NOR Flash 卻可以 —— 接口、傳輸、啟動(dòng)機(jī)制全對(duì)比
RK?平臺(tái)?SPI?開發(fā)完全指南(驅(qū)動(dòng)?+?配置?+?測(cè)試?+?優(yōu)化)
RK平臺(tái)固件升級(jí)失敗?排查流程圖+腦圖+實(shí)操指南,一步搞定!
SPI NOR Flash和SPI NAND Flash存儲(chǔ)芯片的區(qū)別
深入解析TPIC2060A:多功能9通道電機(jī)驅(qū)動(dòng)IC的技術(shù)奧秘
國產(chǎn)SPI NOR Flash接口閃存介紹
華潤(rùn)微7388標(biāo)準(zhǔn)化改裝指南:從器材選型到故障排查的全流程方案
FPGA實(shí)現(xiàn)基于SPI協(xié)議的Flash驅(qū)動(dòng)控制芯片擦除
深入解析?RK?平臺(tái)顯示驅(qū)動(dòng):格式支持、處理流程與實(shí)現(xiàn)原理
X-ray檢測(cè)設(shè)備故障排查與維護(hù)全流程指南
專業(yè)技術(shù)指南——光模塊故障判定排查法
SPI NOR FLASH是什么,與SPI NAND Flash的區(qū)別
SFUD驅(qū)動(dòng)庫實(shí)戰(zhàn)手冊(cè):串行SPI Flash開發(fā)全流程解析
深入解析Rockchip SFC驅(qū)動(dòng):SPI Flash傳輸流程與問題排查指南
評(píng)論