大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是Octal或Hyper Flash上DQS信號(hào)與Dummy Cycle聯(lián)系。
關(guān)于在 i.MXRT 上啟動(dòng) NOR Flash 時(shí)如何設(shè)置正確的 Dummy Cycle 值,痞子衡一共寫(xiě)過(guò)四篇文章:《IS25WP系列Dummy Cycle設(shè)置》、《IS25LP系列Dummy Cycle設(shè)置》、《Dummy Cycle設(shè)置為0的誤區(qū)》、《DTR模式下Dummy Cycle設(shè)置》, 這四篇文章都是針對(duì)普通 QuadSPI 型 Flash 而言的(一般沒(méi)有 DQS 信號(hào))。而如果在 i.MXRT 上啟動(dòng)的是包含 DQS 信號(hào)的 Octal Flash 或者 Hyper Flash,此時(shí) Dummy Cycle 設(shè)置有什么不同之處呢?今天痞子衡就和大家聊聊這個(gè)話題:
一、Flash讀時(shí)序中DQS與Dummy Cycle作用
我們知道對(duì)于普通 QuadSPI 型 Flash,在 FlexSPI 模塊 LUT 里配置讀時(shí)序時(shí),其中 Dummy Cycle 子序列中填的值必須要與 Flash 端的 Dummy Cycle 嚴(yán)格一致,否則會(huì)發(fā)生時(shí)序錯(cuò)亂(如下圖 Extended 時(shí)序所示,圖中是單線模式,四線模式類(lèi)似)。
Flash 里一般都會(huì)開(kāi)放寄存器給用戶(hù)去配置 Dummy Cycle 值,F(xiàn)lash 工作頻率越高,所需的最小 Dummy Cycle 也越大(可以理解為 Flash 存儲(chǔ)體從接收到讀命令開(kāi)始到輸出有效數(shù)據(jù)這一段時(shí)間間隔是恒定的,而我們衡量時(shí)間的基準(zhǔn)是連接到 Flash 的 SCK,SCK 頻率越高,相同間隔內(nèi)所需 SCK 周期數(shù)就越多)。
Note1: 簡(jiǎn)單來(lái)說(shuō),Dummy Cycle 就是 Flash 響應(yīng)主機(jī)每一次讀時(shí)序所需要的準(zhǔn)備時(shí)間,在 NOR Flash 上這個(gè)時(shí)間是固定且可設(shè)的,跟訪問(wèn)地址無(wú)關(guān)。
Note2: 一個(gè)確定的 Dummy Cycle 值決定了 Flash 上限工作頻率,但此時(shí) Flash 并不是只能在這個(gè)上限頻率下工作,低于這個(gè)上限頻率均可以。
DQS 信號(hào)正常是為 OctalSPI / HyperBus 型 Flash 工作在八線 DTR 模式下同步 DQ[7:0] 線輸出而生的(見(jiàn)上圖 Octal DDR 時(shí)序),關(guān)于其基本概念詳見(jiàn)痞子衡舊文 《DQS信號(hào)簡(jiǎn)介》。
Note: 在 Hyper Flash 上負(fù)責(zé) DQS 功能的信號(hào)是 RWDS。
當(dāng) OctalSPI / HyperBus 型 Flash 工作在 Octal DDR 模式下時(shí),DQS/RWDS 信號(hào)會(huì)向主設(shè)備(這里指 i.MXRT)提示 DQ[7:0] 何時(shí)有效,所以這時(shí)候 DQS 信號(hào)其實(shí)也兼?zhèn)淞?Dummy Cycle 的作用。不過(guò)考慮到有時(shí)候主設(shè)備端不一定會(huì)使能 DQS 信號(hào),Dummy Cycle 的存在仍然是有必要的。
二、FlexSPI外設(shè)里DQS和Dummy Cycle聯(lián)系
在 《FlexSPI外設(shè)的LUT機(jī)制》 和 《DTR模式下Dummy Cycle設(shè)置》 兩篇文章里有詳細(xì)的關(guān)于 FlexSPI 外設(shè)中 Dummy Cycle 設(shè)置方法和 DQS 引腳功能配置方法介紹,但是這兩者是怎樣的聯(lián)系關(guān)系呢?
我們?cè)?i.MXRT 參考手冊(cè) FlexSPI 章節(jié)可以找到如下 Hyper Bus 讀時(shí)序示意圖(對(duì)于 Octal Flash 也基本適用,僅微小區(qū)別),這張圖很清晰地闡述了 RWDS 信號(hào)與 Latency Count 的聯(lián)系,F(xiàn)lexSPI 外設(shè)在發(fā)起實(shí)際讀時(shí)序時(shí)一定會(huì)輸出 DUMMY_DDR 子序列里實(shí)際配置的延時(shí)周期,但如果配置的延時(shí)周期結(jié)束后,RWDS 有效信號(hào)還沒(méi)有到來(lái),F(xiàn)lexSPI 會(huì)自動(dòng)插入足夠的延時(shí)周期(即圖中所謂的 Additional Latency count)直到 RWDS 信號(hào)有效。
Note: 在 Hyper Flash 上不用 Dummy Cycle 術(shù)語(yǔ),其術(shù)語(yǔ)是 Latency Count。
基于這樣的設(shè)計(jì),當(dāng)在 FlexSPI 里使能外部 DQS 信號(hào)時(shí),我們?cè)?DUMMY_DDR 子序列里只要象征性地填一個(gè)比 Flash 里 Latency Count 稍小的值就行了,在一些 i.MXRT 型號(hào)上理想情況下甚至可以去除 DUMMY_DDR 子序列(即延時(shí)周期 配 0),但切記這個(gè)值不應(yīng)配得比 Flash 里 Latency Count 大。
三、在i.MXRT1170上實(shí)測(cè)MT35XU512
最近恩智浦 SE 團(tuán)隊(duì)做了一個(gè)基于 i.MXRT1170 的 Auto Development Platform 原型板,在 FlexSPI1 上掛的是來(lái)自 Micron 的 Octal Flash - MT35XU512,這顆 Flash 作為代碼存儲(chǔ)與啟動(dòng)設(shè)備。我們就在這個(gè)原型板上測(cè)試一下 FlexSPI 外設(shè)的 DQS 與 Dummy Cycle 不同配置能否去正常啟動(dòng) Flash。
3.1 MT35XU512基本情況
首先看一下這顆 Octal Flash 的基本情況,主要關(guān)注 DQS 和 Dummy Cycle 方面。Flash 內(nèi)部有 256 個(gè) 8bit 的配置寄存器(address 從 0 - 255),其中 address 0 配置寄存器用于設(shè)置 Flash 工作模式(我們需要設(shè)為 0xE7,開(kāi)啟 Octal DDR 且需要 DQS),address 1 配置寄存器用于設(shè)置 Dummy Cycle(可保持初值 0x00 不變,即使用默認(rèn) Dummy Cycle 值)。
再來(lái)看一下這顆 Octal Flash 所支持的讀命令,根據(jù)工作模式不同一共有 10 種命令,我們選用最后一條命令 4-byte DDR Octal I/O Fast Read(命令值 0xFD),這條讀命令可訪問(wèn)全部 Flash 空間且性能最高,其對(duì)應(yīng)的默認(rèn) Dummy Cycle 是 16。
默認(rèn) 16 的 Dummy Cycle 能支持多高的 Flash 工作頻率呢,在下表里可找到答案,前面我們選擇的是 DDR Octal I/O Fast Read 命令,所以對(duì)應(yīng)最高工作頻率可達(dá) 171MHz。雖然 Flash 本身可跑 200MHz DDR,但是 i.MXRT1170 FlexSPI 外設(shè)最大支持到 166MHz DDR,這就是在前面保持 Flash 中 address 1 配置寄存器值為默認(rèn) Dummy Cycle 的原因,默認(rèn) Dummy Cycle 配置已經(jīng)夠用了。
3.2 測(cè)試啟動(dòng)頭FDCB
基于上面對(duì) Octal Flash 的認(rèn)識(shí),我們很容易給出如下可用于啟動(dòng)的 FDCB 頭,這個(gè)頭里使能了 FlexSPI 端的外部 DQS 使用(octalflash_config.memConfig.readSampleClkSrc),開(kāi)啟了 Flash 端的 Octal DDR 模式(octalflash_config.memConfig.deviceModeArg),LUT 里第一條時(shí)序配置的是 0xFD 讀命令,并且 DUMMY_DDR 子序列等效配置的是 3 個(gè) Dummy Cycle,低于 Flash 里實(shí)際 16 個(gè) Dummy Cycle,一切都符合上文的分析,這個(gè)啟動(dòng)頭在板子上實(shí)測(cè)是可以工作的。
const flexspi_nor_config_t octalflash_config = {
.memConfig =
{
.tag = FLEXSPI_CFG_BLK_TAG,
.version = FLEXSPI_CFG_BLK_VERSION,
.readSampleClkSrc = kFlexSPIReadSampleClk_ExternalInputFromDqsPad,
.csHoldTime = 3,
.csSetupTime = 3,
.deviceModeCfgEnable = 1,
.deviceModeType = kDeviceConfigCmdType_Spi2Xpi,
.waitTimeCfgCommands = 1,
.deviceModeSeq =
{
.seqNum = 1,
.seqId = 6,
.reserved = 0,
},
.deviceModeArg = 0xE7, /* Enable octal DDR mode */
.controllerMiscOption =
(1u << kFlexSpiMiscOffset_SafeConfigFreqEnable) | (1u << kFlexSpiMiscOffset_DdrModeEnable),
.deviceType = kFlexSpiDeviceType_SerialNOR,
.sflashPadType = kSerialFlash_8Pads,
.serialClkFreq = kFlexSpiSerialClk_166MHz,
.sflashA1Size = 64ul * 1024u * 1024u,
.busyOffset = 0u,
.busyBitPolarity = 0u,
.lookupTable =
{
/* 4-BYTE DDR OCTAL I/O FAST READ */
[0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_8PAD, 0xFD, RADDR_DDR, FLEXSPI_8PAD, 0x20),
// 這里 DUMMY_DDR 里填入的值是 0x6,對(duì)應(yīng) 3 個(gè) SCK 周期的 dummy
[1] = FLEXSPI_LUT_SEQ(DUMMY_DDR, FLEXSPI_8PAD, 0x6, READ_DDR, FLEXSPI_8PAD, 0x04),
/* Read Status */
[4 * 1 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x05, READ_SDR, FLEXSPI_1PAD, 0x04),
/* Write Enable */
[4 * 3 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x06, STOP_EXE, FLEXSPI_1PAD, 0x00),
/* Enable Octal DDR mode */
[4 * 6 + 0] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x81, CMD_SDR, FLEXSPI_1PAD, 0x00),
[4 * 6 + 1] = FLEXSPI_LUT_SEQ(CMD_SDR, FLEXSPI_1PAD, 0x00, CMD_SDR, FLEXSPI_1PAD, 0x00),
[4 * 6 + 2] = FLEXSPI_LUT_SEQ(WRITE_SDR, FLEXSPI_1PAD, 0x01, STOP_EXE, FLEXSPI_1PAD, 0x00),
},
},
.pageSize = 256u,
.sectorSize = 4u * 1024u,
.serialNorType = 0x2,
.blockSize = 128u * 1024u,
.isUniformBlockSize = false,
};
現(xiàn)在我們做多一些實(shí)驗(yàn),修改上述啟動(dòng)頭里的 readSampleClkSrc、serialClkFreq 和 DUMMY_DDR 子序列值,其余配置保持不變,測(cè)試結(jié)果如下。這個(gè)結(jié)果基本是符合第二小節(jié)里關(guān)于DQS和Dummy Cycle聯(lián)系關(guān)系的總結(jié)的。
至此,Octal或Hyper Flash上DQS信號(hào)與Dummy Cycle聯(lián)系痞子衡便介紹完畢了,掌聲在哪里~~~