2026/10/12 8:28:59

i.MX RT系列FlexSPI NOR连接方式详解:从引脚分配到Boot ROM启动配置

i.MX RT系列FlexSPI NOR连接方式详解:从引脚分配到Boot ROM启动配置 1. 从一块点不亮的板子说起FlexSPI NOR连接方式为什么值得单独聊搞i.MX RT系列的朋友大概率都经历过这个场景板子打样回来焊上Flash上电串口一片安静仿真器连上去发现芯片卡在ROM阶段PC指针在一个莫名其妙的地址打转。你反复检查电源、复位、时钟都没问题最后发现是FlexSPI的引脚连接方式跟Boot ROM默认的配置对不上。这种问题不涉及任何高深算法纯粹是硬件连接和启动配置的匹配问题但它能让你的板子彻底变砖——连Boot ROM都进不去更别提下载程序了。i.MX RT1xxx系列最核心的卖点就是那颗FlexSPI控制器它让MCU可以直接从外部NOR Flash执行代码也就是所谓的XIPExecute In Place。但FlexSPI的灵活性也是一把双刃剑它支持多种连接方式包括单线、双线、四线、八线还有不同的端口分配方案。对于RT1015、RT1020、RT1050这几个经典型号来说虽然它们都带FlexSPI但引脚复用和默认启动配置各有差异导致很多人在硬件设计阶段就埋下了隐患。这篇文章主要面向正在用RT1015/1020/1050做产品开发的硬件工程师和嵌入式软件工程师尤其是那些第一次接触i.MX RT系列、对FlexSPI启动流程还不太熟悉的朋友。我会把FlexSPI NOR的连接方式从底层原理到实际配置全部拆开讲清楚包括不同型号之间的差异、Boot ROM的默认行为、硬件设计时需要注意的引脚分配以及实际调试中怎么快速定位连接问题。看完之后你至少能做到拿到一颗RT1050知道该把Flash接到哪些引脚上知道怎么配置Fuse和FlexSPI参数让芯片正常启动遇到启动失败时也知道从哪几个方向去排查。2. FlexSPI控制器的底层逻辑它到底是怎么跟NOR Flash对话的2.1 FlexSPI不是普通的SPI控制器很多人第一次看到FlexSPI这个名字会以为它就是普通SPI控制器的增强版能跑快一点而已。实际上FlexSPI的架构跟普通SPI有本质区别。普通SPI控制器通常只有一个移位寄存器发送和接收共用一条数据通道每次只能处理一位数据。而FlexSPI内部有多个并行的数据通道可以同时处理多位数据这就是它支持单线、双线、四线、八线模式的基础。更关键的是FlexSPI有一个叫做Lookup TableLUT的机制。普通SPI控制器你写个寄存器就能发数据但FlexSPI需要你预先在LUT里定义好各种Flash操作的指令序列比如读ID、读状态寄存器、页编程、扇区擦除等等。每条LUT表项包含指令码、操作码、数据线数量、时序参数等信息。Boot ROM在启动时会根据Fuse配置自动加载一套默认的LUT序列但如果你的Flash型号比较特殊或者连接方式跟默认配置不一致就需要自己修改LUT。这个设计的好处是FlexSPI可以适配几乎任何SPI NOR Flash因为不同厂商的Flash指令集可能有细微差异。坏处是配置起来比普通SPI复杂得多尤其是当你需要从Flash启动的时候LUT配置错了芯片根本跑不起来。2.2 NOR Flash的XIP执行原理XIP这个词听起来很高级其实原理并不复杂。NOR Flash的存储单元是并行访问的支持随机读取所以CPU可以直接从Flash地址空间取指令执行不需要先把代码拷贝到RAM里。i.MX RT1xxx把FlexSPI的地址空间映射到了固定的内存区域RT1050上是0x60000000开始的区域RT1020和RT1015略有不同。当CPU取指地址落在FlexSPI映射区域时FlexSPI控制器会自动发起一次读操作从NOR Flash读取数据返回给CPU。这个过程对CPU来说是透明的它以为自己访问的是普通内存。但这里有个关键点FlexSPI的读操作需要遵循NOR Flash的时序要求包括指令阶段、地址阶段、Dummy周期和数据阶段。如果Dummy周期设置不对读回来的数据就是错的CPU执行到错误指令就会跑飞。Boot ROM在启动阶段会先用最保守的方式读取Flash的前几个字节确认Flash存在并且能正常读取然后根据Fuse配置切换到更快的读模式。这个先慢后快的过程是理解FlexSPI启动的关键。2.3 单线、双线、四线、八线的本质区别FlexSPI支持的数据线数量直接决定了理论带宽。单线模式下每个时钟周期传输1位数据四线模式下传输4位八线模式下传输8位。以RT1050为例FlexSPI时钟最高可以跑到133MHz左右四线模式下理论带宽就是133M × 4 532Mbps八线模式下直接翻倍到1064Mbps。但数据线数量不是越多越好。八线模式需要Flash支持Octal SPI接口这类Flash通常价格更高、封装更大。而且八线模式下引脚占用更多PCB布线难度也更大。对于大多数应用来说四线模式已经足够满足需求RT1050在四线模式下从Flash执行代码的性能已经相当可观了。这里有个容易混淆的概念FlexSPI的通道和数据线不是一回事。FlexSPI有两个通道通道A和通道B每个通道可以独立连接一组Flash。但实际使用中大部分设计只用通道A通道B要么不用要么用来接第二片Flash做数据存储。通道A和通道B的引脚是分开的但共享同一套LUT和配置寄存器。3. RT1015/1020/1050的FlexSPI引脚分配差异别把型号搞混了3.1 RT1050的FlexSPI引脚布局RT1050是i.MX RT1xxx系列里最早推出的型号也是FlexSPI功能最完整的。它有两组FlexSPI引脚主组和副组。主组引脚分布在GPIO_SD_B1和GPIO_SD_B2这两个端口上副组引脚分布在GPIO_SPI和GPIO_B0端口上。主组引脚支持八线模式具体包括FLEXSPI_A_SCLK、FLEXSPI_A_SS0_B、FLEXSPI_A_DATA0到DATA7、FLEXSPI_A_DQS。其中DATA0到DATA3是四线模式用的DATA4到DATA7是八线模式额外需要的。DQS是数据选通信号八线模式和高速四线模式下需要用到。副组引脚只支持四线模式引脚包括FLEXSPI_B_SCLK、FLEXSPI_B_SS0_B、FLEXSPI_B_DATA0到DATA3。副组通常用来接第二片Flash或者当主组引脚被其他功能占用时的备选方案。RT1050的Boot ROM默认使用主组引脚并且默认配置为四线模式。如果你用的是八线Flash需要在Fuse里配置成八线模式Boot ROM才会去读DATA4到DATA7。3.2 RT1020的FlexSPI引脚精简RT1020定位比RT1050低一些FlexSPI引脚也做了精简。它只有一组FlexSPI引脚分布在GPIO_SD_B1和GPIO_SD_B2端口上跟RT1050的主组引脚位置类似但只支持四线模式没有八线模式的DATA4到DATA7和DQS。这意味着RT1020不能直接驱动八线Flash。如果你在RT1020上接了一片八线Flash只能当四线用或者用两个四线Flash拼成八线但Boot ROM不支持这种用法需要自己写启动代码。RT1020的FlexSPI时钟频率也比RT1050低一些最高大概100MHz左右。四线模式下理论带宽400Mbps对于大多数应用来说够用了。3.3 RT1015的FlexSPI特殊之处RT1015是这三个型号里最晚推出的定位最低但FlexSPI配置反而有一些特殊之处。它的FlexSPI引脚分布在GPIO_SD_B1和GPIO_SD_B2端口上支持四线模式引脚定义跟RT1020基本一致。但RT1015的Boot ROM默认配置跟RT1020有细微差别。RT1015默认的FlexSPI时钟分频系数不同导致启动时的Flash读取速度略有差异。这个差异在大多数情况下不影响启动但如果你用的Flash对时序要求比较严格可能需要调整Fuse配置。另外RT1015的FlexSPI不支持DQS信号这意味着它不能使用Flash的DQS输出来做数据选通只能靠内部采样时钟。在高速模式下这可能会限制最高可靠时钟频率。3.4 三个型号的引脚对比特性RT1050RT1020RT1015FlexSPI通道数2A/B1A1A最大数据线数8线4线4线DQS支持支持不支持不支持默认启动模式四线四线四线最高FlexSPI时钟~133MHz~100MHz~100MHz典型封装BGA196/144BGA144/100BGA100这个表格里的数据是基于常见配置的典型值实际最高时钟频率还跟芯片等级、温度范围、PCB布线质量有关。我在实际项目中遇到过RT1050在四线模式下跑到120MHz就开始出现读取错误的情况降到100MHz就完全稳定所以高速模式下一定要留足余量。4. 硬件设计阶段最容易踩的FlexSPI连接坑4.1 引脚复用冲突FlexSPI和其他外设抢引脚i.MX RT1xxx的引脚复用非常灵活但这也意味着FlexSPI的引脚可能跟其他外设冲突。比如RT1050的FLEXSPI_A_DATA0跟GPIO_SD_B1_08是同一个物理引脚如果你同时要用SD卡和FlexSPI就得仔细规划哪个功能用哪组引脚。我见过一个典型的设计错误工程师把FlexSPI接在了主组引脚上但同时又把LCD的数据线也分配到了GPIO_SD_B1端口结果LCD和Flash抢引脚两个都用不了。正确的做法是先把FlexSPI的引脚确定下来因为它是启动必需的优先级最高然后再分配其他外设。RT1050的FlexSPI主组引脚跟SD卡、LCD、以太网等外设都有复用关系。如果主组引脚被占用可以考虑用副组引脚但副组只支持四线模式而且Boot ROM默认不从副组启动需要在Fuse里配置。4.2 Flash的复位和写保护引脚怎么接SPI NOR Flash通常有RESET#和WP#写保护两个控制引脚。很多人在设计时图省事直接把这两个引脚拉高或者悬空。悬空是大忌因为Flash的RESET#和WP#是低电平有效悬空时电平不确定可能导致Flash随机复位或者写保护状态异常。正确的做法是RESET#通过一个10kΩ电阻上拉到VCC同时可以连接到MCU的一个GPIO上方便软件控制复位。WP#同样上拉到VCC如果不需要写保护功能直接上拉即可如果需要硬件写保护可以接到GPIO上。还有一个容易忽略的点Flash的VCC和VCCQIO电压要跟MCU的IO电压匹配。i.MX RT1xxx的FlexSPI IO电压通常是3.3V或1.8V取决于VCC_FLASH的供电。如果Flash是1.8V的而MCU的FlexSPI IO配置成了3.3V轻则通信不稳定重则烧毁Flash的IO引脚。4.3 PCB布线对FlexSPI信号完整性的影响FlexSPI在高速模式下对信号完整性很敏感。我见过不少板子原理图完全正确但Flash就是读不出来最后发现是PCB布线的问题。SCLK是FlexSPI里最关键的信号它是所有数据信号的参考时钟。SCLK的走线要尽量短尽量少打过孔并且要远离其他高速信号。如果SCLK和DATA线之间的长度差异太大会导致数据采样窗口偏移高速时就会出现误码。DQS信号在八线模式下尤其重要。DQS是Flash输出的数据选通信号FlexSPI用它来采样数据。DQS和DATA线之间的长度匹配要求更严格通常要求误差在±50mil以内。如果PCB空间允许最好把DQS和DATA线走在同一层参考同一个地平面。对于四线模式如果没有DQSFlexSPI靠内部采样时钟来读数据。这时候SCLK的质量就更加关键任何反射、振铃都会直接影响采样精度。建议在SCLK上串联一个22Ω到33Ω的电阻做阻抗匹配具体阻值可以根据实际波形调整。4.4 电源去耦和Flash的供电时序FlexSPI NOR Flash在擦写操作时电流会有较大波动尤其是页编程和扇区擦除的瞬间。如果电源去耦不充分电压跌落可能导致Flash操作失败甚至影响MCU的正常运行。每片Flash的VCC引脚旁边至少要放一个0.1μF的陶瓷电容尽量靠近引脚。如果Flash和MCU共用3.3V电源建议在Flash的VCC上再串联一个磁珠或者小电感隔离Flash操作对MCU电源的干扰。供电时序方面i.MX RT1xxx对Flash的供电没有特殊要求只要在MCU释放复位之前Flash已经上电并且稳定即可。但有些Flash在上电后需要一段初始化时间通常几百微秒到几毫秒如果MCU启动太快可能在Flash还没准备好就去读导致启动失败。这种情况下可以在Flash的VCC上加大电容延长上电时间或者在Boot ROM配置里增加启动延迟。5. Boot ROM的启动流程与Fuse配置芯片是怎么找到Flash的5.1 上电后的前几百个时钟周期发生了什么i.MX RT1xxx上电后CPU先从内部Boot ROM开始执行。Boot ROM的第一件事是读取Fuse配置确定启动设备类型。如果Fuse里配置的是FlexSPI NOR启动Boot ROM就会初始化FlexSPI控制器然后尝试读取Flash的前几个字节。具体来说Boot ROM会先用最保守的配置最低时钟、单线模式发送读ID指令确认Flash存在。如果读到了合法的Flash ID就认为Flash连接正常然后根据Fuse里的配置切换到更快的读模式加载Flash前4KB的数据到内部RAM最后跳转到用户代码执行。如果读ID失败Boot ROM会尝试其他启动设备比如SD卡、USB等。如果所有启动设备都失败芯片会进入串行下载模式等待上位机通过USB或者UART下载程序。5.2 关键Fuse位FlexSPI启动配置详解i.MX RT1xxx的Fuse里有一组专门用于FlexSPI启动配置的位地址在0x460附近。这些Fuse位决定了Boot ROM怎么初始化FlexSPI包括BOOT_CFG[7:4]选择启动设备类型FlexSPI NOR对应的是0b0001具体值参考芯片参考手册BOOT_CFG[3:0]选择FlexSPI的实例和端口比如通道A还是通道BFLEXSPI_NOR_CFG[31:0]FlexSPI NOR的详细配置包括时钟分频、数据线数量、Dummy周期等这些Fuse位在芯片出厂时都有默认值默认值通常配置为四线模式、中等时钟频率。如果你用的Flash跟默认配置匹配不需要改任何Fuse就能启动。但如果你的Flash需要八线模式或者需要特定的Dummy周期就必须烧写对应的Fuse。烧写Fuse是不可逆的操作烧错了芯片就废了。所以在烧写之前一定要反复确认配置值。我通常的做法是先在RAM里跑一段测试代码用FlexSPI的寄存器直接配置参数确认Flash能正常读写之后再把对应的配置值烧到Fuse里。5.3 不同Flash型号的Dummy周期计算Dummy周期是FlexSPI读操作里一个很容易搞错的参数。NOR Flash在收到读指令和地址之后需要一定的内部处理时间才能输出数据这段时间用Dummy周期来填充。Dummy周期不够读回来的数据就是错的Dummy周期太多浪费带宽但不会出错。Dummy周期的数量取决于Flash的型号和FlexSPI的时钟频率。以常见的W25Q系列Flash为例在四线快速读模式下当FlexSPI时钟为100MHz时通常需要6到8个Dummy周期。具体值可以查Flash的数据手册里面会有一个表格列出不同时钟频率对应的Dummy周期数。如果数据手册里没有明确给出可以通过实验来确定先用一个较大的Dummy周期值比如10确认能正常读取然后逐步减小直到出现读取错误再回退一个值就是安全的Dummy周期。5.4 从串行下载模式恢复砖机的操作步骤如果Fuse配置错了芯片启动失败但还没有完全变砖可以尝试进入串行下载模式恢复。具体步骤是把BOOT_CFG引脚配置成串行下载模式通常是所有BOOT引脚拉低或者拉高具体参考芯片手册上电用USB线连接PC和板子的USB OTG接口打开上位机工具识别到芯片后下载一个临时的Flashloader程序到RAM用Flashloader程序重新烧写正确的Fuse配置或者Flash内容断电把BOOT_CFG引脚改回FlexSPI启动模式重新上电这个流程的关键是芯片的Boot ROM还没有被破坏只要Boot ROM能运行就有恢复的可能。但如果Fuse里把Boot ROM的访问权限也禁用了那就真的没救了只能换芯片。6. 实操调试FlexSPI连接问题的排查链路6.1 第一步确认Flash是否被识别板子上电后如果串口没输出先别急着怀疑代码。用示波器或者逻辑分析仪抓一下FlexSPI的SCLK引脚看启动瞬间有没有时钟波形。如果有波形说明Boot ROM至少在尝试跟Flash通信如果没有波形可能是Fuse配置不对Boot ROM根本没初始化FlexSPI。如果有波形但启动还是失败接下来抓DATA0引脚看Flash有没有返回数据。正常的读ID操作Flash会在收到指令后返回一个字节的制造商ID和设备ID。如果DATA0上没有任何响应说明Flash没有工作检查Flash的供电、复位引脚、片选信号。6.2 第二步用FlexSPI寄存器手动读取Flash ID如果硬件连接看起来没问题但Boot ROM就是读不到Flash可以写一段简单的测试代码直接操作FlexSPI寄存器来读Flash ID。具体步骤是// 使能FlexSPI时钟 CCM-CCGR3 | CCM_CCGR3_FLEXSPI_CLK_MASK; // 配置FlexSPI引脚复用 IOMUXC-SW_MUX_CTL_PAD[FLEXSPI_A_SCLK] 0x01; // ... 其他引脚类似配置 // 复位FlexSPI控制器 FLEXSPI-MCR | FLEXSPI_MCR_SWRSTSD_MASK | FLEXSPI_MCR_SWRSTHD_MASK; while (FLEXSPI-MCR FLEXSPI_MCR_SWRSTSD_MASK); // 配置LUT读取Flash ID FLEXSPI-LUT[0] 0x0A1804EB; // 读ID指令序列 FLEXSPI-LUT[1] 0x00000000; // 发起IP命令 FLEXSPI-IPCR0 0x00000000; FLEXSPI-IPCR1 0x00000001; FLEXSPI-IPCMD FLEXSPI_IPCMD_TRG_MASK; // 等待完成 while (!(FLEXSPI-INTR FLEXSPI_INTR_IPCMDDONE_MASK)); // 读取结果 uint32_t flash_id FLEXSPI-RFDR[0];这段代码的关键是LUT表项的配置。0x0A1804EB这个值对应的指令序列是CMD_SDR发送指令0x9F、RADDR_SDR发送地址读ID不需要地址所以长度为0、READ_SDR读取数据1个字节。如果读回来的flash_id是0xEF4018之类的值说明Flash通信正常问题出在Boot ROM的配置上如果读回来是0xFFFFFFFF或者0x00000000说明硬件连接有问题。6.3 第三步检查Fuse配置是否与硬件匹配如果手动读ID能成功但Boot ROM启动失败大概率是Fuse配置跟硬件不匹配。重点检查这几个方面Fuse里配置的FlexSPI实例和端口是否跟实际连接一致Fuse里配置的数据线数量是否跟Flash支持的一致Fuse里配置的时钟分频是否过高导致Flash来不及响应Fuse里配置的Dummy周期是否跟Flash要求的一致我遇到过一个案例工程师在RT1050上接了一片支持八线模式的Flash但Fuse里配置的是四线模式结果Boot ROM只读DATA0到DATA3DATA4到DATA7悬空读回来的数据高四位全是1导致启动失败。把Fuse改成八线模式后问题解决。6.4 第四步用示波器分析时序问题如果以上步骤都确认无误但高速读取时还是偶尔出错就需要用示波器仔细分析时序了。重点看这几个参数SCLK的上升沿和下降沿是否干净有没有明显的振铃DATA线上的数据建立时间和保持时间是否满足Flash的要求DQS如果有跟DATA的相位关系是否正确片选信号的建立和保持时间是否足够我通常会把示波器设置成余辉模式观察多个时钟周期内的信号变化。如果发现某个数据位的眼图明显比其他的小说明那条线的信号完整性有问题可能需要调整PCB布线或者增加匹配电阻。7. 几个实际项目中的经验教训7.1 不要迷信Flash数据手册的典型值Flash数据手册里给出的时序参数通常是典型值实际芯片在不同批次、不同温度下会有偏差。我在一个工业级项目里遇到过这样的情况常温下FlexSPI跑100MHz完全稳定但到了-40℃低温启动时大概有10%的板子会启动失败。后来把FlexSPI时钟降到80MHz低温启动就完全正常了。所以如果你的产品有宽温要求一定要在极限温度下做充分的启动测试。不要只看常温下的表现低温下Flash的读取速度会变慢高温下信号完整性会变差这些都会影响FlexSPI的可靠性。7.2 保留一个可用的串行下载接口不管你的板子设计得多完美都建议保留一个串行下载接口USB或者UART。这个接口在正常量产时可能用不到但一旦Flash启动出问题它就是你的救命稻草。我见过太多板子因为没留下载接口Flash一坏就只能报废。串行下载接口的引脚最好做成测试点或者排针不要用那种需要焊接的细间距连接器调试的时候不方便。如果PCB空间实在紧张至少把USB的D和D-引出来这两个信号加上电源和地就能实现串行下载。7.3 Flash的擦写寿命和坏块管理SPI NOR Flash的擦写寿命通常是10万次左右看起来很多但如果你的应用需要频繁记录数据很快就会用完。比如一个数据采集设备每秒写一次Flash一天就是86400次不到两天就把一个扇区写坏了。对于需要频繁写入的应用建议在Flash里划分一个区域做磨损均衡或者外挂一片EEPROM专门做数据存储。如果一定要用Flash存数据至少要把写操作分散到不同的扇区避免反复擦写同一个位置。另外SPI NOR Flash出厂时可能会有坏块虽然概率很低但批量生产时还是要做一下坏块检测。可以在产测环节加一个Flash全片擦写测试把坏块标记出来避免用户数据写到坏块上。7.4 FlexSPI和普通SPI的引脚不能混用最后说一个新手容易犯的错误把FlexSPI的引脚当成普通SPI用。FlexSPI的引脚虽然物理上跟普通SPI的SCLK、MOSI、MISO、SS功能类似但FlexSPI控制器和普通SPI控制器是两套独立的硬件引脚复用配置也不同。如果你把Flash接在了FlexSPI引脚上但用普通SPI控制器去驱动是驱动不起来的。反过来也一样如果你把一片普通SPI设备接在了FlexSPI引脚上想用FlexSPI控制器去驱动需要配置LUT表项来适配那个设备的指令集比用普通SPI控制器麻烦得多。所以设计阶段就要规划好哪些设备接FlexSPI哪些接普通SPI不要混在一起。8. 关于FlexSPI NOR连接方式我个人的几点体会FlexSPI NOR的连接方式看起来只是硬件设计的一个小环节但它直接决定了i.MX RT1xxx能不能正常启动。我在多个项目里踩过各种各样的坑从引脚复用冲突到Fuse配置错误从PCB信号完整性问题到Flash时序不匹配每一个问题都耗费了大量调试时间。现在回头看大部分问题其实都可以在硬件设计阶段避免。关键是要把FlexSPI的引脚分配、Flash选型、Fuse配置这三件事放在一起考虑而不是分开处理。引脚分配决定了你能用几线模式Flash选型决定了你需要什么时序参数Fuse配置决定了Boot ROM怎么初始化FlexSPI三者必须匹配。另外调试工具的准备也很重要。一个逻辑分析仪或者带余辉模式的示波器能帮你快速定位大部分连接问题。如果条件允许建议在板子上预留FlexSPI信号的测试点调试的时候直接夹探头就行不用飞线。最后再分享一个小技巧如果你不确定某个Flash型号能不能在i.MX RT1xxx上正常启动可以先在官方评估板上验证。评估板的FlexSPI配置是经过验证的把Flash焊到评估板上如果能正常启动说明Flash本身没问题问题出在你的板子设计上如果评估板上也启动不了那就要检查Flash的型号和配置是否匹配了。