资讯动态

拆解SoC存储家族:从寄存器到Flash,一文理清嵌入式存储层级与选型

发布时间:2026/10/2 7:46:13 来源:尧图企业网站定制
前阵子调一块SoC的启动流程同事问我为什么BootROM里的代码只能用汇编写、为什么固件要先搬进SRAM再跳转、为什么不直接像PC那样把程序放在内存里跑。问的人多了我发现很多做了几年嵌入式的人对SoC内部这一大堆存储的概念其实是含糊的——寄存器、SRAM、Cache、TCM、DRAM、NOR Flash、NAND Flash、eMMC、UFS、OTP、eFuse……名字都能说出来但真要讲清楚为什么要有这么多种每种到底是干什么的选型时怎么权衡就有点绕了。这篇文章就结合我这些年接触过的各类SoC平台把这一大家子存储成员逐个捋一遍。不堆术语重点放在干什么用为什么这么设计彼此之间的核心差异上。无论你是刚接触嵌入式、正在做SoC板级设计还是写驱动、调启动流程这几千字应该能帮你把整个存储体系的框架搭起来。1. 为什么一个SoC内要装这么多种存储先看懂存储层级金字塔我在纸上画过很多次SoC的存储器地图Memory Map每次画完都会感叹一句这玩意儿本质上就是一座金字塔。1.1 单一存储介质撑不起一套系统很多人一开始会问既然要存东西那一种存储器不就行了比如全都用SRAM或者全都用Dram。问题的答案很简单因为不存在一种存储介质能同时满足快、大、便宜、掉电不丢这四个要求。速度快的比如寄存器、SRAM单位造价极高容量做不大。容量大的比如DRAM、Flash要么速度慢要么需要动态刷新要么擦写寿命有限。要掉电不丢非易失就得用Flash、OTP这类浮栅器件但它们写起来慢、擦除更慢而且寿命有限。所以SoC设计者的做法就是用不同特性的存储介质在架构上组成一个分层接力的系统让每一层只负责自己最擅长的活儿。这套思路叫存储层级结构Memory Hierarchy它不是哪家芯片厂拍脑袋定的而是整个计算机体系结构几十年的沉淀。1.2 金字塔每一层的职责分配如果把SoC的存储体系画成一个金字塔从上到下大致是塔尖CPU寄存器访问延迟大约1个时钟周期容量只有几十到几百字节用来放当下正在计算的中间结果。第二层SRAM包括L1 Cache、L2 Cache、TCM延迟几个到几十个周期容量几十KB到几MB用来做CPU和主存之间的缓冲或者放关键代码。第三层DRAM主存延迟几十到上百纳秒容量几百MB到几十GB系统真正运行的程序和数据主要在这里。第四层Flash存储包括NOR、NAND、eMMC、UFS、SD卡延迟从微秒到毫秒级容量从几MB到几TB负责掉电保存代码、固件、文件系统、用户数据。每一层都在给上一层打掩护CPU以为自己要的数据都近在咫尺命中Cache操作系统以为程序都在内存里跑而真正海量的数据则安静躺在Flash里需要时才按块搬上来。理解了这座金字塔后面所有存储类型的定位就都清楚了。下面我按离CPU从近到远的顺序一个一个拆开讲。2. 从寄存器到大容量Flash逐个拆解SoC里的存储成员2.1 寄存器与锁存器离CPU最近的临时便签寄存器是SoC里最微观、也最容易被忽略的存储单元。它由触发器构成直接嵌在CPU核内或者外设模块内访问延迟基本就是一个时钟周期。CPU运算的中间结果、状态标志、指令指针全都存在这里。除了CPU内核寄存器外设也有大量寄存器SFR/SMMIO比如UART的收发数据寄存器、GPIO的输出数据寄存器、DMA的控制寄存器。这部分存储有一个很有意思的特点它的地址是占用Memory Map的一段区间但访问它和访问普通内存有本质区别——读写寄存器往往带有副作用比如写一个控制位硬件立刻就动了所以通常被标记为MMIOMemory Mapped IO区域不能随意缓存。工程上要注意的是操作外设寄存器时如果开了Cache又没有正确配置MMU/MPU可能会读到脏数据或者写操作被缓冲导致硬件行为滞后。这个问题我后文还会单独讲。2.2 SRAM片上速度快但寸土寸金SRAM静态随机存取存储器是SoC片内最重要的高速存储采用六管6T或八管结构靠触发器状态保持数据所以只要供电数据就一直有效不需要像DRAM那样周期刷新。SRAM的速度可以做到与CPU核心频率基本同步延迟非常低。但SRAM的成本和面积相当可观。同样容量下SRAM占用的芯片面积大约是DRAM的好几倍静态漏电也更大。所以片上SRAM一般不会做得太大常见的在几百KB到几MB这个量级。像某些带AI加速的SoC会把NPBNetwork Buffer做成SRAM专门用来放神经网络中间特征图因为这类数据访问极其频繁如果走外部DRAM带宽和延迟都扛不住。在真实SoC里SRAM常见的形态有L1 Cache直接集成在CPU核内分成指令CacheI-Cache和数据CacheD-Cache一般是几十KB。L2 Cache可以理解为CPU核共享的片内大缓存几百KB到几MB。片内通用SRAM比如经常在Memory Map里看到的SRAM0、SRAM1用途很灵活经常被用作启动早期堆栈、DMA缓冲区、关键数据的钉子户。TCM紧耦合存储器下面单独说。2.3 TCM给不容闪失的代码一个确定性保障TCMTightly Coupled Memory紧耦合存储器这名字很多人不熟但它在汽车电子、工业控制和实时系统里非常常见。TCM和CPU之间的连接不经过Cache和总线仲裁延迟固定、确定不受Cache命中率影响。为什么要单独留一块这样的存储因为Cache不是确定性的——同一个循环这次跑可能命中下次因为中断导致Cache被踢掉就又miss了。对于硬实时任务比如刹车控制、电机换向最怕的就是这次比上次慢了20个周期因为那可能导致控制周期超时。TCM就是为了这一类场景生的中断向量表、实时性要求高的任务栈、临界代码段都可以放到TCM里执行时间和CPU主频严格对应。很多Cortex-M内核的SoC里的TCM是直接映射到固定地址的比如ITCM指令TCM和DTCM数据TCM。也有不少SoC允许把一段SRAM配置成TCM。选型时如果对实时性有硬指标优先确认这颗SoC有没有可用的TCM以及TCM大小是否够放关键代码。提示TCM虽然快但是容量很有限一般也就几百KB。它不能替代大内存只能用来放少数关键代码。如果把整个应用都塞进TCM那就是浪费片内宝贵资源。2.4 ROM、OTP与eFuse出厂就定死的基因这一组属于一次性存储和前面那些能反复读写的性质完全不同。Boot ROM掩膜ROM芯片出厂时就固化好的一段代码CPU复位后第一条指令就是去取这里的代码。它是整个系统启动流程的第一棒负责初始化时钟、DDR、选择启动介质、校验和加载下一级引导程序。OTP一次性可编程存储器只能写一次之后就只能读了。典型用途是存芯片序列号、安全密钥、校准参数、Boot配置字。eFuse基于熔丝技术的OTP最常见的用途是芯片级的硬件开关和身份信息。很多SoC的启动模式选择引脚不足时就会用eFuse里的bit来决定是从NOR还是eMMC还是USB启动。这个概念在手机SoC里尤其常见比如CPU锁频、核心数配置、安全熔丝等全都是eFuse的活。这类存储有个特征一旦编程错误没法后悔。所以工厂流程里对eFuse的写入一般都会做多重校验量产过程中还会预留一段用于后续功能扩展。2.5 DRAM系统主存的容量担当DRAM用电容存储电荷来表示0和1因为电容会漏电所以必须周期性刷新这是它工作原理决定的宿命。也正因结构是一个晶体管加一个电容它才能做到大容量、低单价成为系统主存DDR、LPDDR等的不二之选。在SoC里DRAM通常不集成在主芯片内部而是通过接口外接比如DDR4/DDR5、LPDDR4/LPDDR5。手机SoC为了省面积省电普遍用LPDDR并且做POPPackage on Package封装和主SoC叠在一起。PC处理器则直接把内存控制器集成在CPU里彻底绕开南桥走线缩短延迟。DRAM的访问延迟一般在十几纳秒级别CL值看起来不慢但和CPU主频动辄几GHz的时钟一比一次访存可能就要等几百个时钟周期。所以CPU和DRAM之间必须有Cache挡着不然CPU大部分时间都在等待内存。工程上使用DRAM还要注意初始化时序——DDR的PHY训练、读写校准、leveling这些都是启动代码要做的这也是为什么SoC启动的第二棒BL2阶段那么麻烦得先把这支大容量部队训练好才能把后续的程序和数据交到它手上。2.6 Flash家族掉电保数据的民生储备Flash是非易失存储靠浮栅晶体管保存电荷。根据内部逻辑结构的不同分成NOR和NAND两大门派。NOR Flash的特点支持随机读取有独立地址线和数据线可直接映射到CPU地址空间实现XIP片上执行。读速度尚可但写速度慢、擦除速度更慢容量一般做到几MB到几十MB。寿命通常标称10万次擦写。NOR适合放Bootloader、固件、关键配置参数——在DRAM还没初始化好之前CPU可以直接从NOR里取指令执行。这就是启动早期没有内存也能跑代码的实现基础。我调过的很多汽车MCU/SoC都是先从NOR XIP运行完成DDR初始化后再把应用搬到DDR里跑。NAND Flash的特点按页Page读写、按块Block擦除没法字节级别随机访问。顺序读写吞吐高容量单价低容量可以做到GB甚至TB级。有坏块问题需要文件系统层或专门的FTLFlash Translation Layer做坏块管理和磨损均衡。原始NAND还需要ECC纠错控制器或者软件必须做校验。在此基础上衍生的eMMC和UFS本质上是原始NAND 控制器 固件的封装控制器帮上层屏蔽了坏块管理、磨损均衡、ECC这些脏活对外提供标准块设备接口。UFS还引入了串行差分接口、命令队列、双通道顺序读性能比eMMC提升明显这也是现在手机中高端平台普遍用UFS的原因。这里有一个很实用的认知如果你的系统只是存少量固件配置选NOR就行如果是存Linux根文件系统、音视频素材用eMMC/UFS或SD卡。在SoC方案设计的前期就应该把哪些数据放NOR、哪些放NAND/eMMC定下来不然后面改板子等于从头再来。3. 核心差异对照速度、容量、成本、寿命一张表说清楚很多人记不住这些存储的特性我建议直接背下面这张表。这张表是我做方案对比时反复用到的各种存储的定位差异全在里头。存储类型相对访问速度典型容量是否易失写入方式寿命核心用途寄存器最快1周期几十~几百B易失随写无限CPU中间状态、控制配置SRAM极快几周期几十KB~几MB易失随写无限Cache、TCM、片内缓冲DRAM快几十ns几百MB~几十GB易失需刷新随写无限系统主存运行程序与数据NOR Flash读较快写很慢几MB~几十MB非易失写入前需擦除约10万次固件、Bootloader、关键参数NAND Flash顺序读写快随机慢几十MB~几TB非易失按页写、按块擦约1000~3000次MLC/TLC大容量文件存储eMMC/UFS顺序读写快几GB~几TB非易失通过控制器取决于内部NAND系统盘、根文件系统、用户数据OTP/eFuse读快写一次几KB以下非易失烧录一次100年保持序列号、密钥、配置字3.1 访问方式的本质差别地址寻址 vs 命令寻址这是很多初学者最容易卡住的地方。寄存器和NOR Flash是地址寻址的CPU发一个地址存储就把该地址的数据送到总线上读起来和读内存一样。这也是NOR能XIP的原因。NAND不是地址寻址它像一个存储块设备你要读取数据得先发命令、发块号/页号、发列地址然后等芯片内部把页数据搬到页寄存器再通过IO口把寄存器数据读出来。整个流程有点像你从档案室取资料先填申请单命令、报房间号和柜子号地址、等工作人员内部逻辑把整个抽屉页搬出来再一张一张递给你数据搬移。所以NAND的前期访问延迟高顺序传输吞吐才有优势。3.2 掉电保持的差异易失和非易失选用逻辑易失存储寄存器、SRAM、DRAM掉电数据即失非易失存储NOR、NAND、OTP、ROM掉电不丢。系统设计的逻辑就是平时运行的动态数据放易失存储需要长期保存的放非易失存储。但有一个灰色地带值得留意很多SoC支持低功耗模式比如Standby模式系统主电源断了但保留供电Retention Power的一小块SRAM仍然有电数据不乱。这用于快速唤醒比如手机休眠时把一些关键状态放保留SRAM里唤醒后不用重新初始化整个系统。设计低功耗逻辑时要分清哪些SRAM区域是保留域、哪些是非保留域否则数据丢了都不知道怎么回事。3.3 寿命与可靠性的不同处理逻辑Flash类存储都有擦写寿命但因为介质不同寿命差距很大。NOR一般标称10万次擦写适合固件升级次数不多的场景。而MLC/TLC NAND的标称寿命只有几百到几千次P/E Cycle所以必须靠磨损均衡Wear Leveling把写操作尽量均摊到所有块上不然某些块先被写坏了整颗芯片就废了。实际项目里我见过有人把日志高频写进NAND裸分区结果几个月后发现文件系统疯狂报坏块。这不是NAND不能用而是你没给它配健身教练——要么用eMMC/UFS这种自带控制器的方案要么在软件层自己实现Flash磨损管理和坏块替换。这个选题直接影响系统生命周期一定要在方案阶段想清楚。4. 从启动流程看存储协作一场上电后的接力赛存储类型拆完了你可能会问这么多存储它们是怎么协作的最直观的观察窗口就是整个SoC的启动流程。4.1 Boot ROM为什么必须锁死在硅片里SoC上电后CPU从复位向量取第一条指令这个地址就映射到Boot ROM。Boot ROM之所以用掩膜ROM是因为它必须一出生就有、不可能被篡改还要能在任何外部存储都还没准备好时先把CPU哄开。Boot ROM里的代码通常只有几KB到几十KB负责几件事初始化CPU缓存和MMU的最基本配置、探测启动介质根据boot引脚或eFuse配置决定从哪启动、做第一级校验然后把下一级引导程序从启动介质加载到片上SRAM里。为什么必须搬到SRAM而不是直接在NOR里执行一是Boot ROM自身空间太小放不下更大校验逻辑二是有很多SoC的启动介质是NAND/eMMC它们本身就不能XIP必须搬出来才能执行三是SRAM比NOR快加载完代码后切换到高速执行更稳妥。4.2 不同类型启动介质的启动路径之分这里有个很典型的工程问题为什么有些SoC支持NOR Flash直接启动XIP Boot而有些必须先从NAND把代码拷到SRAM再执行NOR启动CPU地址总线直接连NOR把PC指针指过去就能执行Boot ROM只需做很轻量的初始化。优点是启动快、流程简单缺点是NOR容量有限、价格偏高不适合放大的系统镜像。NAND/eMMC/UFS启动这类介质不能XIPBoot ROM里需要内置对应介质的最小启动驱动能识别设备、发命令、读数据。它把Bootloader比如U-Boot SPL读到SRAM然后在SRAM里执行SPLSPL再去初始化DRAM再把完整的U-Boot和内核搬到DRAM。链路长但能支持很大的镜像。手机SoC的启动里这一步还涉及安全启动Secure Boot——Boot ROM用eFuse里烧好的根公钥去验签下一级镜像验不过就死循环。这时候eFuse的价值就体现出来了它的一旦写入不可篡改正好用来构建信任根。4.3 从SRAM到DRAM一次换大house的过程早期启动阶段真正的大内存DRAM还没起来系统在SRAM里螺蛳壳里做道场。等到SPL/BL2阶段把DDR控制器、PHY训练做完后DRAM才真正可用。这时会把完整引导程序和操作系统镜像从Flash搬到DRAM然后长跳转过去执行。这个搬进DRAM的动作也解释了为什么SoC系统里经常能看到分散加载文件如sct/scat文件或者链接脚本lds里定义了多个执行区域一部分放TCM、一部分放SRAM、一部分放DDR每个区域的初始化时机不同必须分开管理。我自己在调试启动时最常用的一个技巧是先看启动日志输出来判断当前执行到哪个阶段再结合Memory Map确认是谁在跑。如果卡在DDR初始化大概率是PHY配置问题如果卡在Loading from MMC基本是eMMC驱动时序问题。能读系统的存储协作流程排错效率会高很多。5. 工程选型与实战中容易翻车的几个细节前面讲的都是底层的道理这一节聊点工程上更实际的东西。我踩过的坑、给客户做方案评审时发现的问题、以及一些常规文档里不太会写的经验集中放这。5.1 优先确认Cache和MMU/MPU的配置策略很多SoC默认开启的是大部分内存区域Cacheable、可写回Write Back。这意味着CPU写数据时先写进Cache再延迟写回主存。这本身没问题但如果你在代码里直接让DMA去搬运一块刚被CPU写过的内存而忘了做Cache Clean把Cache里的脏数据刷回内存那DMA搬到内存的可能就是旧数据——这种Bug极难查因为它不是必现的而是看Cache什么时候写回。反过来DMA写了一块内存CPU接着去读如果没做Cache InvalidateCPU可能读到Cache里残留的旧数据。这两条我在项目里都中过招一次是在网络驱动里一次是在音频采集里。所以做SoC驱动开发规则就是DMA和CPU共享内存时要么缓冲区配置成非Cacheable要么在每次DMA传输前后严格做好Clean和Invalidate。5.2 别把片上SRAM大小当成可用内存有些SoC标称1MB片上SRAM你以为能全用结果看Memory Map发现很大一块被Boot ROM和保留区占了剩下的还要分给中断向量表、DMA描述符、某些外设的FIFO映射区。真正能自由支配的可能就剩一半。所以我画板级方案或者调应用时第一步永远是先把Memory Map完整拉出来标出每段区域的用途、Cacheable特性、可写性然后才规划内存布局。这一步做扎实了后面能少加无数个班。还有一个容易被忽略的是有些SoC里片内SRAM和TCM区在物理上是同一块存储通过配置寄存器的不同选择被映射到不同地址。你在代码里用TCM时要注意它是不是真的被配置成了紧耦合路径还是仅仅形式上名为TCM、实际还在走普通总线——这两者性能差异非常大。5.3 选型时的成本与功耗权衡成本方面大致的单价排序是寄存器/SRAM NOR DRAM eMMC NAND裸片。注意SRAM是SoC内部面积大户所以片上SRAM容量基本上限就是那几MBDRAM作为外挂芯片容量成本弹性很大NAND/eMMC取决于制程和层数。功耗方面值得展开讲一下SRAM的静态漏电随温度上升非常明显。做低功耗产品时如果对SRAM持续供电待机电流会吃掉不少预算。这也是很多SoC提供SRAM Power Gating的原因——把不用的SRAM区域断电。DRAM的刷新功耗很可观所以有了温度补偿刷新“部分阵列自刷新”这些技术。低功耗模式下DRAM可以进入Self-Refresh但仍吃电流。Flash写入和擦除的电流峰值很高。批量写NAND时电流能冲到几百毫安如果供电拓扑没预留足够余量可能直接把板子电压拉垮导致写入失败甚至损坏数据。工程选型上我常给的建议是启动和系统关键代码优先NOR或内置Boot ROM不要为了省几块钱把一个需要频繁擦写的配置区放NOR。运行内存先算清楚峰值需求不要拍脑袋定LPDDR4还是DDR4容量和位宽直接决定带宽。大容量存储如果系统有操作系统和文件系统优先eMMC/UFS而非裸NAND除非团队特别擅长做FTL和坏块管理。实时任务确认有没有TCM可用没有的话把实时代码绑到SRAM的固定地址上并关掉该区域的Cache以确定性换速度。5.4 别忽视启动介质选择与系统升级方案的联动最后聊一个很多人做得不够好的点启动介质的选型和系统升级方案是强相关的。你选了NOR启动固件镜像通常几MB到十几MB升级时擦写时间尚可但如果你坚持用XIP跑复杂应用那应用能力很受限你选了eMMC/UFS启动镜像可以做很大还能放双BankA/B分区实现安全升级但Boot ROM里的第一阶段驱动就必须能识别eMMC/UFS这要求SoC出厂时就内置好对应的介质驱动。真实项目里我见过最典型的返工是因为OTA升级需要A/B双分区——板子上只有一颗小NOR放了引导程序就放不下两个完整镜像方案推倒重来。所以在概念设计阶段建议先把存储分区草图画出来哪一块放Bootloader、哪一块放内核、哪一块放根文件系统、哪一块留作OTA缓存、哪一块是工厂参数区。这张图出来之后选NOR还是eMMC、选多大的基本上就一目了然了。最后再分享一个很实用的排查技巧如果哪天你发现SoC系统启动异常、程序莫名其妙跑飞或者DMA数据对不上别急着怀疑硬件板子先花半小时把Memory Map和Cache策略重新过一遍。我自己的固定排查顺序是先确认复位向量和Boot ROM执行是否正常然后看SRAM/DRAM初始化有没有报错再看MMU/MPU配置和Cache属性最后才去检查DMA缓冲区和一致性维护。这么多年下来至少七成跟存储相关的疑难杂症都能在这一套流程里找到答案。SoC的存储系统看起来种类繁多但本质就一句话每一层存储都在用自己最擅长的方式为整个系统提供快或大或持久的能力而你要做的就是搞清楚自己的应用最需要哪一方面的能力然后去匹配对应的存储选型和配置策略。希望这篇梳理能帮你少走几步弯路。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑