国民技术 N32 开发指南
编制日期 2026-10-14
从硬件安全引擎、RDP 三级读保护与加密下载,到 STM32 移植、低功耗实测与量产烧录 —— 一份把「N32 特有的坑」全部前置的工程手册
结论:国民技术 N32 的差异化不是「更快的平替」,而是 把安全做进了硅片里——国密全系硬件加速 + Flash 加密存储 + MMU 多用户分区 + 安全启动 + 三级读保护 + BOOT 加密下载,这一整条链路在国产通用 MCU 里很少见。它的代价是资料分散且存在版本差异 (同一系列 DS 与 PB 的数值可能不同、不同子系列的寄存器布局有差别),收益是 做安全产品时不用外挂一颗安全芯片。真正让人卡住的从来不是代码,而是四件小事: UID 地址与 STM32 不同(移植必改)、RTC 架构重构且中断改成 EXTI20、 ADC 多一级专用时钟(不配就读不出数)、STM32 有 EEPROM 而 N32 没有。 本文按「选型 → 安全 → 环境 → 外设 → 低功耗 → 硬件 → 移植 → 排障 → 量产」的真实流水线组织, 每一段都给出可复制的代码、可对照的表格、以及该段最常踩的坑。
报告总结
N32 的资料分散在官网产品页、NSING 镜像站、LCSC 参数页、代理商的替代关系表、以及 CSDN / 博客园的迁移实战贴里, 彼此之间没有交叉索引,而且互相矛盾的地方不少(同一个参数 DS 写 4.7 Msps、PB 写 5 Msps; N32L406 的 HSI 有说 8 MHz 有说 16 MHz)。网上的教程绝大多数停留在「装个 PACK → 点灯 → 串口打印」这一步, 一旦遇到读不出芯片 ID、RTC 不唤醒、ADC 恒为 0、量产被抄就无解。本文档做了三件分散资料没做的事:
- 把安全能力当成主线讲:不把 RDP / WRP / 加密存储当成「数据手册最后一章的附加功能」, 而是按四层结构(算法引擎 → 存储保护 → 启动链 → 物理防护)组织,第 3 章是全文最详细的一章。
- 把坑写在坑发生的地方:不单独罗列「常见问题」,而是在讲每个环节时就把该环节的失效现象、原因、处置一起给出。
- 把版本差异标出来:凡 DS 与 PB 冲突、官方与代理商口径不一致的地方,一律标「未核实」并给出该以谁为准, 而不是随手取一个数字写上去。
读者路径
本文档共 11 章 + 4 个附录,按「先跑通、再理解」的顺序组织:
- 只想尽快跑通第一个系统:第 4 章(开发环境)→ 4.6 从零到点灯 → 第 11 章核查清单,三节足够。
- 从 STM32 迁移过来:第 8 章是主线,先看 8.3 二十项必改清单,再按 8.4 的八步做。
- 做安全产品(认证 / 防抄 / 授权):第 3 章全章,重点是 3.4 读保护与 3.8 加密下载。
- 做电池供电或表计:第 6 章低功耗,注意 LPRCNT 可在 STOP2 下计量这条硬约束。
- 做电机 / BMS:5.7 多 ADC 同步采样 + 5.8 片内 OPAMP + 5.9 定时器 Break 保护。
- 遇到故障:直接翻第 9 章,按八大类现象定位。
- 要量产:第 10 章,重点是 10.3 五层防护与 10.5 ICT 设计。
1 · 文档导读与阅读路径
这一章说明本文档的边界:覆盖什么、不覆盖什么,以及面对 N32 资料的口径冲突该以谁为准。
1.1 覆盖范围
本文档覆盖从选型一颗 N32、装好工具链、点起第一盏灯,到产品化量产与安全防护的完整链路:
- 家族与选型:十六条产品线的定位与规格对照、命名规则逐字段解释、按需求而非按型号的选型决策树。
- 硬件安全引擎:算法覆盖矩阵与一处重要纠偏(G4xx 没有把 SM2 列进 Security Features)、 算法库 API 与调用约定、Flash 存储架构与加密存储、RDP 三级真值表与解除流程、WRP 与 MMU 分区、 UID/UCID 与一机一密、TAMPER 与 CSS、安全启动与加密下载的指令级流程、以及 14 项落地检查清单。
- 开发环境:六种 IDE 的官方支持度、DFP 安装与三处 Include 路径、SDK 目录结构、 四类调试器与 J-Link 的xml 合并坑、串口 ISP 与 BOOT 模式、BOOT 指令集与波特率协商、从零到点灯、链接脚本与 RT-Thread BSP。
- 外设与驱动:总线与时钟使能、GPIO 与 EXTI(含 EXTI20 替代 RTC_IRQn)、 USART(printf / RS485 / LIN / ISO7816)、SPI 与 QSPI、I2C / CAN / USB、SDIO 与 XFMC、 ADC(双时钟是移植必加项、多 ADC 同步)、DAC / OPAMP / COMP / Touch、定时器(互补 PWM 与死区、MOE 位)、 RTC(架构重构)与 DMA、Flash 控制器与 EEPROM 模拟。
- 低功耗:三电源域、六种模式的能力对照、N32L 系列电流实测、唤醒源矩阵、进入代码与通用降耗清单。
- 时钟与硬件设计:时钟源与时钟树、144 MHz 配置完整流程、电源引脚与去耦、NRST 复位电路、 晶振负载电容计算与 LSE 相邻引脚禁止翻转、BOOT 引脚、SWD 与 USB 布线、ESD 设计与最小系统 12 项检查清单。
- 移植与排障:兼容性分三层判断、二十项必改清单、八步流程、八大类故障速查表、通用定位方法论与勘误手册。
- 量产:七种烧录方式、产线 ISP 标准流程、加密烧录与五层防护、UID 写入与产线追溯、ICT / ATE 设计建议。
1.2 不覆盖什么
以下内容超出本文档范围,需要时请查阅对应官方资料:
- 算法库内部实现:原厂算法库以
.lib静态库形式提供(需签 NDA 获取),本文只给 函数原型、结构体、返回码与调用顺序,不给算法内部逻辑。 - 每一款封装的完整管脚定义:本文给出接口数量与关键引脚原则,完整管脚表必须查对应子系列的
Datasheet 引脚定义表(尤其
FT/FTf的 5 V 耐受标记)。 - 寄存器位域全集:N32 用户手册动辄上千页,本文只给做决策必须的「哪个模块在哪、找谁帮忙」, 写代码时仍需对着手册核。
- RTOS / 中间件移植:RT-Thread 有官方 N32 BSP、FreeRTOS 改 port 层即可,本文只讲 工程骨架层面必须改的东西(时钟、向量表、堆栈、链接脚本),不逐个驱动过。
- 认证流程本身:EAL4+/EAL5+、商密二级、AEC-Q100 是第三方认证机构的工作, 本文只说明芯片提供哪些能力与认证相关,不解释认证流程。
- PCB 高速仿真与 EMC 整改:本文给的是可执行的规则与官方数值, 实际整改要看板子。
1.3 资料来源与可信度分级
N32 的资料有一个其他国产 MCU 不太常见的特征:同一参数在不同文档里数值不同。 本文对所有数值型信息标注来源与口径,并按下表分级。遇到冲突时的处置原则也写在表下。
| 级别 | 资料 | 提供的内容 | 口径与冲突处理 |
|---|---|---|---|
| A | nationstech.com 产品页 / Datasheet / Product Brief | 各系列官方规格表、电气特性、引脚定义 | 最高权威。同一参数 DS 与 PB 冲突时以所用批次的 DS 为准 |
| A | N32G45 Series User Manual / 硬件设计指南 / Low Power AN | RDP 真值表、WRP 粒度、Flash 布局、去耦与复位要求 | 官方一手。与代理商文章冲突时一律以此为准 |
| A | BOOT 接口指令使用指南 / 算法库用户指南 | 10 条 BOOT 指令、波特率协商、算法库 API | 官方一手。注意 BOOT 版本号 V2.1 与 V2.2 波特率表不同 |
| B | nsing.com.sg 镜像站 | 英文版 DS / PB / UM,常比中文站更新更快 | 官方镜像,但版本可能与官网不同,引用时注明版本号 |
| B | LCSC / 立创商城参数页 | N32L 系列电流实测值、封装库存 | 实测整理,可信但测试条件未必与官方相同 |
| C | 代理商替代关系表(szlvdu / 世强 sekorm 等) | Pin-to-Pin 对应关系、替换能力对比 | 工程参考。原文附注明确写了「具体是否能兼容需客户仔细核对」 |
| C | CSDN / 博客园 / 21ic 迁移实战贴 | NRST 敏感性、GPIO 上电默认态、RTOS 移植经验 | 社区经验,未获官方确认。本文引用时一律标「实测经验」或「未核实」 |
| D | 本文的推算与归纳 | PCROP 替代方案、Flash 模拟 EEPROM 方案 | 标注「推算 / 归纳」,只作为思路起点,必须自行验证 |
- 频率、电压、电流、通道数、温度范围 —— 一律以目标批次 Datasheet 为准, PB(Product Brief)是营销摘要,会滞后于 DS。
- 寄存器行为、位域、保护机制 —— 一律以用户手册 为准,DS 只给概览。 本文章节里凡是讲机制的,都标了手册出处。
- 硬件设计的推荐值 —— 以官方硬件设计指南 为准。 典型冲突:NRST 的推荐值官方写「0.1 µF + 10 kΩ」,而第三方文章称「C≤1 nF、R≤10 kΩ」, 两者冲突时按官方值做,实测不稳再逐步减小电容排查。
2 · 家族全景与选型
这一章把 N32 的十六条子系列摊开,按「你要做什么产品」而不是按型号去理解,最后收敛成一张决策树。
2.1 十六条产品线的分层
国民技术的产品线命名规则是公开的(官网 Product Brief 有专门的型号命名图),先记住一条铁律: 第三个字母决定产品族,第四个字符决定内核,第五个字符决定档位。
| 产品族 | 含义 | 代表子系列 | 内核与主频 |
|---|---|---|---|
G | 通用 MCU | G4xx / G43x / G401 / G03x / G052 | M4F 72~144 MHz / M0 48~64 MHz |
L | 低功耗 | L406 / L403 / L436 / L433 | M4F 64 / 108 MHz |
H | 高性能 | H47x / H48x / H49x / H78x / H76x | M4F 240 MHz / M7 600 MHz 双核 |
WB | 无线蓝牙 | WB452 / WB03x / WB436 / WB020 | M4F+M0 双核 / M0 |
M | 电机控制 | M01x / M016 / M418 | M0 / M4F |
A | 车规 | A003 / A052 / A455 | M0 / M4F,AEC-Q100 |
S | 安全芯片 | S003 / S032 / S033 / S035 / S002 | M0 安全核,EAL4+ ~ EAL5+ |
NS | 可信计算 | NS350 | TPM 2.0 可信计算芯片,CC EAL4+(ANSSI) |
2.2 N32G4xx:主力系列
N32G4xx 是绝大多数项目的落点:M4F @144 MHz + 144 KB SRAM + 512 KB Flash + 4 个 ADC + 4 个 OPAMP, 规格上全面覆盖 STM32F1 / F3 / F4 的中高端应用。G455 是最常被拿来做「F103 平替」的型号。
| 型号 | Flash | SRAM | 封装 | 关键差异 |
|---|---|---|---|---|
| N32G455 | 128 / 256 / 512 KB | 144 KB | LQFP48/64/80/100、QFN | 4 OPAMP + 7 COMP + 2 DAC + SDIO + QSPI + XFMC,主力 |
| N32G452 | 128 / 256 / 512 KB | 144 KB | 含 LQFP128 | 主流型,外设略裁剪 |
| N32G451 | 128 / 256 / 512 KB | 未核实(推算 96~144 KB) | LQFP48/64/100 | 成本优化版 |
| N32G457 | 512 KB | 144 KB | LQFP64/100 | 唯一带 EMAC 10/100M 以太网 + DVP 摄像头接口,97 GPIO |
| N32G4FR | 512 KB | 144 KB | LQFP 系列 | 指纹识别专用(算法库 + 安全存储) |
N32G455 完整规格(官方 DS / PB)
| 模块 | 参数 | 模块 | 参数 |
|---|---|---|---|
| 内核 | Cortex-M4 + FPU,144 MHz,180 DMIPS | U(S)ART | 7 路 @4.5 Mbps(3 USART 支持 ISO7816/IrDA/LIN) |
| I-Cache | 8 KB,Flash 加速单元 0 等待执行 | SPI | 3 路 @36 MHz,其中 2 路支持 I2S |
| Flash | 128/256/512 KB,加密存储、MMU 分区、硬件 ECC | QSPI | 1 路 @144 Mbps |
| D-Flash | 最大 512 KB(仅 RGL7 / VGL7),10 万次 / 20 年 | I2C | 4 路 @1 MHz,从机双地址 |
| SRAM | 144 KB(含16 KB Retention RAM),硬件奇偶校验 | USB | 1×USB2.0 Full Speed Device |
| ADC | 4×12bit 4.7 Msps(PB 写 5 Msps),最多 38 路外部单端,支持差分 | CAN | 2×CAN 2.0A/B |
| OPAMP | 4 路轨到轨,内置最大 32× PGA | SDIO | 1 路,支持 SD / SDIO / MMC |
| COMP | 7 个高速比较器,内置 64 级可调基准 | XFMC | 扩展 SRAM / PSRAM / NOR / NAND / TFT LCD |
| DAC | 2×12bit,1 Msps | GPIO | 最多 80 个(G457 达 97),翻转 50 MHz,多数 5 V 耐受 |
| DMA | 2 个控制器 × 8 通道,源/目的任意可配 | 定时器 | 2×高级(6.9 ns 精度,6 路互补 PWM)+ 4×通用 + 2×基本 |
| 看门狗 | 7bit WWDG + 12bit IWDG | RTC | 闰年万年历、闹钟、周期唤醒、内外时钟校准 |
| 安全 | AES/DES/SM1/SM3/SM4/SM7/SHA/MD5/TRNG/CRC16/32 | 供电 / 温度 | 1.8 ~ 3.6 V / -40 ~ +105 ℃ |
| ESD | ±4 kV HBM,±1 kV CDM | UID / UCID | 96-bit @ 0x1FFF_F7F0 / 128-bit @ 0x1FFF_F7C0 |
| 子系列 | 型号 | 封装 |
|---|---|---|
| N32G455xB(128KB) | N32G455CBL7 / RBL7 / MBL7 / VBL7 | LQFP48 / 64 / 80 / 100 |
| N32G455xC(256KB) | N32G455CCL7 / RCL7 / RCQ7 / MCL7 / VCL7 | 同上 + QFN |
| N32G455xE(512KB) | N32G455CEQ7 / REL7 / MEL7 /VEL7 | 同上 |
封装库:QFN48(6×6)、QFN64(8×8)、LQFP48(7×7)、LQFP64(10×10)、LQFP80(12×12)、LQFP100(14×14)。
2.3 N32G43x:高性价比 M4F
G43x 是「资源够用、价格要低」的那一档。三者的差异集中在模拟外设与电压范围上, 其中N32G430 的电压下限是 2.4 V 而不是 1.8 V,这是最容易踩的坑。
| 子系列 | 主频 | Flash | SRAM | 电压 | DAC | ADC | OPAMP | COMP | USB | CAN | 密码引擎 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| N32G435 | 108 MHz | 64~128 KB | 16~32 KB | 1.8~3.6 V | ● | ● | ● | ● | ● | ● | ● |
| N32G432 | 108 MHz | 64~128 KB | 24~32 KB | 1.8~3.6 V | ● | ● | — | — | ● | ● | ● |
| N32G430 | 128 MHz | 32~64 KB | 16 KB | 2.4~3.6 V | — | ● | — | ● | — | — | — |
- 电压下限 2.4 V:不能接 1.8 V 电池或 1.8 V LDO 输出。选型时如果你的板子已有 1.8 V 轨,G430 直接排除。
- 无 USB、无密码引擎:官方产品页参数表在这两格没有 ● 标记。因此 G430 不适合做 USB 通信设备,也不适合做需要加密下载 / 安全启动的产品。
典型应用(官方列出):电梯控制、5G 通信设备、汽车大灯 / 升窗器 / 电动车控制器 / T-Box、 光伏控制板、BMS、血氧仪、无绳吸尘器、高速风机、电动工具、平衡车。
2.4 N32L4xx / L43x:低功耗与表计
L 系列是电池供电与智能表计的专用线。核心差别不是主频,而是 SRAM2 在 Stop2 / Standby 下保持 + LPRCNT 无磁计量模块能在 Stop2 下工作。
| 项目 | N32L406 / L403 | N32L436 / L433 |
|---|---|---|
| 内核 / 主频 | Cortex-M4F @64 MHz,80 DMIPS | Cortex-M4F @108 MHz,135 DMIPS,2 KB I-Cache |
| Flash | 最大 128 KB | 64 / 128 KB |
| SRAM | 24 KB = 16 KB SRAM1 + 8 KB SRAM2 | 24 / 32 KB(同样含 8 KB SRAM2) |
| Standby 电流 | 1.5 µA(备份寄存器 + IO + 8KB SRAM2 保持) | 1.5 µA(同) |
| Stop2 电流 | 3 µA(RTC 运行 + 8KB SRAM2 + CPU 寄存器保持) | 3 µA(同) |
| RUN 电流 | 60 µA/MHz @64 MHz | 90 µA/MHz @108 MHz |
| LPRUN | PLL 关,MSI 作系统时钟,MR 关 / LPR 开,USB/CAN/SAC 断电 | 同 |
| ADC | 1×12bit 1 Msps,最多 16 路外部单端 + 差分 | 1×12bit 5 Msps,LQFP48 有 10 路 / LQFP64·80 有 16 路 + 3 内部 |
| OPAMP / COMP | 1~2 路(32×PGA)/ 2~3 个(64 级) | 2 路 / 2 个,COMP1 支持 Stop2 工作 |
| DAC | 1×12bit 1 Msps | 1×12bit 1 Msps |
| Touch | 最多 24 通道,低功耗可唤醒 MCU | 最多 24 通道 |
| Segment LCD | 最多 320 段(8×40)或 176 段(4×44) | 4×44 / 8×40(最大 320 段) |
| LPRCNT | — | 支持(低功耗无磁计量,Stop2 可工作) |
| 通信 | 5×U(S)ART(3 USART + 2 UART)+ 1×LPUART(Stop2 唤醒)、2×SPI @16 Mbps(I2S)、2×I2C、1×USB FS、1×CAN | 5 U(S)ART + 1 LPUART、2 SPI/I2S @27 Mbps、2 I2C、1 USB FS、1 CAN |
| 安全 | AES/DES/TDES/SHA1·224·256/SM1/SM3/SM4/SM7/TRNG/CRC | 同 |
| 封装 | LQFP32/48/64/80、QFN32 | LQFP32 / 48 / 64 / 80 |
N32L43x 内部的 x3 与 x6 不是档位差异,而是功能差异:
x3 不支持 Segment LCD,x6 支持。同时 L436 比 L433 多了 LPRCNT
(低功耗 LC 无磁计量模块,可在 Stop2 下工作)。做水表 / 气表选 L436,做纯低功耗传感选 L433。
2.5 N32G03x / G05x:宽压与家电
这两条线的共同点是电压上限到 5.5 V,可以直接用家电的 5 V 或电池组供电,省掉一颗 LDO。 G05x 额外带Segment LCD 与 Beeper,是「家电面板 + 显示」的组合。
| 子系列 | 主频 | Flash | SRAM | 电压 | ADC | OPAMP | COMP | Beeper | LPUART | CAN | 密码引擎 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| N32G033 | 64 MHz | 64 KB | 6 KB(官方表)/ 8 KB | 2.0~5.5 V | ● | ●(3路) | ● | ● | — | — | — |
| N32G032 | 48 MHz | 32~64 KB | 8~16 KB | 1.8~5.5 V | ● | ● | ●(3) | ● | ● | ● | ● |
| N32G031 | 48 MHz | 32~64 KB | 8 KB | 1.8~5.5 V | ● | ● | ● | ● | ● | — | — |
| N32G030 | 48 MHz | 32~64 KB | 8 KB | 1.8~5.5 V | ● | ● | ● | ● | ● | — | — |
| N32G052 | 64 MHz | 128 KB + 8 KB D-Flash | 16 KB | 2.0~5.5 V | ● | — | ●(4) | ● | — | ● | ● |
G030 / G031 是 G032 的精简版:无 CAN、部分型号无 DMA/RTC/GP Timer、ADC/COMP/TSC 精简。 G032 往上 SRAM 提到 16 KB、外设更全、新增 CAN 与硬件加密引擎,最大到 LQFP64。 G033 是2.0~5.5 V 宽压 + 3 路 OPAMP,用于两轮电动车 / 电动工具 / BMS / LED 户外屏。
N32G052 的完整规格:M0 @64 MHz、128 KB Main Flash + 8 KB Data Flash(加密存储、分区管理、硬件 ECC)、 16 KB SRAM(Stop 模式保持)、1×12bit 1 Msps ADC、4 个轨到轨比较器(64 级基准)、 1×8/12bit DAC、Segment LCD 最大 256 段(8×32)、5×UART、3×SPI@16 MHz、2×I2C@1 MHz、1×CAN、 最多 61 GPIO、Beeper 16 mA 驱动、低功耗四模式(Run / Sleep / Stop / Power Down, Power Down 可由 NRST / PA0_WKUP0 / PA2_WKUP1 唤醒)、安全能力含 CRC16 / Flash 加密 / MMU / WRP / RDP 三级 / 时钟失效监测 / 防拆监测 / 96-bit UID + 128-bit UCID。
2.6 N32WB:无线蓝牙系列
| 型号 | 内核 | 主频 | Flash | SRAM | BLE | 关键能力 |
|---|---|---|---|---|---|---|
| N32WB452 | M4F + M0 双核 | 144 MHz | 512 KB | 144 KB | 5.0 | TX/RX 3.5~3.6 mA,+3 dBm,灵敏度 -94 dBm;7×U(S)ART、4×I2C、3×SPI、2×CAN、USB FS、SDIO、DVP;2×12bit 5 Msps ADC、2×DAC、18 通道触摸、密码引擎;QFN48 / QFN88 |
| N32WB031 / WB03x | M0 | 64 MHz | 256 / 512 KB | 48 KB | 5.1 | 1 Mbps / 2 Mbps / 125 kbps(S8) / 500 kbps(S2);AoA / AoD、RSSI、多连接、包长扩展、KEYSCAN、IRC;10bit 1.33 Msps ADC(可配 16bit 16 ksps);模拟 MIC 输入 + PGA;QFN32 |
| N32WB436 | M4 + M0 双核 | 未核实 | 128 KB | 未核实 | 5.1 | 功耗 4.2 / 3.8 mA;高安全物联网 |
| N32WB020 | M0 + M0 双核 | 未核实 | 320 KB | 21 KB | 4.2 | TX/RX 9.7 / 9.3 mA;基于安全芯片 SoC 平台,适合国密物联网 / 安全认证 / OTA |
| 通用射频指标 | — | — | — | — | — | Sleep 1.4 µA · Power Down 130 nA;灵敏度 -96 dBm @1 Mbps;发射可编程最大 +6 dBm;支持片上天线;最小 2×2 mm LGA |
2.7 N32S 与 NS350:安全芯片线
如果你的产品需要通过第三方安全认证(商密二级、EAL4+/EAL5+、AEC-Q100)或者需要 TPM 2.0 可信计算,那就不该在通用 MCU 上凑,而是直接用这条线。这也是国民技术的老本行 (本身是安全芯片与可信计算厂商)。
| 型号 | 内核 / 主频 | Flash / SRAM | 算法 | 认证 | 接口 |
|---|---|---|---|---|---|
| N32S003 | Cortex-M0 @48 MHz | 64 KB / 6 KB | 国际算法 + SM2/3/4 | 商密二级 + EAL4+ | UART、I2C、SCD |
| N32S032 | M0 安全处理器 + AMBA 多总线 @80 MHz | 320 KB / 未核实 | DES/3DES、AES、SHA、RSA/ECC、SM1/2/3/4 | 商密二级 + EAL5+、AEC-Q100 Grade2 | USB2.0 FS、多路 SPI、UART、I2C、ISO7816、SCC/SCD;12bit 1 Msps SAR ADC、10bit DAC、COMP、RTC、PWM |
| N32S033 | Cortex-M0 @80 MHz | 512 KB / 32 KB + 1 KB | 国际算法 + 国密 | EAL4+ | USB、UART、I2C、SPI、I2S、SCC、SCD;10bit 1 Msps ADC、COMP、PWM、5×32bit TIM |
| N32S035 | Cortex-M0 @80 MHz | 100 KB(用户可用)/ 未核实 | 国际算法 + 国密 | 未核实 | UART、I2C |
| N32S002 | Cortex-M0 @16 MHz | 32 KB / 6 KB | 国际算法 + 国密 | 商密二级 + EAL4+ | I2C;2×16/32bit TIM |
| NS350 | — | — | SM2/3/4 + 国际算法 | 商密二级 + CC EAL4+(ANSSI) | TPM 2.0 可信计算芯片 |
| Z32HUA-1/2、Z32HUB | — | — | — | — | 微认证芯片 |
2.8 料号怎么读
N32 的型号命名是公开且规范的,官方 Product Brief 里有专门的命名图。以
N32G455REL7 为例逐字段拆解:
| 字段 | 含义 | 取值范围 |
|---|---|---|
N32 | 公司前缀 + 位宽 | N = Nations / NSING;32 = 32 bit |
G | 产品族 | G 通用 / H 高性能 / L 低功耗 / WB 无线 / M 电机 / A 车规 / S 安全 |
4 | 内核 | 0 = Cortex-M0,4 = Cortex-M4F,7 = Cortex-M7F |
55 | 系列档位 | x0/03 超值型,x1/x2 主流型,x3/x5 高性能型,x6 LCD 系列,x7 互联型,FR 指纹,17/18 SIP |
R | 引脚数 | F=20,P=25,G=28,K=32,T=36,H=40,C=48,R=64,M=80,L=88,V=100,Q=128 |
E | Flash 容量 | 4=16KB,6=32KB,8=64KB,B=128KB,C=256KB,E=512KB,G=1024KB,I=2048KB |
L | 封装 | L=LQFP,Q=QFN,U=UFQFPN,S=TSSOP,W=WLCSP,T=TQFP,E=LGA |
7 | 温度范围 | (无 / 6)= -40~85℃,7 = -40~105℃,8 = -40~125℃ |
- 厂商前缀有两种:PACK 文件名里既有
Nationstech.N32G45x_DFP.*.pack也有Nations.N32G430_DFP.*.pack,历史原因导致,两种前缀都会被 Keil 识别,搜"N32"即可。 - 子系列号与引脚数是两个字段,容易看错:
N32G455REL7里455是子系列号、R是 64 引脚、E是 512 KB Flash、L是 LQFP、7是 -40~105℃。把R看成「R 封装」是最常见的误读。
2.9 选型决策路径
把上面这些收敛成七个问题的决策树,从下往上问,第一个命中的分支就是答案:
来源:nationstech.com 产品页 + nsing.com.sg + RT-Thread BSP
补充三条不成文经验:
- 不确定就买官方评估板对应的型号。STB 评估板已经把时钟、调试口、BOOT 串口、
最小系统全部验证过了 —— 你的产品应该从它出发改,而不是从零画原理图。官方命名规则是
N32G45X<封装>-STB,例如N32G45XRL-STB_LQFP64(N32G457REL7,512 KB Flash, 板载 CMSIS-DAP SWD + USB)。 - 做电机 / BMS 优先看 ADC 与 OPAMP 数量,而不是主频。G455 的 「4×ADC 同步采样 + 4 路 OPAMP(32×PGA)+ 7 个 COMP」这一组能省掉三片外部器件; G435 只有 2 OPAMP + 2 COMP,采样方案要重新设计。
- 同封装内优先选高一档 Flash。G455xB(128KB)与 G455xE(512KB)封装完全相同、 引脚完全相同,差价有限但后期加功能时的返工成本远高于差价。
3 · 硬件安全引擎
这是 N32 真正的差异化所在,也是本文档最详细的一章。国民技术本身是安全芯片与可信计算厂商 (N32S 系列 EAL4+/EAL5+、NS350 TPM2.0、Z32HUA 微认证芯片),N32 通用 MCU 的安全 IP 来自同一套技术栈。
3.0 先看安全能力的四层结构
很多资料把安全能力当成「数据手册最后一章的附加功能」,列一堆算法名就结束了。这样看很容易得出错误结论 —— 比如「有 AES 所以就安全了」。实际上算法只是最基础的一层:如果芯片能被编程器正常读出, AES 加密存储没开,那加密算法再强也没意义。把 N32 的安全能力按四层组织,每层解决不同的问题:
来源:nationstech.com Security Features + N32G45 Series User Manual
四层的关系是叠加生效、缺一不可。举一个具体例子说明为什么:假设只做了第 1 层(用了硬件 SM4) 和第 2 层(开了写保护),没开 Flash 加密存储 —— 攻击者拿编程器读出来仍然是明文固件, SM4 算法再难破解也没有意义。同理,只做了第 2 层(RDP L1)没做第 3 层(加密下载), 攻击者虽然读不出固件,但可以刷进自己的固件,产品就变成了攻击者的载体。
本章按这个四层结构组织:3.1~3.2 讲第 1 层(算法引擎与算法库),3.3~3.5 讲第 2 层(存储保护), 3.6~3.7 讲第 4 层中与芯片强相关的一部分(唯一标识与物理防护),3.8 讲第 3 层(启动链), 3.9 给出把四层落地的 14 项检查清单。
3.1 算法覆盖矩阵与一处重要纠偏
先看全系列算法覆盖情况。这张表来自各系列 Datasheet 与 Product Brief 的 Security Features 段汇总:
| 系列 | 对称 | 摘要 | 非对称 | 其他 |
|---|---|---|---|---|
| N32G455 / G452 / G451 / G457 / G4FR | AES、DES、SM1、SM3、SM4、SM7 | SHA、MD5、SM3 | 未列 RSA/ECC(未核实) | TRNG、CRC16/32 |
| N32L406 / L403 | AES、DES、TDES、SM1、SM3、SM4、SM7 | SHA1/224/256 | 未列 | TRNG、CRC16/32 |
| N32L436 / L433 | AES、DES、TDES、SM1、SM3、SM4、SM7 | SHA1/224/256 | 未列 | TRNG、CRC16/32 |
| N32G032 | AES、SM4(算法库指南仅列这三项) | — | — | RNG |
| N32A455(车规,API 最全) | DES/TDES、AES、SM1、SM4、SM7 | SHA-1/224/256、MD5、SM3 | SM2(签名/验签/密钥协商/加解密)、RSA | RNG(伪随机 + 真随机) |
| N32H49x | DES/TDES、AES、SM4 | SHA-1/224/256/MD5/SM3 | — | RNG |
| N32H7xx | DES/TDES、AES(ECB/CBC/CTR) | SHA-1/224/256/384/512 | — | RNG |
| N32S032(安全芯片) | DES/3DES、AES、SM1、SM4 | SHA、SM3 | RSA、ECC、SM2、SM9 | 硬件算法协处理器 |
| N32S003 | 国际算法 + SM2/3/4 | — | SM2 | — |
官方 G4xx 系列 Datasheet 的 Security Features 段写明的国密算法是 SM1 / SM3 / SM4 / SM7, 没有把 SM2 列进 G4xx 的 Security Features。SM2 出现在两个地方:
- N32A455 算法库(车规系列,算法库 API 最全,含
SM2_SignGen/SM2_SignVerify/SM2_KeyExchange) - N32S 安全芯片的硬件算法协处理器(N32S032 明确列出 RSA / ECC / SM2 / SM9)
所以:如果项目强制要求 SM2 签名 / 验签跑在通用 MCU 上,不要默认 N32G455 支持 SM2。 先确认你的方案是走 N32A455 算法库,还是外挂 N32S 安全芯片做协处理器。 此项务必向原厂或代理商确认,不要靠本文的推断做设计决策。
各算法能力细节
| 算法 | 类型 | 密钥 / 分组 | 工作模式 | 备注 |
|---|---|---|---|---|
| AES | 对称分组 | 128/192/256 bit,128 bit 分组 | ECB / CBC(H7 增 CTR) | 硬件引擎 |
| DES | 对称分组 | 64 bit(56 有效) | ECB / CBC | |
| TDES(3DES) | 对称分组 | 2Key / 3Key | ECB / CBC | L 系列与 A455 支持 |
| SM1 | 对称分组 | 128 bit | ECB / CBC | 算法不公开,以 IP 核形式提供,仅能通过芯片接口调用 |
| SM4 | 对称分组 | 128 bit 密钥 / 128 bit 分组,32 轮 | ECB / CBC | 国密替代 AES |
| SM7 | 对称分组 | 128 bit | — | 非接触 IC 卡场景(门禁、票务、一卡通) |
| SHA-1 / 224 / 256 | 摘要 | 输出 160 / 224 / 256 bit | — | H7 系列支持到 384 / 512 |
| MD5 | 摘要 | 128 bit | — | 已不安全,仅兼容用 |
| SM3 | 摘要 | 输出 256 bit,512 bit 分组 | — | 国密替代 SHA-256 |
| SM2 | 非对称 ECC | 256 bit(≈RSA 3072 强度) | 签名 / 验签、密钥交换、加密 | 需 N32S 或 A455 算法库 |
| RSA / ECC | 非对称 | — | — | N32S032 明确支持 |
| TRNG | 真随机数源 | — | 按字 / 按字节生成 | 基于物理熵源 |
| CRC16 / CRC32 | 校验 | — | — | 独立硬件单元(多项式与初值未核实) |
- 会话密钥 / Nonce / IV 一律用 TRNG,不要用 PRNG。官方算法库同时提供
PRNG_GenerateWord()(伪随机)与TRNG_GenerateWord()/TRNG_GenerateByte()(真随机), 伪随机只用于非安全场景(如抖动延时、仿真测试)。 - 存量系统对接时保留 SHA-256 / AES-128,不要为了「国密」强行替换已上线的算法 —— SM4 与 SM3 的性能在硬件加速下与AES-128 / SHA-256 同级,但工具链、认证测试、第三方组件的成熟度还差一截。 正确做法是新设计用国密,存量设计保持兼容。
- 固件验签优先用 SM3 或 SHA-256做摘要,签名算法按合规要求选。 G4xx 上只有摘要引擎(SM3/SHA)而没有非对称引擎,完整的安全启动需要外挂方案或在 A455 / S 系列上做 —— 这一点必须在方案阶段就想清楚,见 3.8 节。
3.2 算法库 API 与调用约定
国民技术的算法库以 .lib 静态库形式提供(不是源码),需向原厂或代理申请。
以最完整的 EN_UG_NationsN32A455SeriesGeneralCryptographicAlgorithmLibraryUserGuide.pdf 与
EN_UG_N32H49x_Series_Cryptographic_Algorithm_Library_User_Guide_V1.0.0.pdf 为准,
N32G03x 版本仅有 AES / SM4 / RNG 三章。
使用步骤(官方描述):
1. 头文件(n32xxx_aes.h / n32xxx_algo_common.h / Type.h)放入头文件目录
2. 库文件加入工程:
n32xxx_algo_common.lib n32xxx_aes.lib n32xxx_des.lib n32xxx_hash.lib
n32xxx_sm1.lib n32xxx_sm2.lib n32xxx_sm4.lib n32xxx_sm7.lib n32xxx_rng.lib
3. 按指南第 2~9 章的函数描述调用
注意:U32 类型参数要求 4 字节字对齐
基础数据类型(官方 Type.h)
typedef unsigned char bool;
typedef unsigned char u8;
typedef signed char s8;
typedef unsigned short u16;
typedef signed short s16;
typedef unsigned int u32;
typedef signed int s32;
typedef unsigned long long u64;
typedef signed long long s64;
DES / TDES API
| 函数 | 说明 |
|---|---|
DES_Init(...) | DES / TDES 算法初始化 |
DES_Crypto(DES_PARM *parm) | 加 / 解密运算(ECB / CBC,加密或解密由结构体指定) |
DES_Close() | 关闭 DES 模块 |
DES_GetVersion() / DES_VersionInfo() | 获取库版本 |
/* 模式宏定义(官方示例,注意这些是"魔数"不是位域) */
#define DES_ECB (0x11111111)
#define DES_CBC (0x22222222)
#define DES_ENC (0x33333333)
#define DES_DEC (0x44444444)
#define DES_KEY (0x55555555) /* 单倍长密钥 */
#define TDES_2KEY (0x66666666)
#define TDES_3KEY (0x77777777)
/* 参数结构体 */
typedef struct {
u32 *in; /* 待加 / 解密输入 */
u32 *iv; /* 初始向量 */
u32 *out; /* 输出 */
u32 *key; /* 密钥 */
u32 inWordLen; /* 明文 / 密文长度(以 word 计) */
u32 En_De; /* 0x33333333=加密,0x44444444=解密 */
u32 Mode; /* 0x11111111=ECB,0x22222222=CBC */
u32 keyMode; /* 0x55555555 / 0x66666666 / 0x77777777 */
} DES_PARM;
/* 返回码枚举(部分) */
#define DES_Crypto_OK 0x0 /* 操作成功 */
#define DES_Init_OK 0x0 /* 初始化成功 */
#define DES_Crypto_ModeError 0x5a5a5a5a /* 工作模式错误(非 ECB/CBC) */
#define DES_Crypto_EnOrDeError /* 加 / 解密标志错误 */
#define DES_Crypto_ParaNull /* in / out / iv 为空 */
#define DES_Crypto_LengthError /* 输入长度错误(必须为偶数且非 0) */
#define DES_Crypto_KeyError /* keyMode 错误 */
#define DES_Crypto_UnInitError /* 未初始化 */
H7 / H49x 版本的错误码基值与 G4xx 不同(例如 DES_Init_OK = 0x2a2a7a7a,
并且增加了 DES_ATTACKED 防攻击标志)。如果你写了跨系列的抽象层,
不要用返回码数值做分支判断,只判断「是否等于该系列头文件里定义的 OK 值」。
AES / SM4 / SM7 / SM1 API
| 函数族 | Init | Crypto | Close | GetVersion |
|---|---|---|---|---|
| AES | AES_Init(...) | AES_Crypto(AES_PARM*) | AES_Close() | AES_GetVersion() |
| SM4 | SM4_Init(...) | SM4_Crypto(SM4_PARM*) | SM4_Close() | SM4_GetVersion() |
| SM7 | SM7_Init(...) | SM7_Crypto(...) | SM7_Close() | SM7_GetVersion() |
| SM1(闭源 IP 核) | SM1_Init(...) | SM1_Crypto(...) | SM1_Close() | SM1_GetVersion() |
HASH API:分步流式,适合固件验签
大文件或固件镜像的摘要计算必须走流式接口,不要试图一次性读全部数据进内存:
| 函数 | 说明 |
|---|---|
HASH_Init(...) | 初始化,选择算法(SHA1 / 224 / 256 / MD5 / SM3) |
HASH_Start(...) | 启动一次 HASH 运算 |
HASH_Update(...) / HASH_Process(...) | 分步喂入数据(流式) |
HASH_Finish(...) / HASH_GetResult(...) | 完成并取摘要结果 |
HASH_Close() / HASH_GetVersion() | 关闭 / 取版本 |
一次性便捷接口:N32H7xx 库提供 One-shot Hash Function(一次性完成),
G4xx 上没有。固件验签的标准写法是 HASH_Init → HASH_Start →
循环 HASH_Update(分块喂入镜像)→ HASH_Finish → HASH_GetResult → 比对。
SM2 API(N32A455 / N32S 算法库)
| 函数 | 说明 | 函数 | 说明 |
|---|---|---|---|
SM2_JudgePointOnCurve(...) | 判断点是否在曲线上 | SM2_KeyExchange(...) | 密钥协商(交换) |
SM2_KeyPairGen(...) | 密钥对生成 | SM2_UserIDHash(...) | 用户 ID Hash 计算(ZA) |
SM2_PubKeyFromPriKey(...) | 由私钥推导公钥 | SM2_MsgHash(...) | 消息 Hash 值计算 |
SM2_SignGen(...) | 签名生成 | SM2_Encrypt(...) | 公钥加密 |
SM2_SignVerify(...) | 签名验证 | SM2_Decrypt(...) | 私钥解密 |
RNG API:真随机与伪随机
PRNG_Init(...) /* 伪随机初始化 */
PRNG_SeedUpdate(...) /* 伪随机种子更新 */
PRNG_GenerateWord(...) /* 按字生成伪随机数 —— 仅用于非安全场景 */
TRNG_GenerateWord(...) /* 按字生成真随机数 —— 会话密钥 / Nonce / IV 用这个 */
TRNG_GenerateByte(...) /* 按字节生成真随机数 */
RNG_GetVersion()
RT-Thread 官方 BSP(bsp/n32/n32gxx_lxx/)目前未将密码引擎抽象为独立设备驱动 ——
外设支持矩阵里只有 UART / GPIO / I2C / SPI / ADC / CAN / DAC / TIMER / WDT / RTC。
使用密码引擎需要直接调用原厂算法库(自己写 RT-Thread 的 crypto 设备框架封装)。
社区是否有 crypto 驱动包未经核实。
来源:N32G45 Series User Manual Read protection 章节
3.3 Flash 存储架构与加密存储
来源:N32G45 Series User Manual 存储章节
Flash 加密存储(Storage Encryption)
官方描述:「支持加密存储、多用户分区管理及数据保护,支持硬件 ECC 校验, 10 万次擦写,10 年数据保持」。这句话拆开看有四层价值:
- 加密存储 —— Flash 里存放的是密文,读取时经硬件解密后送上总线。 也就是说通过 SWD 或编程器读出来的是密文,无法还原固件。
- 多用户分区管理(MMU) —— 可以把 Flash 划成多个区域,各区域独立配置访问权限与密钥。
- 硬件 ECC —— Flash 有ECC 校验,能检出位翻转。U 盘级可靠性对消费类 MCU 是超配, 但对存校准数据 / 密钥的场合很有价值。
- 10 万次擦写 / 10 年保持 —— 这是参数,不是功能,但它决定了 EEPROM 模拟方案的可行性(见 5.11 节)。
实现要点:需先配置加密密钥(由 TRNG 或用户密钥派生),再通过工具或选项字节使能。 与 RDP 的区别要记清楚:RDP 是访问控制(禁止读),加密存储是保证「就算读出来也不可用」。 两者叠加使用才是完整防护。
3.4 读保护 RDP:L0 / L1 / L2
RDP 是 N32 安全体系里最需要理解清楚、也最容易造成不可逆损失的一环。
它的实现藏在选项字节里,通过 RDP1 / nRDP1(互补)与 RDP2 / nRDP2(互补)
两组字节共同决定当前等级。
| 配置 | RDP1 | nRDP1 | RDP2 | nRDP2 |
|---|---|---|---|---|
| 组合 A | 0xFF | 0xFF | RDP2≠0xCC 或 nRDP2≠0x33 | — |
| 组合 B(= L0) | 0xA5 | 0x5A | RDP2≠0xCC 或 nRDP2≠0x33 | — |
| 组合 C(= L2) | 0xXX | 0xXX | 0x33 | 0xCC |
三级等级的行为定义(这部分内容直接来自 N32G45 系列用户手册 Read protection 章节):
| 等级 | 判定条件 | 行为 |
|---|---|---|
| L0 (无保护) | (RDP1==0xA5 && nRDP1==0x5A) && (RDP2!=0xCC || nRDP2!=0x33) | 主存储区与选项字节可任意读;每页写保护属性可配置 |
| L1 (读保护,可解除) | ~((RDP1==0xA5 && nRDP1==0x5A) && (RDP2!=0xCC || nRDP2!=0x33)) || (RDP2==0xCC && nRDP2==0x33) | 仅允许用户代码从主 Flash 启动时读主存储区;Page 0~1 自动写保护;其他页可由主 Flash 内代码编程(支持 IAP / 数据存储);调试模式或从 SRAM 启动时禁止写 / 擦除(整片擦除除外);仍可通过 JTAG/SWD 加载代码到 SRAM 执行 —— 这也是解除 RDP 的通道;改写 RDP 回 L0 时会自动整片擦除主存储区 |
| L2 (永久锁死) | RDP2 == 0xCC && nRDP2 == 0x33 | 在 L1 基础上:SRAM 启动禁用、调试模式禁用、选项字节写 / 页擦除禁用、保护等级不可修改(不可逆) |
从 L1 解除读保护的官方流程
1. 向 FLASH_OPTKEY 写入正确的密钥序列,解锁选项字节区
2. 总线发起命令擦除整个选项字节区(页擦除)
3. 总线向读保护选项字节写 0xA5
4. 芯片内部自动擦除全部主存储区 ← 注意这一步
5. 芯片内部自动向读保护选项字节写 0xA5
6. 系统复位,选项字节块(含新 RDP 值 0xA5)重新装载,读保护释放
- 降级必然伴随主 Flash 全擦除,这是设计使然(防数据泄露),不是 bug。 所以解除保护之前必须先把固件备份出来。
- 擦除选项字节块本身不会触发自动整片擦除(擦除结果为 0xFF,仍等效于 L1 保护状态)。 很多人在这一步困惑,就是因为只做了第2 步发现保护没解除。
工具侧操作:Nations MCU Download Tool
1. BOOT0 接高电平(或用软件跳转 BOOT),重新上电复位 → 进入芯片 BOOT 模式
2. 用 JLINK / USART / USB 任一方式连接设备
3. 打开 Nations MCU Download Tool → 左上角「常用操作」
4. 选择「使能读保护」/「解除读保护」
5. 点击「下载」执行,工具提示操作成功
工具可解除的是 L1;L2 一旦使能便无法解除(不可逆)。
也可用J-Link 侧工具:官方提供的 JLinkNsUnlockTool V1.0.1.exe(配套 JLinkNsUnlockToolConfig.ini)。
这是一个必须由产品与售后策略决定的取舍,技术上没有唯一答案:
- 选 L1 —— 保留返修通道。售后可以用专用解锁工装 + 备固件救回一台机器, 代价是攻击者也能用同样手段(需要物理接触 + 逐次尝试)。适合消费类、家电类、售后返修率高的产品。
- 选 L2 —— 调试永久禁用,防抄强度最高。适合无人值守、安装后不可拆卸的终端 (如智能电表、燃气表、工业网关)。一旦误使能,这批芯片全部报废。
建议:先在小批量上把「使能 → 解除 → 重新烧录」整个流程走通,再上量产的批量操作。 还要额外考虑一件事:功能自检必须在使能 RDP 之前完成,否则出问题时连测都测不了。
3.5 写保护 WRP 与 MMU 多用户分区
写保护 WRP:粒度很粗,但够用
| 项 | 说明 |
|---|---|
| 保护粒度 | Page 0~61:每 2 页为一个基本保护单元;Page 62~255:整体作为一个保护单元 |
| 配置寄存器 | 选项字节 WRP0 ~ WRP3(每个 32 bit,按位对应保护单元) |
| 生效条件 | 每次配置后需系统复位,新值重新装载才生效 |
| 违规后果 | 对受保护页编程 / 擦除,会在 FLASH_STS 返回保护错误标志 |
| 选项字节自身保护 | 软件写 FLASH_CTRL.OPTWE = 0 加写保护;写正确密钥序列到 FLASH_OPTKEY 解除 |
注意粒度问题:低地址区是 2 页(4 KB)一个单元,高地址区是 194 页一个单元。 这意味着 BootLoader 区(放前几页)能得到较细的保护,但 App 区只能整块保护或整块不保护 —— 所以不要指望用 WRP 做到「保护 App 的前 8 KB」。要做更细的分区,得用 MMU。
MMU 多用户分区:方案商模式的正解
典型用法是:方案商把核心算法烧录到指定分区,加密后开放给下游客户二次开发。 官方在介绍 N32L406/403 时明确提到这个用法:「N32L406/403 可运行国民技术自行开发的加密安全库, 可支持密码保护指定范围程序区,方案商烧录核心算法到此区域,提供给下游客户做二次开发, 强化了产品本身的安全性、可靠性和二次开发的使用便利度。」
分区管理的操作入口是 BOOT 指令:
| 指令 | 作用 |
|---|---|
CMD_USERX_OP | USER1 / USER2 / USER3 分区操作(擦除 / 下载 / 认证) |
CMD_KEY_UPDATE | 分区密钥更新 |
CMD_KEY_RNG + CMD_KEY_UPDATE | 分区擦除 / 下载前需先通过密钥认证 |
也就是说,分区的擦除与下载都需要密钥认证,不是随便一条指令就能改的。这是方案商模式的技术基础。
3.6 UID / UCID 与一机一密
| 项目 | UID | UCID |
|---|---|---|
| 长度 | 96 bit | 128 bit |
| 起始地址(N32G45x) | 0x1FFF_F7F0 | 0x1FFF_F7C0 |
| 存储位置 | Flash 系统配置块(System Configuration Block) | 同 |
| 烧录时机 | 制造期写入,任何情况下保证唯一 | 同 |
| 可读性 | 用户应用 / 外部设备经 CPU 或 SWD 可读 | 同 |
| 可改性 | 不可修改 | 不可修改 |
| UCID 内容 | — | 遵循国民技术芯片序列号定义,含芯片生产与版本信息 |
官方手册给出的典型读法与一机一密的用法:
#define UID_BASE (0x1FFFF7F0UL) /* 96-bit = 3 x 32bit */
#define UCID_BASE (0x1FFFF7C0UL) /* 128-bit = 4 x 32bit */
void ReadUID(uint32_t uid[3])
{
uid[0] = *(volatile uint32_t *)(UID_BASE + 0);
uid[1] = *(volatile uint32_t *)(UID_BASE + 4);
uid[2] = *(volatile uint32_t *)(UID_BASE + 8);
}
/* 官方手册建议的用法:
"当写 Flash 时,将此唯一标识与软件加解密算法结合,可进一步提高 Flash 中代码的安全性。"
典型做法 —— 用 UID 派生密钥,实现"一机一密":
SM4密钥 = SM3( UID || 厂商主密钥 || 产品型号 ) */
STM32F1 的 UID 在 0x1FFFF7E8,STM32F4 在 0x1FFF7A10,
N32G45x 在 0x1FFF_F7F0。三个地址长得像但完全不同,
从 ST 移植过来时必须改地址,否则会读到垃圾数据 ——
而且更隐蔽的问题是:读出来是「看起来合法」的随机数,不一定报错,
会导致一机一密失效或 License 校验逻辑异常。
另外:各N32 子系列的 UID 地址可能不同,G03x / L4xx 需单独查对应系列用户手册,
不要假设全系列统一在 0x1FFF_F7F0。
UID 的价值不只是「读出一个序列号」,而是密钥派生的材料。典型用法有三种,按成本从低到高:
| 用法 | 做法 | 防护强度 | 成本 |
|---|---|---|---|
| 一机一密 | Flash 加密密钥 = Hash(UID || 厂商主密钥) | 高:即使两台设备固件字节相同,Flash 里的密文也不同,批量抄板无效 | 无额外成本,推荐默认做 |
| License / 授权码 | License = f(UID) 或 RSA/SM2 签名,上位机校验 | 中:防止设备被复制到未授权的机器上 | 需要产线写入流程 |
| 密钥分散存储 | 主密钥拆成多段,分别用 UID 的不同字节加密后存不同分区 | 很高:需要多分区 + 多次派生,工程量大 | 适合高价值算法场景 |
3.7 TAMPER 防拆与时钟安全 CSS
各系列 Security Features 段统一列出:「支持时钟失效监测、防拆监测」。 这两项常被当成可靠性特性,但它们本质上是安全特性。
TAMPER 引脚映射
| 信号 | 典型引脚 | 说明 |
|---|---|---|
| TAMPER-RTC | PC13 | 侵入检测输入,可触发备份寄存器清除 + 中断 |
| OSC32_IN / OSC32_OUT | PC14 / PC15 | LSE 32.768 kHz |
| OSC_IN / OSC_OUT | PD14 / PD15(部分型号为 PD0/PD1) | HSE |
注意:TAMPER 与 RTC / PC13 复用。各封装 / 系列引脚位置不同,必须查对应 DS 引脚定义表。 更重要的是:PC13 同时是「用 LSE 时禁止翻转」的引脚之一(见 7.5 节), 如果你的产品既要 TAMPER 又要 LSE,这两件事在 PC13 上是冲突的,要靠 PCB 与软件配合取舍。
四层防拆设计实践
| 层级 | 措施 |
|---|---|
| 硬件 | 外壳微动开关 / 导电胶接到 TAMPER 引脚;PCB 走线网格覆盖在 BGA / QFN 下方 |
| 配置 | TAMPER 触发电平(高 / 低)、滤波时长、是否清除备份寄存器 |
| 响应 | TAMPER 中断中立即清除 RAM 中的密钥、置安全标志、锁死或进入自检 |
| 供电 | VBAT 由超级电容 / 电池供电,保证主电源被拔后 TAMPER 检测仍然工作 |
时钟安全系统 CSS:防的是故障注入攻击
HSE 失效 → 自动切换到 HSI,并可产生中断(NMI)。它的安全意义常被忽略: 防止攻击者通过注入或停振外部时钟,让 MCU 跑在异常时序下跳过安全检查。 这类攻击叫故障注入(Fault Injection),是针对安全启动流程的经典手段。因此CSS 不是纯可靠性特性 —— 安全启动流程里必须使能 CSS,并在 CSS 中断中进入安全失败状态。
RCC_EnableClockSecuritySystem(ENABLE); /* 名称以 SDK 为准 */
3.8 安全启动与加密下载
各系列 Security Features 中统一列出三项能力:「支持安全启动、 程序加密下载、安全更新」。这三项构成第 3 层防护。
典型安全启动流程
下面是基于官方能力声明 + 行业通行实现整理的推荐流程(官方未公开一份端到端的参考实现, 所以具体实现需要按自己的方案设计):
上电复位
│
├─► 芯片内部 BOOT ROM / 用户安全引导区运行(受保护,不可擦改)
│
├─► 读取固件头(版本号 + 长度 + 签名 + 公钥 Hash)
│
├─► 硬件 HASH 引擎计算固件镜像摘要(SHA-256 或 SM3)
│
├─► 硬件非对称引擎验签(RSA/ECC,或 SM2 —— 依系列能力)
│ └─ 公钥可固化在 BootLoader,或存于受保护分区;
│ 公钥 Hash 烧入 OTP / 选项字节
│
├─► 验签通过 → 解密(若 Flash 加密)→ 跳转用户程序
│
└─► 验签失败 → 进入恢复模式 / 锁死 / 触发 TAMPER 事件
G4xx 的硬件引擎覆盖了摘要(SM3 / SHA 系列),但官方 Datasheet 的 Security Features 没有列非对称算法(RSA / ECC / SM2)。这意味着:
- 摘要可以在硬件里算(快、省时间),
- 验签需要软件实现一个大数运算库,或者外挂 N32S 安全芯片 / 外部安全芯片协处理。
所以如果你在 G455 上做安全启动,真实的架构通常是:G455 负责加载 + 摘要 + 跳转, 验签交给一颗 N32S032 或外部 ATECC 之类的器件,两颗芯片之间用 I2C 或 SPI 通信。 这个架构决策必须在方案阶段做,不能等到固件写完才想起来。 如果项目本身就在 N32A455 或 N32S 上做,这层约束就不存在。
加密下载:产线防抄的核心
官方 BOOT 使用指南明确:支持加密下载(AES-128 ECB)。 指令级流程见图7,产线侧的组合建议见 10.3 节。
来源:AN_N32G45x & N32G4FR & N32WB452 Series BOOT interface instruction user guide
安全更新与差分 OTA
国民技术生态资料提到支持「差分 OTA 升级」的行业方案。安全更新有三个要素,缺一不可:
| 要素 | 做法 | N32 上的落点 |
|---|---|---|
| 镜像签名验签 | 整包或差分包都要有签名,BootLoader 侧验签 | HASH 引擎做摘要;非对称验签按 3.8 框的架构处理 |
| 传输加密 | 固件在传输链路上是密文 | BOOT 加密下载(AES-128 ECB);应用层可用 SM4 |
| 回滚保护 | 版本号单调递增,低于当前版本拒绝升级 | 存备份寄存器(VBAT 域,主电源掉电也不丢)或 D-Flash |
3.9 安全能力落地检查清单
把前面四层结构翻译成可勾选的 14 项。这张清单建议直接贴到产品安全评审的 checklist 里: 它同时覆盖了开发阶段、产线阶段和售后阶段的动作。
| # | 项 | 所属层 | 完成 | 说明 |
|---|---|---|---|---|
| 1 | 使能 RDP L1(或 L2,视是否需返修) | 存储保护 | ☐ | L2 不可逆,量产后无法调试 |
| 2 | 配置 WRP 保护 BootLoader 区 | 存储保护 | ☐ | L1 下Page 0~1 已自动保护,其余段需手配 |
| 3 | 使能 Flash 存储加密 | 存储保护 | ☐ | 从工具或代码配置;读出即密文 |
| 4 | 规划 MMU 分区(Boot / App / 算法库 / 数据) | 存储保护 | ☐ | 算法区给下游二次开发时开放 |
| 5 | 实现安全启动:HASH + 验签 | 启动链 | ☐ | 用硬件 SHA / SM3 引擎算摘要;验签架构见 3.8框内说明 |
| 6 | 公钥 Hash 固化(OTP 或选项字节) | 启动链 | ☐ | 防公钥被替换 |
| 7 | 版本号单调防回滚 | 启动链 | ☐ | 存备份寄存器或 D-Flash |
| 8 | 使能 CSS 时钟安全系统 | 物理防护 | ☐ | 防时钟故障注入攻击 |
| 9 | 配置 TAMPER(引脚 + 触发行为 + 清密钥) | 物理防护 | ☐ | 外壳防拆;注意与 LSE 在 PC13 上的冲突 |
| 10 | 密钥派生绑定 UID(一机一密) | 物理防护 | ☐ | UID @ 0x1FFF_F7F0;成本最低、收益最高的一项 |
| 11 | 量产加密下载(AES-128 ECB) | 启动链 | ☐ | 见 3.8 与第 10 章 |
| 12 | 禁用 / 收敛调试口(SWD 复用为 GPIO 或物理去除) | 物理防护 | ☐ | L2 也能禁调试,但要在设计时就决定 |
| 13 | 保留返修通道(L1 + 专用解锁工装) | 流程 | ☐ | L2 无返修通道;不要量产就用 L2 |
| 14 | 记录 UID ↔ 产品 SN 对应关系 | 流程 | ☐ | 追溯与授权;流程见 10.4 |
按投入产出比排序,最值得优先投入的三项是:
- 第 10 项(一机一密) —— 零额外硬件成本,纯软件派生密钥, 直接把「批量抄板」这条路堵死。大部分产品不做安全启动也应该做这一项。
- 第 1 项(RDP L1) —— 工具点两下的事情,挡住 90% 的「编程器读出」类攻击。
- 第 11 项(加密下载) —— 产线侧的一次性配置,挡住「从代工厂流出的固件被抄走」。 如果你的产品要交给代工厂生产,这项的优先级应该提到第一位。
4 · 开发环境与工具链
这一章解决「第一次把 N32 跑起来」的所有问题:装什么IDE、装什么包、 工程怎么配、调试器怎么连、程序怎么烧进去。
4.1 工具链全景与选型
来源:nationstech.com 固件和软件页 + 官方资料包清单
下表是官方资料里能拿到的全部选项与支持度。「支持度」列反映的是原厂提供资料的程度,不是软件质量 —— 社区方案往往更灵活,但遇到问题时能查的资料少。
| 类别 | 选项 | 官方支持度 | 备注 |
|---|---|---|---|
| IDE | Keil MDK(含 DFP pack) | ★★★★★ | 主力,官方提供 PACK 包 |
| IAR EWARM | ★★★★ | 官方提供「IAR 补丁包」(支持 IAR v7.x 及以上,V1.7.0) | |
| GCC + Eclipse(官方环境包) | ★★★ | 官方提供「GCC-N32Gxxx 开发环境搭建」包 | |
| VSCode + GCC + OpenOCD / pyOCD | ★★★ | 社区方案,需自行配置 | |
| RT-Thread Studio | ★★★ | 通过 RT-Thread BSP 使用 | |
| SEGGER Embedded Studio | ★★ | 需自行导入 CMSIS-Pack / 寄存器 SVD | |
| 固件库 | 标准外设库(StdPeriph_Driver,ST SPL 风格) | ★★★★★ | 主力 |
| CMSIS-Pack / DFP | ★★★★★ | Keil 组件 | |
| N32Cube(初始化代码生成) | ★★★ | N32Cube_for_G03x(解压密码 n32) | |
| HAL 库 | ★★ | 部分系列提供;官方 SDK 主推仍是 StdPeriph | |
| 调试下载 | NS-Link / NS-Link-Pro(官方) | ★★★★★ | SWD / JTAG;NS-Link-Pro 支持量产离线 |
| J-Link(需补 JLinkDevices.xml) | ★★★★ | 官方提供补丁包 V1.6.0 | |
| CMSIS-DAP / DAPLink | ★★★ | 官方提供「CMSIS-DAP 驱动及安装指南」;多款 STB 板载 | |
| ULINK | ★★★ | 官方提及支持 | |
| ST-Link | ✗ | 明确不支持(第三方烧录指南明确记载) | |
| ISP 下载 | Nations MCU Download Tool | ★★★★★ | 串口 / USB(DFU) / NSLINK(SWD) |
| 量产 | NS 单路 / 多路量产在线·离线下载工具、第三方烧录器 | ★★★★★ | 第三方清单 V1.1.2 |
这条经常被忽略,然后在项目中期才发现:团队人手一台 ST-Link 是最常见的现状, 但 N32 明确不支持 ST-Link(绿都电子《国民技术单片机烧录指南》明确记载)。 这意味着 N32 项目必须额外配置调试器,有三种务实的选择:
- NS-Link —— 官方标配,最省事,配合 Nations MCU Download Tool 走 SWD 还能免拉高 BOOT0。
- CMSIS-DAP / DAPLink —— 最便宜(一个几十元的板子),多款 N32 官方 STB 评估板板载。 配 Keil 的 CMSIS-DAP Debugger 直接可用。
- J-Link —— 性能最好,但要手动合并
JLinkDevices.xml(见 4.4 节坑点)。
建议:立项评审时把「调试器采购」列为独立条目,不要假设能沿用现有的 ST-Link。
4.2 Keil MDK 与 DFP 安装
PACK 包命名与获取
官方资源页「固件和软件 → IDE 环境包」栏给出如下命名规则与版本要求:
KEIL-N32G030 N32G030 系列 KEIL 开发环境的 PACK 包,支持 KEIL v5.28 及以上 V1.0.4
KEIL-N32G031 ... V1.0.6
KEIL-N32G032 ... V0.2.3
KEIL-N32G43x ... V1.x
KEIL-N32L43x ... V1.x
KEIL-N32G052 ... V1.1.0
IAR NSING MCU 基于 IAR 开发环境添加型号的补丁包,IAR v7.x.x+ V1.7.0
JLink NSING MCU 基于 SEGGER J-Link 添加型号的补丁包,J-Link v6.x.x+ V1.6.0
GCC-N32G030N32G030 系列 GCC 开发环境搭建 V1.1
GCC-N32G052 ... V1.2.0
N32Cube N32Cube_for_G03x 初始化代码生成工具,解压密码:n32 V1.0.2
PACK 文件名形态有两种厂商前缀(历史原因):Nationstech.N32G45x_DFP.1.0.6.pack 与
Nations.N32G430_DFP.1.0.0.pack。安装时两种都会被 Keil 识别,在 Pack Installer 里搜「N32」即可。
安装五步
1. 从官网产品页 →「固件和软件」→「IDE 环境包」下载对应系列 PACK
2. 双击 .pack 文件 → Keil Pack Installer 自动安装(不要手动解压)
3. 打开 Keil → Pack Installer(小立方体图标)搜索 "N32" 确认已安装
4. 新建工程 → Device 数据库选择 "Nationstech :: N32G455REL7"(或对应型号)
5. MDK 自动加载:启动代码、头文件路径、宏定义(如 __N32G455CB__)、
Flash 编程算法、调试配置
- Keil 版本太老 —— 不认识新 PACK 的安装描述格式。官方 PACK 要求 Keil v5.28 及以上。
- Keil 安装路径含中文 —— 装不上或装了异常。
- 多用户 / 多版本冲突 —— 以管理员权限装了一个、普通用户又装了一个。
统一处置:卸载重装到纯英文路径(例如 C:\Keil_v5),只装一份。
新建工程必配:三个 Include 路径 + 一个宏
Include Paths:
├── firmware/CMSIS/Device/Include (或 CMSIS/device)
├── firmware/CMSIS/Include(core_cm4.h 等)
└── firmware/N32G45x_StdPeriph_Driver/inc
C/C++ → Define:
USE_STDPERIPH_DRIVER, <器件宏 如 N32G455xx>
还要把 N32G45x_StdPeriph_Driver/src 下的 .c 源文件加入工程。
编译器版本与 Flash 编程算法
| 项 | 建议 / 事实 | 说明 |
|---|---|---|
| 编译器 | AC5(armcc)与 AC6(armclang)均可 | 从 ST 老工程迁移时建议先切 Use default compiler version 5,确保老的汇编启动文件能编过 |
| RT-Thread 官方测试版本 | MDK5 V5.34 | IAR V8.50 / GCC 6.2.1 20161205 |
| N32G45x Flash 算法 | N32G45x_512K.FLM(按容量选 128 / 256 / 512K) | 在 Options for Target → Utilities 里设置 |
| N32G03x Flash 算法 | 官方提供「下载算法包」= 基于 Keil 的 Flash 编程算法源代码工程(V1.0.x) | 可自行编译,不需等官方出 .FLM |
| N32L43x Flash 算法 | 「N32L43x 系列基于 Keil 开发环境的 Flash 编程算法源代码工程」V1.1.0 | 同上 |
Flash 编程算法里的擦除 / 写入起始地址默认应为 0x0800_0000。
如果算法里的地址配错、或链接脚本的 ORIGIN 不是 0x0800_0000,
就会出现「烧录提示成功但程序不运行」或「Keil 一直擦除失败」。
排查顺序:① 看链接脚本的 FLASH ORIGIN;② 看 Flash 算法文件的 Start Address; ③ 两者必须一致,且等于 MCU 的主存储区基址。
4.3 SDK 目录结构
官方 SDK 的通用结构(以 N32G43x 为例):
N32G43x_SDK/
├── Docs/ # 版本说明、芯片文档索引、readme ← 先看它!
├── Libraries/
│ ├── CMSIS/
│ │ ├── device/ # startup_n32g43x.s、system_n32g43x.c、n32g43x.h
│ │ └── include/ # core_cm4.h 等
│ └── N32G43x_StdPeriph_Driver/
│ ├── inc/ # n32g43x_gpio.h ...
│ └── src/ # n32g43x_gpio.c ...
├── Projects/
│ ├── Examples/ # 按外设分目录:GPIO / UART / ADC / SPI / TIM ...
│ └── Templates/ # 裸机模板、HAL 模板
└── Tools/
N32G430 的实际 SDK(第三方实操帖记录的形态,注意它多了一层中文目录):
N32G430xx_V1.0.0\
└── 6.软件开发套件\
├── PACK\
│ └── Nations.N32G430_DFP.1.0.0.pack
└── Nations.N32G430_Library.1.0.0\
└── projects\
└── n32g430_EVAL\
└── examples\
└── GPIO\
└── MDK-ARM (Keil 工程)
通用资料包(工具都在这里,不在 SDK 里):
GeneralFile_V1.0.6
└── CommonPlatform_V1.0.6
└── Tools
├── CMSIS-DAP驱动及安装指南\
├── Nations MCU Download Tool V1.3.2\
├── Nations MCU Download Tool V1.3.2.7z
├── NS general MCU multiple download tool V1.0.7.7z
└── 第三方量产下载工具清单V1.1.2.xlsx
Projects/Examples/ 下的官方例程是最权威的参考,比任何教程都准。
遇到「这个外设怎么配置」,第一件事应该是打开对应目录下的例程对照。
本文后面第 5 章的所有代码片段,函数命名风格都是照着这个目录的风格写的。
4.4 调试器:NS-Link / J-Link / CMSIS-DAP
NS-Link / NS-Link-Pro(官方,推荐首选)
- 支持 SWD / JTAG,支持 Flash 编程、在线调试、断点跟踪。
- NS-Link-Pro 额外支持量产在线 + 离线下载,产线方案要考虑它。
- 用 Nations MCU Download Tool 通过 NSLINK(SWD) 烧录时,不需要拉高 BOOT0 —— 这是 NS-Link 相对其他调试器的最大优势(但仅限 NSLINK,其他烧录器不支持走上位机 SWD 口烧录)。
- 资料包:「NSLink 安装、使用、升级资料包」V1.0.0。
J-Link:需要手动添加设备
官方提供的 jlink工具添加Nationstech芯片Vx.x.x 资料包内容:
Device/ # 下载算法文件(如 N32G45x.FLM)
Samples/ # J-Flash 工程
Nationstech-JLinkDevices.xml # 需添加的国民技术芯片型号描述
JLinkNsUnlockTool V1.0.1.exe # 解锁国民技术芯片读保护 L1 的应用程序
JLinkNsUnlockToolConfig.ini # 解锁工具配置文件
jlink工具添加Nationstech芯片流程_V1.0.pdf # 官方教程(推荐先读这个)
配置步骤:
1. 把 N32G45x.FLM 复制到 Keil 安装目录 ARM\Flash\ 下
2. 把 Devices / Sample 目录内容复制到 J-Link 安装目录对应位置
3. 修改 JLinkDevices.xml,把 Nationstech-JLinkDevices.xml 内容合并进去
Keil 使用的 J-Link 是 Keil 安装目录下的副本,它的 JLinkDevices.xml
不一定在 Keil 安装目录里。改错了地方的表现是「J-Link 在别的工具里能认到 N32,
但 Keil 里还是 Unknown device」,或者「改了完全没效果」。
处置:先定位真实的 xml 路径再改。改完后不要只在 Keil 里验证, 用命令行直接验:
JLink.exe
> connect
> ? # 按提示选 SWD / 指定器件
> # 能读出芯片 ID 即配置成功CMSIS-DAP / DAPLink
- 官方资料包含「CMSIS-DAP 驱动及安装指南」。
- 国民技术多款 STB 评估板板载 CMSIS-DAP 调试器(如 N32G45XRL-STB 的 J4 接口),零成本。
- Keil 里配置:Debug → Use:
CMSIS-DAP Debugger→ Settings → SW。
四类接口的引脚
| 接口 | 引脚 | 说明 |
|---|---|---|
| SWD(推荐,2 线) | SWDIO (PA13)、SWCLK (PA14)、GND、VCC(可选) | 默认调试口;N32 IDE 与 Keil 默认都用它 |
| JTAG(5 线) | TMS、TCK、TDI、TDO、nTRst | 占用更多引脚(PA13~PA15 + PB3/PB4),量产产品常引出但不用 |
| 串口 ISP | USART1 TX = PA9 / RX = PA10 | BOOT 模式;产线主力通道 |
| USB DFU | USB_DP = PA12 / USB_DM = PA11 | BOOT 模式;需型号支持 USB BOOT |
来源:BOOT interface instruction user guide + 官方使用指南
以 N32WB452 为例,不同型号的 BOOT 串口引脚完全不同:
| 系列 / 型号 | USART1-TX | USART1-RX | USB-DP | USB-DM |
|---|---|---|---|---|
| N32G452 / G455 / G457 | PA9 | PA10 | PA12 | PA11 |
| N32WB452REQ6 | PA9 | PA10 | PA12 | PA11 |
| N32WB452LEQ6 / CEQ6 | PB6 | PB7 | PA12 | PA11 |
做板前务必核对该型号的引脚表,WB 系列尤其容易踩。
4.5 串口 ISP 与 BOOT 模式
进入 BOOT 的两种方式
| 方式 | 操作 | 适用场景 |
|---|---|---|
| 硬件 | BOOT0 引脚拉高,重新上电 / 复位 MCU | 常规产线与开发调试 |
| 软件 | 用户程序内跳转到 BOOT(官方提供例程) | BOOT0 引脚不方便改动的场景(比如已经灌胶的产品) |
官方硬件设计指南原文:「BOOT 引脚拉高,芯片复位后从 BOOT 区启动;BOOT 引脚拉低,芯片复位后从用户区启动。」
波特率协商:两条路径
上电后接口自动识别(USART / USB),波特率有两种协商方式:
| 方式 | 适用 BOOT 版本 | 流程 |
|---|---|---|
| A · 串口自动波特率检测 | 仅 BOOT V2.1 | 上电后上位机通过串口发送 0x7F,MCU 检测该数据并识别上位机波特率 |
| B · 串口波特率协商 | V2.1 / V2.2 通用 | ① 上电后以 9600 bps 通信 → ② 上位机发送 CMD_SET_BR 设置目标波特率 → ③ MCU 应答成功后再切换 → ④ 目标波特率不支持则返回失败状态 |
两代 BOOT 的波特率对照
| BOOT 版本 | 支持的波特率 | 限制 |
|---|---|---|
| V2.1 | 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 128000 | 全部支持。适用外部/内部时钟 4 / 6 / 8 / 12 / 16 / 24 / 32 MHz |
| V2.2(扩展) | 2400, 4800, 9600, 14400, 19200, 38400, 57600, 115200, 128000, 256000, 576000, 923076, 1M, 2M, 2.25M | 外部时钟 16 MHz 与 32 MHz、内部时钟 8 MHz 时,2M 与 2.25M 不支持 |
| N32G032(独立 BOOT 文档) | 4800, 9600, 14400, 19200, 38400, 57600, 115200, 128000, 256000, 576000, 923076 | 初始 9600 bps;BOOT 区 3 KB,SRAM 8 KB,系统时钟配置为 48 MHz |
BOOT 指令集(N32G45x / G4FR / WB452,V2.1 与 V2.2 通用)
| 命令 | 名称 | 功能 |
|---|---|---|
CMD_SET_BR | 设置波特率 | 协商串口波特率 |
CMD_GET_INF | 获取信息 | 芯片型号 / BOOT 版本 / Flash 容量 / 分区信息 |
CMD_KEY_RNG | 取随机数 | 供上位机生成会话密钥 |
CMD_KEY_UPDATE | 更新密钥 | 分区密钥更新 / 认证 |
CMD_FLASH_ERASE | Flash 擦除 | 下载前必须先擦除对应页 |
CMD_FLASH_DWNLD | Flash 下载 | 程序 / 数据下载,支持 AES-128 ECB 加密 |
CMD_DATA_CRC_CHECK | 数据 CRC 校验 | 对下载数据做 CRC32 校验 |
CMD_OPT_RW | 选项字节读写 | RDP / WRP / USER 配置 |
CMD_USERX_OP | 用户分区操作 | USER1 / USER2 / USER3 分区擦除 / 下载 / 认证 |
CMD_SYS_RESET | 系统复位 | 软件复位芯片 |
其他官方能力:上电 BOOT 自校验(power-on BOOT self-verification)、 跳转到用户区执行、Flash 分区与分区擦除下载的密钥认证、加密下载(AES-128 ECB)。 状态字分「成功状态字 / 失败状态字 / 其他状态字」(详见指南 2.3 节)。
N32G032 的指令集是精简版:CMD_SET_BR、CMD_GET_INF、CMD_FLASH_ERASE、
CMD_FLASH_DWNLD、CMD_DATA_CRC_CHECK、CMD_OPT_RW、CMD_SYS_RESET、
CMD_APP_GO——没有 CMD_KEY_RNG / CMD_KEY_UPDATE / CMD_USERX_OP,
所以 G032 上做不了分区密钥认证的加密下载。
4.6 从零到点灯
最小工程三步走(Keil)
第一步:新建工程,Device 选 N32G455REL7(若无对应器件,先装 DFP)
第二步:把 firmware/CMSIS 与 firmware/N32G4xx_StdPeriph_Driver/src 下的 .c 加入工程
头文件路径加三处:CMSIS/Device/Include、CMSIS/Include、StdPeriph_Driver/inc
第三步:写 main —— 开 GPIO 时钟 → 配置引脚 → 翻转电平
#include "n32g45x.h"
int main(void)
{
GPIO_InitType GPIO_InitStructure;
/* 1. 使能 GPIOB 时钟 —— 一切外设前必须先开时钟 */
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB, ENABLE);
/* 2. 配置 PB2 推挽输出 50 MHz */
GPIO_InitStructure.Pin = GPIO_PIN_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
/* 3. 翻转 */
while (1)
{
GPIO_SetBits(GPIOB, GPIO_PIN_2);
delay_loop(500000);
GPIO_ResetBits(GPIOB, GPIO_PIN_2);
delay_loop(500000);
}
}
- 函数名在不同 SDK 版本间有差异:如
GPIO_InitPeripheralvsGPIO_Init、GPIO_SetBitsvsGPIO_SetBit。以所用 SDK 头文件为准,不要照抄本文。 - 忘了开时钟 —— 寄存器写进去但不生效。这是 N32 / STM32 新工程最常见的第一死因。
- Speed 填成电压 ——
GPIO_Speed_50MHz是输出翻转速率,不是输出电压。 EMI 敏感场合应降到 2 MHz 或 10 MHz。
时钟配置:最关键也最容易错的一段
/* 若外接 12 MHz 晶振,PLL 倍频系数必须匹配
错误示例:HSE=12MHz 时 PLL_MUL 仍填 18 → SYSCLK = 216 MHz 超规格
后果:程序随机死机或复位(表现为「跑一会儿就挂」) */
RCC_ConfigPll(RCC_PLL_SRC_HSE_DIV1, RCC_PLL_MUL_12, ...); /* 正确:12×12 = 144 */
/* 改完务必验证实际时钟 —— 这一步不能省 */
RCC_ClocksType clocks;
RCC_GetClocksFreq(&clocks);
printf("SYSCLK=%lu HCLK=%lu PCLK1=%lu PCLK2=%lu\r\n",
clocks.SysclkFreq, clocks.HclkFreq,
clocks.Pclk1Freq, clocks.Pclk2Freq);三个最常见的编译错误
| 现象 | 原因 | 处置 |
|---|---|---|
一堆 undefined identifier | Include Paths 没加 StdPeriph_Driver/inc | 魔术棒 C/C++ → Include Paths 补齐三处 |
| 标准外设库头文件未生效 | 缺 USE_STDPERIPH_DRIVER 宏 | C/C++ → Define 加上 |
| 启动文件 / 汇编报错 | 用 AC6 编老的 .s 文件 | 切回 Compiler Version 5,或换成 AC6 版启动文件 |
4.7 编译选项与链接脚本
GCC 编译选项(参考 RT-Thread BSP)
CFLAGS = -mcpu=cortex-m4 -mthumb
+= -mfpu=fpv4-sp-d16 -mfloat-abi=hard /* M4F 硬件浮点 */
+= -DUSE_STDPERIPH_DRIVER
+= -ffunction-sections -fdata-sections /* 配合 --gc-sections */
LDFLAGS = -T board/linker_scripts/link.lds
+= -Wl,--gc-sections -Wl,-Map=rtthread.map
+= -specs=nano.specs -specs=nosys.specs /* newlib-nano 减小体积 */
链接脚本 / 分散加载文件
| 工具链 | 文件 | 典型内容 |
|---|---|---|
| GCC | link.lds | FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512KRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 144K |
| Keil armcc | link.sct | 分散加载描述,例:LR_IROM1 0x08000000 0x00080000 { ... } |
| IAR | link.icf | define symbol __ICFEDIT_region_ROM_start__ = 0x08000000; |
堆栈配置(RT-Thread 迁移时最常踩)
- OS 初始化卡死 —— 常见原因是堆栈空间设置不当。需要调大
rtconfig.h中的RT_MAIN_THREAD_STACK_SIZE或启动文件里的栈大小。 - N32G45x 的 144 KB SRAM 中16 KB 是 Retention RAM,链接时可以按需规划(通常留给低功耗保持区)。
N32G45x 内存布局
| 区域 | 起始地址 | 大小 | 说明 |
|---|---|---|---|
| Main Flash | 0x0800_0000 | 最大 512 KB | 程序 / 常量 |
| System Memory(BOOT) | 内部 | 16 KB | 出厂 BootLoader,不可改 |
| System Config Block | 0x1FFF_F7C0 起 | 2 KB | UID @ 0x1FFF_F7F0 / UCID @ 0x1FFF_F7C0 |
| Option Bytes | — | 2 KB | RDP / WRP / USER |
| SRAM | 0x2000_0000 | 144 KB(含 16 KB Retention) | |
| 外设寄存器 | 0x4000_0000 起 | — | APB1 / APB2 / AHB |
| Cortex-M4 外设 | 0xE000_0000 起 | — | NVIC / SysTick / MPU / FPU |
VSCode + GCC + OpenOCD(社区方案)
// .vscode/tasks.json
{ "label": "build", "type": "shell", "command": "make",
"args": ["-j8"], "group": { "kind": "build", "isDefault": true } }
// .vscode/launch.json(cortex-debug 扩展)
{ "name": "Debug N32 (OpenOCD)", "type": "cortex-debug", "request": "launch",
"servertype": "openocd", "device": "N32G45x",
"configFiles": ["interface/cmsis-dap.cfg", "target/n32g45x.cfg"],
"executable": "./build/n32.elf", "svdFile": "./N32G45x.svd", "runToMain": true }
OpenOCD 官方 upstream 对 N32 的 target 支持不完整。社区常见的三种绕行做法:
- 直接用
target/stm32f4x.cfg之类的近似 target(读 IDCODE 可能不匹配,需改set _CPUTAPID); - 用 pyOCD + 从 DFP pack 提取的器件描述生成 target;
- 用 NS-Link 的 CMSIS-DAP 模式 + pyOCD。
这部分属社区经验,未获官方确认,标记为「未核实」。如果你的团队不熟悉 OpenOCD 调试配置, 直接用 Keil 或 N32 IDE 会省下大量时间。
4.8 RT-Thread 与 N32Cube
| 工具 | 说明 |
|---|---|
| RT-Thread Studio | 内置 N32 BSP,可直接创建 RT-Thread 工程,图形化配置组件(FinSH、文件系统、网络) |
| N32Cube | 国民技术自研的初始化代码生成工具(类似 STM32CubeMX);当前公开版本为 N32Cube_for_G03x V1.0.2,解压密码:n32 |
RT-Thread BSP 结构(n32g45xrl-stb)
bsp/n32/n32gxx_lxx/n32g45xrl-stb/
├── applications/ # 用户应用 main.c
├── board/
│ ├── board.c / board.h # 系统时钟初始化、堆内存配置
│ ├── linker_scripts/
│ │ ├── link.lds # GCC
│ │ ├── link.sct # MDK(armcc) 分散加载
│ │ └── link.icf # IAR
│ └── N32G45x_Firmware_Library/
│ ├── CMSIS 器件头文件
│ ├── n32g45x_std_periph_driver/
│ └── USB FS driver
├── Kconfig / SConscript / SConstruct
├── rtconfig.h / rtconfig.py
├── project.uvprojx / .uvoptx # MDK5
└── project.ewp / .ewd / .eww # IAR
官方测试版本:MDK5 V5.34 / IAR V8.50 / GCC 6.2.1 20161205。
三部工具链配置(rtconfig.py)
| 工具链 | 关键配置 |
|---|---|
| GCC | 前缀 arm-none-eabi-,CPU cortex-m4,-mfpu=fpv4-sp-d16 -mfloat-abi=hard,链接 board/linker_scripts/link.lds,产物 rtthread.bin |
| MDK5 (armcc) | --cpu Cortex-M4.fp,散列文件 board\linker_scripts\link.sct,产物 rtthread.bin |
| IAR (iccarm) | --cpu=Cortex-M4 --fpu=VFPv4_sp,链接 board/linker_scripts/link.icf |
BSP 引脚映射示例(N32G457REL7 STB 板)
| 功能 | 引脚 | 功能 | 引脚 |
|---|---|---|---|
| USART1_TX / RX | PA9 / PA10 | SPI1_NSS | PA4 |
| USART2_TX | PA2 | SPI2_NSS | PB12 |
| USART3_TX | PB10 | SPI3_NSS | PA15 |
| UART4_TX | PA13 | ADC1_IN2 | PA1 |
| UART5_TX | PB13 | ADC2_IN1 | PA4 |
| UART6_TX | PB0 | ADC3_IN1 | PB11 |
| UART7_TX | PC2 | ADC4_IN4 | PB14 |
| CAN1_RX | PB8 | DAC_OUT1 | PA4 |
| CAN2_RX | PB12 | LED1 / 2 / 3 | PA8 / PB4 / PB5 |
| KEY1 / 2 / 3 | PA4 / PA5 / PA6 | WAKEUP | PA0 |
官方 BSP 的外设支持矩阵只包含:UART、GPIO、I2C、SPI、ADC、CAN、DAC、CLOCK_TIMER、WDT、RTC。 USB、SDIO、XFMC、OPAMP、COMP、Touch、QSPI、Crypto 都没有,需要自行适配。
另外注意 UART4_TX 用了 PA13 —— 这也是 SWDIO 引脚。如果你的 BSP 配置占用了 PA13, 调试口会被复用掉,表现为「下载一次之后就再也连不上了」。用 BSP 时务必检查这三个引脚 (PA13/PA14/PA15/PB3/PB4)与调试口的冲突。
已收录的 N32 BSP(v5.0.1 ChangeLog)
n32g43xcl-stb、n32g457qel-stb、n32g45xcl-stb、n32g45xml-stb、
n32g45xrl-stb、n32g45xvl-stb、n32140xcl-stb、n321436_evb、
n32143xml-stb、n32143xrl-stb、n32wb45xl-evb、n32g4frml-stb
串口默认控制台:115200-8-1-N。
5 · 外设与驱动开发
本章按「从 STM32 迁移时最容易踩坑」的顺序组织,而不是按外设分类。 每一节都标出与 STM32 的差异点。
5.0 先看N32G455 的外设总量
对外部设之前,先建立总量概念 —— 这决定了你能用什么方案,省掉多少外部器件。
来源:N32G455 Datasheet + Product Brief
看完这张图,最该记住的三件事:
- 4 个 ADC 可配置为同步 / 交错采样 —— 这是 N32G455 在电机、BMS 场景的核心卖点。 做电机三相电流 + 母线电压同步采样时,采样时刻一致性直接影响控制精度。
- 4 路 OPAMP(32× PGA)+ 7 个 COMP(64 级基准) —— 可以省掉外部运放与比较器。 COMP 输出还能直接连TIM 的 Break 输入做硬件级过流保护。
- USB 只有 Device,没有 Host —— 需要 USB Host / OTG 就得上 N32H49x。
5.1 总线与时钟使能
| 总线 | 挂载的外设 |
|---|---|
| AHB | CPU、DMA、Flash、SRAM、XFMC |
| APB2(高速) | GPIO、USART1、SPI1、TIM1 / TIM8、ADC、EXTI、AFIO |
| APB1(低速) | USART2~7、SPI2 / SPI3、I2C、CAN、USB、TIM2~7、RTC、WWDG、PWR、BKP |
N32G45x 有内部高速 AHB 总线 + 2 条低速外设总线 APB + 总线矩阵(官方 DS 描述)。
使用任何外设前必须先开时钟:RCC_EnableAPB2PeriphClk() /
RCC_EnableAPB1PeriphClk()。不开时钟写寄存器,寄存器写进去了但不生效 ——
这是新工程第一死因。
注意定时器的倍频规则:APB 预分频 ≠ 1 时,定时器时钟会 ×2(与 STM32 一致)。 按官方时钟树章节配置时要注意这条。
5.2 GPIO 与 EXTI
工作模式(与 STM32 SPL 命名基本一致)
| 模式 | 宏名(参考) | 说明 |
|---|---|---|
| 模拟输入 | GPIO_Mode_AIN | ADC / DAC / OPAMP / COMP;低功耗时未用 IO 必须设成这个 |
| 浮空输入 | GPIO_Mode_IN_FLOATING | 需外部上下拉 |
| 上拉输入 | GPIO_Mode_IPU | 内部上拉 |
| 下拉输入 | GPIO_Mode_IPD | 内部下拉 |
| 推挽输出 | GPIO_Mode_Out_PP | 强驱动,LED / 驱动 |
| 开漏输出 | GPIO_Mode_Out_OD | I2C、线与、5V 电平转换 |
| 复用推挽 | GPIO_Mode_AF_PP | UART TX、SPI、PWM |
| 复用开漏 | GPIO_Mode_AF_OD | I2C SDA / SCL |
速度档:GPIO_Speed_2MHz / GPIO_Speed_10MHz / GPIO_Speed_50MHz。
Speed 是 IO 翻转速率,不是输出电压。EMI 敏感场合降到 2 MHz 或 10 MHz。
硬件约束
| 项 | 参数 |
|---|---|
| 最大GPIO 数 | N32G455:80;N32G457:97;N32L43x:64;N32G052:61;N32G032R8L7:56 |
| 翻转速度 | 最大 50 MHz |
| 5 V 耐受 | 多数 GPIO 支持 5 V 耐压(非全部,需查 DS 引脚表的 FT / FTf 标记) |
| 上电脉冲 | 上电期间 IO 有不确定脉冲,敏感负载需硬件处理(官方硬件设计指南 1.8 章) |
| LSE 相邻引脚 | 使用 LSE 时,PC13 与 PD0(LQFP64 例)不能有 GPIO 翻转信号,否则 LSE 不稳定 |
复用 AF 与重映射
- N32 提供 AFIO 模块做引脚重映射(remap),机制与 STM32F1 类似。
- 差异警告:N32 的重映射选项数量可能与 STM32 不同(例如 SPI1 的 NSS 重映射选项更少),
移植时必须查 DS的
Alternate function表。 - JTAG / SWD 引脚释放:通过 AFIO 把 PA13 / PA14 / PA15 / PB3 / PB4 释放为普通 GPIO (会失去调试能力,慎用;需留 ISP 通道)。
上电默认状态差异(STM32F103 → N32G45X,实测经验,部分未核实)
| 引脚 | STM32F103 | N32G45X | 硬件影响 |
|---|---|---|---|
| PA8 | 浮空输入 | 启动阶段下拉输入 | 外接上拉可能冲突,LED 会闪一下 |
| BOOT0 | 浮空输入 | 固定下拉输入 | 需强上拉才能进 BOOT 模式 |
| PB2(BOOT1) | 浮空输入 | 固定下拉输入 | 复用功能注意初始电平 |
| JTAG 引脚 | 浮空输入 | 固定上拉(PB3 除外) | 调试口上下拉需重新评估 |
这个现象在移植时经常被当成「硬件有问题」上报。实际上是 N32G45X 在启动阶段 PA8 是下拉输入, 而你的 LED 电路是上拉 + LED 到地,所以从输入切到推挽输出之间会有一次电平跳变。 处置:不用管它。但如果你把这个引脚接了继电器驱动或敏感电路, 就要在硬件上考虑这个启动脉冲的影响 —— 官方硬件设计指南 1.8 章专门讲了「上电期间 IO 脉冲」。
EXTI:移植时最关键的一处差异
| 项 | 说明 |
|---|---|
| 线数 | 0~19(典型;具体以系列手册为准) |
| 触发 | 上升沿 / 下降沿 / 双边沿 |
| 模式 | 中断模式 / 事件模式(事件可唤醒而不进 ISR) |
| GPIO 映射 | EXTI0~15 经 AFIO 选择 PA / PB / PC / ... 的对应位 |
| 专用线 | EXTI16 = PVD,EXTI17 = RTC Alarm,EXTI18 = USB Wakeup,EXTI19 = 以太网唤醒(G457),EXTI20 = RTC 唤醒 / 侵入 |
STM32F103 用 RTC_IRQn;N32G45X 改为 EXTI20 中断。
从 ST 移植过来如果不改,RTC 唤醒中断永远不会进ISR,表现为
「低功耗唤醒功能失效」或「RTC 闹钟不触发」,而且编译器不会报错:
/* N32G45X RTC 唤醒中断配置(迁移时必须新增) */
EXTI_InitType EXTI_InitStruct;
EXTI_InitStruct.EXTI_Line = EXTI_Line20; /* ← N32 用 Line20 */
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_InitPeripheral(&EXTI_InitStruct);中断服务函数命名差异(高频报错源)
| STM32 命名 | N32 命名(参考) |
|---|---|
DMA1_Channel1_IRQHandler | DMA1_CH1_IRQHandler |
USART1_IRQHandler | USART1_IRQHandler(大概率一致) |
RTC_IRQHandler | RTC_IRQHandler / RTCAlarm_IRQHandler(N32 改造了 RTC 架构) |
处置方式:按编译报错逐个改,或参考 SDK 的 n32g45x_it.c。
NVIC 与向量表重定位
| 项 | 说明 |
|---|---|
| 内核 | Cortex-M4F NVIC,支持优先级分组 |
| 优先级分组 | NVIC_PriorityGroup_0 ~ 4(配置抢占 / 子优先级的位数分配) |
| 配置函数 | NVIC_Init(NVIC_InitType*) |
| 向量表重定位 | SCB->VTOR,IAP 场景必须设置 |
/* IAP BootLoader 跳转前 —— VTOR 必须 512 字节对齐 */
SCB->VTOR = FLASH_BASE | APP_VECTOR_OFFSET;
__set_MSP(*(__IO uint32_t*)APP_ADDR);
((void(*)(void))(*(__IO uint32_t*)(APP_ADDR + 4)))();
5.3 USART / UART:printf、RS485、LIN
| 系列 | 串口资源 |
|---|---|
| N32G455 / G457 | 7 路:3×USART(支持 ISO7816、IrDA、LIN)+ 4×UART,最高 4.5 Mbps |
| N32L406 / L43x | 5×U(S)ART(3 USART + 2 UART)+ 1×LPUART(低功耗 Stop2 唤醒) |
| N32G032 | 2×UART + 2×LPUART |
| N32G052 | 5×UART(异步 / 多处理器 / 单线半双工) |
N32G455 的 3 个 USART 中,官方描述是「支持 1×ISO7816、1×IrDA、LIN」 ——注意这是「3 个 USART 合起来支持这三种」,不是每个 USART 都同时支持。
printf 重定向
/* Keil (armcc) —— 重写 fputc */
#include <stdio.h>
#include "n32g45x.h"
int fputc(int ch, FILE *f)
{
USART_SendData(USART1, (uint8_t)ch);
while (USART_GetFlagStatus(USART1, USART_FLAG_TXDE) == RESET);
return ch;
}
- GCC (newlib) —— 重写
_write/_write_r; 需要浮点支持时加-u _printf_float(体积 +约 10 KB)。 - RT-Thread 下无需重定向,直接用
rt_kprintf(),控制台串口在rtconfig.h指定。
RS485:必须等 TC 而不是 TXE
void RS485_Send(uint8_t *buf, uint16_t len)
{
RS485_DE_HIGH();
for (uint16_t i = 0; i < len; i++)
{
USART_SendData(USART2, buf[i]);
while (USART_GetFlagStatus(USART2, USART_FLAG_TXDE) == RESET);
}
/* 必须等 TC(发送完成),等 TXE 会丢最后一字节 */
while (USART_GetFlagStatus(USART2, USART_FLAG_TXC) == RESET);
RS485_DE_LOW();
}
| 项 | 做法 |
|---|---|
| 方向控制 | 用一个 GPIO 控制 485 收发器 DE / RE |
| 切换时机 | 发送前拉高 DE;等待 TC(发送完成)标志后再拉低(不能用 TXE,会丢最后一字节) |
| 硬件 | A/B 差分线平行等长,远离噪声源;终端电阻 120 Ω;A 上拉、B 下拉(失效保护偏置) |
LIN 与 ISO7816
- LIN:N32G4xx 的 USART 官方明确支持 LIN。主节点需 LIN 收发器(如 TJA1020); 从节点可用 USART Break 检测。LIN Break 长度 ≥13 bit 显性位,用 USART 的 LIN Break Detection 功能。
- ISO7816:用于智能卡 / ESAM / PSAM,常与安全芯片(N32S032)或外部安全模块对接 —— 这是 N32 生态的一个特色组合。ISO7816 需要 USART 提供 CLK 输出(如 USART CK 引脚)。
- IrDA:官方描述 3 个 USART 支持 1×IrDA。
5.4 SPI 与 QSPI
| 系列 | SPI 路数 | 最高速率 | I2S | QSPI |
|---|---|---|---|---|
| N32G455 / G457 | 3 路 | 36 MHz | 2 路支持 I2S | 1 路 @144 Mbps |
| N32L43x | 2 路(SPI1 / SPI2) | 27 Mbps | 支持 I2S | — |
| N32L406 | 2 路 | 16 Mbps | 支持 I2S | — |
| N32G052 | 3 路 | 16 MHz | — | — |
| N32G032 | 3 路 | — | 1 路 I2S | — |
_SPI 模式配置四要素
SPI_InitType spi;
spi.DataDirection = SPI_DIR_DOUBLELINE_FULLDUPLEX; /* 全双工 */
spi.SpiMode = SPI_MODE_MASTER;
spi.DataLen = SPI_DATA_SIZE_8BITS;
spi.CLKPOL = SPI_CLKPOL_LOW; /* CPOL */
spi.CLKPHA = SPI_CLKPHA_FIRST; /* CPHA(第一边沿采样) */
spi.NSS = SPI_NSS_SOFT; /* 软件 NSS */
spi.BaudRatePres = SPI_BR_PRESCALER_8;
spi.FirstBit = SPI_FB_MSB;
spi.CRCPoly = 7;
NSS 硬件设计要点
| 场景 | 配置 |
|---|---|
| 单从机 | NSS 可配置为推挽输出(硬件 NSS) |
| 多从机 | 必须配置为高阻态输出,每个从机单独用 GPIO 片选 |
/* 多从机:SPI 初始化后关闭 NSS 输出 */
SPI_SSOutputCmd(SPI1, DISABLE);
SPI 接各类存储与SD 卡
| 应用 | 接口 | 要点 |
|---|---|---|
| SPI NOR Flash | 普通 SPI 或 QSPI | QSPI @144 Mbps 可 XIP;普通 SPI 用 DMA + 双缓冲 |
| SPI NAND Flash | SPI | 需 ECC 管理、坏块表;N32 无硬件 NAND 控制器(用 XFMC 可接并行 NAND) |
| SD 卡(SPI 模式) | SPI | CMD0 / CMD8 / ACMD41 初始化;块读写 512 字节;SPI 模式 CRC 默认 OFF |
| SD 卡(SDIO 模式) | SDIO | N32G455 有 1×SDIO,支持 SD / SDIO / MMC,4-bit 总线,配 DMA |
N32G455 有 2 个 DMA 控制器 × 8 通道,官方描述是 「channel source address and destination address can be configured arbitrarily」—— 地址很灵活,但通道与外设的映射关系与 STM32 不同。 从 ST 移植时 DMA 可能需要重新映射,这是 8.3 节二十项必改清单里的一项。
5.5 I2C / CAN / USB
| 项 | N32G455 | N32L43x / L406 | N32G052 |
|---|---|---|---|
| I2C 路数 | 4 | 2 | 2 |
| I2C 速率 | 最高 1 MHz | 最高 1 MHz | 最高 1 MHz |
| 主 / 从可配 | ✓ | ✓ | ✓ |
| 从机双地址响应 | 支持 | 支持 | — |
| 速度档 | 100 kHz / 400 kHz / 1 MHz | 同 | 同 |
| CAN 路数 | 2×CAN 2.0A/B | 1×CAN 2.0A/B | 1×CAN 2.0A/B |
| USB | 1×USB2.0 FS Device | 1×USB2.0 FS Device | — |
I2C 实践要点:SDA / SCL 必须配置为复用开漏 + 外部上拉电阻 (4.7 kΩ @100 kHz,2.2 kΩ @400 kHz);从 ST 移植时 I2C 时序参数(TIMINGR 类)需重算; 总线挂死恢复用主机发 9 个 SCL 脉冲 + STOP。
CAN 需要外部收发器(如 SN65HVD230、TJA1050);CANH / CANL 差分走线,终端 120 Ω (总线两端各一个);过滤器用标识符屏蔽 / 列表模式,用法与 STM32 bxCAN 类似。 需要 CAN-FD 就得上 N32H48x / 49x(官方列出 CAN-FD,支持任意 I/O 映射)。
官方 Datasheet 只写 Device。如果你要做 USB Host 或 OTG, N32G4xx 做不到,必须上 N32H49x(USB FS Device + USB HS Host/Device)。 另外注意 N32G430 无 USB。
| 系列 | USB |
|---|---|
| N32G455 / G452 / G457 / G4FR | 1× USB2.0 Full Speed Device |
| N32L406 / L43x / N32WB452 | 1× USB2.0 FS Device |
| N32G430 | 无 USB |
| N32H49x | USB FS Device + USB HS Host / Device |
引脚:USB_DP = PA12、USB_DM = PA11。
部分 MCU 内置 1.5 kΩ D+ 上拉(N32G4xx 需查 DS 确认,未核实)。
USB BOOT(DFU)使用同一组引脚。
官方设备类支持:CDC(虚拟串口,Win10+ 自带 usbser.sys,无需驱动)、
HID、MSC(大容量存储,配合 SDIO / SPI Flash)、DFU(芯片内置 BOOT 支持)——SDK 都有例程。
5.6 SDIO 与 XFMC
| 接口 | N32G455 | 说明 |
|---|---|---|
| SDIO | 1 路 | 支持 SD / SDIO / MMC 格式,4-bit 总线 |
| XFMC(扩展存储控制器) | 有 | 可扩展 SRAM、PSRAM、NOR / NAND Flash、TFT LCD |
N32 把它命名为 XFMC(部分代理商资料写 FSMC)。 从 STM32 FSMC 移植时,Bank 划分与地址映射不完全一样,需重新调整(迁移实战贴明确提到)。
XFMC 的三类典型应用:
- 外部 SRAM / PSRAM 扩展内存 —— GUI 显存。
- 8080 并口 TFT LCD —— 把 LCD 当作 SRAM 设备寻址,用 1 个地址线做 RS / DC 选择。
- 并行 NOR / NAND —— N32G4xx 没有硬件 NAND 控制器,需要并行 NAND 时走 XFMC。
5.7 ADC:双时钟是移植必加项
来源:N32G45x 用户手册 ADC 章节 + CSDN 迁移实战
规格对照
| 系列 | ADC | 分辨率 | 采样率 | 外部通道 |
|---|---|---|---|---|
| N32G455 | 4×12bit | 12 / 10 / 8 / 6 bit 可配 | 12bit:4.7 Msps(PB 版 5 Msps);6bit 模式 8.9 ~ 9 Msps | 最多 38 路外部单端,支持差分 |
| N32L436 / L433 | 1×12bit | 12 / 10 / 8 / 6 bit | 5 Msps(6bit 下 9 Msps) | LQFP48:10;LQFP64 / 80:16 + 3 内部 |
| N32L406 | 1×12bit | — | 1 Msps(LCSC 版写 4.5 Msps) | 最多 16 路外部单端 |
| N32G435 / G432 | 1×12bit | — | 5 Msps | — |
| N32G430 | 1×12bit | — | 4.7 Msps | — |
| N32G401 | 1×12bit | — | 4.2 Msps | — |
| N32G03x | 1×12bit | 12bit | 1 Msps | 15(G052)/ 其他 |
| N32WB031 | 1×10bit | 10bit(可配 16bit 16 ksps) | 1.33 Msps | — |
| N32WB452 | 2×12bit | — | 5 Msps | — |
内部通道
| 通道 | 说明 |
|---|---|
| Vrefint | 内部参考电压(N32L43x / L406:内部 2.048 V 独立参考;N32G052:1.2 V;N32G45x 未核实) |
| Temperature | 内部温度传感器(需校准,精度有限,仅做趋势 / 过温粗判) |
| VBAT | 部分系列支持(未核实) |
提高精度的硬件与软件措施(官方硬件设计指南 1.7 / 5.3)
| 措施 | 说明 |
|---|---|
| 独立 VDDA | ADC 有独立供电引脚 VDDA / VSSA,可单独滤波屏蔽 |
| 去耦 | VDDA 输入管脚建议 0.1 µF + 1 µF |
| 外部 VREF+ | 支持外部输入独立参考电压源(高精度场合必用) |
| 采样时间 | 高阻抗信号源需延长采样周期 |
| 唤醒后延时 | ADC 上电后需稳定时间 |
| 校准 | 上电后执行 ADC 校准 |
| 相邻引脚 | 使用 LSE 时 PC13 / PD0 不得翻转(影响模拟) |
5.8 DAC / OPAMP / COMP / Touch
| 系列 | OPAMP | COMP | DAC |
|---|---|---|---|
| N32G455 | 4 路独立轨到轨,内置最大 32× PGA | 7 个高速比较器,内置 64 级可调基准 | 2×12bit 1 Msps |
| N32G435 | 2 路轨到轨(32× PGA) | 2 个(64 级) | 1×12bit 1 Msps |
| N32G432 | 无 | 无 | 1×12bit 1 Msps |
| N32L406 | 1~2 路(32× PGA) | 2~3 个(64 级) | 1×12bit 1 Msps |
| N32L43x | 2 路(32× PGA) | 2 个(64 级),COMP1 支持 Stop2 工作 | 1×12bit 1 Msps |
| N32G052 | 无 | 4 个轨到轨(64 级) | 1×8 / 12bit 1 Msps |
| N32G033 | 3 路差分轨到轨 | 1 个 | — |
| N32H48x / 49x | 4 个轨到轨 PGA(GBW = 40 MHz,压摆率 40 V/µs) | 7 个(22 ns 延迟) | — |
典型应用:OPAMP 用于电机相电流放大(省外部运放)、微弱信号调理、PGA; COMP 用于过流 / 过压快速保护(直接连 TIM 的 Break 输入关断 PWM)、过零检测、低功耗唤醒。
Touch Key(电容触摸)
| 系列 | 通道数 |
|---|---|
| N32L406 | 最多 24 通道,支持低功耗状态唤醒 MCU |
| N32L43x | 最多 24 通道 |
| N32WB452 | 最多 18 通道 |
| N32G032K6Q7 / C8L7 / R8L7 | 17 / 20 / 24 通道 |
- 硬件:感应盘建议覆铜 + 开窗,避免覆铜铺地过近;串联 1 kΩ 电阻抑制 ESD。
- 软件:需定期基线校准(温湿度漂移);防水 / 防误触算法。
5.9 定时器:PWM 互补与死区
| 类型 | 数量 | 位宽 | 能力 |
|---|---|---|---|
| 高级控制定时器 | 2(TIM1、TIM8) | 16 bit | 输入捕获、互补输出、正交编码输入;最高控制精度 6.9 ns;每定时器 4 独立通道,其中 3 通道支持 6 路互补 PWM 输出 |
| 通用定时器 | 4 | 16 bit | 输入捕获 / 输出比较 / PWM / 单脉冲 |
| 基本定时器 | 2(TIM6、TIM7) | 16 bit | 时基、DAC 触发 |
| SysTick | 1 | 24 bit | 系统节拍 |
| 窗口看门狗 WWDG | 1 | 7 bit(N32G052 为 14 bit) | |
| 独立看门狗 IWDG | 1 | 12 bit |
N32L43x 额外:通用 5 + 高级 2 + 基本 2 + LPTIM 1(16 bit 低功耗定时器,
支持双脉冲计数,Stop2 可工作),精度 9.25 ns。
N32G052:高级 1(5 通道,4 通道 → 8 路互补 PWM)、通用 4、基本 1(支持 STOP 唤醒)、
WWDG 14 bit、IWDG 12 bit。
PWM 互补输出 + 死区(电机 / 电源核心)
TIM_TimeBaseInitType tim;
tim.Period = PWM_PERIOD; /* 自动重装载 */
tim.Prescaler = 0;
tim.ClkDiv = 0;
tim.CntMode = TIM_CNT_MODE_UP;
TIM_InitTimeBase(TIM1, &tim);
TIM_OCInitType oc;
oc.OcMode = TIM_OCMODE_PWM1;
oc.OutputState = TIM_OUTPUT_STATE_ENABLE;
oc.OutputNState = TIM_OUTPUT_NSTATE_ENABLE; /* 互补通道使能 */
oc.Pulse = duty;
oc.OcPolarity = TIM_OC_POLARITY_HIGH;
oc.OcNPolarity = TIM_OCN_POLARITY_HIGH;
oc.OcIdleState = TIM_OC_IDLE_STATE_RESET;
oc.OcNIdleState = TIM_OCN_IDLE_STATE_RESET;
TIM_InitOc1(TIM1, &oc);
/* 死区时间配置(关键,防止上下管直通) */
TIM_BDTRInitType bdtr;
bdtr.DeadTime = DEADTIME_NS_TO_TICKS(500); /* 需按时钟频率换算 */
bdtr.BreakState = TIM_BREAK_STATE_ENABLE; /* 接 COMP 过流 */
bdtr.BreakPolarity = TIM_BREAK_POLARITY_HIGH;
bdtr.AutomaticOutput = TIM_AUTOMATIC_OUTPUT_ENABLE;
TIM_ConfigBkdt(TIM1, &bdtr);
TIM_EnableCtrlPwmOutputs(TIM1, ENABLE); /* ← 高级定时器必须调用(MOE 主输出使能) */
TIM_Enable(TIM1, ENABLE);
TIM_EnableCtrlPwmOutputs(TIM1, ENABLE) 里的 MOE(Main Output Enable)位
不打开,三路互补 PWM 一个都不会输出,但定时器在跑、寄存器也在写 ——
现象是「配了半天没波形」,而且不报任何错。这一条在移植时中招率极高,
因为 ST 工程里通常已经有这个调用,但如果你手写了 TIM 初始化就很容易漏。
编码器 / 霍尔 / 低功耗计数
- 编码器:高级与通用定时器支持正交编码输入(X2 / X4),直接读
TIM->CNT。 - 霍尔:可用 TIM 的 XOR / Hall 接口(部分系列支持),或用 3 路输入捕获 + 组合中断; N32H48x 有专门的霍尔 / 超高精度定时器。
- 无磁计量:N32L43x 的 LPTIM 支持双脉冲计数,适合水表计量; N32L436 的 LPRCNT(低功耗 LC 无磁计量模块)可在 STOP2 状态工作,是超低功耗计量的核心。
5.10 RTC 与 DMA
RTC
| 项 | 说明 |
|---|---|
| 日历 | 闰年万年历、闹钟事件、周期唤醒 |
| 校准 | 支持内部与外部时钟校准 |
| 时钟源 | LSE 32.768 kHz(推荐)/ LSI(30~40 kHz,精度差)/ HSE 分频 |
| 供电 | VBAT 域,主电源掉电后由 VBAT 维持 |
| 备份寄存器 | 位于 VBAT 域,掉电保持 |
| TAMPER | 侵入检测(如 PC13-TAMPER-RTC),可触发清除备份寄存器 |
- STM32F103 的 RTC 是简单的 32 位计数器;N32G45X 的 RTC 模块架构被重构 (预分频器配置、唤醒机制均不同)。
- 中断:STM32 用
RTC_IRQn;N32 改为 EXTI20(见 5.2 节)。 - 迁移实战贴的结论是:RTC 驱动层代码得「重写」,而不是简单替换几个函数。 把这个模块排在移植计划的后半段,不要指望一上来就搞定。
另有官方《N32G031 系列 LSE 晶体选型指南》V1.0.0 —— LSE 晶体选型有疑问时先读它。
DMA
| 系列 | DMA 控制器 | 通道 |
|---|---|---|
| N32G455 / G457 | 2 个高速 DMA 控制器 | 各 8 通道(共 16);通道源地址与目的地址任意可配 |
| N32L43x / L406 | 1 个高速 DMA 控制器 | 8 通道 |
| N32G052 | 1 个 | 5 通道 |
| N32G03x(G030 / G031) | 无(精简掉) | — |
DMA_InitType dma;
dma.PeriphAddr = (uint32_t)&ADC1->DAT;
dma.MemAddr = (uint32_t)adc_buf;
dma.Direction = DMA_DIR_PERIPH_SRC; /* 外设 → 内存 */
dma.BufSize = ADC_BUF_LEN;
dma.PeriphInc = DMA_PERIPH_INC_DISABLE;
dma.MemoryInc = DMA_MEM_INC_ENABLE;
dma.PeriphDataSize = DMA_PERIPH_DATA_SIZE_HALFWORD;
dma.MemDataSize = DMA_MEM_DATA_SIZE_HALFWORD;
dma.CircularMode = DMA_MODE_CIRCULAR; /* 循环模式(连续采样) */
dma.Priority = DMA_PRIORITY_HIGH;
dma.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(DMA1_CH1, &dma);
DMA_EnableChannel(DMA1_CH1, ENABLE);
N32G45x 的官方描述是「通道源地址与目的地址可以任意配置」, 听起来比 ST 灵活,但通道与外设请求的映射关系和 STM32 不一样。 迁移要点里明确提到这一点。移植时:
- 先查 N32 的 DMA 请求映射表,确认「我用的 DMA1_CH1 对应哪个外设」;
- 不要假设
DMA1_Channel1(STM32 命名)在 N32 上就是DMA1_CH1的同一个功能。
CRC
N32G455 有独立的 CRC16 / CRC32 硬件运算单元(官方列在 Security Features 段)。
用途:通信校验、固件完整性校验、BOOT 下载数据校验(CMD_DATA_CRC_CHECK)。
CRC_Reset();
uint32_t crc = CRC_CalcCrc32((uint32_t*)buf, len_in_words);
uint16_t crc16 = CRC_CalcCrc16((uint16_t*)buf, len);
常见 CRC32 为 IEEE 802.3(0x04C11DB7);N32 的具体多项式与初值未核实, 用之前查用户手册的 CRC 章节。这一点在与上位机 / 产线工具联调时尤其重要 —— 多项式或初值不同,校验永远对不上。
5.11 Flash 控制器与 EEPROM 模拟
存储结构(N32G45x)
| 区域 | 大小 | 页 | 说明 |
|---|---|---|---|
| 主存储区 | 最大 512 KB | 2 KB | 程序 / 数据;擦除按页 |
| 系统存储区 | 16 KB | — | 出厂 BootLoader,不可改 |
| 系统配置区 | 2 KB | — | UID / UCID,不可改 |
| 选项字节区 | 2 KB | — | RDP / WRP / USER |
| D-Flash | 最大 512 KB | — | 仅 N32G455RGL7 / VGL7;10 万次擦写,20 年保持 |
页大小 2 KB 是从 WRP 描述反推的(「Page 0~61 每 2 页为一个保护单元,Page 62~255 为一单元」, 两者一致)。具体值请查对应批次 DS 电气特性确认。
等待周期(Wait State / Latency)
N32G455 内置 8 KB 指令 Cache + Flash 加速单元,支持 0 等待执行程序, 但仍需按主频 / 电压配置 Flash 等待周期。精确的 Latency ↔ 频率对照表未在公开 DS 中查到, 可靠的处置是:
/* 官方 SDK 里 SetSysClock() 的做法 —— 直接照抄,不要自己推 */
FLASH_SetLatency(FLASH_LATENCY_4); /* 数值以官方 SDK 为准 */
FLASH_PrefetchBufCtrl(FLASH_PrefetchBuf_ENABLE);
FLASH_ICacheCtrl(FLASH_ICache_ENABLE); /* 8 KB I-Cache */
- 上电默认用 HSI 低主频跑,配置完 PLL 后再设置 Flash Latency。
- 顺序:先提 Latency → 再提主频;降频时反向。
(常见参考逻辑,推算、非官方值:≤24 MHz → 0;≤48 MHz → 1;≤72 MHz → 2;
≤108 MHz → 3;≤144 MHz → 4~5。务必以官方 SDK system_n32g45x.c 与实际测试为准。)
读 / 写 / 擦流程
FLASH_Unlock(); /* 1. 解锁(写 KEY 序列) */
FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
if (FLASH_ErasePage(0x08010000) != FLASH_COMPLETE) /* 2. 擦除(按页) */
error_handler();
if (FLASH_ProgramWord(0x08010000, data32) != FLASH_COMPLETE) /* 3. 编程(字 / 半字) */
error_handler();
FLASH_Lock(); /* 4. 上锁 */
- 必须先擦后写(擦除后为 0xFF)。不擦直接写,编程会失败。
- 擦写期间不能从被操作的 Flash 区取指 → 需关中断, 或把擦写代码放到 RAM 执行(IAP 场景必须这样做)。
- 电压不足时擦写会失败。低压跌落场景要注意。
- 擦除页按2 KB 对齐;擦写时间典型值:页擦除数 ms、字编程数十 µs (具体值未核实,查 DS 电气特性)。
EEPROM 模拟:N32 系列没有片内 EEPROM
这一点是 STM32 迁移的高频坑:STM32F1 系列有片内 EEPROM,N32 全系列没有
(官方与代理确认:「N32 系列不支持 EEPROM,需使用 Flash 模拟 EEPROM 功能」)。
典型表现是:原代码里的 EEPROM_Read() / EEPROM_Write()
在 N32 上根本没有对应模块,必须自己实现或改方案。
| 方案 | 做法 | 适用 |
|---|---|---|
| Flash 模拟 EEPROM | 划 2 页(或更多)做 A / B 页轮转;写入时先写新页再擦旧页;需磨损均衡 | 所有型号都可用;注意 Flash 只有 10 万次寿命,需靠均衡摊薄 |
| 使用 D-Flash | N32G455RGL7 / VGL7 有最大 512 KB D-Flash(10 万次 / 20 年);N32L406 部分型号有 256 KB Data Flash;N32G052 有 8 KB Data Flash | 有对应型号时优先选这个,硬件保证寿命,比软件模拟可靠 |
Flash 模拟 EEPROM 的四个要点:
- 每页开头写状态字(ERASED / RECEIVING / VALID),掉电后能判断页的有效性。
- 页满时搬移有效数据到另一页再擦原页。
- 掉电保护:写入过程中掉电要有恢复逻辑。
- 变量用「虚拟地址 + 数据」格式存,便于查找。
IAP 跳转
#define APP_ADDR 0x08010000 /* App 起始(Boot 占前 64 KB) */
void JumpToApp(void)
{
uint32_t app_sp = *(volatile uint32_t*)(APP_ADDR);
uint32_t app_rst = *(volatile uint32_t*)(APP_ADDR + 4);
if ((app_sp & 0x2FFE0000) == 0x20000000) { /* 栈指针合法性检查 */
__disable_irq();
/* 关闭已开启的外设、DMA、中断 */
SysTick->CTRL = 0;
SCB->VTOR = APP_ADDR; /* 重定位向量表 */
__set_MSP(app_sp);
((void(*)(void))app_rst)();
}
}
App 侧必须同步改三处:链接地址改为 0x08010000;
system_n32g45x.c 中的 VECT_TAB_OFFSET 改为 0x10000;
或直接在代码里设 SCB->VTOR = 0x08010000;。三处只改一处是 IAP 跑不起来的经典原因。