痞子衡嵌入式:一個關於Segger J-Flash在Micron Flash固定區域下載校驗失敗的故事(SR暫存器BP[x:0]位)

2022-10-01 06:00:31

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家講的是一個關於Segger J-Flash在Micron Flash固定區域下載校驗失敗的故事

  痞子衡最近在支援一個 i.MXRT1170 歐美客戶,客戶專案裡選用了來自 Micron 的四線 NOR Flash - MT25QL256ABA8E12-0AAT 作為啟動裝置,一般讀寫倒是沒有問題,但是在 Segger J-Flash 下燒寫遇到了特定區域內校驗失敗的問題。

  從痞子衡過往豐富的 Flash 支援經驗來看,亞太區客戶一般選用 ISSI(芯成)/Winbond(華邦)/MXIC(旺宏)/GigaDevices(兆易創新) 的 Flash 比較多,痞子衡對這些廠商 Flash 可以說是門清了。這個歐美客戶選用的是痞子衡不太熟的 Micron(鎂光) 產品,藉著這個問題,痞子衡帶大家一起稍微深入地瞭解下 Micron Flash 產品:

一、引出客戶問題

  首先是復現下客戶的問題,痞子衡找了塊 MIMXRT1170-EVK 開發板,將板載其他廠商 Flash 換成這顆 MT25QL256ABA8E12-0AAT(因為是 T-PBGA24 封裝,所以需要放到原來的 OctalFlash 位置 - U21),然後將 \SDK_2.11.1_MIMXRT1170-EVK\boards\evkmimxrt1170\driver_examples\flexspi\nor\polling_transfer 例程稍作適配性修改,主要是將 customLUT 裡的命令表按 Micron 資料手冊命令表做調整(全用了四位元組地址命令),然後跑了一下例程發現基本的 Flash 讀寫擦操作沒有問題(預設操作的是 0x14000 處的 Sector),這表明硬體修改沒有問題。

const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
    /* Fast read quad mode - SDR */
    [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR,       kFLEXSPI_1PAD, 0xEC, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_4PAD, 0x20),
    [4 * NOR_CMD_LUT_SEQ_IDX_READ_FAST_QUAD + 1] = 
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_DUMMY_SDR, kFLEXSPI_4PAD, 0x0a, kFLEXSPI_Command_READ_SDR,  kFLEXSPI_4PAD, 0x04),

    /* Erase Sector */
    [4 * NOR_CMD_LUT_SEQ_IDX_ERASESECTOR] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR,       kFLEXSPI_1PAD, 0xDC, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x20),

    /* Page Program - quad mode */
    [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR,       kFLEXSPI_1PAD, 0x34, kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, 0x20),
    [4 * NOR_CMD_LUT_SEQ_IDX_PAGEPROGRAM_QUAD + 1] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 0x04, kFLEXSPI_Command_STOP,      kFLEXSPI_1PAD, 0x00),
};

  接下來就是按客戶操作流程來複現 Segger J-Flash 燒寫校驗失敗問題,客戶其實是嘗試燒寫全部 32MB 資料來檢視 J-Flash 及其配套下載演演算法能否適用這顆 Flash,這裡痞子衡就用 《超級下載演演算法RT-UFL v1.0》,經過測試,確實復現了客戶的問題。經過反覆測試,定位了問題是這顆 Micron 32MB 的 Flash 前 3/4 區域(0x0 - 0x17FFFFF)是沒問題的,但是在後 1/4 區域(0x1800000 - 1FFFFFF)均會出現校驗錯誤(J-Flash軟體裡看擦寫操作是能進行的,但後面發現其實根本沒有正常擦寫)。

二、Micron QuadSPI NOR Flash有什麼不同?

  在分析客戶問題之前,我們先來簡單認識一下這顆 Micron NOR Flash,痞子衡瀏覽了 Micron 的官網以及這顆 Flash 的資料手冊,發現它確實跟其他廠商的 NOR Flash 設計有點區別。

  首先是 Flash 容量,其他廠商一般都是能夠提供從 512Kb 到 2Gb 全範圍的 Flash 產品,但是 Micron 序列 NOR Flash 最小容量就是 128Mb,果然是國際 Memory 大廠,設計就是豪橫。但是從 Flash 作為 XIP 啟動裝置角度而言,128Mb 其實挺多的,普通的嵌入式專案沒有這麼大的程式碼儲存需求。

  其次是 NOR Flash 裡的高頻問題 《QE bit 設計》,一般 Flash 的 IO2/3 引腳複用功能都是通過內部狀態暫存器裡的 QE 位來控制,QE 關閉則 IO2/3 是 RESET#/HOLD#/WP# 功能:如果 QE 開啟則 IO2/3 用於資料傳輸(這種情況下才可以用 Quad I/O 相關命令)。然而 Micron Flash 根本就沒有 QE 位控制,IO2/3 功能主要靠當前命令型別來決定:如果是 Single SPI 或者 Dual I/O SPI 命令,則 IO2/3 是 RESET#/HOLD#/WP# 功能;如果是 Quad I/O SPI 命令,則 IO2/3 用於傳輸資料。

  其它設計上的區別就不再詳細展開了,等用到具體功能檢視資料手冊再去了解對比。

三、找到問題原因

  現在來分析客戶問題,Flash 後 1/4 區域在 J-Flash 下校驗錯誤,那我們先修改 polling_transfer 例程去操作 0x1800000 之後的 Sector,發現確實跑不過。如果不是 Flash 媒介問題,也不是讀寫擦命令問題,那隻能有一種解釋,那就是 Flash 裡這個區域被保護了,Flash 裡是有非易失暫存器可以設定軟體保護的,但是預設應該是全部區域不保護,而第一小節裡我們先跑了 polling_transfer 例程驗證 Flash 讀寫,那大概率這個例程裡有修改 Flash 內部暫存器操作,經過排查痞子衡定位到了 flexspi_nor_enable_quad_mode() 函數。

#define FLASH_QUAD_ENABLE            0x40U

const uint32_t customLUT[CUSTOM_LUT_LENGTH] = {
    /* Enable Quad mode */
    [4 * NOR_CMD_LUT_SEQ_IDX_WRITESTATUSREG] =
        FLEXSPI_LUT_SEQ(kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, 0x01, kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_1PAD, 0x04),
};

int main(void)
{
    // 程式碼省略

    /* Enter quad mode. */
    status = flexspi_nor_enable_quad_mode(EXAMPLE_FLEXSPI);
    if (status != kStatus_Success)
    {
        return status;
    }

    // 程式碼省略
}

  第二小節介紹裡我們知道 Micron Flash 是沒有 QE 位設計的,因此 flexspi_nor_enable_quad_mode() 函數在這裡是多餘的,這個函數是將 0x40 寫入到了命令標號為 0x01 的 Status Register(這個操作適用於 ISSI Flash),我們在資料手冊裡找到這個暫存器定義,發現被置位的 bit 6 是塊保護控制位 BP[3:0] 裡的最高位,並且 BP[3:0] 設定是非易失性的(斷電不丟失)。

  再進一步往下找 BP[3:0] 設定與 Flash 空間對應關係,發現 4'b1000 設定就是保護後 1/4 區域裡的所有 block,至今似乎真相大白了。為了驗證發現,我們需要將 Status Register 重設為 0x00,然後再用 J-Flash 燒寫一次,這時候校驗失敗問題消失了,一切恢復正常。

  回顧這個故事,如果痞子衡事先不用 polling_transfer 例程去操作一次 Flash,或者即使跑了例程但事先意識到了 Micron Flash 沒有 QE 設計而刪除 flexspi_nor_enable_quad_mode() 函數,也就無法復現客戶問題了,這也是本次故事裡最神奇的地方,客戶和痞子衡犯了同樣的失誤,也許這就是緣分?

  至此,一個關於Segger J-Flash在Micron Flash固定區域下載校驗失敗的故事痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

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

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