做嵌入式开发这些年换过的平台不少但真正让我在开箱阶段就停下来重新审视“存储”这件事的STM32N6 算头一个。这颗基于 Cortex-M55、主频最高 800MHz 并集成 NPU 的旗舰级 MCU内部居然没有 Flash。对你没看错代码和数据的“家”不再在芯片内部而是在外部通过 XSPI 接口连接。很多从 H7、F4 迁移过来的朋友第一反应是外挂 Flash 怎么选有限制吗选错会有什么后果这篇文章我就基于实际选型和调试经验把 STM32N6 外部 Flash 选型里那些“真限制”和“伪限制”一条条理清楚。适合正在画 N6 板卡的硬件工程师也适合准备做 AI 应用评估、被烧录报错折腾得头疼的软件工程师。1. 先搞清楚STM32N6 的 Flash 到底在哪1.1 一颗没有内置 Flash 的旗舰 MCU做过 MCU 开发的人都知道传统 STM32 的 Flash 都在芯片内部程序用调试器一烧上电就跑简单粗暴。但 STM32N6 把这条路径彻底改了它没有内部非易失存储器所有固件和业务数据都必须放在外部 Flash 里。第一次看数据手册的人很容易漏掉这个细节等到画完板、焊完样片才发现“怎么下载失败”那就晚了。为什么 ST 要这么干说白了就是性能与工艺的取舍。Cortex-M55 在 800MHz 下跑指令带宽需求很高而嵌入式 Nor Flash 的读取速度、随机访问延迟和容量扩展都受限硬塞到内部会让功耗、面积、工艺成本全面失控。N6 选择把存储放到外部通过高性能 XSPI 接口做 memory-mapped 映射再用 Cortex-M55 自带的 I-Cache/D-Cache 以及片内大容量 SRAM 来“兜底”。这个架构思路跟当年 PC 上把 BIOS 放到 SPI Flash、系统盘放到 SSD 是类似的CPU 并不直接面对慢速存储而是靠缓存和分层把延迟藏起来。这也意味着外部 Flash 不再是“随便挂一个能存数据的芯片”而是决定了系统能不能启动、代码能不能稳定运行、AI 模型能不能装得下的核心组件。选型这件事从“采购顺手”变成了“系统设计的一部分”。1.2 外部 Flash 在系统中的三个角色在 STM32N6 的典型应用里外部 Flash 至少要扮演三个角色中的一两个。第一个角色是代码存储与执行介质。N6 上电后内置 ROM 引导程序会从 XSPI 接口读取启动镜像并把外部 Flash 映射到 CPU 地址空间中CPU 直接取指执行。这个过程叫 XiPExecute in Place。如果你的代码量不大、对实时性要求不极端完全可以从外部 Nor Flash 直接跑省去拷贝到 SRAM 的步骤。第二个角色是数据与 AI 模型的仓库。STM32N6 的核心卖点是 NPU而 NPU 跑模型需要海量权重数据。一颗几十 MB 甚至上百 MB 的外部 Flash能把模型、图像、日志、固件备份都塞进去。这个时候NAND Flash 或者大容量 Nor Flash 就派上用场了。第三个角色是安全启动和安全分区的基础。N6 支持 TrustZone 以及安全启动代码分为安全区和非安全区分区信息、签名密钥、启动镜像都存放在外部 Flash 里。Flash 选不好不只是“跑不起来”的问题而是整个安全体系地基就不稳。所以选型前先想清楚你的系统里这颗 Flash 是“代码盘”“数据盘”还是“安全盘”不同定位选型约束完全不同。2. Flash 选型的硬性限制清单2.1 接口限制必须是 XSPI 兼容器件STM32N6 访问外部 Flash 的通道是 XSPI 接口芯片上通常提供两个 XSPI 实例。这个接口向下兼容传统 SPI、双线 SPI、四线 QSPI也支持八线 OctalSPI。听起来很宽松但这里有个关键点如果只是接一颗普通 QSPI Flash比如经典 W25Q128能不能用能。但 800MHz 的 CPU 跑到一颗四线 SPI Flash 上取指带宽会严重不足代码执行基本靠缓存续命稍微有点 cache miss 就卡顿。换句话说接口物理上兼容但性能上限完全不同。我建议把“至少支持 4 线优先 8 线”作为选型红线。做完整性能验证的板子直接选 Octal NOR Flash比如 Macronix MX25 系列、Winbond W25Q 高端系列、ISSI IS25WX 系列等。普通 QSPI Flash 只适合做低功耗原型验证、数据存储不适合承载高频代码执行。另外XSPI 对 Flash 的指令集有要求。N6 的 ROM 引导程序在启动时会尽量读取 JEDEC SFDP 参数表来自动配置时序这意味着所选 Flash 必须实现标准 SFDP 表否则引导程序无法正确识别容量、页大小、读命令等关键参数。某些小厂 Flash 或者老型号 Flash 的 SFDP 表不完整很可能连启动都过不去。2.2 性能限制读速度决定代码能不能“跑得动”很多人觉得“只要接口对上就能用”其实真正卡脖子的是时序和带宽。XSPI 在 N6 上可以跑到最高约 200MHz 的时钟频率配合 DTR 双沿传输和 8 根数据线理论峰值带宽能做到 400MB/s 级别。但这是总线侧的理论值实际能不能达到取决于 Flash 内部的阵列读速度和 AC 时序参数。举个例子DTR 模式下数据在时钟上升沿和下降沿都有效这对 Flash 的数据输出建立时间要求很高。如果 Flash 的 tDV数据输出有效时间裕量不足高速运行时就会出现偶发读错表现是“程序大部分时间正常偶尔跑飞、死机、校验失败”。这种问题最难受因为不是必现排查起来极耗精力。所以选型时不要只看 Flash 标称的“最高频率 200MHz”要重点看它在 DTR 模式、8 线模式下的实际最高工作频率以及数据手册里的 AC Timing 是否留有余量。还有一个小细节为了配合 CPU 的 cache line 填充最好选择支持 wrap burst回卷突发读的 Flash。没有这个功能cache miss 时总线会多读无效数据带宽浪费很严重。另外要明确无论 XSPI 多快它跟片内 SRAM 还是有量级差距。把全部代码放外部 Flash 跑性能一定不如放内部 SRAM。我的做法是启动代码、RTOS 内核、高频中断、延时敏感的 DSP 处理全部放 SRAM普通业务逻辑放外部 FlashNPU 模型也放外部 Flash运行时按需加载。这样既省了内部 SRAM又保住实时性。2.3 电压与信号完整性限制Flash 选型还有一个容易被忽略的硬限制电压域。N6 的 XSPI I/O 工作电压需要跟 Flash 供电电压匹配。很多高性能 OctalFlash 是 1.8V 器件如果你的板子 DDR 域或者主电源是 3.3V要么加电平转换要么直接选 3.3V 版本。电平转换在高频 DTR 模式下会引入额外延迟和信号畸变我建议直接用同电压域的 Flash 或者通过成熟的电平转换方案不要拍脑袋加电阻分压。高速信号不是插上就能用的。XSPI 在 200MHz DTR 模式下信号上升沿和下降沿的时间裕量非常紧张。PCB 走线要尽量短、等长注意阻抗连续避免过孔和长 stub。这跟布 DDR 的思路很像只是把地址线换成命令线数据线也只有 8 根但该做的仿真和走线控制不能省。实际调试中如果程序在低温或高温下偶发异常第一怀疑对象就是采样延迟和信号完整性而不是代码逻辑。2.4 容量限制Memory Map 和启动窗口外部 Flash 在 memory-mapped 模式下会被映射到 CPU 地址空间的特定区域比如 XSPI1 通常映射在 0x7000_0000 附近XSPI2 映射在 0x9000_0000 附近具体以参考手册为准。这意味着 CPU 能直接寻址访问的外部 Flash 空间是有限的不能无限接大容量 Flash。这个限制对 Nor Flash 问题不大常见的 8MB、16MB、32MB、64MB 都在映射窗口内。但对 NAND Flash 就要注意一颗 1Gbit 甚至 2Gbit 的 SPI NAND映射窗口可能装不下完整空间或者只能映射部分区域。超出映射范围的部分需要用 XSPI 的非映射模式间接模式通过寄存器读写不能直接执行代码。所以你想把一个大 NAND 全部映射成代码空间是行不通的。ROM 引导程序对启动设备也有自己的“小九九”。它只会按预设流程去外部 Flash 的起始位置找启动镜像如果 Flash 容量或地址映射方式和引导程序的预期不符启动就会失败。这个限制在数据手册的“Boot configuration”章节写得比较隐晦我踩过一次之后才明白不是所有 Flash 都能当启动盘必须选引导程序验证过的类型和配置。3. NOR 还是 NAND选型边界的进一步细分3.1 NOR Flash主流且省心的选择对绝大多数 STM32N6 项目首选是 Octal NOR Flash。原因很简单支持 memory-mapped 模式代码可以直接在外部执行随机读取延迟低指令流和常量访问都能接受寿命相对长不需要复杂的坏块管理和 ECC软件栈也成熟所有烧录工具和引导程序都优先支持 NOR。我见过很多工程师拿传统 W25Q128QSPI先跑起来验证逻辑没问题但等到性能调试阶段就发现瓶颈。W25Q128 在 QSPI SDR 模式下带宽有限跑大程序、频繁访问常量表时明显感觉响应变慢。换成 Octal NOR 之后瓶颈基本消失。所以我现在的建议是如果做的是量产产品直接按 Octal NOR 设计如果只是学习评估手头有 QSPI Flash 可以先顶着但别把性能测试结果当真。官方评估板通常使用的都是经过验证的 Octal NOR Flash。最省事的做法就是照着官方评估板比如 STM32N6570-DK的 BOM 选同一款或同系列 Flash。这样启动流程、外部加载器、CubeMX 配置都有现成参考能省掉一大半从零摸索的时间。3.2 NAND Flash能存大模型但执行受限如果 AI 模型很大Nor Flash 的容量和成本会让你肉疼这时候 SPI NAND 就来了。N6 的 XSPI 也支持 SPI NAND但有几个先天限制必须认清第一NAND 不支持按字节随机读页式读取结构决定了它做 XiP 不现实代码和数据要先拷到 SRAM 才能执行第二NAND 有坏块问题出厂坏块和运行中新增坏块都需要软件管理还要做 ECC 校验这部分代码和逻辑不能省第三NAND 的读延迟比 NOR 高即使走 XSPI短时间内大量连续读的吞吐可能不错但随机读和中断现场恢复场景就比较痛苦。所以 NAND 在 N6 系统里的典型定位是“数据仓库”存 AI 模型、存文件系统、存升级包。启动把精简引导从 NOR 加载到 SRAM然后从 NAND 把模型和数据搬到 SRAM 或 PSRAM。这种 NOR NAND 的组合方案在边缘 AI 设备上非常常见。顺带说一句很多人看到“3D NAND”这个词就以为跟 SPI NAND 是两回事。其实 3D NAND 是闪存内部的堆叠工艺结构它决定了页大小、块大小和寿命特性。选型时要关注的是封装和接口而不是纠结堆叠层数。3.3 对比表与决策建议维度NOR FlashSPI NAND代码直接执行XiP支持主流用法不支持需拷贝到 SRAM随机读延迟低高连续读带宽较高适合指令流较高适合大数据块容量常见 8MB~64MB更大偏贵常见 128MB~1GB容量成本优势明显坏块管理不需要需要软件管理 ECC写擦寿命通常 10 万次左右通常 1 万次~10 万次参数差异大典型用途代码、常量、启动镜像AI 模型、文件系统、日志决策逻辑很简单跑代码、做启动选 NOR装模型、存大文件选 NAND既要快速启动又要大容量就 NOR NAND 双 Flash两个分别挂到两个 XSPI 实例上。预算极其紧张且对性能无要求可以只用小容量 NOR 加映射窗口外的数据区但我不推荐因为后期扩展很被动。4. 实操从选型到烧录的完整路径4.1 参考设计与器件清单拿到一颗新平台我最先做的是找官方评估板的原理图和 BOM不是自己从头发明。STM32N6 的评估板原理图里外部 Flash 的接线、上拉电阻、去耦电容、启动配置都有标准答案直接抄过来是最稳妥的。如果你用的 Flash 不在官方验证列表里那我建议至少先用手头目标 Flash 做一块最小系统板把启动和烧录跑通再决定是否全板铺开。选型阶段可以按这个清单过一遍接口是否支持 8 线 DTRSFDP 表是否完整是否支持 4 字节地址模式是否支持 wrap burst工作电压和 I/O 电压是否匹配是否有已验证的外部加载器耐温和寿命是否满足产品要求。前四项直接决定能不能用、好不好用后三项决定开发效率和产品可靠性。4.2 使用 STM32CubeProgrammer 烧录外部 FlashSTM32N6 没有内部 Flash所以烧录方式跟传统 STM32 完全不同。传统 STM32 用 ST-Link 直接下载到内部 FlashN6 需要借助外部加载器External Loader文件后缀 .stldr。这个加载器本质上是一段小固件由 STM32CubeProgrammer 下载到 SRAM 中运行然后通过 XSPI 接口操作外部 Flash。具体操作流程连接 ST-Link打开 STM32CubeProgrammer在 External Loader 一栏选中所用 Flash 对应的 .stldr 文件然后正常执行擦除、编程、校验。加载器文件一般在 CubeProgrammer 安装目录的 ExternalLoader 文件夹下或者由 STM32CubeMX 根据你的 Flash 型号自动生成。这里最常翻车的就是忘选 External Loader或者选错了型号程序会直接报错。如果你用的外部 Flash 没有现成加载器那就需要自己写。把 XSPI 初始化、读 ID、擦除、写入、校验这几个函数实现出来按加载器规范编成 .stldr 文件。这个过程第一次做比较繁琐但做一次之后就能复用后面换型号只改参数表和指令序列。4.3 启动与性能验证烧录成功不代表启动成功。N6 要从外部 Flash 启动必须保证 Boot 引脚配置正确同时 Flash 起始地址处的数据结构符合引导程序的预期。镜像通常需要包含合法的向量表、栈指针初始值和入口地址如果这些信息不对引导程序会认为镜像无效表现为“烧了程序但上电没反应”。启动通了之后性能验证别只看跑分要看真实场景。我一般会做一个简单的 GPIO 翻转测试把同一个翻转循环分别放在外部 Flash 和内部 SRAM 里跑用示波器或者逻辑分析仪测翻转频率。这个数据能直观反映 XiP 模式下的实际执行效率。如果外部 Flash 执行速度远低于预期优先检查三件事XSPI 是否配成了 DTR 模式采样延迟参数RxSampling是否合适I-Cache 是否开启。提示采样延迟不是越大越好也不是越小越好。它取决于 Flash 的 AC 时序和 PCB 走线长度最稳妥的方法是用 CubeMX 里的调试工具扫一遍采样点选一个在所有温度和电压条件下都稳定的值。5. 常见问题与排查实录5.1 “Flash Download Failed: Cortex-M3”的几种成因这个报错对 N6 新手来说几乎是必经之路。第一次看到“flash download failed - cortex-m3”时很多人会懵N6 不是 Cortex-M55 吗怎么跟 Cortex-M3 扯上关系其实这跟内核无关而是调试工具在识别目标失败时退回的通用错误信息。常见成因有三个第一SWD 连接不稳定调试器没有正确读到内核 ID第二没有选择或者选错外部加载器下载器不知道该往哪写第三目标板供电异常或复位时序不对导致调试器无法建立稳定的调试会话。排查时先把 SWD 时钟降到低速比如 4MHz排除高速通信不稳的问题。然后确认 ST-Link 固件、驱动、IDE 的器件支持包都是最新版本N6 是新器件太老的工具可能根本不认识。最后检查板子的供电和复位按键很多“下载失败”其实是硬件没上电或者复位脚有干扰。另一个高频报错是“erase failed! cannot access memory internal command error flash download failed”。这个通常是下载器进入了外部 Flash 但擦除过程中访问失败原因可能是 Flash 供电不稳、加载器里擦除命令时序不对或者 Flash 处于写保护状态。遇到这种问题我习惯先手动读一下 Flash ID如果 ID 都读不到问题大概率在硬件连接或加载器配置如果 ID 能读到但擦除失败再看状态寄存器的保护位。5.2 启动失败的排查思路启动失败的表现很多上电后电流异常、调试器连不上、复位后 PC 指针乱跳、程序跑一半死掉。我的排查顺序是先确认 Boot 引脚和启动源配置看引导程序到底从哪个外设找镜像再用示波器量 XSPI 的时钟和片选信号确认引导程序有没有真的去访问外部 Flash最后抓取 Flash 数据线的波形看读出来的数据和镜像文件是否一致。这里最容易踩的坑是时序余量不足。如果 Flash 在常温下能启动但一冷一热就起不来或者同一批板子有的能启动有的不能基本可以断定是 XSPI 采样时序处在临界状态。解决方法是调采样延迟参数同时检查 PCB 走线长度和阻抗。还有一次我遇到“程序能跑但一开中断就死”最后发现是中断向量表配置在外部 Flash但中断触发时 Cache 刚好没命中导致取指延迟过大。解决办法是把中断向量表和关键中断服务函数挪到 SRAM。5.3 安全区与非安全区配置的坑N6 的 TrustZone 安全机制把外部 Flash 空间也纳入了管理范围。应用安全区和应用非安全区的划分直接影响调试器和运行时代码能否访问对应存储区域。在这个上面我吃过一次大亏使能安全启动后忘记调整调试器对非安全区域的访问权限结果调试会话直接失联程序跑在安全区里调试器却停在非安全区两边互相看不到。如果你在工程里开了安全分区烧录和调试时要注意先用支持 TrustZone 的调试方式连接确认当前 CPU 处于哪个安全状态CubeProgrammer 烧录时外部加载器的访问也要匹配目标分区属性。还有一个很容易忽略的点安全启动使能后引导程序会校验镜像签名和加载地址。如果你只是临时改了链接脚本把镜像加载地址挪了但没更新签名头里的地址信息同样会被拒绝启动。遇到“bootloader 明明能跑就是加载不了我们的镜像”的情况先查签名和地址而不是怀疑 Flash 坏了。5.4 NAND 坏块与 ECC 的软件功课如果系统里用了 NAND还有一个绕不开的功课坏块管理和 ECC。SPI NAND 出厂就可能有坏块而且使用过程中还会新增。N6 的 XSPI 控制器不会替你处理这些必须在文件系统层或者驱动层自己做映射、跳过坏块、附加 ECC 校验信息。选型时要注意 NAND 的页大小常见 2KB 或 4KB和 spare area 大小这直接决定 ECC 数据怎么摆放。很多人在开发早期图省事不写坏块管理结果产品用几个月后出现数据读错返修排查极其痛苦。我的建议是如果项目一定要上 NAND在立项阶段就把坏块管理、磨损均衡、掉电保护这三件事列入计划不要把这个当成“以后再加”的功能。文件系统可以选择成熟方案它们对 NAND 的坏块处理相对完善但也要根据具体 NAND 型号做适配和压力测试。最后再分享一点个人体会写到这里回头看这几次 STM32N6 项目的经历最大的感受是外部 Flash 选型这件事本质上是在跟“性能、成本、可靠性”做三角博弈。官方验证列表里的 Flash 永远是省心之选但如果你有特殊容量或成本要求也不要怕踩坑重要的是一开始就把时序验证、加载器适配、安全分区规划排进开发计划里。我自己现在的一套固定动作是先抄官方评估板原理图用同款 Octal NOR 跑通启动和烧录再把 AI 模型搬到外部 NAND用 SRAM 做运行时缓存最后才根据量产成本优化 Flash 具体型号。这个流程看起来保守但踩坑最少、交付最快。如果你也正在 N6 上挣扎 Flash 选型希望这篇能帮你少走几段弯路。后续如果大家感兴趣我可以再把外部加载器自研流程和 XSPI 时序扫点的方法单独拆开聊。