天天看点

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程

我们需要摸清i.MXRT启动串行NOR Flash设备到底是怎样的初始化流程,搞清这个流程,将来定位启动问题才能游刃有余

  大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程。

  从外部串行NOR Flash启动问题是i.MXRT系列开发最高频的话题,无论是开发调试XIP应用程序阶段还是最终产品量产阶段都绕不开NOR Flash选型以及为它设计一个匹配的FDCB配置块。如果不了解FDCB是什么,先去看痞子衡之前的文章 《Bootable image格式与加载》。

  实际开发过程中,影响串行NOR Flash正常下载/启动的因素有很多,痞子衡已经写过三篇:《16MB以上使用不当因素》、《SFDP因素》、《QE bit因素》,列举了三个不同因素,当然这都是出了问题,具体调试分析才定位出来的,显然还有很多未知因素等待陆续被发掘。

  如果总是被动去解决问题,那问题是解不完的。不如我们主动出击,摸清i.MXRT启动串行NOR Flash设备到底是怎样的初始化流程,搞清这个流程,将来定位启动问题才能游刃有余,话不多说,开始今天的主题。

备注:本文主角是i.MXRT1050,但内容也同样适用i.MXRT1020/1015,对于i.MXRT1010也算适用但有两处微小差别(冗余App启动支持,Flash上电等待时间处理)。

  我们知道外部串行NOR Flash是接到i.MXRT的FlexSPI外设引脚上,有时串行NOR Flash启动也叫FlexSPI NOR启动。关于FlexSPI NOR启动流程,i.MXRT1050参考手册System Boot章节有如下流图,蓝框之外的流程属于常规i.MXRT启动XIP App流程,是个通用流程。蓝框之内才是具体FlexSPI初始化步骤,这个步骤概括得比较精炼。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程

  为了让大家对FlexSPI NOR设备启动初始化流程有个更具体的概念,痞子衡重新画了一张更详细的流程图,图中灰底框里描述得是FlexSPI初始化流程,痞子衡将其分解成了六步,我们有必要深入这六步初始化流程。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程

  第一步是尝试复位Flash芯片,这步是可选的,在fuse_0x6e0[7]里配置,默认是不使能的。复位Flash目的是为了让Flash处于一个确定的初始状态,方便i.MXRT BootROM去配置访问。为什么要强调Flash的初始状态,因为很多时候i.MXRT未必是冷启动(上电启动),也有可能是软复位启动(比如调用NVIC_SystemReset),这时候外部Flash已经被软复位前执行过的BootROM甚至用户App配置过,因此Flash的状态可能不是上电初始状态(一般来说板级设计里Flash的RESET#引脚要么悬空,要么连接i.MXRT的POR#引脚),这可能会影响软复位后BootROM去再次配置启动这块不定态的Flash。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程

  正常的Flash都提供了RESET#引脚来实现跟上电复位一样的功能,对于普通8-pin的QSPI Flash,这个RESET#引脚往往是跟信号线IO3复用的(仅在QE bit没使能情况下有效),而对于16-pin的QSPI Flash或者HyperFlash,其RESET#引脚都是独立的。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程

  BootROM就是借助了Flash的RESET#引脚来实现的复位操作,实现代码比较简单,i.MXRT1050 BootROM直接指定了GPIO1[9]当做复位信号线,板级设计里需要你将GPIO1[9]连到Flash的RESET#引脚,然后BootROM就是简单地拉低GPIO1[9]即可。RESET#信号都是低电平有效,BootROM直接拉低这个信号持续250us,这个低电平持续时间对于复位来说是够够的,很多Flash数据手册里其实仅要求几us即可。

备注:对于BootROM的Flash复位功能来说,主要适用有独立RESET#引脚的Flash。

  第二步是准备一个初始的FDCB配置块(即flexspi_nor_config_t,大小为512字节),这个初始FDCB配置块将被用来做FlexSPI外设的第一次初始化,目的是为了能够保证FlexSPI初始化之后CPU能够使用AHB方式正常读取Flash(访问性能不要求最高,但求稳定访问)。这个初始FDCB并不是一个完全定死的配置块,部分值也是根据fuse来配置的,一共有三处fuse位置,其中最重要的是FLASH_TYPE:

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程

  初始FDCB配置块中仅给memConfig设了值,这个memConfig才是用于配置FlexSPI外设本身。如下部分赋值是固定的FDCB设置,不受fuse影响,从这个固定配置你可以看到,BootROM假定了所有外接Flash都是128MB,且访问时钟(SCK)速度能支持30MHz,不要对这个假定感到焦虑,它只是用于FlexSPI第一次初始化,目的只求能正常访问Flash前4KB即可:

  然后便是从fuse里获取flashType,根据具体flashType来对初始FDCB配置块做进一步动态赋值,这进一步赋值才用于区分不同Flash种类(Pad数量、DQS信号属性、最重要的lookupTable等)。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程

  上图中最重要的FDCB赋值是config.memConfig.lookupTable,它是FlexSPI外设需要的核心配置,有了这个配置,CPU便可以直接从AHB总线读取Flash的内容,因为FlexSPI会自动解析AHB总线读请求然后翻译成具体FlexSPI读时序,底层读时序需要的命令、地址字节数、DUMMY周期都在lookupTable里。BootROM预存了如下6大类Flash的lookupTable:

  第三步就是利用上述配置完成的初始FDCB块对FlexSPI外设进行第一次初始化,就是下面代码,这个流程跟官方SDK里的flexspi_nor_flash_init()大同小异,这里不予具体展开。如果在这里初始化就返回失败(这里一般不会失败,因为仅仅是FlexSPI外设自身初始化,并不涉及操作外部Flash芯片的动作),BootROM则直接退出FlexSPI NOR设备启动,转入SDP下载。

  上述第一次FlexSPI初始化一般都会成功的,但这并不代表fuse里的flashType等配置跟板子上Flash型号是匹配的,也就是说初始FDCB配置块此时还没有被充分验证其是否适用板载Flash型号。

  FlexSPI第一次初始化结束后,为了保证后续能正常AHB访问,BootROM里做了一些善后工作,主要是两件事:

做一些访问前的延时:根绝fuse 0x450[3:2] - HOLD TIME来调用microseconds_delay()做延时,以使FlexSPI外设完全准备好。 做一次无效AHB访问:类似这样的代码 volatile uint32_t dummy = *(uint32_t *)0x60000000;,无效AHB读可以使Flash退出continuous read模式

  善后工作结束之后,此时CPU应该可以通过AHB正常访问Flash了,这个阶段我们只需要从Flash的偏移0地址处读取用户FDCB,验证用户FDCB是否存在,这里才是对前面初始FDCB配置块以及第一次FlexSPI外设初始化的真正考验。

  验证用户FDCB是否存在就是简单读取FDCB的前四个字节(tag),验证这个tag是否合法。如果第一次验证tag不成功(有可能是FlexSPI配置不正确,也有可能是用户FDCB不存在),会尝试做一次三字节地址切换到四字节地址的LUT更新(仅适用QSPI Flash),然后做第二次tag读取验证,如果此时还是验证失败(大概率是不存在用户FDCB了),BootROM则直接退出FlexSPI NOR设备启动,转入SDP下载。

  上面代码里有flexspi_clear_cache()操作,这个其实就是利用FLEXSPI0->MCR0[SWRESET]做一个外设级别的软复位,另外代码里还涉及到一个四字节地址QSPI Flash的LUT表,即如下所示:

  到了这里,基本代表第一次FlexSPI初始化是正确且可用的,并且能够拿到有效的用户FDCB配置块。这时候就是利用用户FDCB配置块对FlexSPI外设做第二次初始化,初始化代码流程跟第一次初始化是一模一样的。

  这个第二次初始化是非常有必要的,因为它反映了用户的真实需求,用户FDCB配置块里会准确描述板载Flash的全面特性(访问速度,真实存储空间大小,特殊定制LUT等等),这些信息必须由用户来提供。

  需要注意的是,第二次FlexSPI初始化返回成功并不代表用户FDCB配置块一定就是正确的,还是那句话,这仅仅是对FlexSPI外设自身的初始化。后续常规App解析流程里才是对这个用户FDCB配置块的真正考验。

  至此,深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程痞子衡便介绍完毕了,掌声在哪里~~~

文章会同时发布到我的 博客园主页、CSDN主页、知乎主页、微信公众号 平台上。

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

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程

  最后欢迎关注痞子衡个人微信公众号【痞子衡嵌入式】,一个专注嵌入式技术的公众号,跟着痞子衡一起玩转嵌入式。

痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程
痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程
痞子衡嵌入式:深入i.MXRT1050系列ROM中串行NOR Flash启动初始化流程

  衡杰(痞子衡),目前就职于恩智浦MCU系统部门,担任嵌入式系统应用工程师。

  专栏内所有文章的转载请注明出处:http://www.cnblogs.com/henjay724/

  与痞子衡进一步交流或咨询业务合作请发邮件至 [email protected]

  可以关注痞子衡的Github主页 https://github.com/JayHeng,有很多好玩的嵌入式项目。

  关于专栏文章有任何疑问请直接在博客下面留言,痞子衡会及时回复免费(划重点)答疑。

  痞子衡邮箱已被私信挤爆,技术问题不推荐私信,坚持私信请先扫码付款(5元起步)再发。