痞子衡剛剛拿到i.MXRT1170 B0版本的晶元,迫不及待地在上面跑了一些A0版本上早已驗證過的demo,功能一切正常,沒有什麼額外遷移工作。因為目前只有B0版本晶元,沒有配套EVK,所以痞子衡是在RT1170內部Validation板上做測試的(RT主晶元以及Flash晶元全部放在Socket里... ...
大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是恩智浦i.MX RT1170 FlexSPI NOR啟動時間。
痞子衡剛剛拿到i.MXRT1170 B0版本的晶元,迫不及待地在上面跑了一些A0版本上早已驗證過的demo,功能一切正常,沒有什麼額外遷移工作。因為目前只有B0版本晶元,沒有配套EVK,所以痞子衡是在RT1170內部Validation板上做測試的(RT主晶元以及Flash晶元全部放在Socket里的,非常方便更換),正好痞子衡最近整理工位,找到了非常多來自不同廠家的串列Flash樣片,何不趁此時順便測一下Serial NOR啟動時間,畢竟Serial NOR是i.MXRT啟動首選設備,啟動時間肯定是大家比較感興趣的。
關於i.MXRT1170啟動時間,痞子衡之前在A0版本上測過 《SEMC NAND啟動時間》,有了之前的測試基礎,本篇文章就是照葫蘆畫瓢。不過由於Serial NOR的特殊性,本文會同時測XIP和Non-XIP時間,以及兩種典型的Flash工作模式下(四線SDR,八線DDR)的時間,工作量要稍微大一些,讓我們開始吧。
一、準備工作
1.1 知識儲備
Serial NOR可以說是大家最熟悉的啟動設備了,雖然這個設備可以支持兩類App(XIP和Non-XIP)去啟動,但大家用得最多的無疑是XIP App,因為XIP下App代碼長度可以和Flash容量一樣大,這對於複雜功能的應用很重要,但是編寫XIP App代碼也有一些需要註意的地方,比如在配置系統時鐘(不能影響FlexSPI模塊)或者擦寫Flash時(不支持RWW的話需要拷貝到RAM里執行)有一些限制。
至於Non-XIP,相比XIP會多一個App拷貝過程,啟動時間難免會變長。拷貝目標設備選擇種類很多,可以是內部RAM(包含TCM和OCRAM),也可以是外部RAM(SDRAM或者HyperRAM)。如果是為了提高代碼執行效率,通常會搬移到內部TCM里執行。當然也有搬移到外部SDRAM執行的,不過這種情況需要額外利用DCD功能來完成SEMC模塊的初始化之後才能做搬移工作。
1.2 時間界定
關於時間終點,參考《SEMC NAND啟動時間》 里的1.2節,方法保持一致。而關於時間起點,本次的測試選點做了一些優化,測NAND啟動時為了圖方便選在了最靠近POR引腳的電壓轉換器NC7SP125P5X的輸入腳(Pin1)所在的Header上,但是我們知道任何一個被動電源器件都有轉換時間,為了儘可能精確測量啟動時間,我們應該消除這種誤差,因此本次選點放在了NC7SP125P5X的輸出腳(Pin4),這個腳與主晶元POR引腳是直連的。
為了讓大家對電源器件轉換時間有個深刻感受,痞子衡這次還特地量了一下Validation板上原始電源輸入(5V Jack)到POR引腳上電的時間,這個時間足有210ms,根據電源電路設計以及器件選型的不同,這個時間是不同的,所以應該從啟動時間里拋除出來。
1.3 製作應用程式
關於應用程式製作,依舊是參考《SEMC NAND啟動時間》 里的1.3節,只有一個微小改進,就是把翻轉GPIO的代碼放在SystemInit()函數最前面,儘可能地靠近Reset_Handler。
void SystemInit (void) {
{
CLOCK_EnableClock(kCLOCK_Iomuxc);
gpio_pin_config_t led_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_03_GPIO9_IO02, 0U);
GPIO_PinInit(GPIO9, 2, &led_config);
GPIO_PinWrite(GPIO9, 2, 1u);
}
// 關開門狗和SysTick
while (1);
// ...
}
1.4 下載應用程式
應用程式的下載需藉助痞子衡開發的NXP-MCUBootUtility工具(v2.3版本及以上),本次痞子衡一共測試了兩款Flash,針對不同的Flash,在下載時選擇的模型不一樣:
下麵模型適用華邦W25Q256系列,配置成了四線、SDR、133MHz工作模式去啟動:
下麵模型適用旺巨集MX25UM51345系列,配置成了八線、DDR、166MHz工作模式去啟動:
1.5 示波器抓取信號
一切準備就緒,可以用示波器抓Serial NOR啟動時間了。通道一監測原始5V電源輸入信號,通道二監測晶元POR信號,通道三來監測Flash片選信號(FSPI1A_SS0_B),通道四監測LED GPIO信號。
二、開始測試
2.1 測試結果
在公佈結果之前,痞子衡先帶大家分析一下示波器抓取的啟動時間波形,方便大家理解後續表格裡的各項組成。
先來看大家相對陌生的Non-XIP啟動的波形(MX25UM51345G,247KB App)。通道二連接POR引腳,電平拉高是啟動計時的開始,啟動後會先經歷BootROM時間(CM7內核先執行ROM代碼,做一些常規系統初始化,讀取用戶啟動配置,然後配置好FlexSPI模塊),底下再經歷BootFlash時間(還是在ROM里執行,不過此時開始訪問外部Flash,從Flash里讀取FDCB、IVT、BootData以及搬移App,所以你會看到通道三(Flash的片選信號)上會有持續的波形變化,搬移完成之後便跳轉到App里執行),最後你會看到通道四電平拉高了(App在執行)。
作為比較,再來看一下XIP啟動的波形(MX25UM51345G,246KB App)。BootROM時間跟Non-XIP基本差不多,這是可以理解的,同樣的ROM代碼在執行,消耗的機器周期是不變的。BootFlash的時間明顯縮短了,Flash片選的波形只有屈指可數的幾次,這是因為ROM此時只需要讀取FDCB、IVT、BootData,根據IVT里的鏈接地址信息得知App不需要搬移就直接跳轉了。
分析完了啟動時間組成,讓我們看結果吧。痞子衡基於Flash工作模式、App長度、App執行地址的組合一共做了8個測試,結果如下表所示(註:表中結果都是在1.25M次/秒的採樣率下所得):
Flash型號 Timing模式 |
App長度 (bytes) |
App執行位置 | BootROM時間 | BootFlash時間 | 總啟動時間 |
---|---|---|---|---|---|
W25Q256J 4bit, SDR, 133MHz |
16390 | XIP | 6.926 ms | 1.611 ms | 8.537 ms |
17922 | ITCM | 6.939 ms | 2.203 ms | 9.142 ms | |
251910 | XIP | 6.920 ms | 1.612 ms | 8.532 ms | |
253442 | ITCM | 6.953 ms | 8.795 ms | 15.748 ms | |
MX25UM51345G 8bit, DDR, 166MHz |
16390 | XIP | 6.942 ms | 1.618 ms | 8.560 ms |
17922 | ITCM | 6.944 ms | 2.312 ms | 9.256 ms | |
251910 | XIP | 6.916 ms | 1.647 ms | 8.563 ms | |
253442 | ITCM | 6.935 ms | 8.897 ms | 15.832 ms |
2.2 結果分析
從上面表格裡的結果我們可以得到如下三個結論:
- 結論1:不管是哪種Flash連接,BootROM時間差不多是固定的,大概在6.9ms
- 結論2:XIP啟動的情況下,BootFlash時間幾乎也是固定的,跟App長度無關,大概在1.6ms
- 結論3:Non-XIP啟動的情況下,BootFlash時間跟App長度成正比,但是跟Flash工作模式(速度)不是正比(甚至可以說關係不太大)
關於結論3里的BootFlash時間跟Flash工作模式(速度)不是正比這點有必要展開研究一下。痞子衡的測試結果是ROM從Flash拷貝247KB數據到ITCM,無論是從QSPI Flash拷貝還是從Octal Flash拷貝所花時間竟然幾乎是一致的,這個看起來挺奇怪的,畢竟僅從Flash自身讀訪問速度而言,Octal Flash應該是QSPI Flash的五倍(8bit x 2 x 166MHz) / (4bit x 1 x 133MHz)。
為瞭解開謎題,痞子衡對時序圖裡CS信號做了進一步分析,下圖是QSPI Flash的啟動時序圖,ROM拷貝247KB的數據耗時約7.833ms,每個CS周期是114.4us,扣除時序前期的空閑時間以及讀Boot Header,拷貝App期間共有62個CS周期,那麼每個CS周期實際拷貝了4KB數據,這代表ROM配置了FlexSPI prefetch buffer的長度為4KB(RT1170最大是4KB,RT1060最大是1KB)並且使能了Prefetch功能。從QSPI Flash本身速度理論計算,讀4KB數據應該耗時 4KB / (4bit x 133MHz) = 61.59us,這與實際測量的CS信號的低電平時間是吻合的。再來看CS信號周期的高電平(idle)時間足有52.8us,為什麼會有這麼長的空閑時間?疑問先放在這裡。
同樣的方法再來分析一下Octal Flash的啟動時序圖。從Octal Flash本身速度理論計算,讀4KB數據應該耗時 4KB / (8bit x 2 x 166MHz) = 12.33us,這與實際測量的CS信號的低電平時間依然是吻合的。結合上面分析的QSPI Flash CS低有效時間來看,兩者確實是五倍的關係。但是此時的CS信號周期的高電平時間比QSPI Flash下的時間要更長,達到了100.47us,最終導致兩種不同性能Flash下拷貝時間差不多。
分析到這裡,我們已經找到了線索,ROM從Flash prefetch buffer里拷貝4KB數據到TCM固定耗時約112us,因此速度瓶頸不在Flash本身讀速率,而在於搬移時的開銷,那麼是什麼導致了這個固定開銷?
因為ROM代碼是個黑盒子,我們看不見,痞子衡為了找到這個系統開銷,在Octal Flash Non-XIP啟動的App里用memcpy做了同樣的數據搬移。根據上面表格裡的結果,我們知道ROM里搬移230KB數據需耗時6.576ms,經測試App里搬移230KB數據僅需3.265ms,ROM和App的區別主要是執行效率不一樣(ROM預設配置的CPU主頻是400MHz(註:最高可以配到696MHz),App配置的CPU主頻是996MHz),所以CPU主頻是影響固定開銷的因素。
memcpy((void *)0x6000, (const void *)0x30002000, 230 * 1024);
因為Non-XIP App沒有為FlexSPI映射地址開啟cache,痞子衡特地開了cache再次做了測試,這次拷貝230KB數據僅需724us,這個值幾乎已經逼近了理論計算值(230KB/4KB) x 12.33us = 708.9us,所以ROM是在沒有使能cache下做的數據搬移,Cache是否使能也是影響固定開銷的因素。
//#if defined(XIP_EXTERNAL_FLASH) && (XIP_EXTERNAL_FLASH == 1)
/* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back. */
MPU->RBAR = ARM_MPU_RBAR(7, 0x30000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_RO, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_16MB);
//#endif
這個發現也告訴我們使用memcpy()函數搬移Flash數據,是否使能cache對執行效率影響非常大。使能cache之後,做數據搬移時,CPU往TCM寫數據與cache從Flash里預取數據可以更大程式的並行,並且cache的讀都是burst操作,能加速搬移。而如果不使能cache,下一次的Flash讀需要等待上一次CPU寫完TCM才會開始,搬移時間會長。
至此,恩智浦i.MX RT1170 FlexSPI NOR啟動時間痞子衡便介紹完畢了,掌聲在哪裡~~~
歡迎訂閱
文章會同時發佈到我的 博客園主頁、CSDN主頁、微信公眾號 平臺上。
微信搜索"痞子衡嵌入式"或者掃描下麵二維碼,就可以在手機上第一時間看了哦。