痞子衡嵌入式:關於i.MXRT中FlexSPI外設lookupTable裡配置Normal read的一個小誤區

痞子衡發表於2021-06-01

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是i.MXRT中FlexSPI外設lookupTable裡配置Normal read的一個小誤區

  關於序列四線NOR Flash,當其作為啟動(XiP)裝置時,我們最常配置的讀模式應該是 Fast Read Quad I/O SDR (0xEB),這種模式在資料傳輸時會用上全部四根I/O線(IO0-3),並且SCK可達最高頻率(通常133MHz),這種讀模式下Flash效能相當高。但有時候某些設計裡為了保證通用性(比如我們想要一個相容所有型別Flash型號的啟動頭),我們也會嘗試配置最基礎的讀模式 Normal Read (0x03),基礎的讀模式在資料傳輸時僅使用一根I/O線(IO1),並且SCK頻率通常最高50MHz,這種模式其實更多是為了相容SPI介面的EEPROM器件。

  Normal Read是任何序列NOR Flash都支援的讀模式,也是最簡單的一種模式,但在i.MXRT的FlexSPI外設裡配置這種模式會存在關於Dummy Cycle設定的一個小誤區,且聽痞子衡道來:

一、在FDCB裡使能Normal Read

  關於FDCB及lookupTable相關知識詳見痞子衡舊文 《從頭開始認識i.MXRT啟動頭FDCB裡的lookupTable》。現在我們嘗試準備一個使能Normal read的FDCB頭,Flash器件就以華邦W25Q64JWS-IQ為例,檢視其資料手冊,找到如下Normal read時序圖:

  從Normal read時序圖裡可以看出,其僅包含命令序列、地址序列、讀資料序列、停止序列共四個子序列,與Fast Read Quad I/O SDR時序相比少了模式序列和Dummy序列,因此示例FDCB如下。經i.MXRT1050-EVKB板子實測,這個示例FDCB是可以正常用於啟動的。

const flexspi_nor_config_t qspiflash_config = {
    .memConfig =
        {
            .tag              = FLEXSPI_CFG_BLK_TAG,
            .version          = FLEXSPI_CFG_BLK_VERSION,
            // 低速情況下可以使用LoopbackInternally
            .readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackInternally,
            .csHoldTime       = 3u,
            .csSetupTime      = 3u,
            .controllerMiscOption = 0x10,
            .deviceType       = kFlexSpiDeviceType_SerialNOR,
            // 實際上這裡不管設定1Pad/2Pads/4Pads,在iomuxc裡都會配置IO0-3
            .sflashPadType    = kSerialFlash_1Pad,
            // 配置SCK頻率不要超過50MHz
            .serialClkFreq    = kFlexSpiSerialClk_50MHz,
            .sflashA1Size     = 8u * 1024u * 1024u,
            .lookupTable =
                {
                    // Normal Read LUTs
                    // 包含四個子序列,且全是通過 FLEXSPI_1PAD 傳輸
                    [4*CMD_LUT_SEQ_IDX_READ + 0] = FLEXSPI_LUT_SEQ(CMD_SDR,   FLEXSPI_1PAD, 0x03, RADDR_SDR, FLEXSPI_1PAD, 0x18),
                    [4*CMD_LUT_SEQ_IDX_READ + 1] = FLEXSPI_LUT_SEQ(READ_SDR,  FLEXSPI_1PAD, 0x04, STOP,      FLEXSPI_1PAD, 0x00),
                },
        },
    .pageSize           = 256u,
    .sectorSize         = 4u * 1024u,
    .blockSize          = 64u * 1024u,
    .isUniformBlockSize = false,
};

  按照文章 《實抓Flash訊號波形來看i.MXRT的FlexSPI外設下AHB讀訪問情形(無快取)》 第二小節裡的軟硬體測試環境,我們測試無快取下的 memcpy((void *)0x20200000, (void *)0x60002400, 8); 語句執行在Flash端時序如下(為便於捕捉Flash訊號,實際測試時SCK頻率降到了30MHz):

二、關於Dummy Cycle的小誤區是什麼?

  在配置Fast Read Quad I/O SDR時序的lookupTable裡,我們常常會根據不同的Flash器件特性在Dummy子序列裡填入不同的Cycle數值。現在我們配置的是Normal read時序,有人可能會保留Dummy子序列,但是將其引數值設0(如下程式碼所示),根據字面理解,這樣似乎也沒問題,但在FlexSPI外設裡,這樣是不行的,這就是關於Dummy Cycle的誤區。

#include "fsl_flexspi.h"

#define NOR_CMD_LUT_SEQ_IDX_READ_NORMAL 0

uint32_t s_customLUT_wrong[4] = {
    /* Normal read mode -SDR */
    [4*NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 0] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR,       kFLEXSPI_1PAD, 0x03, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x18),
    // 保留kFLEXSPI_Command_DUMMY_SDR序列,但引數值填0
    [4*NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 1] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_1PAD, 0x00, kFLEXSPI_Command_READ_SDR,  kFLEXSPI_1PAD, 0x04),
    [4*NOR_CMD_LUT_SEQ_IDX_READ_NORMAL + 2] = FLEXSPI_LUT_SEQ(kFLEXSPI_Command_STOP,      kFLEXSPI_1PAD, 0x00, 0, 0, 0),
};

三、Dummy Cycle設0的誤區帶來什麼後果?

  使用第二小節裡的 s_customLUT_wrong[] 去配置FlexSPI LUT到底會產生什麼後果,我們繼續在文章 《實抓Flash訊號波形來看i.MXRT的FlexSPI外設下AHB讀訪問情形(無快取)》 第二小節裡的軟硬體測試環境下抓一下時序圖。可先借助SDK裡flexspi驅動如下兩個函式來更新LUT,因為是在XiP環境下執行的ramfunc程式碼,所以無需再從頭初始化FlexSPI模組。

#include "fsl_flexspi.h"

/* Update LUT table. */
FLEXSPI_UpdateLUT(FLEXSPI, 0, s_customLUT_wrong, 4);

/* Do software reset. */
FLEXSPI_SoftwareReset(FLEXSPI);

  現在我們在IAR下線上除錯看看結果,當使用 s_customLUT_wrong 更新掉FlexSPI的LUT後,Flash的訪問立刻出現了異常,memory視窗觀察到的數值全部變成了0xFF, 並且拷貝目的地內部RAM相應地址處也全是0xFF,說明 memcpy 語句並沒有產生預想效果(但此時 ramfunc 程式碼是能正常往下執行的)。

  抓出Flash端波形,我們發現僅8位元組資料的 memcpy 竟然產生了長達 33ms 的讀時序,放大最前面的時序,可以看到命令(0x03)、地址(0x002400)、初始讀出資料(0x01、0x02、0x03...)都是正常的,並且確實沒有Dummy Cycle子序列,但是後面的時序就完全異常了,此時FlexSPI外設內部狀態機已然錯亂,這也是開發環境memory視窗無法再看到真實Flash資料的原因。

  至此,i.MXRT中FlexSPI外設lookupTable裡配置Normal read的一個小誤區痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

文章會同時釋出到我的 部落格園主頁CSDN主頁知乎主頁微信公眾號 平臺上。

微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

相關文章