大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是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 軟體原始碼:https://github.com/hyOzd/serialplot
- Serial Plot 軟體安裝包:https://serialplot.ozderya.net/downloads/serialplot-0.12.0-win32-setup.exe
Serial Plot 軟體做得最好的地方是對串列埠接收資料格式的完善支援,既可以是 Binary(單通道位元組長度可設),也可以是 ASCII 碼(通道間隔符可設),還可以是自定義資料幀(幀頭、幀格式可設),通道數也可以任意設,基本上可以滿足大部分串列埠波形顯示需求了。
四、測試結果分析
準備就緒,給板卡通上電,將測試程式下載進去跑起來,開啟 Serial Plot 設定好串列埠接收引數後觀測結果,我們發現波形顯示是一條直線,即 65536 個 Page 寫入時間是穩定的,都是 271us(測試工程選擇的是 debug build),這個結果推翻了我們之前的兩個猜測,寫入 API 執行時間是穩定的,Flash 的各 Page 表現也是一致的。後來跟客戶進一步溝通,客戶反饋他們是在 ThreadX 的 LevelX 中發現的,所以看起來客戶問題和 ThreadX 系統排程有關,那就是另外一個話題了,以後再展開。
至此,i.MXRT系列FlexSPI驅動Flash頁程式設計執行時間痞子衡便介紹完畢了,掌聲在哪裡~~~
歡迎訂閱
文章會同時釋出到我的 部落格園主頁、CSDN主頁、知乎主頁、微信公眾號 平臺上。
微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。