
本文章对单片机的RAM, ROM, FLASH, 堆区, 栈区全局区(静态区)文字常量区程序代码区进行说明。一、易失性存储器-RAMRAM随机存取存储器也称易失性存储器。RAM通常用于存储运行时数据、堆栈、寄存器正在运行的操作系统、应用程序和临时数据等。1.随机存取 这是“随机存取”名称的由来。CPU可以直接访问RAM中的任意位置的数据访问时间与数据的物理存储位置无关。这使得RAM非常适合用于需要快速、任意访问数据的应用如计算机内存和缓存。2.快速读写RAM具有非常快速的读取和写入速度可以实现高性能的数据存取。这使得RAM非常适合用于存储正在运行的程序和临时数据以提供快速的计算和响应。3. 临时存储RAM主要用于临时存储数据和程序当计算机断电或重新启动时RAM中的数据将被清除。因此RAM通常用于存储正在运行的操作系统、应用程序和临时数据而不是长期存储。4. 高价格相比于Flash等非易失性存储器RAM的价格较高。这是因为RAM需要更高的性能和更复杂的制造工艺以实现快速访问和随机访问的能力。RAM是主存角色是程序运行时数据和指令的主要存放地。RAM可以分为动态随机存储器 DRAM 以及静态随机存储器 SRAM 。速度ROMFLASHDRAMSRAM单片机的内部存储器为SRAMDRAM主要用于外部扩展RAM存储变量的地址是链接器在编译阶段分配的CPU把变量的地址发送给RAM1.1 静态随机存储器–SRAM(Static RAM)1. 使用触发器Flip-Flop电路通常由4-6个晶体管组成来存储一个比特0或1。只要保持通电状态就能稳定保持不需要外部操作来维持数据(静态)。2. SRAM速度非常快是目前读写最快的存储设备访问速度通常 1~10ns 级3. 但它结构复杂成本高功耗大密度低常用于CPU高速缓存寄存器(片内)1.2 动态随机存储器–DRAM(Dynamic RAM)1. DRAM的具体的工作过程由 1个晶体管1个电容1T1C构成存储单元一个存储单元存储的是0还是1取决于电容是否有电荷有电荷代表1无电荷代表0。但时间一长代表1的电容会放电代表0的电容会吸收电荷这就是数据丢失的原因所以他需要定期刷新操作重新写一遍即 Dynamic动态的2. 速度较慢访问速度通常 50~100ns 级。3. 结构简单容量大成本低常用于主内存显卡显存(片外)根据时钟同步机制DRAM分为SDRAM和异步DRAM。异步DRAM无时钟信号其操作由独立的控制信号如RAS#,CAS#,WE#的边沿或电平触发。→ 读写时序与CPU时钟不同步需要复杂的“等待状态”逻辑匹配速度差异。基本被淘汰。SDRAM依赖系统时钟CLK所有操作命令、地址、数据传输在时钟上升沿同步执行。→ 与CPU/内存控制器时钟严格同步时序可预测。电脑的内存条(DDR4, DDR5本质上都是SDRAM二、非易失性存储器-ROM And FLASH2.1 ROMROMRandom Only Memory-只读存储器它是计算机和其他电子设备中一种重要的非易失性存储器类型。顾名思义其主要特点是1.只读在正常工作状态下数据只能从 ROM 中读取不能像 RAM 那样被用户程序轻易地、频繁地写入或修改。2.非易失性存储在 ROM 中的数据在设备断电后不会丢失。这是它与 RAM 最核心的区别之一。RAM 在断电后会丢失所有数据。3.高可靠由于ROM中的数据无法被修改或擦除所以它具有非常高的可靠性和稳定性。这使得ROM非常适合用于存储关键的系统代码和数据以确保系统的正常运行。4. 低功耗由于ROM不需要电力来维持存储的数据所以它具有很低的功耗。这使得ROM非常适合用于低功耗设备和嵌入式系统以延长电池寿命ROM 的核心特性和作用存储固件/引导程序这是 ROM 最重要的作用之一。它存储计算机启动时必需的基本指令BIOS/UEFI这些指令负责初始化硬件、进行开机自检并加载操作系统到 RAM 中。没有 ROM 中的这些初始代码计算机就无法启动。例如计算机的BIOS是存储在ROM中的。存储固定的数据和程序存储那些在设备生命周期内基本不需要改变的数据或程序例如计算器、电子词典中的内置函数和字典。微控制器中的控制程序查找表存储固定的数学函数值、字符生成点阵字库等供 CPU 快速查找使用。配置数据存储设备的硬件配置信息或校准数据。ROM 类型的演变按编程和擦除方式ROM 技术经历了从完全不可更改到可以多次擦写的发展掩膜ROM - PROM - EPROM - EEPROM -Flash 闪存现在所常用为EEPROM和Flash闪存EEPROM原理即电可擦除可编程只读存储器。基于浮栅晶体管技术。擦除方式最大的进步是可以通过施加电信号来擦除数据。可以按字节擦除和写入。编程使用电信号写入电压比擦除低特点可以在电路板上直接擦写无需取下芯片。可以按字节操作非常灵活。擦写速度比 EPROM 快但比 RAM 慢得多。擦写次数有限通常在 10⁴ 到 10⁶ 次。成本高于 EPROM。应用存储需要频繁少量修改的配置数据、用户设置、密码、校准参数等。例如主板 BIOS 设置、智能卡、传感器校准数据2.2 Flash闪存原理闪存是 EEPROM 技术的一种重要发展和子类。它也基于浮栅晶体管擦除方式使用电信号擦除但通常不能按字节擦除而是按块或扇区擦除如 4KB, 128KB, 256KB 等。擦除前必须先将整个块的数据备份出来擦除后再将修改后的数据写回。编程按字节或页写入。特点1. 非易失性断电数据不丢失不需要电源维持。这使得FLASH闪存非常适合用于存储重要 的数据和程序代码。2. 快速访问FLASH闪存具有快速的读取和写入速度可以实现高性能的数据存取。这使得它适用于需要快速存取数据的应用如操作系统、应用程序和游戏。3.高密度FLASH闪存的存储单元采用浮栅晶体管结构可以非常紧密地组织在一起从而实现高存储密度成本更低容量更大容量可达 TB 级如 NAND Flash。4.低功耗FLASH闪存在读取和写入数据时消耗的能量相对较低适合用于便携设备和移动设备例如手机、相机等。5.有限寿命FLASH每个存储单元有擦写次数限制。需要依靠磨损均衡算法来延长整体寿命。擦写次数有限通常在 10³ 到 10⁵ 次取决于技术和应用。并不是说Flash不能单个字节写(1-0)而只是不能单个字节擦除(0-1)。2.2.1 为什么“写”可以单字节1→0在物理层存储单元记录数据靠的是“浮栅”中的电子数量擦除状态代表逻辑“1”浮栅中没有电子。此时PN结导通阈值低很容易被识别为1。写入/编程状态代表逻辑“0”浮栅中注入了大量电子。写入Program本质上是“注入电子”。这只需要在单个存储单元的特定引脚上加高压就能把电子“挤”进去。因为电压可以精准只给到这一个字节所以Flash是支持按字节写入1→0的。2.2.2 为什么“擦除”必须整片0→1擦除Erase本质上是“抽出电子”。要把电子从浮栅里硬拽出来需要施加反向高压。为了节省芯片面积Flash在物理设计上让一整块扇区/块的存储单元共用一个“衬底P-well”。当你要抽电子时高压是加在整个衬底上的。物理电路上根本没办法只给这一个字节单独加抽电子的高压只要一加压这一大块区域里所有的电子全都被拽走了2.2.3NOR Flash 和 NAND FlashFlash有两种主要结构Nand Flash像硬盘一样组织高密度、高速度连续读写、低成本适合大容量数据存储U盘、SSD、SD卡、手机存储。NOR Flash像 RAM 一样组织支持芯片内执行读取速度快随机访问但密度较低、成本较高。常用于存储固件代码如 BIOS/UEFI 固件芯片、手机 Bootloader。根据存储单元电路不同分为 NOR Flash 和 NAND Flash。NOR Flash 和 NAND Flash 的共性是在数据写入前都需要进行擦除操作而擦除操作一般是以 “ 扇区 / 块 ” 为单位的。NOR 和 NAND 特性的差别主要在于其内部 “ 地址 / 数据线 ” 是否分开。NOR 的内部单元是并联结构有独立的地址总线和数据总线CPU可以把NOR Flash直接挂在内存总线上。CPU想取某个地址的指令只需把该地址值放在地址总线上NOR Flash立刻就能把对应的数据放到数据总线上这种“分离”结构使得NOR Flash在物理上等价于只读的SRAM完美支持XIP就地执行。CPU上电后程序计数器PC指向地址0数据瞬间就取回来了无需任何搬运因此要放在NOR Flash里面运行而 NAND 的内部单元是串联结构它没有专门的地址总线地址、数据、甚至命令Command都共用同一组I/O引脚通常是8根或16根。CPU不能直接给它一个地址来取数据。CPU必须像操作硬盘一样先发命令Command再发地址Address然后等待NAND内部寻址最后才能从I/O口读回数据。这个过程是串行化的且极耗时。单片机内部和外挂的Flash(例如W25Q)都为NOR FLASH2.3 EEPROM 和 FlashEEPROM和Flash都可以擦写但是EEPROM可以按字节擦除而Flash必须按扇区擦除这是因为EEPROM每个字节都配备了选择晶体管作为开关这使得电路可以精准寻址到最小开关施加高压只擦除改单元。而Flash去掉了每个字节的独立开关让一排存储单元公用一根源极线擦除时必须对这跟共用的源极线施加高压导致整个区域全部擦除。三、栈区(Stack)和堆区(Heap)栈区和堆区都位于RAM中3.1 栈区(Stack)栈用于存储局部变量、函数参数、函数调用时的返回地址以及中断或函数调用的上下文如寄存器值。它管理着程序的执行流程。程序在编译期和函数分配内存都是在栈上进行且程序运行中函数调用时参数的传递也是在栈上进行。3.1.1 管理方式1. 栈区由编译器自动分配和释放。2. 当一个函数被调用时编译器会自动在栈上为其分配一块空间称为栈帧用于存放该函数的局部变量和参数。3. 当函数执行完毕返回时它的栈帧会被自动销毁栈指针移动空间被立即回收以供后续函数使用。3.1.2 特点1.后进先出 (LIFO)就像一摞盘子最后放上去的盘子总是最先被取下来。最后被调用的函数最先返回。2.高速高效分配和回收只是移动栈指针速度极快。3.空间有限在单片机中栈的大小通常在启动文件或链接脚本中预定义。如果栈空间不足例如函数调用层次太深或局部变量太大会发生栈溢出 (Stack Overflow)导致程序崩溃这是非常危险的错误。3.2 堆区(Heap)堆用于动态内存分配。当程序在运行时需要一块大小可变、生命周期灵活的内存时就使用堆。3.2.1 管理方式1.手动管理由程序员主动控制2. 使用标准库函数如malloc(),calloc(),realloc()在堆上申请指定大小的内存。3. 申请成功后函数返回一个指向该内存块的指针。4. 当这块内存不再使用时程序员必须使用free()函数将其释放否则会造成内存泄漏 (Memory Leak)。3.2.2 特点1. 灵活可以在运行时决定需要多大的空间生命周期由程序员控制2.速度相对慢分配和释放需要在高散的内存块中寻找合适空间、管理空闲链表等操作比栈操作慢得多3.容易产生碎片频繁地、不规则地申请和释放不同大小的内存块会导致内存碎片从而降低内存使用效率甚至可能导致分配失败即使总空闲空间足够4.空间较大堆区的大小也在链接脚本中定义但通常它可用的空间比栈大得多在单片机开发中不建议使用malloc动态分配内存容易产生内存碎片。内部碎片malloc时为了内存对齐分配器通常会多分配一些空间其中一些空间就会没有用到而造成浪费。不过free的时候也会全部free掉。外部碎片malloc时分配的地址不是按照地址顺序分配的两个动态内存之间的空间可能被浪费。例如两个动态内存中间有一块32字节的内存当内存需要分配一块64字节的内存时这个32字节的内存就不能被使用四、全局区(静态区)全局区静态区是程序在启动时就被分配好的一块内存区域属于RAM区域用于存储全局变量和静态变量。这块内存在程序的整个生命周期中都存在从程序开始运行到结束为止。它之所以也被称为“静态区”是因为这里存储的变量其生命周期是静态的——即它们的内存地址和生命周期在程序编译和链接阶段就已经确定不会在运行时改变。(Static)内部细分全局区(静态区)内部细分为.data 和 .bss 段。主要由是否显式初始化来决定变量存放在哪里。这个细分对于优化程序体积至关重要。.data段存放初始化值不为0的变量这些变量需要保存在Flash的程序中把初始值复制到RAM中。.bss段存放未初始化初值或初值为0的变量。编译器只记录大小不存放在Flash中。上电后启动代码将整个.bss段在RAM中清零。注关于把变量的初始值从Flash中复制到RAM地址是怎么对应的在编译链接阶段链接器会生成地址的对应关系并且变量存储的顺序也是一样的。五、文字常量区文字常量区也称为只读数据区是程序存储器中一块专门用于存放在程序运行期间不会改变的常量数据的区域。· 所在位置Flash (ROM)。因为其中的数据不需要修改断电后也必须保存。·关键特性只读。任何试图向这个区域写入数据的操作都会导致硬件错误如内存访问错误 HardFault。这是它与RAM中区域的本质区别·目标文件中的段名在编译和链接时这部分数据通常被放在.rodata段Read-Only Data的缩写文字常量区主要用来保存字符串常量、CONST修饰的全局变量都是固定不变的量。讲这些变量保存在Flash中节省RAM空间。六、程序代码区程序代码区也称为文本段是单片机Flash存储器中一块专门用于存储程序执行代码的区域。它包含了单片机CPU能够直接识别和执行的机器指令。包括函数代码库函数代码中断向量表启动代码。七、单片机内存分布参考STM32F407的数据手册整体来看从地址0x0000 0000开始首先是Flash之后是RAM。7.1 FlashFlash中又分为主存储器系统存储器OTP选项字节参考STM32F407参考手册主存储器1. 存储应用程序代码2. 存储常量数据例如CONST字符串等3. 存储中断向量表4. bootloader系统存储器存储芯片内置的bootloader程序OTA区域(One-Time Programmable Area):一次性可编程区域顾名思义每个存储位只能编程一次。主要用于存储永久的配置数据如产品序列号、加密密钥、校准参数等选项字节这是一组特殊的配置寄存器用于配置芯片的各种硬件特性和保护功能。例如读保护级别 (RDP)、低功耗模式下的看门狗设置、启动配置模式、掉电阈值级别以及许多与安全相关的设置例如专有代码读取保护 (PCROP) 和写保护区域 (WRP)。因此单片机上电后运行到地址0x0000 0000时通过Boot脚决定当Boot00时地址映射到主Flash地址0x0800 0000正常用户程序运行模式当Boot01时地址映射到系统存储区0x1FFF 0000系统Bootloader模式可通过串口等烧录程序