痞子衡嵌入式:恩智浦i.MXRT1xxx系列MCU启动那些事(11.0)FlexSPINOR启动时间(RT1170)

编程

痞子衡刚刚拿到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才会开始,搬移时间会长。

  至此,恩智浦i.MX RT1170 FlexSPI NOR启动时间痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

文章会同时发布到我的 云海天主页、CSDN主页、微信公众号 平台上。

微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

原文链接:https://www.cnblogs.com/henjay724/archive/2020/06/14/13125636.html

以上是 痞子衡嵌入式:恩智浦i.MXRT1xxx系列MCU启动那些事(11.0)FlexSPINOR启动时间(RT1170) 的全部内容, 来源链接: utcz.com/z/517445.html

回到顶部