Skip to content

块、扇区、页

我们可以用一个**“笔记本”**来完美比喻这个结构:

1. 结构层级(从大到小)

假设 W25Q64 是一本厚厚的笔记本(总共 8MB)。

Block(块)—— 相当于“一章”

  • 大小:通常是 64KB
  • 地位:是较大的逻辑单元。W25Q64 总共有 128 个 Block(8MB / 64KB = 128)。
  • 操作:支持“整块擦除”(指令 0xD8)。如果你想撕掉一大叠纸,就用这个。

Sector(扇区)—— 相当于“一张纸”

  • 大小:固定为 4KB
  • 关系:1 个 Block 里面包含了 16 个 Sector。
  • 地位这是 Flash 擦除的最小单位!(敲黑板重点)
    • 在 Flash 里,你不能只擦掉一个字,你必须把整张纸(4KB)上的字全部擦掉(变成 0xFF),才能重新写字。
  • 操作:支持“扇区擦除”(指令 0x20)。这是最常用的擦除指令。

Page(页)—— 相当于“一行”

  • 大小:固定为 256 Bytes
  • 关系:1 个 Sector 里面包含了 16 个 Page。
  • 地位这是 Flash 写入(编程)的基本单位。
    • 虽然你可以一个字节一个字节地写,但硬件内部其实是按页来缓存的。
    • 关键限制:一次写入操作(Page Program 0x02)最多只能写 256 字节,而且不能跨行写

2. 算术关系表 (W25Q64)

层级大小数量关系常用操作
Chip (芯片)8MB1 个Chip Erase (0xC7) - 全片擦除
Block (块)64KB128 个Block Erase (0xD8) - 块擦除
Sector (扇区)4KB每个 Block 有 16 个Sector Erase (0x20)- 扇区擦除
Page (页)256 B每个 Sector 有 16 个Page Program (0x02)- 页编程
Byte (字节)1 B每个 Page 有 256 个Read Data (0x03) - 读取

3. 写代码时的两个“大坑”

坑一:必须“先擦后写” (Erase before Write)

Flash 有个物理特性:只能把 1 变成 0,不能把 0 变成 1。

  • 擦除 (Erase):把整个扇区(4KB)所有的位都变成 1 (即 0xFF)。
  • 写入 (Program):把某些位变成 0 (比如写入 0x55, 即 01010101)。

后果: 如果你没擦除(扇区里有旧数据),直接去写新数据,新旧数据会进行**“与运算”**,导致数据变废。

  • 比如原数据是 0xAA (10101010),你想写 0x55 (01010101)。
  • 结果变成:0xAA & 0x55 = 0x00
  • 解决: 写入前,必须检查该位置是否为 0xFF。如果不是,必须先把整个 Sector(4KB) 读出来缓存,擦除该 Sector,修改缓存里的数据,再把整个 4KB 写回去。

坑二:页写入回绕 (Page Wrap Around)

这是 0x02 指令最容易踩的坑。

规则: 一次 Page Program 指令,只能在同一页(256字节)内操作,不能跨过页的边界。

举例:

  • 假设一页的范围是地址 0x00000x00FF
  • 你想从 0x00F0 开始,写入 20 个字节。
  • 理应写到:0x00F0 ~ 0x0103 (跨到了下一页)。
  • 实际发生: 硬件写到 0x00FF 后,指针会跳回本页的开头0x0000 继续写!
  • 结果: 你的数据会覆盖掉本页开头的数据 (0x0000~0x0003),而下一页 0x0100 啥也没写进去。

解决: 写代码时必须计算**“页剩余空间”**。如果数据长度超过本页剩余空间,必须要把数据切成两段,分两次发送 0x02 指令。

总结

  • Sector (4KB)橡皮擦的最小单位(要擦就擦一张纸)。
  • Page (256B)提笔写字的最大连续单位(一次最多写一行,写到行尾要换行)。