痞子衡刚刚拿到i.MXRT1170 B0版本的芯片,迫不及待地在上面跑了一些A0版本上早已验证过的demo,功能一切正常,没有什么额外迁移工作。因为目前只有B0版本芯片,没有配套EVK,所以痞子衡是在RT1170内部Validation板上做测试的(RT主芯片以及Flash芯片全部放在Socket里的,非常方便更换),正好痞子衡最近整理工位,找到了非常多来自不同厂家的串行Flash样片,何不趁此时顺便测一下Serial NOR启动时间,毕竟Serial NOR是i.MXRT启动首选设备,启动时间肯定是大家比较感兴趣的。
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是恩智浦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才会开始,搬移时间会长。
2.3 特别备注
因为此次拿到的B0版本芯片是刚出厂的,芯片校正值没有烧录(校正值一般放在eFuse里),而实际芯片POR之后会有校正的过程,会带来额外的Boot Time开销。下面是痞子衡此次测试的样片里的eFuse值:
至此,恩智浦i.MX RT1170 FlexSPI NOR启动时间痞子衡便介绍完毕了,掌声在哪里~~~