简介面向ARM架构MCU开发者与嵌入式技术爱好者的STM32N6启动流程技术文档聚焦这颗带NPU的芯片片内ROM极小、须依赖外部Flash或USB/UART启动的新特性梳理FSBL第一阶段引导加载程序的工作机制适合希望掌握ST新体系启动原理与工程搭建方法的初中级工程师。内容围绕BootROM校验与搬运、Dev boot与Flash boot/Serial boot模式差异展开逐一拆解仅运行FSBL、FSBL加载并运行应用LoadRun、外置存储XiP原地执行三种典型架构并给出ST Signing Tool对镜像签名加头的命令行参数说明与Cut版本区分末尾以IARSTM32N6 DK板示例项目串起从创建到部署的完整流程及注意事项。资源包共1个PDF文件约2.07MB已有162人学习可作为启动调试与镜像签名环节的查阅手册。1. 上电没输出不是板子坏了STM32N6 与 FSBL 到底在干什么第一次给 STM32N6 上电串口助手一个字都不吐调试器也连不上很多人第一反应是板子焊坏了。真实原因是这颗芯片的启动链路和那些自带 Flash 的 MCU 完全不是一回事片内没有用户 Flash只有一小段固化 ROM用户代码必须放在外挂 Flash 里或者由 USB串口送进来中间还得有一个 FSBLFirst Stage Boot Loader把场面撑住。这份应用笔记讲的就是这条链路——两种启动模式、三种工程框架、1024 字节 Header 的签名以及 IAR 下从编译到烧进外部 Flash 的完整动作。它适合已经会点灯、但第一次碰 N6 启动流程的人尤其是从传统 MCU 迁移过来、习惯了“点下载就能跑”的开发者。2. 启动模式与三种工程框架从 BootROM 到 SRAM2 的那一跳做嵌入式系统迁移时最容易出现的误判是把 N6 当成“Flash 更大一点的 F4”。它不是。上电以后真正跑起来的第一段代码不在你的工程里而在片内 ROM 里这段 BootROM 只做几件固定的事读启动引脚、决定镜像从哪来、校验头部、把镜像搬到指定地址、改 PC 指针跳过去。你能控制的只有最后落地的那段 FSBL以及 FSBL 之后的事。2.1 Boot1Boot0 决定的两种启动模式板子上决定命运的是 BOOT1 引脚它把启动分成两大分支。dev boot 模式下BootROM 直接从内部 RAM 启动配合调试器把 image 下载到 RAM 里跑速度快、可断点、可单步是开发阶段唯一舒服的姿势。Flash bootBoot1 0、Boot0 0模式下BootROM 会去外部 Flash 的映射区读镜像如果那里是空的或者头部校验不过芯片就停在那儿串口一声不响。Serial boot 是第三条路靠 USB 或 UART 把镜像喂进来产线刷第一版固件或者板子刷成砖时用它救场。这三种模式的物理入口在 DK 板和 Nucleo 板上位置不同一个是拨码跳线一个是排针帽。我一般会在板子背面贴一张纸写明“调试dev出厂Flash”因为切错模式导致的“程序不见了”占了新手问题的一半以上。CPU 启动模式这件事在 N6 上不是一个寄存器位而是上电瞬间采样的引脚电平运行起来以后改不了必须断电重来。2.2 三种框架纯 FSBL、LoadRun、XiP同样是“能跑”工程框架有三种选错了后面全是坑。纯 FSBL 框架最简单BootROM 校验完头部把整段程序搬到内部 SRAM2 的0x34180000PC 跳过去你的应用就是 FSBL 本身。SDK 里那个UART_HyperTerminal_IT例子就是这个结构一个工程、一次编译、一次烧录适合验证板子和外设。它的硬约束是 BootROM 单次最多搬 512K 字节。FSBL Load Run 是两级结构FSBL 很小只负责把 APP 的 code 和 data 完整拷贝到内部 SRAM然后跳转。APP 在 RAM 里执行取指快、可以自我修改缺点是 APP 体积被内部 SRAM 剩余容量卡死而且每次上电都要拷一遍启动时间会变长。FSBL XiPExecute in Place是另一条路FSBL 把外部 Flash 的控制器配成内存映射模式然后直接把 PC 跳到外部 Flash 映射地址上的第一条指令代码原地执行不搬家。容量不再是问题代价是取指要过外部总线和 cacheFSBL 里那段 XSPI 配置一旦写错跳过去就是取指异常。框架代码运行位置容量约束典型用途纯 FSBL内部 SRAM2≤ 512K含 1K Header外设验证、小应用FSBL Load Run内部 SRAM受 SRAM 剩余空间限制需要高速执行的算法FSBL XiP外部 Flash 映射区受外部 Flash 容量限制大固件、带 NPU 模型2.3 512K 上限与地址账本很多人会问既然 FSBL 里也能塞应用那全塞进去不就完了只维护一个工程多省事。不行BootROM 的搬运上限就是 512K 字节工程一超芯片连启动都做不到而且失败得很安静——没有报错没有串口输出只有一块发热正常的板子。真到那一步只能拆成 FSBL APP。地址这块要记三个数0x34180000是 BootROM 约定的 FSBL 落点你的 FSBL 链接地址必须和它一致否则搬过去执行的是错位的指令0x70000000是外部 Flash 的映射基址烧录和 XiP 跳转都围绕它0x80000000是签名工具里-of的 option flags 值属于头部字段不是内存地址。这三个数混起来用是后面所有翻车的源头建议直接写在工程的 README 里。3. FSBL 签名与 1024 字节 HeaderSigningTool 命令行逐条拆Binary Signing 这一步在传统 MCU 项目里根本不存在所以最容易被跳过。跳过它的后果不是编译报错而是“调试一切正常切到 Flash 启动就死”排查成本极高。这一章把签名工具的每个参数拆开讲清楚。3.1 为什么没签名的 FSBL 一定起不来Flash boot 模式下BootROM 干的第一件事不是搬运是校验。它从外部 Flash 起始处读进 1024 字节这段就是 FSBL 的 Header里面装着魔术字、header 版本、镜像长度、入口地址和校验信息。校验通过它才把 Header 之后的实体内容搬到 SRAM2 并跳转校验不过流程直接终止。关键在于dev boot 模式走的是另一条路径代码由调试器直接写进 RAM压根不经过 BootROM 的校验逻辑。于是“调试能跑”这件事完全不能证明“烧进去能跑”。签名后的文件会比原始 bin 大 1024 字节这个差值本身就是最省事的自检手段——文件大小没变说明你签的是个寂寞。3.2 SigningTool 参数逐条拆解签名前要先装好最新版 CubeProgrammer并把STM32MP_SigningTool_CLI.exe所在目录加进 Windows 的 PATH否则命令行只会回你一句“不是内部或外部命令”。命令本身不长# Cut 1.1 版本芯片 STM32MP_SigningTool_CLI.exe -bin FSBL.bin -nk -of 0x80000000 -t fsbl \ -o FSBL-trusted.bin -hv 2.1 -dump FSBL-trusted.bin # Cut 2.0 版本芯片只有 -hv 不一样 STM32MP_SigningTool_CLI.exe -bin FSBL.bin -nk -of 0x80000000 -t fsbl \ -o FSBL-trusted.bin -hv 2.3 -dump FSBL-trusted.bin-bin指向 IAR 或 Keil 编译出来的原始 bin-nk是 no keys表示不使用密钥只做头部包装开发阶段都用它-of是 option flags固定写0x80000000-t声明镜像类型为 fsbl工具靠这个决定头部的字段布局-o是输出文件名-hv是 header version必须和芯片的 Cut 版本对上-dump会把生成文件里的头部信息打印出来方便肉眼确认。我习惯把输出命名成FSBL-trusted.bin并且绝不覆盖原始FSBL.bin。有一次图省事直接-o FSBL.bin签坏了以后连原始文件都没了只能重新编译而那版代码刚好没提交。3.3 Cut 版本对应关系与 dump 结果怎么看-hv用错是仅次于“忘记签名”的高频错误。Cut 1.1 的片子要2.1Cut 2.0 的片子要2.3两者的头部布局不同版本对不上BootROM 校验照样失败现象和没签名一模一样。芯片版本靠 Rev Code 区分拿不准就用编程器连上看 device info别靠猜。-dump打出来的是一串十六进制。新手看它像天书其实只需要盯两个字段镜像长度和入口地址。改完 FSBL 代码重新编译后长度字段应该跟着变如果你在链接脚本里挪了起始地址入口字段也应该跟着变。我一般在第一次跑通后存一份 dump 输出当基线后面每次改动拿新输出跟它比一眼比反复烧片快得多。这一步做完Binary Signing 才算真的掌握而不是抄了一条命令。4. IAR 工程落地Device 补丁、Reset 选项与串口第一行输出签名和烧录是后话先让代码在 RAM 里跑起来。这一节用 IAR 加 DK 板走一遍工程取自 SDK 的Projects\STM32N6570-DK\Examples\UART\UART_HyperTerminal_IT结构对应上一章的纯 FSBL 框架。4.1 先把板子切进 Development 模式上电之前先确认跳线。DK 板上把 BOOT1 拨到 dev 侧Nucleo 板上是把对应的跳线帽换到 dev 位置两种板子的丝印位置不一样别照着另一块板的图拨。切好以后插上调试器设备管理器里能认到 ST-LINK 就说明供电和连线没问题。这一步有个容易忽略的细节模式切换必须断电生效。热插拔跳线再复位芯片有时仍按上一次采样的电平走表现出来的现象是“明明拨了 dev 还是连不上”。养成拨完线按一次硬复位的习惯。4.2 工程选项四件事Device、ST-LINK、Output、Debugger打开工程后先看 Device列表里必须能选到 STM32N6 系列。选不到不是工程坏了是本机的器件支持包太旧SDK 里带了 N6 的补丁包装完重启 IDE 才会出现。Keil 和 IAR 都需要装对应补丁CubeIDE 则是升级 IDE 版本本身。第二件是 ST-LINK 配置接口用 SWD速度不要拉满。N6 上高频率容易连不上或者连上就掉我一般从 4MHz 往下试。第三件是 Output务必勾上生成 bin 文件——后面签名要用 binhex 不是必需。第四件是 Debugger 里的 Reset 方式必须设成 Software。这四项里最坑的是 Reset。默认值往往不是 Software结果就是下载成功但一运行就跑飞或者干脆连 target 都进不去。改完 Reset 设置后要先退出调试会话重新下载一次新配置才生效。这个“退出再进”的动作很多人省掉然后反复怀疑代码。4.3 编译、调试与串口验证选项确认完用默认编译配置直接编。这个 demo 的逻辑很简单收一个字节回一个字节/* UART_HyperTerminal_IT 的核心中断收回调里发回去 */ int main(void) { HAL_Init(); SystemClock_Config(); /* 时钟树在 FSBL 阶段就要配对APP 直接继承 */ MX_USART1_UART_Init(); uint8_t rx 0; HAL_UART_Receive_IT(huart1, rx, 1); /* 开单字节中断接收 */ while (1) { /* 主循环留空收发都在中断里完成 */ } } /* 收到一个字节就原样发回串口助手里敲什么就看到什么 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if (huart-Instance USART1) { HAL_UART_Transmit(huart1, g_rx_byte, 1, 100); HAL_UART_Receive_IT(huart1, g_rx_byte, 1); /* 重新武装接收 */ } }SystemClock_Config()在 FSBL 里配好时钟是有讲究的纯 FSBL 框架下应用就是 FSBL时钟配置天然生效一旦拆成两级结构外部 Flash 的 XSPI 时钟、串口波特率全依赖这一步APP 里再配一次容易和 FSBL 打架。HAL_UART_Receive_IT只武装一次接收回调里必须重新调用否则只能收到第一个字节——这是 HAL 库的老规矩N6 上一样适用。调试阶段不需要签名直接点下载、点运行串口助手敲字符应该能立刻回显。如果没反应先确认波特率和串口号再确认 Reset 是不是 Software最后才怀疑代码。回显出来那一刻说明工具链、器件包、调试器配置三样都对了可以往下走烧录。5. 烧录与排查External Loader 命令行、0x70000000 与五条翻车记录Flash Programming 在 N6 上比传统 MCU 多一层编程器本身不知道怎么擦写板子上的那颗外部 Flash得靠 External Loader 这个插件翻译。DK 和 Nucleo 板自带 loader自己画的板子要先用其他文档的方法做一个否则命令行会直接告诉你找不到 loader。5.1 环境变量 DKEL 与命令行烧录烧录前有两件准备工作板子切进 dev 模式把对应开发板的 External Loader 目录配成环境变量DKEL同时把STM32_Programmer_CLI所在目录加入 PATH。loader 文件名和板上 Flash 型号是对应的别拿 A 板的 loader 刷 B 板。# Windows-w 后面是文件 目标地址 STM32_Programmer_CLI -c portSWD modeHOTPLUG ap1 -el %DKEL% -hardRst \ -w FSBL-trusted.bin 0x70000000 # Linux 下环境变量写法不同 STM32_Programmer_CLI -c portSWD modeHOTPLUG ap1 -el $DKEL -hardRst \ -w FSBL-trusted.bin 0x70000000-c是连接参数portSWD走调试口modeHOTPLUG表示不断电直接挂上去ap1指定访问端口-el指定 External Loader这一步决定了擦除和写入能不能落到外部 Flash-hardRst写完拉一次硬复位-w是写操作后面跟文件名和目标地址。地址写0x70000000不是随便挑的那是外部 Flash 的映射基址BootROM 也从这个位置读镜像。5.2 hex 与 bin 的地址差异工程编译出来的 hex 里自带地址信息而 IDE 默认给的是内部 RAM 的地址段。直接拿这个 hex 去烧编程器会老老实实写进 RAM 区域掉电即失重启当然不跑。要么改成烧 bin 并显式给0x70000000要么在 IDE 里把 hex 的起始地址改到外部 Flash 映射区。我倾向第一种命令行里地址写得明明白白脚本可复用还能塞进 CI。CubeProgrammer 图形界面同样两条路Open file 之后要手动填地址选 loader 那一步在下拉框里挑对应开发板的条目填错地址一样白烧。烧完把 BOOT1 拨回 Flash boot断电再上电。Cut 1.1 的片子在这个模式下没有关调试口可以在 IAR 里用 attach to running target 挂上去看变量不用重新下载。从 Cut 2.0 开始行为有变化别把旧片子的经验直接套到新片子上。5.3 五条翻车记录现象、原因、解决现象一调试一切正常切到 Flash boot 后串口无任何输出。原因是没有签名或者烧的是原始FSBL.bin。解决是用 SigningTool 生成-trusted.bin比较文件大小确认多了 1024 字节再烧。现象二编程器报找不到外部 loader或者擦除阶段就失败。原因是DKEL没设、指向了错误的 loader 文件或者 loader 与板上 Flash 型号不匹配。解决是核对板上 Flash 丝印与.stldr文件名把环境变量指到正确目录命令行里用-el显式指定。现象三烧录显示成功重启后不运行。原因是烧了 hex内容落在 RAM 地址段。解决是改烧 bin 并指定0x70000000或者改 hex 的起始地址后重新编译。现象四IAR 下载失败或者下载后立刻跑飞。原因是 Reset 方式不是 Software或者板子还停在 Flash boot 模式。解决是改 Debugger 选项、退出调试会话重新下载同时确认 BOOT1 在 dev 侧。现象五工程稍大一点就完全起不来连 BootROM 的阶段都过不去。原因是纯 FSBL 框架撞上了 512K 搬运上限。解决是拆成 FSBL APP按 Load Run 或 XiP 组织FSBL 里只留搬运和跳转逻辑。6. 二次开发把 demo 的 FSBL 改成能装载 APP 的 Bootloaderdemo 里的 FSBL 只是个“能跑的程序”离真正的 bootloader 还差三件事会判断、会跳、会自检。第一步是把职责切开。FSBL 工程里只留时钟、外部 Flash 的 XSPI 配置、串口用于打印启动日志把应用拆成独立工程编译。第二步是给 APP 定义自己的镜像头放在 bin 前面若干字节字段至少包含魔术字、版本号、长度和 CRC。注意只有 FSBL 需要被 BootROM 校验并签名APP 是 FSBL 自己去校验的别把两层搞混。第三步是跳转这段代码写不对就是 HardFaulttypedef void (*app_entry_t)(void); /* 从 FSBL 跳到 APP关中断、设栈顶、改向量表基址、跳 */ static int jump_to_app(uint32_t app_base) { uint32_t sp *(volatile uint32_t *)(app_base 0x00); /* 向量表第 0 项初始 MSP */ uint32_t pc *(volatile uint32_t *)(app_base 0x04); /* 向量表第 1 项Reset_Handler */ if ((sp 0xFFF00000U) ! 0x34100000U (sp 0xFF000000U) ! 0x70000000U) { return -1; /* 栈顶不在合理区间宁可不跳 */ } __disable_irq(); SysTick-CTRL 0; SCB-VTOR app_base; /* XiP 运行时直接指向外部 Flash 映射区 */ __set_MSP(sp); ((app_entry_t)pc)(); return 0; }app_base在 Load Run 下是 APP 在 SRAM 里的落点在 XiP 下是外部 Flash 映射区地址两种框架传的值不同但向量表结构一样。栈顶检查那两行是给自己留的后悔药镜像没烧好时sp往往是0xFFFFFFFF直接__set_MSP再跳调试器只会告诉你 HardFault不告诉你为什么。签名这一步建议做成编译后动作别手动敲。IAR 的 Build Actions 里加一条 post-build 命令用$TARGET_BPATH$取输出路径编完自动生成-trusted.bin从此不会再出现“忘了签名”这种事。验证方法我固定跑四步RAM 里跑通功能、签名后-dump比对长度字段、烧到0x70000000、切 Flash boot 冷启动看串口日志。前两步五分钟能挡掉绝大多数“烧进去不跑”的问题。从那以后我每次动 FSBL 的链接地址或者加新功能都强制走一遍签名、dump、烧 bin、冷启动这条链路不再相信“调试能跑就行”。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
季节-趋势分解+掩码建模:时间序列结构感知新范式 1. 项目概述:为什么“季节-趋势分解掩码建模”正在成为时间序列建模的新范式最近在几个工业预测场景里反复验证了一件事:直接把原始时序喂给Transformer,效果常常不如预期——模型总在学噪声、漏掉关键拐点、对突发扰动反应迟钝。直到我系统重… · 2026/11/2 7:47:28
蜜罐技术实战指南:从原理到可落地的主动防御体系 1. 什么是蜜罐:不是“摆设”,而是主动防御的神经末梢“蜜罐技术”这四个字,最近在安全圈里被反复提起,但很多人一听到就下意识觉得——这是红队玩的高级玩具,是给APT组织准备的“豪华单间”,离自己太远。我… · 2026/11/5 20:47:17
蜜罐不是诱捕箱,而是攻防认知博弈的主动引擎 1. 蜜罐不是“摆设”,而是攻防博弈中主动布设的“认知诱饵”很多人第一次听说蜜罐,脑子里浮现的是一个孤零零的服务器,上面挂着几个假账号、几份带水印的测试文档,等着黑客来“光顾”——这画面没错,但只说对了10%。真… · 2026/11/4 9:24:07
EasyU优启通PE维护盘实战指南:制作、启动与核心操作全解析 1. 为什么一个PE维护盘值得单独拿出来聊装系统、修引导、救数据、清病毒,这些活儿但凡干过几次的人都知道,真正决定效率的往往不是你手速多快,而是手边那套PE环境靠不靠谱。EasyU(圈内习惯叫优启通)就是在这个场景下被… · 2026/11/5 16:49:35
Rust原来很简单二:所有权系统 Part 2 核心篇 —— 所有权系统
本篇覆盖 第 6 ~ 10 章:所有权、借用与引用、生命周期、字符串与切片、内存模型。 ⚠️ 这是全书最重要的一篇。 把它吃透,Rust 从此“很简单”;跳过它,你会处处碰壁。请慢下来,动手敲每一段代码。 第 6 章 所有权:Rust 的第一性原理
6… · 2026/11/5 16:26:08
基于Hadoop+Spark的民宿智能推荐系统设计与实现 1. 项目概述:大数据时代的民宿智能推荐这个毕业设计项目融合了当前大数据领域最主流的技术栈,构建了一个完整的民宿推荐系统解决方案。作为一名长期从事大数据系统开发的工程师,我认为这个选题非常贴合实际应用场景——随着旅游业的复苏和共享… · 2026/11/5 14:59:25
ADS122U04IPWR+STM32F427ZI工业级温度测量信号链设计 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
UART接口24位ADC搭配RS485,解决远距离温度监控难题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
UART接口24位ADC搭配PIC18F46K22的RTD与热电偶测温实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 14:10:41
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:27:59
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:03
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 10:28:07