大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是同一廠商不同系列Flash型號下Dummy Cycle設定方法的差異。
上一篇文章 《在i.MXRT啟動頭FDCB裡調整Flash工作頻率也需同步設Dummy Cycle》, 痞子衡是以i.MXRT1170-EVK上板載Flash型號IS25WP128為例來介紹Dummy Cycle設定的。最近痞子衡在支援一個i.MXRT1020客戶的問題,需要用到i.MXRT1020-EVK,這個板載Flash是IS25LP064A,跟IS25WP128一樣是來自同一Flash廠商ISSI的QSPI NOR產品,痞子衡想當然地認為之前的經驗可以直接用在這顆Flash上,於是把FDCB原封不動地拷貝過來直接使用,但是發現i.MXRT1020竟然啟動不了,這是怎麼回事?
一、同一廠商不同系列Flash型號Dummy Cycle設定差異
ISSI(芯成半導體)是一個比較老牌的儲存器廠商,規模上不算頂級,但旗下Flash產品線眾多,品類很齊全。其中序列NOR產品涵蓋QuadSPI NOR、Octal Flash、Twin Quad NOR、HyperFlash等。
ISSI Flash種類: https://www.issi.com/US/product-flash.shtml
恩智浦官方EVK板上選用的是IS25xP系列,屬於最常用的QuadSPI NOR大類。這個系列主要分兩大類:3.3V供電的IS25WP系列、1.8V供電的IS25LP系列。
前面我們對IS25WP系列Flash的Dummy Cycle設定很瞭解了,那麼IS25LP系列Flash是不是一樣的設計呢?我們檢視IS25LP064A資料手冊來確認一下。
我們找到如下Read Dummy Cycle與最大工作頻率的對應表,從表裡可以看到當IS25LP工作在Fast Read Quad I/O模式時,預設的6個Dummy Cycle適用的最大工作頻率是104MHz(這點上與IS25WP系列是一致的),不過與IS25WP系列不同的是IS25LP系列Dummy Cycle僅有四檔(2bit設定,對應4/6/8/10四種值),而IS25WP系列Dummy Cycle有十五檔(4bit設定,對應1-15取值),所以Dummy Cycle設計在IS25LP上其實是精簡版。
二、如何更改Flash裡的Dummy Cycle?
意識到IS25LP與IS25WP在Dummy Cycle設計上的差異,改起來就容易了。我們繼續看Flash資料手冊,IS25LP064A內部有個8bit的Read Register,其bit4-bit3是Dummy Cycles設定(精簡設計一),暫存器型別裡標明僅易失性一種屬性(精簡設計二)。
在IS25LP064A的指令集表裡,可以看到專門寫Read Register的指令,即SRP指令,注意指令值就是唯一的0xC0(精簡設計三)。
分析到這裡,額外的小工程修改Dummy Cycle是不可能了,只能老老實實在i.MXRT每次啟動時直接藉助FDCB啟動頭裡的設定用SRP指令更改Flash的Dummy Cycle,即如下所示:
// 設定Dummy Cycle數
#define FLASH_DUMMY_CYCLES 8
#define FLASH_DUMMY_VALUE 0x2
// 寫Read Register時序在LUT中的index(可自定義位置,但不要佔BootROM預設的幾個時序位置)
#define CMD_LUT_SEQ_IDX_SET_READ_PARAM 7
// BootROM中預設的LUT命令時序的index
#define CMD_LUT_SEQ_IDX_READ 0
#define CMD_LUT_SEQ_IDX_READSTATUS 1
#define CMD_LUT_SEQ_IDX_WRITEENABLE 3
const flexspi_nor_config_t qspiflash_config = {
.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_133MHz,
.sflashA1Size = 8u * 1024u * 1024u,
// 使能Flash暫存器配置操作
.configCmdEnable = 1u,
.configModeType[0] = kDeviceConfigCmdType_Generic,
// 指示Flash暫存器配置時序在LUT中index
.configCmdSeqs[0] =
{
.seqNum = 1,
.seqId = CMD_LUT_SEQ_IDX_SET_READ_PARAM,
.reserved = 0,
},
// 設定Flash暫存器配置值(這裡就是寫入Read Register的值)
// Note1: 這裡寫入Read Register的值在IS25WP系列和IS25LP系列有區別
.configCmdArgs[0] = FLASH_DUMMY_VALUE << 3,
.lookupTable =
{
// Fast Read Quad I/O
[4*CMD_LUT_SEQ_IDX_READ] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xEB, RADDR_SDR, FLEXSPI_4PAD, 0x18),
[4*CMD_LUT_SEQ_IDX_READ + 1] = FLEXSPI_LUT_SEQ(MODE8_SDR, FLEXSPI_4PAD, 0x00, DUMMY_SDR, FLEXSPI_4PAD, FLASH_DUMMY_CYCLES-2),
[4*CMD_LUT_SEQ_IDX_READ + 2] = FLEXSPI_LUT_SEQ(READ_SDR, FLEXSPI_4PAD, 0x04, STOP, FLEXSPI_1PAD, 0x00),
// READ STATUS REGISTER
[4*CMD_LUT_SEQ_IDX_READSTATUS] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x01),
[4*CMD_LUT_SEQ_IDX_READSTATUS + 1] = FLEXSPI_LUT_SEQ(STOP, FLEXSPI_1PAD, 0x00, 0, 0, 0),
// WRTIE ENABLE
[4*CMD_LUT_SEQ_IDX_WRITEENABLE] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP, FLEXSPI_1PAD, 0x00),
// Flash暫存器配置時序(這個時序需要上面READ STATUS, WRITE ENABLE的配合)
// Note2: 這裡寫入的指令在IS25WP系列和IS25LP系列有區別
[4*CMD_LUT_SEQ_IDX_SET_READ_PARAM] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0xC0, WRITE_SDR, FLEXSPI_1PAD, 0x01),
[4*CMD_LUT_SEQ_IDX_SET_READ_PARAM + 1] = FLEXSPI_LUT_SEQ(STOP, FLEXSPI_1PAD, 0x00, 0, 0, 0),
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.blockSize = 64u * 1024u,
.isUniformBlockSize = false,
};
至此,同一廠商不同系列Flash型號下Dummy Cycle設定方法的差異痞子衡便介紹完畢了,掌聲在哪裡~~~
歡迎訂閱
文章會同時釋出到我的 部落格園主頁、CSDN主頁、知乎主頁、微信公眾號 平臺上。
微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。