痞子衡嵌入式:在i.MXRT啟動頭FDCB裡使能序列NOR Flash的Continuous read模式

痞子衡發表於2021-05-19

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是在FDCB裡使能序列NOR Flash的Continuous read模式

  前面關於序列Flash傳輸時序的文章 《Fast Read Quad I/O SDR模式》《Fast Read Quad I/O DTR模式》, 痞子衡介紹的其實都屬於經典SPI工作模式大類下的Non-Continuous read傳輸模式,即任何獨立的Fast Read Quad I/O讀資料時序(一次CS低有效期間),都必須由Command子序列(命令碼0xEB/0xEC/0xED/0xEE)先行,且不管是SDR還是DTR模式,命令碼都是要在8個SCK週期內由IO0訊號進行傳輸(別小看這8個SCLK週期,對於小資料塊讀取時序,它在總傳輸時間裡佔比是不可忽視的)。

  我們知道在XIP情況下CPU從Flash裡取指令資料往往是非常隨機且零碎無序的,這時候雖然有L1 Cache和和FlexSPI Prefetch Buffer加速,但如果還想再進一步提升訪問效能,就只能從Flash底層傳輸序列裡想辦法了。Flash讀時序裡有五大子序列CMD + ADDR + MODE + DUMMY + READ,其中除了CMD和DUMMY子序列是固定的,其他子序列引數值都可能會變,會變的就不能被優化,所以只能想辦法在CMD和DUMMY子序列裡做文章。今天痞子衡要介紹的Continuous read模式就是拿CMD子序列開刀:

一、什麼是Continuous read模式?

  Continuous read顧名思義就是連續讀。在序列Flash世界裡,連續讀的意思是讀傳輸時序裡除了第一次CS有效期必須傳輸Command子序列,其後的讀傳輸時序裡均省去Command子序列。下面痞子衡結合i.MXRT的FlexSPI外設來對比介紹Non-Continuous read與Continuous read模式的區別:

1.1 FlexSPI的XIP Enhanced Mode

  我們知道NOR Flash因為支援主裝置隨機讀取其任意地址處的資料,因此從原理上可以用作XIP裝置。但因為是序列介面,所以不能直接XIP(沒有獨立並行地址線,CPU無法直接定址),需要FlexSPI外設在底層完成AHB匯流排讀訪問的實時響應工作,這個實時響應工作就是FlexSPI的XIP特性。

  FlexSPI的XIP特性可以支援任意序列NOR Flash,對Flash廠商設計沒要求。為了提升XIP程式碼執行效率,FlexSPI中也整合了XIP Enhanced Mode特性(其實就是Continuous read模式),見下圖,CS1是包含CMD子序列的讀時序(即第一次CS),CS2/3(包括後續所有CS)相比CS1少了CMD子序列,這就是Continuous read訪問時序。

  FlexSPI的XIP Enhanced Mode特性並不能夠用於任意序列NOR Flash,這對Flash廠商設計有要求,必須Flash本身支援Continuous read模式才行

1.2 Fast Read Quad I/O Continuous read時序

  瞭解了XIP Enhanced Mode,我們再來看LUT裡Quad I/O Read SDR Continuous read傳輸序列,它由CMD_SDR + RADDR_SDR + MODE8_SDR + DUMMY_SDR + READ_SDR + JMP_ON_CS + STOP七個子序列組成,如下表所示。

  這個Continuous read傳輸序列相比Non-Continuous read傳輸時序主要有兩處區別:

1. 原MODE8_SDR子序列裡引數值不同:這個引數值用於通知Flash器件當前傳輸型別(Non-Continuous read/Continuous read),具體數值由Flash廠商定義。下圖是以Cypress S25FS-S系列Flash為例的,0xA0表明Flash需進入/保持Continuous read模式。
2. 新增了JMP_ON_CS子序列:該子序列是FlexSPI外設實現Continuous read的核心,第一次CS有效傳輸時序裡CMD_SDR子序列命令碼會被自動存在該子序列引數值裡,這樣後續傳輸FlexSPI就不用再發命令碼了。

  LUT中Quad I/O Read DDR Continuous read傳輸序列如下,差異與前面SDR下的分析一致,這裡不予贅述。

二、不同Flash廠商關於Continuous read特性設計

  現在跟著痞子衡去看幾家主流Flash廠商關於Continuous read特性的設計(如果你想快速確認某一款型號Flash是否支援這個特性,找到其資料手冊搜尋"Continuous read"看有沒有如下時序圖):

2.1 賽普拉斯S25FS-S系列

  MODE子序列裡引數值M[7:4]通過包含/不包含Command子序列來控制下一次讀傳輸時序的長度,M[7:4] = 0xA則進入/保持Continuous Read模式,否則不進入/退出。

2.2 Adesto AT25SL系列

  MODE子序列裡引數值M[7:4] = 0xA則進入/保持Continuous Read模式,否則不進入/退出。

2.3 芯成IS25WP系列

  MODE子序列裡引數值M[7:4] = 0xA則進入/保持AX Read模式(就是Continuous Read),否則不進入/退出。

2.4 華邦W25QxxJV-DTR系列

  MODE子序列裡引數值M[5:4] = 2'b10則進入/保持Continuous Read模式,否則不進入/退出。 如果要退出Continuous Read模式,Flash資料手冊裡特別推薦下一次時序裡命令碼臨時設為0xFF,以保證M4=1使得Flash徹底回到Non-Continuous Read模式。

2.5 兆易創新GD25Q系列

  MODE子序列裡引數值M[5:4] = 2'b10則進入/保持Continuous Read模式,否則不進入/退出。

三、在i.MXRT1170-EVK上實戰(IS25WP128)

  瞭解了上面關於Continuous read模式知識後,我們在恩智浦i.MXRT1170-EVK板子上實踐一下。預設連線的Flash是IS25WP128,這款Flash是支援Continuous read模式的,我們隨便在SDK包裡找一個XIP例程,修改工程裡 evkmimxrt1170_flexspi_nor_config.c 檔案裡的 FDCB 啟動頭如下(主要就是改LUT表),改完下載程式進Flash執行,程式碼執行效率應該會有所提升(等下一篇QPI模式文章寫完,痞子衡會設計一個用例一起來實測下效能)。

const flexspi_nor_config_t qspiflash_config_100mhz_sdr_cont = {
    .memConfig =
        {
            .tag              = FLEXSPI_CFG_BLK_TAG,
            .version          = FLEXSPI_CFG_BLK_VERSION,
            .readSampleClkSrc = kFlexSPIReadSampleClk_LoopbackFromDqsPad,
            .csHoldTime       = 3u,
            .csSetupTime      = 3u,
            // Enable Safe configuration
            .controllerMiscOption = 0x10,
            .deviceType           = kFlexSpiDeviceType_SerialNOR,
            .sflashPadType        = kSerialFlash_4Pads,
            .serialClkFreq        = kFlexSpiSerialClk_100MHz,
            .sflashA1Size         = 16u * 1024u * 1024u,
            .lookupTable =
                {
                    // Fast Read Quad I/O LUTs
                    [4*CMD_LUT_SEQ_IDX_READ + 0] = FLEXSPI_LUT_SEQ(CMD_SDR,   FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
                                                                   // MODE8_SDR裡引數值填入0xA0
                    [4*CMD_LUT_SEQ_IDX_READ + 1] = FLEXSPI_LUT_SEQ(MODE8_SDR, FLEXSPI_4PAD, 0xA0, DUMMY_SDR, FLEXSPI_4PAD, 0x04),
                                                                                                  // 增加JMP_ON_CS子序列
                    [4*CMD_LUT_SEQ_IDX_READ + 2] = FLEXSPI_LUT_SEQ(READ_SDR,  FLEXSPI_4PAD, 0x04, JMP_ON_CS, FLEXSPI_1PAD, 0x01),
                    [4*CMD_LUT_SEQ_IDX_READ + 3] = FLEXSPI_LUT_SEQ(STOP,      FLEXSPI_1PAD, 0x00, 0, 0, 0),
                },
        },
    .pageSize           = 256u,
    .sectorSize         = 4u * 1024u,
    .blockSize          = 256u * 1024u,
    .isUniformBlockSize = false,
};

  至此,在FDCB裡使能序列NOR Flash的Continuous read模式痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

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

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

相關文章