前言

存储器相关知识的笔记。

一、存储器分类

在这里插入图片描述
参考:http://t.csdnimg.cn/Jqffo

1.RAM 系列

1.1 RAM(随机存储器)

早期的RAM是一种易失性存储器,它可以随机读取和写入数据。在这个阶段,RAM是一种相对易失的存储,通常在电源断开时会失去存储的数据。

现代RAM仍然是易失性存储器,但有了更快的速度和更高的密度。在计算机系统中,RAM用于临时存储正在运行的程序和数据。

1.2 SRAM(静态随机存储器)

SRAM是一种高速缓存存储器,以其快速的读写速度和相对较低的功耗而闻名。它由触发器电路构成,能够在不断电的情况下保持存储数据。

SRAM芯片通常用于高速缓存(如CPU和GPU中的L1/L2缓存),因为它们具有快速读写能力和不需要刷新的特性。由于每个SRAM存储单元需要6个晶体管,因此其集成度较低,存储容量有限,通常在几MB到几十MB之间。

1.3 DRAM(动态随机存储器)

DRAM是一种常见的内存类型,以其高密度和相对低廉的价格而受欢迎。它的存储单元是由一个电容和一个晶体管组成,需要定期刷新以保持数据。虽然DRAM的读写速度较慢,但在系统内存方面表现出色。

1.4 SDRAM(同步动态随机访问存储器)

SDRAM是同步性存储器,它的操作是与系统时钟同步的。相对于早期的DRAM(动态随机访问存储器)来说,提供了更高的数据传输速度。它通常具有较低的延迟,适用于需要快速读写的应用场景。

1.5 DDR SDRAM(双倍数据速率同步动态随机访问存储器)

DDR 全称是 Double Data Rate SDRAM
DDR SDRAM是SDRAM的一种升级版本,数据传输速率是SDRAM的两倍,提高内存带宽。 DDR SDRAM有不同的版本,如DDR2、DDR3、DDR4等,每个版本都提供了更高的频率和更好的性能。

DDR1:SDRAM 在一个 CLK 周期传输一次数据,DDR 在一个 CLK 周期传输两次数据,也就是在上升沿和下降沿各传输一次数据,这个概念叫做预取(prefetch),相当于 DDR 的预取为 2bit,因此DDR 的 速度直接加倍 。

DDR2: 在 DDR 基础上进一步增加预取(prefetch),增加到了 4bit,相当于比 DDR 多读取一倍的数据。

DDR3 :在 DDR2 的基础上将预取(prefetch)提高到 8bit,因此又获得了比 DDR2 高一倍的传输速率。

2.ROM 系列

2.1 ROM(只读存储器)

最初,ROM是一种非易失性存储器,一旦数据被写入,通常就不能被随意擦除或修改。

随着技术的进步,现代计算机系统中的“ROM”通常指的是非易失性存储器,但不再严格限制为只读。闪存技术,如NAND Flash和NOR Flash,允许多次擦除和重写数据。因此,现代的“ROM”更灵活,可以用于存储可更新的固件和操作系统。

2.2 Mask ROM(掩模只读存储器)

Mask ROM是一种固化数据的只读存储器,其内容在制造时由芯片制造商预设。由于其固定性,无法被用户修改,通常用于存储固件和基本的系统软件。

2.3 PROM(可编程只读存储器)

PROM允许用户一次性编程,通过烧录数据来定制存储内容。一旦编程完成,数据将永久存储在其中。PROM在一些应用中提供了更大的灵活性。

2.4 EPROM(可擦写可编程只读存储器)

EPROM具有擦写功能,擦除操作需要使用紫外线,然后重新编程。尽管这种过程有一定的繁琐性,但EPOM在一些特殊应用中仍然有其独特的价值。

EPROM常用于嵌入式系统中,用于存储固件或引导程序。

2.5 EEPROM(电可擦写可编程只读存储器)

EEPROM不需要紫外线,通过电信号就能实现擦写操作。这使得EEPROM更加灵活,可在系统运行时进行修改。它常用于存储配置信息和小规模的数据。

2.6 Flash存储器>NAND Flash & NOR Flash

Flash存储器结合了高密度和可擦写的优势,广泛应用于移动设备、存储卡和固态硬盘等领域。它以块的形式擦除,相对于EEPROM而言,Flash存储器的擦写速度更快。Flash又分为NAND Flash和NOR Flash

NAND Flash

NAND Flash以块(Block)的形式组织数据,每个块包含多个页面(Page),而每个页面包含多个字节。数据是以页为单位进行读写,以块(Block)为单位进行擦除操作。NAND Flash的寿命较长,但其擦写次数有限,因此适用于需要大容量、高速度、相对较低擦写次数的应用场景

常用于大容量、高性能的存储需求,例如固态硬盘(SSD)、USB驱动器、SD卡、eMMC等。

NOR Flash

NOR Flash以字节为单位进行寻址,具有直接访问任意字节的能力,不需要通过块擦除。这使得它更适用于随机读取。NOR Flash的寿命通常较长,适用于需要频繁擦写和相对较低容量的应用。

常用于嵌入式系统、固件存储、引导代码等场景。

二、固态硬盘-ROM

固态硬盘(Solid State Drive,简称SSD)是一种基于闪存(NAND Flash)等电子存储介质的高性能存储设备。

参考:
用最好的动画为你讲解–固态硬盘(SSD)的原理

1.量子隧穿效应

量子隧穿效应是一种量子现象,指微观粒子在能量低于势垒高度的情况下,仍有一定概率穿越势垒的现象。
微观粒子:电子
势垒:绝缘墙
在这里插入图片描述

在这里插入图片描述

2.浮栅-非易失的原因

浮栅(Floating Gate)是半导体非易失性存储器中的核心技术之一,广泛应用于闪存(Flash Memory)等器件中,其核心功能是通过捕获和释放电荷来实现数据的长期存储,即使断电也不会丢失信息。

1.基本结构
浮栅晶体管本质上是MOSFET的改进版本,在控制栅(Control Gate)与沟道之间增加了一个被二氧化硅绝缘层完全包围的导电层——即“浮栅”。由于该栅极没有直接电气连接,像“漂浮”在绝缘介质中,故称“浮栅”。

2.工作原理
捕获电荷:施加电压,电流方向从左向右
在这里插入图片描述
内部导体外围有绝缘体,所以电子无法溢出,得以保存。
在这里插入图片描述

释放电荷:施加电压,电流方向从右向左
在这里插入图片描述

3.mos管

在这里插入图片描述

N型和P型半导体都是可以导电的,但两者交界处的PN结不导电,故两个N型半导体不导通。

在这里插入图片描述
当形成电压差时,大量电子聚集在绝缘层附近:
在这里插入图片描述
此时,两个N型半导体导通:
**加粗样式**

4.浮栅晶体管

在这里插入图片描述

捕获电子:
在这里插入图片描述
释放电子:
在这里插入图片描述

判断浮栅中有无电子
N型半导体导通的阈值电压为5v,有电子,压差小于5v,不导通;无电子,压差为5v,导通。
导通不意味着浮栅中就会发生量子隧穿效应,N型半导体导通时的电压,不一定形成量子隧穿效应,电压差够大才行。
在这里插入图片描述
在这里插入图片描述
SLC(Single-Level Cell)‌: 每个单元存储 ‌1比特‌ 数据(0或1),仅需区分两种电压状态。由于状态少、电压裕量大,读写速度快,误码率低,耐用性极强。

MLC(Multi-Level Cell)‌: 每个单元存储 ‌2比特‌ 数据,需区分 ‌4种电压状态‌(00、01、10、11),根据电子的多少进行判断。存储密度提升,但对电压控制精度要求更高,导致读写速度下降、出错率上升。

在这里插入图片描述
TLC(Trinary-Level Cell)‌: 每个单元存储 ‌3比特‌ 数据,需区分 ‌8种电压状态‌。成本进一步降低,容量更大,但性能与耐久性显著下降。

同理,QLC。

5.NAND Flash

浮栅晶体管共用一个N型半导体,属于串联关系。
在这里插入图片描述

与非门中的串联浮栅晶体管结构:
与非-》NOT AND -》 NAND
Flash-》读写速度快
故起名NAND Flash
在这里插入图片描述

串:头尾各有一个普通mos管,类似于开关:
在这里插入图片描述
块:多个串共用一个衬底。
在这里插入图片描述

在这里插入图片描述

页:同一字线下的浮栅晶体管
在这里插入图片描述

5.1 读操作:以页为单位进行读取

串选和地选通线设置为高电平,使两侧的N型半导体导通。
在这里插入图片描述
将其他字线设置为高电平,实现两侧的N型半导体导通,但又不会发生量子隧穿效应。
在这里插入图片描述

使用阈值电压(5v)进行测试,有电子,电压差小于阈值,不导通,位线上的无电压;无电子,导通,位线有电压。
在这里插入图片描述
对读出的数据进行保存:
在这里插入图片描述

5.2 写数据:只能控制电子进入浮栅

串选通线高电平,导通;地选通线低电平,不导通。
位线0v,浮栅晶体管的压差够大,形成量子隧穿效应,电子进入浮栅。
位线8v,浮栅晶体管的压差不够大,不形成量子隧穿效应,电子不进入浮栅。在这里插入图片描述

5.3 擦除操作:以块为单位释放电子

栅极低电压,衬底高电平,因为块是共用衬底的,所以整个块都会被擦除。

5.4 3D NAND Flash

在这里插入图片描述

5.5 坏块管理

坏块管理是识别并标记Nand Flash中无法正常使用的物理块,避免数据写入这些区域导致错误.

坏块识别:在 NAND Flash 制造过程中,由于工艺等原因,会产生一些不良块(坏块)。这些坏块无法正常读写,因此需要在使用前进行识别和标记。
坏块映射:识别后的坏块需要进行映射,通常会使用一个额外的坏块表(Bad Block Table)来记录坏块的位置,以便在文件系统或存储控制器中进行管理。

5.6 磨损均衡

磨损均衡则通过算法将数据均匀分布在不同存储块上,防止某些块因过度擦写提前损坏

数据分布均衡:尽量保持数据在存储器中的分布均匀,避免频繁写入同一块或同一组块,以减缓块的擦写速度,延长存储器寿命。
热点数据管理:管理可能形成的热点数据,减少对热点数据的访问次数,避免某些块的过度使用。
块擦写次数平衡:监测每个块的擦写次数,对擦写次数较高的块进行数据迁移操作,将数据迁移到擦写次数较低的块上,平衡块的使用状况。
擦除空闲块:及时回收已经擦除的空闲块,并确保它们在下一次写入操作时被合理地利用,减少特定块的过度使用。

参考链接:https://blog.csdn.net/m0_62140641/article/details/136308202

5.7 ECC(Error Correction Code)

NAND Flash ECC(错误检查与纠正)技术是固态存储中保障数据完整性的核心机制,其主要功能为‌检测并自动纠正‌因物理老化、电荷泄漏、读写干扰或制造缺陷导致的位错误(bit flips)。该技术通过在原始数据中嵌入冗余校验信息,实现对单比特乃至多比特错误的精准修复。每512字节数据通常附加16~64字节校验位,纠错能力从1-bit到120-bit不等,取决于NAND类型与厂商设计。

三、内存-RAM

1. 1T1C结构-DRAM

在这里插入图片描述
一个电容能够表示一位数据,所以连接电容的线叫 位线;控制电容开关的线叫 字线
在这里插入图片描述
电容排列成网状结构,横向字线,控制着一排电容的开关;纵向位线,代表电容是否有电压。所以同一时刻只能开启一条字线。
在这里插入图片描述

库:65536 X 8192 个电容,多个库组成一个内存颗粒,多个内存颗粒可以形成一个内存条。
在这里插入图片描述

2. 刷新操作

虽然有半导体开关,但电容还是会缓慢漏电,所以需要定时刷新内存。
步骤:
预充电,字线设置为电容最高电压(1.1v)的一半(0.55v)。
字线高电平,控制一排电容导通。
感应放大电路位于字线上,当电容电压大于0.55v,字线上电压上升,该电路将字线电压提高到1.1v,此时电容充电到1.1v;当电容电压小于0.55v,字线上电压下降,该电路将字线电压下降到0v,此时电容放电到0v。

3. 读操作

先刷新,保持电容状态,再读取相应位线即可。

4. 写操作

先刷新,改变相应位线电压即可。

四、DDR容量-SDRAM

参考:存储器知识简介
DDR容量计算中的数据位宽指的是单个内存芯片(颗粒)在一次数据传输中能够并行处理的位数.

传统的SDRAM在通信时,仅在时钟的上升沿将数据采样并进行存储处理,即一个CLK周期只采样一次数据。若DDR的数据位宽为8bit,则一个时钟周期内采样数据量为8bit,即为1Byte。如下:

在这里插入图片描述

为了提高SDRAM的通信速度,设计了在时钟上升沿和下降沿都对数据进行采样的储存器,一个CLK周期内采样两次数据。若DDR的数据位宽为8bit,则一个时钟周期内采样数据量为16bit即为2Bytes。采样速度变为传统SDRAM的两倍,故命名为Double Data Rate SDRAM, 即
为DDR DRAM。如下:

在这里插入图片描述
在这里插入图片描述
由2(n)位行地址和2(m)位列地址所组成的4位地址可以寻址到的存储单元个数为:2的2次方 × 2的2次方 = 2的4次方 =16 ,即n的2次方 × m的2次方 .

在这里插入图片描述
在这里插入图片描述
库地址2个:BA1、BA2
行地址15个:A0-A14
列地址10个:A0-A9
并行带宽,数据线16根:DQU + DQL = 8 + 8

五、Flash容量-ROM

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

六、SPI Flash-Nor Flash

参考:STM32—W25Q64
嵌入式——Flash(W25Q64)

STM32—W25Q64 介绍了内存分布情况。
嵌入式——Flash(W25Q64)介绍了如何操作。

以下只是参考文献的备份,建议直接看链接文献。

1.W25Q64简介

W25Oxx系列是一种低成本、小型化、使用简单的非易失性存储器
    易失性存储器 般就是SRAM、DRAM等
    非易失性存储器 般就是E2PROM、Flash等
常应用于数据存储、字库存储、固件程序存储等场景
存储介质:Nor Flash(闪存)
时钟频率:80MHz  /  160MHz(DualSPI)双重SPI   /   320MHz(Quad SPI)四重SPI
存储容量(24位地址):
    W25040:        4Mbit / 512KByte
    W25080:        8Mbit / 1MByte
    W25Q16:       16Mbit / 2MByte
    W25Q32:       32Mbit / 4MByte
    W25064:        64Mbit / 8MByte
    W250128:      128Mbit / 16MByte
    W250256:      256Mbit / 32MByte

2的24方=16777216 / 1024 = 16384KB /1024 =16MB 所以24位地址的最大寻址空间是16MB W25Q40到Q128, 使用 3字节24位的地址都是足够的,所以W25Q256分为3字节地址模式和4字节地址模式,在3字节地址模式下,只能读写前16MB的数据,后面16MB,3个字节的地址够不着,要想读写到所有存储单元,可以进入4字节地址的模式

0X00 00 00 ~0XFF FF FF,其中每一个地址代表一个字节byte。

AT24C02它的容量,一般是KB级别的

在这里插入图片描述

2.硬件电路

除了SPI通信引脚,还有两个引脚,一个是WP写保护,另一个是HOLD,这两个引脚,如果不需要的话,也可以拉过来,充当数据传输引脚,加上MOSI和MISO,这就可以4个数据位同时收发了,这就是四重SPI,其实这就有点并行传输的意思了,串行是根据时钟,一位一位地发送,并行是一个时钟,8位同时发送,所以这个四重SPI模式,其实就是4位并行的模式

1号引脚这个CS左边画了个斜杠,代表是低电平有效,或者这边,CS上面画了个横线,也是低电平有效,CS对应之前我们讲SPl的名称就是SS,意思是SPI的片选引脚

3号,WP(Write Protect),它的意思是写保护,配合内部的寄存器配置,可以实现硬件的写保护,写保护低电平有效,WP接低电平,保护住,不让写

最后7号,HOLD数据保持,低电平有效,就是如果你在进行正常读写时,突然产生 中断 ,然后想用SP|通信线去操控其他器件,这时如果把CS置回高电平,那时序就终止了,但如果你又不想终止总线,又想操作其他器件,这就可以HOLD引脚置低电平,这样芯片就HOLD住了,芯片释放总线,但是芯片时序也不会终止,它会记住当前的状态,当你操作完其他器件时,可以回过来,HOLD置回高电平,然后继续HOLD之前的时序,相当于SPI总线进了一次中断,并且在中断里,还可以用SPI午别的事情,这就是HOLD功能

这个DI、DO、WP和HOLD旁边都有括号,写了1O0、IO1、1O2、IO3,这个就对应我们刚才这里说的,双重SP|和四重SPI,如果是普通的SPI模式,那括号里的都不用看,如果是双重SPI那DI和DO就变成IO0和IO1,也就是数据同时收和同时发的2个数据位,同理四重。。
3.框图
在这里插入图片描述

首先,右上角这一大块,描述的是存储器的规划示意图,我们这个W25Q64,容量是8MB,如果不进行划分,而只按照一整块来使用的话,那这一整块的容量就太大了,不利于管理,而且后续,我们涉及到F当sH擦除,或者写入的时候,都会有个基本单元,我们得以这个基本单元为单位进行,所以,这里,这 整块大蛋糕,8MB的存储空间,就有必要进行一些合理的划分

那常见的划分方式就是一整块存储空间,先划分为若干的块Block,其中每一块再划分为若干的扇区Sector,对于每个扇区,内部又可以分成很多页Page

那我们看下W25064是怎么划分的呢,首先,这一整个矩形空问里,是所有的存储器存储器以字节为单位,每个字节都有唯一的地址,之前说了,W25Q64的地址宽度是24位,3个字节,所以可以看到,左下角,第一个字节,它的地址是00 00 00H,H代表16进制,之后的空间,地址依次自增直到最后一个字节,地址是7FFFFFh,那最后一个字节为啥是7F开头,不是FF开头呢,因为24位地址,最大寻址范围是16MB,我们这个芯片只有8MB,只用了一半

然后在这整个空间里,我们以64KB为一个基本单元,把它划分成若干的块Block,从前往后,依次是块0、块1、块2、等等等等,直分到最后一块,那整块蛋糕是8MB,以64KB为一块进行划分,最后分得的块数,就是8MB/64KB=128块,那块序号就是块0,一直到块127,然后观察一下块内地址值的变化规律,比如块0的起始地址是00 00 00,结束地址是00 FF FF,之后,块31,起始是1F0000,结东是1FFFFF,在每一块内,它的地址变化范围就是低位的2个字节,每个块的起始是xx 0000,结東是xx FF FF

之后看一下左边,这个示意图就是我们还要再对每一块进行更细的划分,分为多个扇区Sector,这里的虚线看到没,指向了右边的各个块,也就是告诉你,每一块里面都是这个样子的,那在每个块里它的起始地址是xx 00 00,结東地址是xx FF FF,在一块里,我们再以4KB为一个单元,进行切分,块是64KB,我4KB一切,切成16份,所以在每一块里,都可以分为扇区0,一直到扇区15,每个扇区内的地址范围是减xx 0x 00到xx xF FF,这就是对每一块,再细分为16个扇区的分配方式,当然,地址划分,到扇区就结束了

但是当我们在写入数据时,还会有个更细的划分,这就是页Page,当然你也可以把它看作,在扇区里,再进行划分,都是一样,那页的大小呢,是256个字节,一个扇区是4KB,以256个字节划分,4x1024/256=16页,页的地址规律,我们也看一下,在这里,每一行就是一页,左边这里指了个箭头,写的是页地址的开始,右边这里也指了个箭头,写的是页地址的结束,在一页中,地址变化范围xx xx 00到xx xx FF,页内的地址变化,仅限于地址的最低一个字节

左下角,这是SPI 控制 逻辑,也就是芯片内部进行地址锁存、数据读写等操作,都可以由控制逻辑来自动完成,这个不用我们操心,控制逻辑就是整个芯片的管理员,我们有什么事,只需要告诉这个管理员就行了,然后,控制逻辑左边,就是SPl的通信引脚,有WP、HOLD、CLK、DI和DO,这些引脚,就和我们的生控芯片相连,主控芯片通过SPI协议,把指令和数据发给控制逻辑,控制逻辑就会自动去操作内部电路来完成我们想要的功能,

然后继续看,控制逻辑上面有个状态寄存器Status Register,这个状态寄存器是比较重要的,比如芯片是否处于忙状态、是否写使能、是否写保护,都可以以在这个状态寄存器里体现

然后上面,是写控制逻辑Write Control Logic和外部的WP引I脚相连,显然,这个是配合WP引l脚实现硬件写保护的,接着继续,右边这里,是个高电屈生成器High Voltage Generators,这个是配合Flash进行编程的。因为 Hash 是掉电不丢失的,如何实现掉电不丢失呢,比如你点亮一个LED表示1,熄灭LD表示0,但如果整个系统电都没有,那1和0就无从说起了,所以要想掉电不丢失,就要在我们的存储器里,产生些刻胃铭心的变化,比如,一个LED,我给它加很高的电压,那LED就烧坏了,我们用烧坏的LED表示1,没烧坏的LED表示0,然后再断电,烧坏的LED还是烧坏的,有电没电,它都是坏的,这个烧没烧坏的状态,不受有电还是没电的影响,所以它就是掉电不丢失的

那对于我们的非易失性存储器来说,也是一样,我们要让它产生一个即使断电也不会消失的状态,般都需要一个比较高的电压去刺激它,所以这种掉电不丢失的存储器,一般都需要一个高压源,那这里,芯片内部集成了高电压发生器,所以就不需要我们再外接高电压了,比较方便

然后在下面,这里是页地址锁存/计数器(Page Address Latch / Counter),然后下面还有个字节地址锁存数器(Byte Address Latch / Counter),这两个地址锁存和计数器,就是用来指定地址的,我们通过SPI,总共发过来3个字节的地址,因为一页是256字节,所以一页内的字节地址,就取决于最低一个字节,而高位的2个字节,就对应的是页地址,所以在这里,我们发的3个字节地址,前两个字节,会进到这个页地址锁存计数器里,最后一个字节,会进到这个字节地址锁存计数器里,然后,页地址,通过这个写保护和行解码,来选择我要操作哪一页,字节地址,通过这个列解码和256字节页缓存,来进行指定字节的读写操作,那又因为我们这个地址锁存,都是有一个计数器的,所以这个地址指针,在读写之后,可以自动加1,这样就可以实现从指定地址开始,连续读写多个字节的目的了

那最后,右边这里,有个256字节的页缓存区,它其实是一个256字节的RAM存储器,然后,我们数据读写,就是通过这个RAM缓存区来进行的,我们写入数据,会先放到缓存区里,然后在时序结束后,芯片再将缓存区的数据复制到对应的Flash里,进行永久保存
为啥要弄一个缓存区呢?我们直接往Flash里写不好吗,那这是因为,我们的SPI写人的频率是非常高的,而Flash的写入,由于需要掉电不丢失,留下刻骨铭心的印象,它就比较慢,所以,这个芯片的设计思路就是你写入的数据,我先放在页缓存区里存着,因为缓存区是RAM,所以它的速度非常快,可以跟得上SPl总线的速度,但是这里有个小问题,就是这个缓存区只有256字节,所以写入的时序有个限制条件就是写入的一个时序,连续写入的数据量,不能超过256字节,然后等你写完了,我芯片再慢慢地把数据,从缓存区转移到Flash存储器里,那我数据从缓存区转到Flash里,需要一定的时间,所以在写入时序结束后,芯片会进入一段忙的状态,在这里,它就会有一条线通往状态寄存器,给状态寄存器的BUSY位置1,表示芯片当前正在搬砖呢,很忙,那在忙的时候,芯片就不会响应新的读写时序了,这就是写入的执行流程

然后我们读取数据呢,虽然这里画的应该也会通过缓存区来读取,但是由于读取,只是看一下电路的状态就行了,它某本不花时间,所以读取的限制就很少了,速度也非常快
4.Flash操作注意事项

写入操作时:

写入操作前,必须先进行写使能
每个数据位只能由1改写为0,不能由0改写为1
写入数据前必须先擦除,擦除后,所有数据位变为1
擦除必须按最小擦除单元进行
    Flash的擦除,有最小擦除单元的限制,你不能指定某一个字节去擦除,要擦,就得一大片一起擦,在我们这个芯片里可以选择,整个芯片擦除,也可以选择,按块擦除,或者按扇区擦除然后再小,就没有了,所以最小的擦除单元,就是一个扇区4KB,就是4096个字节
    那你说,我只想擦除某一个字节怎么办呢,这没办法,你只能把那个字节所在扇区的4096个字节全都掉,如果存储了数据怎么办,这也没办法,要想不丢失数据,你只能先把4096个字节都读出来,再把4096个字节的扇区擦掉,改写完读出来的数据后再把4096个字节全都写回去
    实际情况下,我们还有别的方法可以优化一下这个流程,比如,上电后,我先把Flash的数据读出来,放到RAM里,当有数据变动时,我再统一把数据备份到Flash里,或者,我把使用频繁的扇区,放在RAM里,当使用频率降低时,我再把整个扇区备份到FLash里,或者,如果你数据量确实非常少,只想存几个字节的参数就行了,那直接一个字节占一个扇区,不就行了嘛,尽限奢之风
连续写入多字节时,最多写入一页的数据256字节,超过页尾位置的数据,会回到页首覆盖写入
写入操作结束后,芯片进入忙状态,不响应新的读写操作

读取操作时:

直接调用读取时序,无需使能,无需额外操作,没有页的限制,
读取操作结束后不会进入忙状态,但不能在忙状态时读取

我们来看下Hash操作的注意事项,这里列出了这么多Hash写入和读取的要求,那你可能会有些疑惑,不就是个存储器吗,我直接指定地址写或者指定地址读然后它直接给我把数据存在对应的存储单元里不就行了嘛,为啥还要搞这么多的注意事项呢,其实,这是因为Flash,作为一种掉电不丢失的存储器,为了保证掉电不丢失这个特性,同时还要保证存储容量足够大、成本足够低,所以,Flash存储器会在其他地方,比如操作的便捷性等做出一些要协和让步,Hash的写入和读取并不像RAM那样简单直接,RAM是指哪打哪,想在哪写就在哪写,想写多少就写多少,并且RAM是可以覆盖写入的,但是Flash并没有这个特性,总之,Hlash的读写有很多要求,其中写入的要求是非常多的,需要我们掌握
————————————————
版权声明:本文为CSDN博主「m0_60322134」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_60322134/article/details/142785359

一、初识W25Q64

  1. 基本认识

     W25Q64是华邦公司推出的大容量 基于SPI通信 的FLASH 产品,工作电压为 2.7~3.6V,存储容量为 64Mb(8MB),擦写周期可达 10万次,数据保存时间可达 20年。 W25Q64系列 Flash存储器与 普通串行Flash存储器 相比,其使用 更灵活、性能更出色,非常 适合用于存储声音、文本和数据。
    
         W25Q64 有 32768个 可编程页,每页 256字节。
    
         使用 页编程指令 就可以 每次编程 256字节。
    
         使用 扇区擦除指令 可以 每次擦除 256字节。
    
         使用 块擦除指令 可以 每次擦除 256 页。
    
         使用 整片擦除指令 可以 擦除整个 芯片。
    
         W25Q64 共有 2048个可擦除扇区(一个大小 4096字节) 或 128个 可擦除块。
    
  2. 引脚介绍
    在这里插入图片描述

     W25Q16、 W25Q32 和 W25Q64 支持标准的 SPl接口,传输速率最大 75 MHz,采用四线制,即4个引脚。
    
     ① 串行 时钟引脚 (CLK)
    
     ② 芯片 选择引脚 (CS)
    
     ③ 串行数据 输出引脚(DO)
    
     ④ 串行数据 输入 / 输出引脚(DIO):在普通情况下,该引脚是 串行输入引脚(DI),当使用 快读双输出 指令时,该 引脚就变成了 输出引脚,在 这种情况下,芯片就有 2个 DO引脚,所以称为 双输出,其 通信速率 相当于翻了 一番,所以 传输速率更快。
    

二、W25Q64特性

  1. SPI模式

     W25Q16 / 32 / 64支持通过 四线制SPl总线方式访问,支持 两种 SPI通信方式,即模式 0 和模式 3 都支持。
    
         模式 0 和 模式 3 的主要区别是:当主机的SPl接口处于空闲或者没有数据传输时,CLK的电平是 高电平还是 低电平。对于模式 0,CLK的电平为 低电平;对于模式 3,CLK的电平为 高电平。在 两种模式下芯片都是在 CLK的上升沿 采集输入数据,下降沿 输出数据。
    
  2. 双输出SPI方式

     W25Q16 / 32 / 64 支持 SPI 双输出方式,但需要使用 快读双输出指令(Fast Read Dual Output),这时通信速率相当于标准 SPI 的 2倍。这个命令非常适合在 需要一上电就快速下载代码到内存中的情况 或者 需要缓存代码段到内存中运行的情况。在使用快读双输出指令后,DI 引脚变为 输出引脚。
    

3.保持功能

    芯片处于使能状态(CS=0)时,把 HOLD引脚拉低可以 使芯片暂停工作,适用于芯片和其他器件 共享主机 SPI 接口的情况。

        例如:当 主机接收到一个更高优先级的中断时 就会抢占主机的 SPl接口,而这时芯片的页缓存区(Page Buffer)还有一部分 没有写完,在这种情况下,保持功能可以保存好 页缓存区的数据,等中断释放 SPI 口时,再继续完成刚才 没有写完的工作。

    使用保持功能,CS引脚必须为低电平。在 HOLD引脚出现下降沿以后,如果CLK引脚为低电平,将 开启保持功能;如果 CLK引脚为高电平,保持功能在 CLK引脚的下一个 下降沿开始。在 HOLD引脚 出现上升沿以后,如果 CLK引脚为低电平,保持功能将结束;如果 CLK引脚为高电平,在 CLK引脚的下一个下降沿保持功能将结束。

        在 保持功能起作用期间,DO引脚 处于 高阻抗状态,DI引脚 和 DO引脚上的信号将被忽略,而且在此期间,CS引脚 也必须 保持低电平,如果在此期间 CS引脚电平 被拉高,芯片内部的 逻辑将会被重置。

三、状态寄存器
在这里插入图片描述

  1. BUSY位

     忙位,是只读位,位于状态寄存器中的S0。当执行页编程、扇区擦除、块擦除、芯片擦除、写状态寄存器等指令时,该位将自动置 1。此时,除了读状态寄存器指令,其他指令都忽略;当页编程、扇区擦除、块擦除、芯片擦除和写状态寄存器等指令执行完毕之后,该位将自动清 0,表示芯片可以接收其他指令了。
    
  2. WEL位

     写保护位,是只读位,位于状态寄存器中的S1。执行完写使能指令后,该位将置 1。当芯片处于写保护状态下,该位为 0。
    
         在下面两种情况下,会进入 写保护状态:掉电后执行指令写禁止、页编程、扇区擦除、块擦除、芯片擦除,以及 写状态寄存器。
    
  3. BP2、BP1、 BP0位

     块保护位,是可读可写位,分别位于状态寄存器的S4、S3、S2,可以用 写状态寄存器指令置位 这些块保护位。        
    
     在默认状态下,这些位都为 0,即 块处于 未保护状态下。可以设置块为没有保护、部分保护或者全部保护等状态。
    
         当 SPR位为 1 或 /P引脚 为低电平时,这些位 不可以被更改。
    
  4. TB位

     底部和顶部块的保护位,是可读可写位,位于状态寄存器的 S5。该位默认为 0,表明顶部和底部块 处于未被保护状态下,可以用 写状态寄存器指令置位该位。当 SPR位为 1 或 /WP引脚 为低电平时,这些位不可以被更改。
    
  5. 保留位

     位于状态寄存器的 S6,读取状态寄存器值时,该位为 0。
    
  6. SRP位

     状态寄存器保护位,是可读可写位,位于状态寄存器的 S7。该位结合 /P引脚 可以禁止写状态寄存器功能。
    
     该位默认值为0。当SRP=0时,/WP引脚 不能控制状态寄存器的写禁止;当 SRP=1 且 /P=0时,写状态寄存器指令失效;当SRP=1 且 /P=1 时,可以执行写状态寄存器指令。
    

四、常用操作指令
在这里插入图片描述

  1. 写使能指令(06h)

     该指令会使 状态寄存器WEL位置位。在执行每个页编程、扇区擦除、块擦除、芯片擦除和写状态寄存器等指令之前,都要先置位 WEL。/CS引脚 先拉低为低电平后,写使能指令代码 06h 从 DI引脚输入,在 CLK上升沿采集,然后将 /CS引脚 拉高为高电平。
    
  2. 写禁止指令(04h)

     该指令将会使 WEL位 变为0。/CS引脚 拉低为低电平后,再把 04h 从 DI引脚 输入到芯片,将 /CS引脚 拉高为高电平后,就可完成这个指令。
    
         在执行完 写状态寄存器、页编程、扇区擦除、块擦除、芯片擦除等指令之后,WEL位就会自动变为 0。
    
  3. 读状态寄存器指令(05h)

     当 /CS引脚 拉低为低电平后,开始把 05h 从 DI引脚 输入到芯片,在 CLK的上升沿 时数据被芯片采集,当芯片采集到的数据为 05h 时,芯片就会把 状态寄存器的值从 DO引脚输出,数据在CLK的下降沿输出,高位在前。
    
         读状态寄存器指令 在任何时候都可以用,甚至在 编程、擦除 和 写状态寄存器的过程中也可以用,这样就可以 根据状态寄存器的 BUSY位 判断编程、擦除和写状态寄存器周期有没有结束,从而知道芯片 是否可以接收 下一条指令了。
    
         如果 /CS引脚 没有被拉高为高电平,状态寄存器的值将一直从DO引脚输出。/CS引脚拉高为高电平后,读状态寄存器指令结束。
    
  4. 写状态寄存器指令(01h)

     在执行 写状态寄存器指令之前,需要 先执行写使能指令。先将 /CS引脚 拉低为低电平后,然后把 01h 从 DI引脚 输入到芯片,接着把 想要设置的状态寄存器值通过 DI引脚 输入到芯片,/CS引脚拉高为高电平时,写状态寄存器指令结束。如果此时没有把 /CS 引脚 拉高为高电平 或者 拉得晚了,值将不会被写入,指令无效。
    
         只有 状态寄存器中的 SRP、TB、BP2、BP1、BP0 位可以被写入,其他只读位的值不会变。在该指令执行的过程中,状态寄存器中的 BUSY位为 1,这时可以用 读状态寄存器指令读出 状态寄存器的值并进行判断。当 写寄存器指令 执行完毕时,BUSY 位将自动变为 0,WEL位 也自动变为 0。
    
         通过对 TB、 BP2、 BP1、 BP0 等位写 1,就可以 实现将芯片的部分或全部存储区域设置为只读。通过对SRP位写 1,再把 /WP引脚 拉低为低电平,就可以 实现禁止写入 状态寄存器的功能。
    
  5. 读数据指令(03h)

     该指令 允许读出一个字节或一个以上的字节。先把 /CS引脚 拉低为低电平,然后把 03h 通过DI引脚 写入芯片,再送入 24位的地址,这些数据将在 CLK 的上升沿被芯片采集。
    
     芯片接收完 24位地址 之后,就会把相应地址的数据在 CLK引脚的下降沿从 DO引脚 发送出去,高位在前。当发送完这个地址的数据之后,地址将自动增加,然后通过 DO引脚把 下一个地址的数据发送出去,从而形成一个 数据流。也就是说,只要时钟在工作,通过 一条读指令,就可以把 整个芯片存储区的数据读出来。
    
         把 /CS引脚 拉高为高电平时,读数据指令将结束。当芯片在 执行页编程、扇区擦除、块擦除、芯片擦除和读状态寄存器指令的周期内,读数据指令不起作用。
    

五、相关代码
W25Q64的常用操作驱动。

/**
 * @brief	W25Q64等待空闲。读取状态寄存器,查询BUSY状态位命令。  
 *
 * @return  void
 */
void W25Q64_Busy(void)
{
    uint8_t cmd[2],data[2];
    
    cmd[0] = 0x05;  // 读寄存器指令
    cmd[1] = 0xFF;  // 激活时钟
    
    do
    {
    	CS_ENABLE;
        HAL_SPI_TransmitReceive(&hspi1,cmd,data,2,1000);
    	CS_DISABLE;
    	
    } while ((data[1]&0x01)==0x01);     // 判断 BUSY位 是否为 0
}


/**
 * @brief	W25Q64写使能。  
 *
 * @return  void
 */
void W25Q64_WriteEnable(void)
{
    uint8_t cmd;
    
    cmd = 0x06;
    
    W25Q64_Busy();      // 等待W25Q64空闲
    CS_ENABLE;
    HAL_SPI_Transmit(&hspi1,&cmd,1,1000);
    CS_DISABLE;
}


/**
 * @brief	擦除一个扇区  4kB
 *
 * @param   SectorNum   指定扇区编号
 *
 * @return  void
 */
void W25Q64_SectorErase(uint32_t SectorNum)
{
    uint8_t cmd[4];
    
    cmd[0] = 0x20;  // 擦除寄存器指令
    cmd[1] = (SectorNum*4096)>>16;// 4096 B = 4kB
    cmd[2] = (SectorNum*4096)>>8;
    cmd[3] = (SectorNum*4096)>>0;
    
    W25Q64_WriteEnable();   // W25Q64写使能
    W25Q64_Busy();      // 等待W25Q64空闲
    CS_ENABLE;
    HAL_SPI_Transmit(&hspi1,cmd,4,1000);
    CS_DISABLE;
}


/**
 * @brief	W25Q64写入一个页(256B)
 *
 * @param   date      待保存数据
 * @param   PageNum   指定页编号
 *
 * @return  void
 */
void W25Q64_WritePage(uint8_t* date, uint32_t PageNum)
{
    uint8_t cmd[4];
    
    cmd[0] = 0x02;  // 擦除寄存器指令
    cmd[1] = (PageNum*256)>>16;
    cmd[2] = (PageNum*256)>>8;
    cmd[3] = (PageNum*256)>>0;
    
    W25Q64_WriteEnable();   // W25Q64写使能
    W25Q64_Busy();      // 等待W25Q64空闲
    CS_ENABLE;
    HAL_SPI_Transmit(&hspi1,cmd,4,1000);
    HAL_SPI_Transmit(&hspi1,date,256,5000);
    CS_DISABLE;
}


/**
 * @brief	W25Q64读取数据
 *
 * @param   rdate   读取数据的保存地址
 * @param   addr    读取数据的地址
 * @param   len     读取数据的长度
 *
 * @return  void
 */
void W25Q64_ReadData(uint8_t* rdate, uint32_t addr, uint32_t len)
{
    uint8_t cmd[4];
    
    cmd[0] = 0x03;  // 擦除寄存器指令
    cmd[1] = addr>>16;
    cmd[2] = addr>>8;
    cmd[3] = addr>>0;
    
    W25Q64_Busy();      // 等待W25Q64空闲
    CS_ENABLE;
    HAL_SPI_Transmit(&hspi1,cmd,4,1000);
    HAL_SPI_Receive(&hspi1,rdate,len,50000);
    CS_DISABLE;
}

七、NOR Flash 与 NAND Flash 核心差异对比‌

7.1 存储结构与访问机制‌

NOR Flash‌:采用‌并联存储单元架构‌,每个存储单元独立连接到位线与字线,支持‌字节级随机访问‌,可直接通过地址总线寻址任意位置,行为类似传统RAM。
NAND Flash‌:采用‌串联存储单元架构‌,多个浮栅晶体管串联成链,数据必须以‌页(Page,4–16KB)为单位读取‌,以‌块(Block,8–32KB)为单位擦除‌,无法直接随机访问单个字节。

✅ ‌关键影响‌:NOR支持‌XIP(Execute In Place)‌,CPU可直接从Flash中执行代码;NAND必须将数据先加载至RAM再运行,无法直接启动。

7.2 读写与擦除性能对比‌

在这里插入图片描述

7.3 寿命与可靠性‌

在这里插入图片描述

7.4 成本与容量‌

在这里插入图片描述

7.5 典型应用场景‌

NOR Flash‌:

嵌入式系统启动代码‌(Bootloader)
工业控制、汽车ECU、医疗设备‌的固件存储
STM32、ESP32、RISC-V‌等MCU的片外程序存储
SPI NOR‌:用于IoT设备、智能传感器(如GD25Q系列)

NAND Flash‌:

SSD、U盘、SD卡‌等大容量存储介质
智能手机、平板‌的主存储(eMMC、UFS)
数码相机、智能电视、车载娱乐系统‌
3D NAND‌:数据中心、AI服务器、自动驾驶数据记录(如特斯拉Cybertruck)

八、NAND Flash

参考:正点原子STM32】FSMC_FMC——NAND FLASH实验
正点原子阿波罗 STM32F429 开发指南

建议直接看上面的参考文献,下面的内容只是摘要和补充

8.1 NAND FLASH 信号线

在这里插入图片描述
因为 NAND FLASH 地址/数据是共用数据线的,所以必须有 CLE/ALE 信号,告诉 NAND FLASH,发送的数据是命令还是地址。

8.2 存储单元

以阿波罗 STM32F429 开发板所使用的 FSNS8B004G(x8, 8 位数据)为例进行介绍

在这里插入图片描述
FSNS8B004G 由 2 个 plane 组成,每个 plane 有 2048 个 block,每个 block 由 64个 page 组成,每个 page 有 2K+64 字节(2112 字节)的存储容量。所以, FSNS8B004G 的总容量为: 2204864*(2K+64) =553648128字节(512MB)。

NAND FLASH 的 page 由 2 部分组成:数据存储区(data area)和备用区域(spare area) ,备用区域(spare area),一般用来存放 ECC(Error Checking and Correcting)校验值,在本章中,我们将利用这个区域,来实现 NANDFLASH 坏块管理和磨损均衡。

NAND FLASH 的的地址分为三类: 块地址(Block Address)、页地址(Page Address)和列地址(Column Address)。以 FSNS8B004G 为例,这三个地址,通过 5 个周期发送:
在这里插入图片描述
CA0~CA11为列地址(Column Address), 用于在一个Page内部寻址, FSNS8B004G的一个 Page大小为 2112 字节,需要 12个地址线寻址;2的11次方为2048,不够,所有要12次方,即12个地址线。
PA0-PA5 为页地址(Page Address),用于在一个 Block 内部寻址, FSNS8B004G 一个 Block 大小为 64 个 Page,需要 6 个地址线寻址;
BA6~BA17 为块地址(Block Address),用于块寻址, FSNS8B004G 总共有 4096 个 Block,需
要 12 根地址寻址。

在这里插入图片描述

8.3 FTL

FTL 是 Flash Translation Layer 的简写,即闪存转换层,它是一个NAND闪存芯片与基础文件系统之间的一个转换层,它自带了坏块管理和磨损均衡算法。

要做好 NAND FLASH 的坏块管理,我们有以下几点需要实现:
1, 如何识别坏块,标记坏块;
2, 转换表
3, 保留区

①如何识别坏块
NAND FLASH 的坏块识别有几种方式:
1, NAND 厂家出厂的时候,会在每个 Block 的第一个 page 和第二个 page 的 spare 区的第一个字节写入非 0XFF 的值来表示,我们可以通过这个判断该块是否为坏块;
2,通过给每个 Block 写入数值(0XFF/0X00),然后读取出来,判断写入的数据和读取的数据是否完全一样,来识别坏块;
3,通过读取数据时,校验 ECC 错误,来识别坏块。

②标记坏块;
使用每个 Block 的第一个 page 和第二个 page(第二个 page 是备份用的) spare 区的第一个字节来标记, 当这个字节的值为 0XFF 时,表示该块为好块,当这个字节的值不等于 0XFF 时,表示该块为坏块。

③转换表
文件系统访问文件的时候,使用的是逻辑地址,是按顺序编号的,它不考虑坏块情况。而NAND FLASH 存储地址,我们称为物理地址,是有可能存在坏块的。所以,这两个地址之间,必须有一个映射表,称之为逻辑地址-物理地址转换表
在这里插入图片描述
采用一个数组来存储逻辑地址到物理地址的映射关系,这个数组即映射表(简称:lut 表),同时,这个映射表必须存储到 NAND FLASH 里面, 以便上电后重建。这里,我们也是利用每个 Block 的第一个 page 的 spare 区来存储映射表,

每个 Block 第一个 page 的 spare 区第一个字节用来表示该块是否为坏块(前面已介绍);第二个字节用来表示是否被占用(0XFF,表示未占用; 0XCC,表示已被占用);第三和第四个字节,用来存储该块所映射到的逻辑地址,如果为 0XFFFF,则表示该块还未被分配逻辑地址,其他值,则表示该块对应的逻辑地址, FSNS8B004G 有 4096 个 Block,
所以这两个字节(16bit 可表示65536个block)表示的有效逻辑地址范围,就是 0~4095。

上电的时候,重建映射表(lut 表)的过程就是读取 NAND FLASH 每个 Block 第一个 page的 spare 区前 4 个字节,当这个块是好块(第一个字节为 0XFF),且第三和第四字节组成的uint16_t类型数据(逻辑地址,记为: LBNnum), 小于 NAND FLASH 的总块数-4096,则这个 Block地址(物理地址,记为: M)就是映射表里面第 LBNnum 个元素所对应的地址,即:lut[LBNnum]=M。

④保留区
保留区有两个作用:
1,产生坏块的时候,用来替代坏块;
2,在复写数据的时候,使用保留区中的空闲块用来替代被复写的块,以提高写入速度,并实现磨损均衡处理;

⑤ECC
假如每 512个字节的数据,会生成 3个字节的 ECC值,为了方便读写,我们用 4 个字节来存储这 3 个字节的 ECC 值
每个 page 的一个数据区有 2048 个字节,而每个 512 字节数据生成一个 ECC值,用4个字节存储,这样,每个page需要16个字节用于存储ECC值从每个 page 的 spare 区第 16 个字节(0X10)开始存储 ECC值, 总共占用 16 字节

八、EMMC

参考:深入讲解eMMC简介
eMMC之分区管理、总线协议和工作模式
参考文献中有emmc寄存器、通信协议等内容,建议直接看《eMMC之分区管理、总线协议和工作模式》。

eMMC是embedded MultiMediaCard的简称,即嵌入式多媒体卡,是一种闪存卡的标准,它定义了基于嵌入式多媒体卡的存储系统的物理架构和访问接口及协议。eMMC是一种嵌入式、非易失的存储系统,它主要由闪存、闪存控制器和eMMC协议接口等组成,以BGA的形式封装在一起。eMMC的构成如下图所示:
在这里插入图片描述

8.1 eMMC接口

eMMC接口主要实现将eMMC接入到Host的MMC总线上,与Host进行通信,实现eMMC的协议逻辑。eMMC接口与Host之间的连接如下图:
在这里插入图片描述
接口中各信号线的作用如下:

CLK:时钟信号,用于Host与Device间的同步。

Data Strobe:数据锁存信号,Device端的输出信号,用于HS400模式下,频率与CLK相同,主要用于同步从Device端输出的数据。

CMD:用于传输从Host端发出的command和Device端发出的response。

DATA0 ~ DATA7:用于在Host和Device间传输数据。

Reset:复位信号线,主要用于Host对Device进行复位操作。

8.2 闪存控制器

闪存控制器主要用来对内部的Nand Flash进行操作和管理。由于Nand Flash自身的物理特性,需要实现坏块管理、磨损均衡、ECC等诸多功能,这些功能就是由FTL(Flash Translation Layer)来实现。eMMC内部集成的闪存控制器则实现了FTL等功能,减少了由于不同型号Nand Flash的各种特性差异,造成的软件开发复杂度;同时闪存控制器也提供了Cache、Memory array、interleave等多种功能,大大提高了Nand Flash读写操作性能。

8.3 Flash memory

Flash Memory 是一种非易失性的存储器,通常在嵌入式系统中用于存放系统、应用和数据等,类似于 PC 系统中的硬盘。目前,绝大部分手机和平板等移动设备中所使用的 eMMC 内部的 Flash Memory 都属于 NAND Flash。

eMMC 在内部对 Flash Memory 划分了几个主要区域,如下图所示:
在这里插入图片描述
BOOT Area Partition 1 & 2

此分区主要是为了支持从 eMMC 启动系统而设计的。该分区的数据,在 eMMC 上电后,可以通过很简单的协议就可以读取出来。同时,大部分的 SOC 都可以通过 GPIO 或者 FUSE 的配置,让 ROM 代码在上电后,将 eMMC BOOT 分区的内容加载到 SOC 内部的 SRAM 中执行。

RPMB Partition

RPMB 是 Replay Protected Memory Block的简称,它通过 HMAC SHA-256 和 Write Counter 来保证保存在 RPMB 内部的数据不被非法篡改。在实际应用中,RPMB 分区通常用来保存安全相关的数据,例如指纹数据、安全支付相关的密钥等。

General Purpose Partition 1~4

此区域则主要用于存储系统或者用户数据。General Purpose Partition 在芯片出厂时,通常是不存在的,需要主动进行配置后,才会存在。

User Data Area

此区域则主要用于存储系统和用户数据。User Data Area 通常会进行再分区,例如 Android 系统中,通常在此区域分出 boot、system、userdata 等分区。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐