我用哈佛架构构建了一个 32 位 RISC-V CPU,我想用 C 为它编写程序。我有一个 RISC-V 编译器集(https://xpack.github.io/riscv-none-embed-gcc / ) 可以做到这一点并且工作正常 - 对于大多数事情。当我想使用全局变量、全局数组等时,问题就开始了,因为这些类型在启动/重置时被启动脚本复制到 RAM。
这是我的 CPU 的框图:(稍后会很重要。请注意指令存储器 = FLASH 和数据存储器 = RAM)
(如果您对我的 CPU 感兴趣,我制作了一个关于它的视频:https ://www.youtube.com/watch?v=KzSaFFpBPDM )
例子:
一个典型的程序看起来像这样:
#include <stdint.h>
int static_var_1 = 2;
int static_var_2 = 4;
int main(void)
{
int var = static_var_1 + static_var_2;
}
它的 objdump 是这样的:
/opt/xpack-riscv-none-embed-gcc-10.1.0-1.1/riscv-none-embed/bin/objdump build/APP.elf -D
build/APP.elf: file format elf32-littleriscv
Disassembly of section .text:
00000000 <_start>:
0: 00080137 lui sp,0x80
4: ffc10113 addi sp,sp,-4 # 7fffc <_estack>
8: 00c000ef jal ra,14 <main>
c: 0040006f j 10 <_exit>
00000010 <_exit>:
10: 0000006f j 10 <_exit>
00000014 <main>:
14: fe010113 addi sp,sp,-32
18: 00812e23 sw s0,28(sp)
1c: 02010413 addi s0,sp,32
20: 00002703 lw a4,0(zero) # 0 <_start>
24: 00402783 lw a5,4(zero) # 4 <static_var_2>
28: 00f707b3 add a5,a4,a5
2c: fef42623 sw a5,-20(s0)
30: 00000793 li a5,0
34: 00078513 mv a0,a5
38: 01c12403 lw s0,28(sp)
3c: 02010113 addi sp,sp,32
40: 00008067 ret
Disassembly of section .data:
00000000 <static_var_1>:
0: 0002 c.slli64 zero
...
00000004 <static_var_2>:
4: 0004 0x4
...
Disassembly of section ._user_heap_stack:
00000008 <._user_heap_stack>:
...
(<_start>是我的启动脚本的一部分,它将初始化堆栈指针)
问题:
以下是尝试加载全局变量的两条指令:
20: 00002703 lw a4,0(zero) # 0 <_start>
24: 00402783 lw a5,4(zero) # 4 <static_var_2>
但是有一个问题——它们从未被放入 RAM,因此 CPU 很可能最终会得到一些垃圾数据,这是不可接受的。
解决方案?
有人建议将链接器放松作为我之前的问题(RISC-V:全局变量)的一部分,同样,情况似乎并非如此,但我仍然可能是错的!
根据我的研究,大多数“经典”CPU 使用启动脚本,复制发生的地方,但由于这不是冯诺依曼架构,我没有将闪存映射到数据存储器,因此无法读取由程序(见上面的框图)。输出程序必须包含已解码为可执行指令的变量,例如,如果我们希望 RAM 中位置 0x0 处的值 0x4,则可以将其解码为:
addi t0, zero, 0x4
sw t0, 0(zero)
将我的 CPU 重新构建为 von-neuman 将需要更多的门和 IC,这是一个离散构建,每个 IC 都很重要。
如上所述,对我来说,用硬件来做是最糟糕的解决方案,所以如果它可以用软件来做,我完全赞成——它可以!显然,有一个解决方案,但迄今为止最丑陋的:编译代码,提取数据(使用python),使用python脚本解码的这些变量生成一个新的启动脚本,然后再次编译。
我真的不想走那条路,所以如果可以通过修改启动脚本、链接器等来完成,那就太好了。
AVR IC 基本上是哈佛架构(尽管经过修改),那么它们有什么不同的地方可以学习吗?