痞子衡嵌入式:藉助Serial Plot軟體測量i.MXRT系列FlexSPI驅動Flash頁程式設計執行時間

痞子衡發表於2021-11-01

  大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是i.MXRT系列FlexSPI驅動Flash頁程式設計執行時間

  痞子衡之前寫過一篇文章 《序列NOR Flash的頁程式設計模式對於量產效率的影響》,簡要分析了 NOR Flash 的 Page Program 命令不同模式對於整體量產時間的影響,文章僅從理論計算角度做了分析,假定了 Flash 中所有 Page 擦寫表現都是一致的,但是每個 Page 的表現真的是完全一致嗎?今天我們從一個客戶問題出發來探討下這個話題:

一、引入客戶問題

  最近有一個 i.MXRT1170 客戶反饋,他們的應用程式裡 IAP 功能程式碼對於 Flash 擦寫表現不穩定。他們的 IAP 程式碼就是移植的 \SDK_2.10.0_MIMXRT1170-EVK\boards\evkmimxrt1170\driver_examples\flexspi\nor\polling_transfer 例程,Flash 選用得跟官方 EVK 上一樣的型號 IS25WP128-JBLE,測試程式碼會把整個 Flash 的 16MB 迴圈擦除寫入,反覆進行測試,在測試過程中發現的部分割槽域表現速度較慢,這個慢的定義是在部分 256 位元組(一個 Page)寫入時,寫入 API 返回時間較長(因為是輪詢模式),但是返回狀態是正確的。

  由於客戶並沒有進一步給出 Page 寫入快慢時間分別是多少,痞子衡只能先盲猜。既然寫入 API 返回狀態是正確的,那說明 FlexSPI 驅動是能正常工作的,先排除板級硬體設計問題。那麼只剩下兩種可能:一、FlexSPI 軟體驅動執行穩定性問題;二、Flash 本身 Page 表現一致性問題。這兩個問題都可以通過觀察統計全部 Page 的寫入時間來進一步確認。對於第二個可能性,從 Flash 手冊裡我們可以得知 Page 寫入命令的等待時間典型值是 0.2ms,最大值是 0.8ms,但這個表述並沒有明確這是針對不同 Flash 晶片而言,還是針對同一 Flash 內不同 Page 而言。

二、確定測量方案

  帶著上述疑問,痞子衡決定在官方 MIMXRT1170-EVK 上實測一下,我們僅需簡單改造一下 \SDK_2.10.0_MIMXRT1170-EVK\boards\evkmimxrt1170\driver_examples\flexspi\nor\polling_transfer 例程,在 flexspi_nor_polling_transfer.c 原始檔中 main() 函式里加入計時程式碼統計 flexspi_nor_flash_page_program() 函式執行時間即可,其中計時實現可用 https://github.com/JayHeng/microseconds 專案,具體用法參考 《通用微秒(microseconds)計時函式框架設計與實現》 一文。

// 儲存 65536 個 Page 的寫入 API 執行時間
uint16_t timeRes[65536];

int main(void)
{
    // 省略原 Flash 初始化、擦除程式碼

    microseconds_init();

#if !(defined(XIP_EXTERNAL_FLASH))
    uint32_t startAddr = 0;
#else
    uint32_t startAddr = 0x8000;
#endif
    uint32_t endAddr = 0x1000000;
    while (startAddr < endAddr)
    {
        // 計時開始
        uint64_t startTicks = microseconds_get_ticks();
        uint64_t endTicks = startTicks;
        uint64_t deltaTicks = 0;
        status_t status = flexspi_nor_flash_page_program(FLEXSPI1, startAddr, (void *)s_nor_program_buffer);
        if (status == kStatus_Success)
        {
            // 計時結束
            endTicks = microseconds_get_ticks();
            deltaTicks = endTicks - startTicks;
            uint16_t costMicroseconds = microseconds_convert_to_microseconds(deltaTicks);
            timeRes[startAddr / 256] = costMicroseconds;
        }
        startAddr += 256;
    }

    for (uint32_t i = 0; i < sizeof(timeRes) /sizeof(uint16_t); i++)
    {
        PRINTF("%d\r\n", timeRes[i]);
    }
    
    while (1)
    {
    }
}

三、選一款串列埠波形顯示軟體

  上一節程式碼中,我們把所有 Page 的寫入時間都通過串列埠列印了出來,現在需要一款串列埠波形顯示軟體,來直觀地看這 65536 個時間結果的差異。痞子衡試用了好幾款軟體:Serial Plot v0.12.0、Serial Chart V034、Serial Hunter V31,發現做得最完善的是 Serial Plot 軟體,推薦給大家:

  Serial Plot 軟體做得最好的地方是對串列埠接收資料格式的完善支援,既可以是 Binary(單通道位元組長度可設),也可以是 ASCII 碼(通道間隔符可設),還可以是自定義資料幀(幀頭、幀格式可設),通道數也可以任意設,基本上可以滿足大部分串列埠波形顯示需求了。

四、測試結果分析

  準備就緒,給板卡通上電,將測試程式下載進去跑起來,開啟 Serial Plot 設定好串列埠接收引數後觀測結果,我們發現波形顯示是一條直線,即 65536 個 Page 寫入時間是穩定的,都是 271us(測試工程選擇的是 debug build),這個結果推翻了我們之前的兩個猜測,寫入 API 執行時間是穩定的,Flash 的各 Page 表現也是一致的。後來跟客戶進一步溝通,客戶反饋他們是在 ThreadX 的 LevelX 中發現的,所以看起來客戶問題和 ThreadX 系統排程有關,那就是另外一個話題了,以後再展開。

  至此,i.MXRT系列FlexSPI驅動Flash頁程式設計執行時間痞子衡便介紹完畢了,掌聲在哪裡~~~

歡迎訂閱

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

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

相關文章