在 RISC-V 这种典型的嵌入式系统里,“flash 能不能像内存一样 lw 读取?”这是一个很多人刚开始都会迷糊的问题。其实答案非常简单:
可以,前提是 flash 被 CPU 通过总线映射到地址空间(Memory-Mapped I/O)中。
下面给你掰开揉碎讲清楚——实话实说,硬件上就是这么干的。
⭐ 为什么 lw t0, (a0) 能直接从 Flash 读?
因为在 MCU / SoC 里:
Flash 不是通过 SPI 或外设读出来的(那要命慢)。
Flash 是直接挂在系统总线上,被“映射(mapped)到某个固定地址区间”。
换句话说:
Flash 就像 ROM 一样,CPU 把其中内容当成内存一样读即可。
⭐ Memory-Mapped 的本质
比如系统里的地址空间可能是这样分布的(随便举例):
| 地址范围 | 设备 |
|---|---|
| 0x0000_0000 – 0x0003_FFFF | Flash(ROM) |
| 0x2000_0000 – 0x2000_FFFF | SRAM |
| 0x4000_0000 – … | 外设寄存器 |
启动代码里 _data_lma 通常指向 flash 里的 .data 段实际位置:
_data_lma = 0x00008000 # 位于 Flash
_data_vma = 0x20000000 # data 在 RAM 里的最终位置
CPU 执行:
lw t0, (a0)
当 a0 = 0x00008000 时,实际上是在从 flash 的某个物理地址读取。
Flash 控制器会在背后完成访问时序,比如:
-
address latch
-
read cycle
-
wait state(flash 慢所以要等)
-
返回数据
对 CPU 来说就是一个普通的 load 指令。
⭐ 为什么能这样设计?
因为这样有几个硬优点:
🟦 1. 启动速度快
CPU reset 后 PC=flash 的入口地址,直接执行,不需要“先从 Flash 读一段代码再搬到 RAM 再执行”。
🟦 2. 访问简单
软件不需要管理 flash 控制器复杂的读时序。
🟦 3. 芯片内置 flash 本来就和 CPU 紧耦合
绝大多数 MCU(STM32、GD32、Nuclei、Kendryte、ESP32)内部都是:
CPU —— AHB —— Flash 控制器 —— Embedded Flash array
CPU load/store 就能读。
⭐ 你在写的 startup code 是 “XIP 模式”
XIP = eXecute In Place
意思是:在 flash 里直接执行指令,不需要 preload 到 RAM。
-
指令直接从 flash 读
-
数据段要搬到 RAM 用(你代码里就是在复制 .data)
-
.bss清零
⭐ 一个生活中的比喻
很像一本存放在书架(flash)上的字典:
-
查字(load):你直接翻书查,不需要把整本书搬到桌子上
-
写字(store):你不能直接写(flash 不能随便写)
-
你要做笔记(data 段):你会把必要内容抄到草稿纸(RAM)
代码里做的正是:
-
从“书架”(flash)把 data 抄到“草稿纸”(RAM)
-
然后程序运行全用 RAM 中的可写数据
⭐ 再回答你的核心一句话
为什么 lw 能直接操作 flash?
因为 flash(只读存储器)通过总线映射在 CPU 地址空间里,CPU load 指令自动走 flash 控制器读取数据。
如果你要,我还能给你画一张 RISC-V SoC 内部 bus + Flash 映射结构图,让你一眼就看懂整个访问流程。


被折叠的 条评论
为什么被折叠?



