前段時(shí)間有客戶在官方社區(qū)反映i.MX RT1170下,使用官方SDK里FlexSPI驅(qū)動(dòng)去擦寫Flash時(shí)不能很好地支持全局中斷。 客戶項(xiàng)目里用了兩塊NOR Flash,分別掛在不同的 FlexSPI上,一塊Flash用于存儲(chǔ)XIP代碼(FlexSPI1),另一塊Flash用于存儲(chǔ)項(xiàng)目資源數(shù)據(jù)(FlexSPI2),顯然這樣的設(shè)計(jì)原理上是沒有問題的,那為什么使能了中斷會(huì)出問題呢?今天就來分析下這個(gè)問題:
注: 客戶測(cè)試的SDK版本為 2.12.1,對(duì)應(yīng)的FlexSPI driver版本為2.3.6
一、為什么擦寫Flash時(shí)經(jīng)常需要關(guān)全局中斷?
在具體分析客戶問題之前,我們先來聊聊嵌入式應(yīng)用里應(yīng)對(duì)NOR Flash的擦寫,為何大部分情況下都是要關(guān)閉全局中斷(這里假設(shè)執(zhí)行代碼空間與擦寫操作空間在同一個(gè) Flash上,當(dāng)然是在不同區(qū)域),這其實(shí)跟如下兩個(gè)特性有關(guān):
RWW特性的意思是在Flash執(zhí)行擦寫命令進(jìn)入Busy 狀態(tài)期間(Flash內(nèi)部狀態(tài)寄存器 WIP位變狀態(tài)1)還能否繼續(xù)響應(yīng)非操作區(qū)域的讀訪問。如果SR[WIP] = 1 時(shí)還能夠支持讀訪問,則該Flash 支持RWW,反之則不支持RWW。
絕大部分Flash都是不支持RWW特性的,這就是為什么Flash擦寫操作代碼本身是需要重定向到RAM里去執(zhí)行(尤其是回讀SR[WIP]狀態(tài)的代碼)。
對(duì)于支持RWW特性的Flash,一般是以Block為單位,F(xiàn)lash擦寫操作代碼放在BlockX 里執(zhí)行,則可以操作BlockX以外的其它Block 區(qū)域,且不需要做代碼重定向。
現(xiàn)在你應(yīng)該知道對(duì)于不支持RWW的Flash為什么擦寫時(shí)需要關(guān)閉全局中斷了,因?yàn)闊o法保證中斷響應(yīng)相關(guān)代碼全都重定向到RAM里了,所以干脆在Flash擦寫期間不響應(yīng)任何中斷。
1.2 SCLK Stop特性
SCLK Stop特性的意思是在Flash執(zhí)行寫入命令接受主設(shè)備傳輸過來的Page數(shù)據(jù)期間,如果總線上SCLK停止(一般情況是FlexSPI這一端的TXFIFO為空或者觸發(fā)空條件),則Flash能否也暫停接受當(dāng)前Page數(shù)據(jù)直到SCLK繼續(xù)輸出從而繼續(xù)處理剩下的Page數(shù)據(jù)。
絕大部分Flash是不支持SCLK Stop特性的,因此在MCU端如果傳輸Page數(shù)據(jù),需要一次性連續(xù)傳輸完成,一旦中途被打斷,則兩次不連續(xù)的Page數(shù)據(jù)傳輸可能無法得到想要的Page寫入結(jié)果。這也是為何Flash寫入期間我們需要關(guān)閉中斷。
二、FlexSPI外設(shè)寫操作設(shè)計(jì)
關(guān)于i.MX RT上的FlexSPI外設(shè)基本情況,以前有兩篇舊文 《FlexSPI支持在Flash XIP原理》、《FlexSPI支持AHB方式寫入Flash》,大家先讀一下有個(gè)初步了解。 這里想重點(diǎn)說一下FlexSPI關(guān)于IPG方式寫操作的設(shè)計(jì),下圖為FlexSPI外設(shè)的模塊框圖,綠色線標(biāo)出了 IPG 方式寫入的通路,這里大家可以看出,其中 IP_TX_FIFO 模塊起了重要的數(shù)據(jù)緩沖作用,驅(qū)動(dòng)里往 FLEXSPI->TFDRx 寄存器寫入的 Page 數(shù)據(jù)會(huì)先被裝載進(jìn) IP_TX_FIFO 里,然后再傳輸出去。
不同i.MX RT型號(hào)中IP_TX_FIFO大小不一樣,目前有三種大小:128、256或1024 Bytes。
對(duì)于QuadSPI/OctalSPI NOR Flash來說,Page 大小一般是256 Bytes;對(duì)于 HyperBus Flash,Page 大小一般是 512 Bytes。所以在 i.MX RT10xx 上 IP_TX_FIFO 是不足以緩沖整個(gè) Page 的,i.MX RT117x 上可以緩沖 QuadSPI/OctalSPI NOR 類型的 Page,i.MX RT118x/5xx/6xx 上則可以緩沖全部 NOR Flash 類型的 Page。
對(duì)于 Page 數(shù)據(jù)不能全部緩沖的情況,則需要一邊傳輸一邊緩沖。
在具體裝載數(shù)據(jù)進(jìn) IP_TX_FIFO 時(shí),主要涉及如下三個(gè) FLEXSPI 寄存器,IP_TX_FIFO 一次只能被填入watermark level大小的數(shù)據(jù),想要把全部 Page 數(shù)據(jù)填進(jìn) IP_TX_FIFO,需要分多次裝載。只要 FLEXSPI->INTR[IPTXWE] 標(biāo)志為 0, 即代表 IP_TX_FIFO 剩余空間大于等于 watermark level,那么就可以繼續(xù)裝載。
FLEXSPI->IPTXFCR[TXWMRK] -- 設(shè)置一次裝載進(jìn) IP_TX_FIFO 的數(shù)據(jù)長(zhǎng)度(即 watermark level),8 Bytes為單位
FLEXSPI->TFDRx -- 按 watermark level 長(zhǎng)度填入 IP_TX_FIFO 裝載數(shù)據(jù)
FLEXSPI->INTR[IPTXWE] -- 觸發(fā) IP_TX_FIFO 的一次裝載
三、客戶問題及FlexSPI driver寫操作流程
前面鋪墊了這么多,終于來到客戶遇到的 FlexSPI 驅(qū)動(dòng)對(duì)于中斷不支持的問題了。因?yàn)榭蛻羰褂昧藘善現(xiàn)lash,所以不存在 RWW 限制問題,那剩下的原因就跟 SCLK Stop 特性有關(guān),即 IP_TX_FIFO 并沒有緩沖全部的 Page,導(dǎo)致 Page 傳輸過程被中斷打斷了,然后 IP_TX_FIFO 因?yàn)榫彌_數(shù)據(jù)全部發(fā)完而使 FlexSPI 模塊進(jìn)入了 SCLK Stop 狀態(tài)。
我們直接打開fsl_flexspi.c驅(qū)動(dòng)文件,找到跟寫操作相關(guān)的 FLEXSPI_TransferBlocking() 函數(shù),在函數(shù)實(shí)現(xiàn)里可以發(fā)現(xiàn),啟動(dòng)寫傳輸時(shí)序的控制位 FLEXSPI->IPCMD[TRG] 是在 IP_TX_FIFO 填充動(dòng)作 FLEXSPI_WriteBlocking() 函數(shù)之前被開啟的,那這樣的實(shí)現(xiàn)確實(shí)是不能夠很好地支持中斷的。
四、如何改進(jìn)FlexSPI driver支持中斷?
知道了原因所在,改起來也很簡(jiǎn)單。如果是QuadSPI/OctalSPI NOR Flash類型(Page=256 Bytes),在 i.MX RT117x 上,其 IP_TX_FIFO 大小為 256 Bytes,能夠緩沖全部的 Page 大小,則可以先調(diào)用 FLEXSPI_WriteBlocking() 裝載全部的 Page 數(shù)據(jù),然后再開啟 FLEXSPI->IPCMD[TRG] 去觸發(fā)寫傳輸時(shí)序,這時(shí)候就不怕被中斷打斷了,如下代碼所示。
當(dāng)然下面代碼只是一個(gè) workaround 式的實(shí)現(xiàn)示例,不是一個(gè)完整的解決方案,畢竟 FlexSPI 驅(qū)動(dòng)要適配全部 i.MX RT 型號(hào)以及全部類型的 NOR Flash,此外還適用 NAND 型 Flash(Page 一般是 2KB),這時(shí)候需要根據(jù)情況拆分調(diào)用多次 FLEXSPI_WriteBlocking() 函數(shù)(不管怎樣要保證啟動(dòng)寫傳輸時(shí)序前,把 IP_TX_FIFO 先裝滿)。
status_t FLEXSPI_TransferBlocking(FLEXSPI_Type *base, flexspi_transfer_t *xfer) { // 代碼略去 /* Start Transfer. */ if ((xfer->cmdType == kFLEXSPI_Write) || (xfer->cmdType == kFLEXSPI_Config)) { result = FLEXSPI_WriteBlocking(base, xfer->data, xfer->dataSize); base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK; } else if (xfer->cmdType == kFLEXSPI_Read) { base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK; result = FLEXSPI_ReadBlocking(base, xfer->data, xfer->dataSize); } else { base->IPCMD |= FLEXSPI_IPCMD_TRG_MASK; } // 代碼略去 }
審核編輯:湯梓紅
-
FlaSh
+關(guān)注
關(guān)注
10文章
1614瀏覽量
147655 -
編程
+關(guān)注
關(guān)注
88文章
3565瀏覽量
93536 -
中斷
+關(guān)注
關(guān)注
5文章
895瀏覽量
41349 -
driver
+關(guān)注
關(guān)注
0文章
526瀏覽量
66556 -
SDK
+關(guān)注
關(guān)注
3文章
1020瀏覽量
45697
原文標(biāo)題:探討i.MX RT下FlexSPI driver實(shí)現(xiàn)Flash編程時(shí)對(duì)于中斷支持問題
文章出處:【微信號(hào):NXP_SMART_HARDWARE,微信公眾號(hào):恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論