ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

第 10 章 内存与 PSRAM:存储器的原理与程序的内存布局

第 10 章 内存与 PSRAM:存储器的原理与程序的内存布局 本章从元件原理讲起SRAM/Flash/PSRAM 各自是什么器件、为什么断电后一个会忘一个不会忘程序各段text/data/bss在启动时如何装载栈和堆的运作机制以及本板 PSRAM 的配置与使用。10.1 三类存储器的器件原理SRAM用触发器记住 1 位SRAM 的一个存储单元由几个晶体管组成触发器flip-flop两个交叉相连的开关稳定在一个开一个关两种状态 → 记住 0/1通电就稳定记住断电立即丢失没有能量维持状态。特点快随机访问——想读第 N 格就直接读第 N 格不用像磁带那样从头找但贵、费电每比特 6 个晶体管左右。Flash用浮栅晶体管记住 1 位Flash 单元是一个特殊晶体管栅极里藏着一块浮栅写 1高压把电子注入浮栅电子被关在里面读浮栅里有电子 → 管子阈值变高 → 读出 0/1阈值刚好能把管子打开所需的最低电压像考试的及格线断电后电子还困在浮栅里→ 掉电不丢✅特点慢写入要擦除整块、寿命有限约 10 万次擦写、只能擦块写页不能随意改一个字节。PSRAM把 DRAM 做成伪 SRAM真正的 DRAM 每比特 1 个晶体管 电容靠电容存电荷要周期性地刷新refreshing保持PSRAM Pseudo SRAM内部把刷新做进芯片对外看起来像 SRAM接口简单实际底层是 DRAM 的密度。一句话记住SRAM触发器掉电忘Flash浮栅掉电记PSRAM伪装的 DRAM掉电忘容量大。10.2 本板存储规格存储容量接口/速度用途内置 SRAM512KB内部总线程序运行主场地外置 Flash16MBSPI80MHz程序和常量外置 PSRAM8MBOctal 8 线80MHz大数据仓库8MB PSRAM 用Octal8 根数据线并行模式比 4 线Quad快一倍PSRAM 占用 GPIO33~37 时钟/片选等——这些引脚专用别用Flash 占用 GPIO 26~32Quad 数据线——同样专用。10.3 程序段的装载启动时发生什么第 5 章讲过段这里补装载细节段内容存放启动时.text指令Flash直接执行或映射到地址空间.rodata常量Flash直接访问.data有初值变量初值在 Flash复制初值到 SRAM.bss无初值变量无清零启动代码crt0在app_main前做复制 .data → 清零 .bss → 设栈/堆。推论const char *TAG l298n;的字符串在 .rodataFlash工程里的完整写法是static constexpr const char *TAG第 8 章逐字块里就是——这里只是简化书写static int s_active_instances 0;在 .bssSRAM清零——它正是第 8 章定义、第 12 章 12.5 双电机实战里最后一个实例才卸载fade 服务的那个实例计数器int x 5;的初值 5 占 Flash。中断服务函数要求快和低延迟所以常用IRAM_ATTR放进指令 RAM不从 Flash 取指令——第 15 章。10.4 栈Stack和堆Heap的机制栈函数调用自动用由SP栈指针管理从高地址向低地址生长函数进入压入返回地址 局部变量返回弹出后进先出栈溢出压过头超出栈区→ 覆盖其他数据 → 崩溃或静默出错。FreeRTOS 的每个任务都有自己的栈设多大、用uxTaskGetStackHighWaterMark查剩余水位、溢出时怎么排查——第 13 章。堆程序员主动申请malloc(size)在堆区找一块空闲登记占用返回地址free(ptr)标记空闲泄漏malloc 了忘了 free → 堆逐渐耗尽 → 大 malloc 失败。ESP-IDF 里malloc默认先试 SRAM 堆大块自动用 PSRAMCONFIG_SPIRAM_USE_MALLOCy——这就是8MB 仓库怎么用上的默认通道。两个细节①CONFIG_SPIRAM_USE_MALLOC在你打开CONFIG_SPIRAMy后默认就是开的不用额外操作②大块有个门槛——CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL默认 16KB小于这个尺寸的分配会优先留在内部 SRAM大于它的 malloc 才会自动落到 PSRAM。所以申请几 KB 的小对象照样占 SRAM别奇怪。10.5 内存映射所有东西都在一张地址表里芯片把 Flash/SRAM/外设寄存器统一编址第 0 章外设寄存器GPIO/LEDC 等在特定地址区——写这些地址控制硬件崩溃时EXCVADDR是地址 → 结合映射表能猜出访问了什么东西第 11 章。地址 内容 0x3C00_0000 PSRAM外挂大仓库 0x3FC8_0000 内置 SRAM草稿纸 0x4200_0000 Flash代码指令区 0x6000_0000 外设寄存器旋钮们这几个地址只是每类区域挑一个代表的节选示意真实映射要宽得多、分区也多得多精确数值以 ESP32-S3 技术参考手册TRM的地址映射章节为准。10.6 PSRAM 的三种使用方式自动默认CONFIG_SPIRAM_USE_MALLOCymalloc 大块自动落到 PSRAM——零成本本书默认手动指定heap_caps_malloc(bytes, MALLOC_CAP_SPIRAM)明确只要 PSRAM直接地址访问用链接脚本符号拿 PSRAM 起始地址不推荐。启动日志确认 PSRAM 就绪I (147) octal_psram: Found 8MB PSRAM device I (693) esp_psram: Adding pool of 8192K of PSRAM memory to heap allocator【动手框】① 在哪执行l298n 工程根目录IDF 终端跑过 export 的那个窗口2.3② 敲什么idf.py -p COM3 flash monitorCOM3 换成你的实际端口③ 预期看到开机滚动的日志里有上面那两行——octal_psram和esp_psram各一行括号里的毫秒数你的会不一样无关紧要。看到它们才可以说8MB 仓库已经并入 malloc 池这句话是真的④ 没看到找不到octal_psram行 → 对照 10.7 检查三项配置若你改的是sdkconfig.defaults它不会自动覆盖已有的sdkconfig——先idf.py fullclean再重新构建fullclean 只删 build 目录源码无损但旧的 .elf 也一起没了参考 11.9 的备份提醒flash 报端口被占用 → 多半是另一个窗口还开着 monitor关掉再试第 2 章烧录一节讲过flash 一直等待连接 → 手动进下载模式按住 BOOT → 点按 EN →松开 BOOT第 2 章三步。10.7 本项目配置与 sdkconfig 对应下面是工程sdkconfig.defaults里真实的 PSRAM 段逐字含注释。注意它是三项配置第一项CONFIG_SPIRAMy是总开关漏了它后两项都是空谈# ---------- PSRAM ---------- # R8 8MB 八线 PSRAM。八线模式对时序敏感80MHz 是稳的选择 # 120MHz 在 Octal 下属于实验特性温度漂移约 20 度就可能随机崩溃。 CONFIG_SPIRAMy CONFIG_SPIRAM_MODE_OCTy CONFIG_SPIRAM_SPEED_80My配置全名陷阱见第 3 章 3.6defaults 里必须写_80M全名。10.8 常见问题速查现象原因解决heap exhaustedSRAM 堆耗尽大块用 PSRAM / 检查泄漏启动没发现 PSRAMSPIRAM 配置没开/模式错检查三项配置无规律崩溃栈溢出第 13 章给具体改法暂时规避减小局部数组内存越用越少泄漏malloc/free 配对检查10.9 想一想 小测验想一想Flash 为什么掉电不丢PSRAM 为什么掉电就丢static int n 0;放哪个段const char *s hi;的字符串放哪大数组1MB放哪最合适小测验SRAM 用哪种器件记住 1 位A. 触发器 B. 浮栅 C. 电容刷新本板 PSRAM 容量A. 512KB B. 8MB C. 16MBmalloc 借了不还叫什么A. 溢出 B. 泄漏 C. 碎片PSRAM 占用的 GPIO 范围是A. 33~37 B. 1~10 C. 40~4510.10 本章总结SRAM触发器快、掉电忘、Flash浮栅慢、掉电记、PSRAM伪 DRAM大、掉电忘启动时.data 复制初值、.bss 清零栈函数自动用后进先出、堆malloc/free借了要还本板 8MB Octal PSRAM 默认自动并入 malloc 池。下一章优化和调试——固件怎么变小、崩溃怎么定位。
返回列表