news 2026/9/29 4:35:12

芯参谋(23):并口/并行NOR_PPI_NOR_软件设计规范

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
芯参谋(23):并口/并行NOR_PPI_NOR_软件设计规范

并行NOR_PPI_NOR_软件设计规范

http://39.108.239.75:5001/share/DNylYp0iuzRP5QChttp://39.108.239.75:5001/share/DNylYp0iuzRP5QC

并行 NOR Flash(PPI NOR)软件设计规范

编制日期 2026-09-24 | 版本号 Rev 1.5

面向异步 SRAM 类并行总线 NOR(CFI Primary Command Set 0x0002 / AMD-Fujitsu 命令集,x8 / x16, TSOP-56 与 BGA-64)的固件驱动设计约定 —— 覆盖解锁周期与命令序列、DQ7/DQ6/DQ5 状态轮询、写缓冲与 Unlock Bypass、扇区保护(PPB / DYB / WP#)、XIP 冲突处置与掉电数据完整性,逐条给出可落地的命令序列、轮询判据与超时预算。

文档编号PPI-NOR-SW-SPEC-001
版本 / 状态V1.0 · 正式发布
适用器件芯天下 XTX XT29F(XT29F512ATSHGA / XT29F01GATSHGA)、M29F(M29F512BTSJGA / M29F512BBGJGA / M29F01GBTSJGA / M29F01GBBGJGA / M29F02GBBGJGA)及命令集兼容的第三方并行 NOR
参考标准JEDEC JEP137 / JESD68(CFI)· CFI Primary Command Set 0x0002 · 各型号 datasheet 与 Errata
配套文档并行NOR_PPI_NOR_电路设计指南.html(原理图 / 布线 / 时序 / 信号完整性)

0. 目的与范围

本规范约束并行 NOR 器件在嵌入式固件中的软件行为:命令序列、地址换算、状态轮询、扇区保护、 XIP 冲突处置、掉电保护。凡本文与器件 datasheet 冲突,以 datasheet 为准。

  • 统一命令序列:读(无命令,直接寻址)、编程(解锁 + A0h + 地址 + 数据)、擦除(六周期)各自固化为一套标准流程。
  • 统一状态判读:只用 RY/BY# 或 DQ7 / DQ6 判定完成,并强制配 DQ5 超时二次确认,禁止固定延时。
  • 统一地址换算:明确 x8 / x16 下的命令地址与「字地址 ↔ 字节地址」关系,消灭移植时最高频的地址错位 bug。
  • 统一 XIP 规则:擦写期间禁止从本器件取指,给出三种可执行方案与各自的适用边界。
  • 统一掉电保护:给出写窗口、A/B 双区提交协议与 IAP 双 Bank 流程,明确哪些操作是原子的。

不在本规范范围:原理图、PCB 布线与端接(见《并行 NOR Flash(PPI NOR)电路设计指南》); 文件系统与参数管理算法选型;同步突发 / ADM 复用模式的具体寄存器配置(仅给出识别与约束)。

一句话结论:并行 NOR 是「读像 SRAM、写像命令」的器件 —— 读只要拉低 CE#/OE# 就出数据, 任何写都是解锁周期(0x555 ← AA / 0x2AA ← 55)+ 命令码;擦写完成只看RY/BY# 或 DQ7/DQ6, 并且必须用DQ5兜底判超时。不做轮询的写会写出半字,不配 DQ5 的轮询会死循环,XIP 下不隔离取指的擦写会让程序直接跑飞。

文档使用说明

  • 本文是《并行 NOR Flash(PPI NOR)电路设计指南》的软件配套篇:硬件篇解决「怎么接、怎么供电、怎么走线、等待周期怎么算」,本文解决「驱动怎么写、命令怎么发、状态怎么判、XIP 怎么保命」。
  • 命令码以CFI Primary Command Set = 0x0002(AMD / Fujitsu)为准,这是并行 NOR 的主流命令集;Intel 命令集(0x0001)器件不在本文范围内,须另行核对。
  • 文中代码为x16 总线示例(volatile uint16_t *),x8 总线需按 1.3 节的换算规则调整地址与数据宽度。
  • 文中 C 代码为协议骨架伪代码,演示流程与判断条件;nor_cmd()、systick_ms()、delay_us()为平台相关底层。

贯穿全文的三条铁律

①绝不用固定延时替代状态轮询——擦写时间随 P/E 次数、温度、个体差异成倍变化,典型值只能用来安排轮询节奏; ②写/擦前必须确认扇区已解保护且已擦除——DYB 上电默认为保护态,且 NOR 只能把 1 写成 0; ③XIP 下擦写期间禁止取指——轮询本身也是「读器件」,读到的是状态位而非指令。

1 · 器件定位与阵列组织

并行 NOR 与串行器件最大的差别是地址线直连:CPU 的地址总线就是存储器的地址,读操作不需要任何命令。 软件设计的第一件事,是把「擦除粒度」和「地址换算」这两件事彻底搞清楚。

1.1 器件定位与关键参数

70~110 ns

随机读 tACC

与 SRAM 同量级,XIP 可行的基础

100 000

P/E endurance

每扇区 10 万次擦写

20 年

数据保持

TA ≤ 85 ℃ 条件下

4 KB~128 KB

扇区擦除粒度

由 CFI 区块表给出,禁止硬编码

16~32 字

写缓冲深度

CFI 0x2A 字段 = 2N 字节

16~60 µs

单字编程 tWHWH1

典型值;最大可达 300 µs

0.3~1 s

扇区擦除 tSE

最大 5 s;寿命末期可达 2~4 倍

1~15 µA

DPD 电流

RESET# 拉到 VSS±0.3 V

上述为跨厂商、跨工艺的典型值区间,仅用于方案评估;定稿前必须用目标型号 datasheet 对应表格替换(XTX 系列以 datasheet 为准)。

项目取值 / 范围软件影响
接口形态异步 SRAM 类并行总线,40 ~ 50 根引脚读无需命令;需配置总线等待周期
位宽x8 / x16(BYTE# 引脚选择)地址换算与命令地址随位宽变化(1.3 节)
容量范围1 Mb ~ 2 Gb(XTX 当前 512 Mb ~ 2 Gb)容量从 CFI 0x27 读取,不要硬编码
速度等级tACC = 70 / 90 / 100 / 110 ns决定 SoC 等待周期;配错表现为偶发读错
工作电压3 V 型 2.7 ~ 3.6 V;1.8 V 型 1.65 ~ 1.95 VCFI 0x1B/0x1C 以 BCD 给出,上电自检应核对
命令集CFI Primary Command Set =0x0002本文全部命令基于此;0x0001(Intel)不适用
坏块 / ECC出厂基本无坏块;不需要 ECC只需维护「运行期失败扇区表」(7.6 节)
封装TSOP-56(14×20 mm)/ BGA-64(8×10 ~ 9×11 mm)仅影响硬件,软件无差异

1.2 区块(Region)与扇区组织

并行 NOR 的擦除粒度不是全片统一的:器件把不同大小的扇区分成若干个「区块区域(Erase Block Region)」。 典型布局是「底部 / 顶部若干个 8 KB 小扇区 + 中间大量 64 KB 大扇区」,小扇区通常留给 bootloader 与参数区。

并行 NOR 的层级:Device → Region → Sector → Word(擦除粒度由 CFI 给出)1 Device = 全部地址空间(1 Mb ~ 2 Gb)地址线性映射,读操作无需发任何命令1 Erase Region = 若干同尺寸 Sector(CFI 0x2C 给出区域数)常见布局:8 KB × 8 小扇区 + 64 KB × 254 大扇区1 Sector = 4 KB ~ 128 KB(擦除的最小单位)擦除地址 SA 取扇区内任意地址即可1 Word = 16 bit(x16)/ 1 Byte = 8 bit(x8)编程的最小单位;写缓冲一次最多 16 ~ 32 字扇区布局禁止硬编码上电必须从 CFI 区块表(0x2E 起)读出并缓存

图 1-1 并行 NOR 的存储层级。擦除粒度与区块分布是器件相关的,同一个驱动要兼容多料号,就必须从 CFI 查询区读出来,而不能写死 64 KB。

「扇区大小写死 64 KB」是最常见的兼容性事故

把sector_size = 64 * 1024写进驱动的后果:在「8 KB × 8 + 64 KB × 254」布局的器件上,擦除底部 8 KB 小扇区时会把相邻 56 KB 一起擦掉; 而在 128 KB 大扇区器件上,一次擦除只覆盖了半个扇区,擦除永远「擦不干净」。

正确做法:上电遍历 CFI 区块区域表,构建一张「扇区起始地址 → 扇区大小」的查找表,所有擦写 API 只接受扇区索引。

1.3 位宽、地址错位与字节序

这是并行 NOR 移植时出错率最高的一节。同一条命令序列,在 x8 与 x16 下落到 SoC 地址总线上的数值并不相同。

同一个解锁地址 0x555,在 x8 与 x16 下对应的 SoC 字节地址不同x16(BYTE# = 1)SoC 字节地址0x00000AAA器件地址总线 A[10:0]= 0x555(不除以 2)x8(BYTE# = 0)SoC 字节地址0x00000555器件地址总线 A[10:0]= 0x555(一一对应)字地址换算word = byte >> 1x8 模式由 DQ15/A-1 充当最低位地址x16 模式 DQ15 为数据最高位典型踩坑:把 x8 的地址 0x555 再乘 2 当字地址用解锁序列失效 → 器件把整条命令当成一次普通写 → 不报错、也不执行。命令锁存比较的是「地址总线上的值」,x16 下 0x555 就是 0x555,不再做字节换算。

图 1-2 x8 / x16 的地址换算。命令地址在两种位宽下同为 0x555 / 0x2AA,变的是它在 SoC 字节地址空间中的位置;务必用逻辑分析仪实测确认地址线的实际电平。

模式BYTE#编程单位解锁地址(SoC 侧)数据宽度DQ15 作用
x80(下拉)1 字节字节地址0x555/0x2AA8 bit复用为A-1(最低位地址)
x161(上拉)1 字(2 字节)字节地址0xAAA/0x55416 bit数据最高位 DQ15

BYTE# 浮空 = 位宽不确定

BYTE# 由外部电阻固定(x16 上拉 10 kΩ 到 VCC,x8 下拉到地),绝不允许浮空。软件侧无法补救: 浮空时器件可能间歇性地在两种位宽间跳变,表现为「大部分时间能读,偶尔读出错位数据」,极难定位。

驱动初始化时应读取 CFI 0x28 接口描述字段确认实际位宽(0 = x8 only / 1 = x16 only / 2 = 可切换),与编译期配置不符即报错停机。

1.4 与 SPI NOR / 并行 NAND 的关键差异

维度并行 NOR(本文)SPI NOR并行 NAND
读方式地址直连,拉 CE#/OE# 即出数据,无命令发03h+ 地址 + dummy发命令 + 地址,页读进 cache
随机读延迟70 ~ 110 ns首字节 60 ~ 100 ns + 指令开销25 ~ 50 µs(页搬 SRAM)
写方式解锁周期 +A0h+ 地址 + 数据06h+02h+ 地址 + 数据命令 + 页装载 + 编程执行
状态判读DQ7 / DQ6 / DQ5 + RY/BY# 引脚读状态寄存器05h读状态 / R/B# 引脚
坏块 / ECC出厂无坏块,不需要 ECC不需要必须 BBT + 硬件 ECC
擦除粒度扇区 4 KB ~ 128 KB(多区域混合)4 KB / 32 KB / 64 KB块 128 KB ~ 1 MB
XIP原生最优(地址直映射)好(需 cache / 预取)不可,需影子 RAM
主谓引脚数40 ~ 50 根4 ~ 6 根复用 8 / 16 位,28 ~ 48 根

2 · 术语与缩写

本章统一术语口径,避免「扇区 / 块 / 区域 / 字」在文档与代码里指的不是同一件事。

2.1 接口与命令术语

缩写 / 术语全称本文中的含义
Sector / Block扇区 / 块擦除的最小单位,4 KB ~ 128 KB,大小由器件决定
RegionErase Block Region同尺寸扇区的集合;CFI 0x2C 给出区域数,0x2E 起逐区描述
Word—x16 模式下的编程单位(2 字节);x8 模式下为 Byte
PA / PDProgram Address / Data编程命令最后两个周期给出的目标地址与数据
SASector Address目标扇区内任意地址;擦除 / 保护命令用它定位扇区
Unlock Cycle解锁周期命令序列前置的0x555←AA/0x2AA←55写操作
DQ7Data# Polling操作进行中读出「写入值 DQ7 的反码」,完成后读出真值
DQ6Toggle Bit 1操作进行中连续读会翻转,完成后停止翻转
DQ5Error / Timeout超出内部时序限制时置 1;须二次确认后才判失败
DQ3Erase Timer擦除命令窗口内 = 0,真正开始擦除后 = 1
DQ2Toggle Bit 2擦除挂起期间持续翻转,与 DQ6 组合判断挂起状态
DQ1Write Buffer Abort写缓冲装载了非法地址 / 跨扇区时置 1,本次缓冲作废
RY/BY#Ready / Busy开漏输出,低 = 忙;最省 CPU 的完成判据
CFICommon Flash InterfaceJEDEC JEP137 / JESD68 定义的自描述查询区
PPBPersistent Protection Bit非易失保护位,写次数有限,适合永久保护
DYBDynamic Protection Bit易失保护位,上电默认保护,擦写前必须显式解除
XIPeXecute In PlaceCPU 直接从 NOR 取指执行,无需搬到 RAM
RWWRead-While-Write一个 Bank 读的同时擦写另一个 Bank(需器件支持)
A-1—x8 模式下由 DQ15 复用充当的最低位地址

2.2 本文书写约定

  • 命令码用小写十六进制带后缀h书写(如A0h、F0h);写周期写作0x555 ← 0x00AA,表示「向地址 0x555 写入数据 0x00AA」。
  • x16 模式为默认示例;x8 模式下的差异在 1.3 节与附录 A 单独标注。
  • 状态位写作DQ7/DQ6形式,判据用掩码表示,如(d1 ^ d2) & 0x40判断 DQ6 是否翻转。
  • 时序符号沿用 datasheet:tACC(地址到数据有效)、tSE(扇区擦除)、tWHWH1(单字编程)、tWHWH2(写缓冲编程)。「典型值 / 最大值」成对给出时,超时必须按最大值预算。
  • 代码示例为 C 伪代码,省略 SoC 总线控制器配置,只表达命令序列与判据。

3 · 驱动架构与初始化

并行 NOR 的驱动比串行器件多两件事:总线时序配置与XIP 隔离。这两件事没做对,后面的命令序列写得再标准也跑不起来。

3.1 分层职责

层职责禁止做的事
应用层业务调用 read/write/ioctl;不感知扇区与命令直接拼解锁周期、直接算扇区地址
存储管理层扇区表、坏扇区表、保护状态、提交协议、IAP 流程绕过扇区表直接擦写物理地址
命令协议层解锁周期、命令码、状态轮询、Reset 恢复省略解锁、用固定延时代替轮询
总线抽象层等待周期、位宽、地址移位、XIP 隔离(RAM 驻留)在命令序列中途切换总线时序或频率

命令协议层必须整体驻留 RAM

发送解锁周期与轮询状态的代码本身不能放在被操作的 NOR 上执行——擦写期间从 NOR 取指读到的是状态位,不是指令。 工程做法:把nor_cmd()、nor_wait_ready()、nor_program()、nor_erase()用链接脚本放到 RAM 段(如__attribute__((section(".ramfunc")))),或整段用__ramfunc修饰。

3.2 上电初始化流程

初始化顺序不能颠倒:先有时序,后有识别。总线等待周期没配好就去读 CFI,读回来的一定是噪声。

上电初始化六步:先配总线,再识别器件,最后解保护1. 上电与复位释放:VCC 稳定 → RESET# 拉高VCC < VLKO 期间操作被忽略;RESET# 释放后需等 tRH(µs ~ ms 级)2. 配置外部总线:位宽 / 等待周期 / 读写建立保持先把等待周期给足(如 30 个),成功后再二分收敛到最优值3. 读复位 F0h:把器件拉回「读阵列」状态任何残留状态(Autoselect / CFI / 旁路 / 错误)都被清除4. CFI 查询:读 'QRY' → 容量 / 区块表 / 时序参数读不到 'QRY' 即停机报障,不猜、不硬编码5. Autoselect 校验 MID / DID,与 BOM 预期比对防止贴错料;不一致则拒绝启动并上报6. 建立扇区表 + 坏扇区表,按需解除 DYB 保护保护按需解除、写完即恢复,不做全局解除

图 3-1 上电初始化六步。第 2 步与第 4 步的顺序不可颠倒:等待周期不足时,CFI 查询会读到噪声,而噪声最容易被误判成「器件不兼容」。

/* 上电初始化:返回 0 表示成功 */ int nor_init(void) { /* 1. 复位释放后等待 tRH(按 datasheet,通常 µs ~ ms 级) */ board_reset_release(); delay_us(100); /* 2. 总线:先给足等待周期,后续可收敛 */ bus_config(BUS_WIDTH_16, WAIT_STATES_SAFE); /* 例如 30 个等待周期 */ /* 3. 读复位 */ nor_cmd(0x0000, 0x00F0); /* 4. CFI 查询 —— 读不到 'QRY' 直接失败 */ if (cfi_probe(&g_cfi) != 0) return -E_NODEV; if (g_cfi.interface == 2 && g_cfi.interface != BUS_WIDTH_16) return -E_WIDTH; /* 位宽与配置不符 */ /* 5. Autoselect 校验厂商 / 器件 ID */ if (autoselect_check(EXPECT_MID, EXPECT_DID) != 0) return -E_NODEV; /* 6. 构建扇区表 + 坏扇区表 */ sector_table_build(&g_cfi); bad_sector_table_load(); return 0; }

初始化最容易漏的两件事

① 等待周期给得太紧。首版调试时先把等待周期设到最大(例如 30 个),确认 CFI 能读出来,再二分收敛。 反过来做的话,「读不到 QRY」会被误判成器件或焊接问题,排查方向完全跑偏。

② 忘了发 F0h 读复位。若上一次运行停在 Autoselect 或 CFI 模式(例如看门狗复位前正在读 ID), 本次上电后器件仍在特殊模式,读出来的是 ID 或查询表而不是阵列数据。F0h 是唯一能把它拉回来的通用手段。

3.3 器件识别:CFI / Autoselect 双通道

  1. CFI 查询(首选):向0x55写0x0098(x8 模式为向0xAA写0x98)进入查询模式,按偏移读取自描述信息。它给出容量、写缓冲深度、区块区域表、编程/擦除典型与最大超时、VCC 范围,是驱动自适应多料号的唯一可靠来源。
  2. Autoselect(校验用):三周期进入(0x555←AA/0x2AA←55/0x555←90),读偏移 0x00 得制造商 ID、0x01 得器件 ID,用于防贴错料。读完必须发 F0h 退出。
  3. 交叉校验:CFI 0x27 给出的容量应与 Autoselect 器件 ID 推断的容量一致;不一致说明读到了噪声或贴错料,应停机而非继续。

什么时候必须读 CFI 而不是硬编码

只要驱动需要兼容两家以上供应商或两种以上容量,扇区布局、写缓冲深度、超时参数就必须来自 CFI。 硬编码的代价不是「换料要改代码」,而是「换料后静默擦错扇区」——后者会烧出批量事故。

4 · 命令体系与解锁周期

并行 NOR 的所有写操作(编程、擦除、识别、保护)都遵循同一个骨架:解锁周期 → 命令码 → 地址 / 数据。 命令码写错、解锁地址写错,器件都会静默忽略——既不执行也不报错。

4.1 命令集总览

命令周期数地址序列(x16)数据序列(x16)
读阵列 / 复位1任意0x00F0(部分器件0x00FF)
Autoselect(读 ID)30x555 / 0x2AA / 0x5550x00AA/0x0055/0x0090
CFI 查询10x0055(x8:0x00AA)0x0098
字 / 字节编程40x555 / 0x2AA / 0x555 / PA0x00AA/0x0055/0x00A0/ PD
Unlock Bypass20x555 / 0x2AA0x00AA/0x0020
旁路编程2任意 / PA0x00A0/ PD
旁路复位2任意 / 任意0x0090/0x0000
写缓冲编程3 + N0x555 / SA / SA0x00AA/0x0025/ (N−1);随后 N 字;末周期0x0029
扇区 / 块擦除60x555 / 0x2AA / 0x555 / 0x555 / 0x2AA / SAAA/55/80/AA/55/30
整片擦除6同上,末地址为 0x555… /0x0010
擦除挂起 / 恢复1任意0x00B0/0x0030
状态判读(DQ 轮询)1任意DQ7/DQ6/DQ5 轮询
(AMD 无 0x70/0x71 状态命令)

扇区保护(PPB / DYB / Password)为厂商自定义扩展,命令序列各厂商不同,必须查各自的 application note;本文只给出软件层面的使用原则(第 9 章)。

4.2 解锁周期与地址错位

以字编程为例:解锁周期 → 命令码 → 目标地址与数据,四步缺一不可① 0x555← 0x00AA解锁周期 1② 0x2AA← 0x0055解锁周期 2③ 0x555← 0x00A0命令码:编程④ PA← PD目标地址 + 数据命令码决定操作类型A0h = 编程 · 80h = 擦除建立 · 90h = Autoselect · 98h = CFI · 25h = 写缓冲 · B0h = 擦除挂起 · 70h = 状态读换掉命令码即可换操作,但前两个解锁周期永远不变x16 模式下解锁地址不再除以 2命令锁存比较的是地址总线上的值:A[10:0] = 0x555 时,对应 SoC 字节地址 0xAAA。写成 0xAAA 或 0x2AA 都会让解锁失效,且器件不报错。

图 4-1 解锁周期与命令序列。前两个解锁周期是所有命令的共同前缀;写错任何一个地址或数据,整条命令被静默丢弃。

/* 16 位总线:命令写宏(wa 为字地址,SoC 侧自动右移 1 位输出) */ static volatile uint16_t *const nor = (volatile uint16_t *)NOR_BASE; static void nor_cmd(uint32_t wa, uint16_t d) { nor[wa] = d; } /* 单字编程:解锁 → A0h → PA/PD */ int nor_program_word(volatile uint16_t *pa, uint16_t pd) { nor_cmd(0x555, 0x00AA); nor_cmd(0x2AA, 0x0055); nor_cmd(0x555, 0x00A0); *pa = pd; /* 第 4 周期:目标地址 + 数据 */ return nor_wait_ready(pa, pd, T_PROG_US); }

4.3 读复位 F0h:万能恢复键

F0h是单周期命令,可在任意地址写入,作用是让器件从任何特殊模式(Autoselect / CFI / 状态读 / 旁路) 退回读阵列状态,同时中止正在进行的编程或擦除。

  • 它是异常恢复的第一动作:状态位异常、读不到正确数据、操作超时,先发 F0h 再排查。
  • 部分器件也接受FFh;优先用 F0h,它是 CFI 0x0002 命令集的标准复位码。
  • 中止擦除后,被操作的扇区处于不确定状态,必须重新擦除,不能直接使用。
  • 写缓冲编程中途发 F0h,本次缓冲内容作废,需重新装载。

4.4 Unlock Bypass

连续编程多个字时,每次都发三个解锁周期会浪费约 30 % 的总线带宽。Unlock Bypass 让器件进入「已解锁」状态,后续每个字只需 2 个周期。

Unlock Bypass:进入要 2 周期、退出要 2 周期,中间每个字只要 2 周期读阵列普通命令需完整解锁(AA / 55 / 命令码)AA / 20hUnlock Bypass 模式每字只需:A0h + PA/PD批量写省约 30 % 开销90h / 00h读阵列恢复普通命令语义(必须两次写)忘了退出旁路模式的后果器件停留在旁路态,后续普通命令(如擦除、CFI)被当成旁路编程,整片数据可能被随机改写。退出必须发「0x0090 → 0x0000」两次写,不是一次。

图 5-1 Unlock Bypass 状态机。进入 2 周期(AA / 20h),退出 2 周期(90h / 00h);中间每个字的编程开销从 4 周期降到 2 周期。

/* Unlock Bypass 批量编程:进入 → N 个字 → 退出 */ int nor_program_bypass(volatile uint16_t *pa, const uint16_t *buf, size_t n) { nor_cmd(0x555, 0x00AA); nor_cmd(0x2AA, 0x0020); /* 进入旁路 */ for (size_t i = 0; i < n; i++) { *pa = 0x00A0; /* 旁路编程命令 */ pa[i] = buf[i]; /* 第 2 周期:地址 + 数据 */ if (nor_wait_ready(&pa[i], buf[i], T_PROG_US) != 0) { nor_bypass_reset(); /* 异常也要退出,别把器件留在旁路 */ return -E_PFAIL; } } nor_bypass_reset(); /* 0x0090 → 0x0000 */ return 0; } static void nor_bypass_reset(void) { nor_cmd(0x0000, 0x0090); nor_cmd(0x0000, 0x0000); }

4.5 写缓冲编程

写缓冲是最高效的大块写入方式:一次装载最多 16 ~ 32 字(由 CFI 0x2A 给出),再统一执行内部编程。

  • 装载的字数 N 必须写在第 3 周期的N−1位置,写错会导致缓冲长度不符。
  • 所有装载地址必须落在同一个扇区内;跨扇区会触发 DQ1 放弃标志,本次缓冲作废。
  • 装载完成后必须写「缓冲编程确认」0x0029到扇区地址 SA,内部编程才真正开始。
  • 缓冲编程的地址连续性要求各厂商略有差异(是否要求严格连续递增),必须查 datasheet。

4.6 命令下发五步准则

  1. 进入临界区:XIP 下禁止取指(RAM 执行 / 关中断 / 双 Bank),并禁止其它任务抢占总线。
  2. 下发解锁周期:0x555 ← 0x00AA、0x2AA ← 0x0055(x8 模式地址与数据宽度按 1.3 节换算)。
  3. 下发命令码与地址 / 数据:严格按命令表的周期数,不多发也不少发。
  4. 轮询等待完成:RY/BY# 或 DQ7 / DQ6,并强制配 DQ5 二次确认(第 8 章)。
  5. 退出与校验:Autoselect / CFI / 旁路必须显式退出;编程后回读比对,擦除后做 Blank Check。

命令序列中途被打断 = 命令作废

解锁周期与命令码之间是状态机相关的连续写。若中间被中断服务程序插进一次对同一片选的访问(哪怕只是一次读), 解锁状态可能被破坏,器件会把后续字节当成普通写——结果是「命令没生效,而且扇区里多了几个莫名其妙的字」。

对策:把整个命令序列封装成关中断的临界区,临界区内只访问 NOR 的命令地址,不做任何其它总线操作。

后续章节请下载「芯参谋」查看

……(篇幅原因, 还有17章· 详见芯参谋→方案设计)

当前分享仅开放前5章正文。详细资料请在芯参谋客户端中打开完整文档。

打开路径:🔧解决方案&应用市场分析 -> 原理方案设计 -> 并行NOR_PPI_NOR_软件设计规范

📥 下载芯参谋客户端

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 4:34:34

AI前端美化规则 Taste Skill:用 SKILL.md 让 Cursor 告别塑料感界面

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 4:34:26

Win10安装JDK1.8完整教程:从下载到环境变量配置与排错

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/29 4:29:15

同城电商系统:库存变更怎么同步到订单

同城电商系统库存变更若不同步到订单占用层&#xff0c;会出现「后台显示有货、实际已被未支付单占满」。宜库存 物理量 - 占用量&#xff1b;占用在下单创建&#xff0c;支付成功转实扣&#xff0c;超时释放。模型 sku_stock: on_hand sku_hold: sum(active holds) available…

作者头像 李华
网站建设 2026/9/29 4:25:46

hindsight浏览器历史取证实战:从SQLite碎片还原行为时间线

最近接了一个数据审计的活儿&#xff0c;客户拿了一台旧笔记本过来&#xff0c;说想搞清楚某天晚上这台设备到底访问了哪些网站、下载过什么文件、登录过哪些账号。设备早就关了机&#xff0c;现场也早就收拾干净了&#xff0c;唯一的线索就是浏览器里残留的那些数据库文件。这…

作者头像 李华
网站建设 2026/9/29 4:25:39

Keil C51和MDK-ARM共存:51与STM32双平台开发环境搭建全攻略

直接上干货&#xff0c;不兜圈子。这篇写给那些手边同时摆着51开发板和STM32开发板的人&#xff0c;也就是我踩过一遍坑的地方。先说结论&#xff1a;Keil C51和Keil MDK-ARM不是同一个软件的两个版本&#xff0c;而是两套完全独立的工具链&#xff0c;只是共用了一个名叫Visio…

作者头像 李华