在哈佛 CPU 中用 C 语言初始化全局变量

问题描述

我使用 Harvard 架构 构建了一个 32 位 RISC-V cpu,我想用 C 为它编写程序。我有一个 RISC-V 编译器集 (https://xpack.github.io/riscv-none-embed-gcc/)可以做到这一点并且工作正常 - 对于大多数事情。当我想使用全局变量、全局数组等时,问题就开始了,因为这些类型会在启动脚本启动/重置时复制到 RAM 中。

这是我的 cpu 的框图:(这将在以后很重要。请注意指令存储器 = FLASH 和数据存储器 = RAM)

Block diagram of my CPU

(如果你对我的 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,-32
  18:   00812e23            sw  s0,28(sp)
  1c:   02010413            addi    s0,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,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,4(zero) # 4 <static_var_2>

但是有一个问题——它们从未被放入 RAM 中,因此 cpu 很可能最终会得到一些垃圾数据,这是不可接受的。


解决方案?

有人建议将链接器放松作为我上一个问题 (RISC-V: Global variables) 的一部分,同样,情况似乎并非如此,但我仍然可能是错的!

根据我的研究,大多数“经典”cpu 使用启动脚本,在那里进行复制,但由于这不是冯诺依曼架构,我没有 FLASH内存映射到数据内存,因此不能被程序读取(见上面的框图)。输出程序必须包含已经解码为可执行指令的变量,例如,如果我们想要RAM中0x0位置的值0x4,它可以解码为:

addi t0,zero,0x4
sw t0,0(zero)

将我的 cpu 重新构建为冯诺依曼将需要更多的门和 IC,这是一个离散构建,其中每个 IC 都很重要。

正如我上面所说的那样,通过硬件来做对我来说是最糟糕的解决方案,所以如果它可以在软件中完成,我完全支持它 - 它可以!显然,有一个解决方案,但迄今为止最丑陋的:编译代码提取数据(用python),用python脚本解码的这些变量生成一个新的启动脚本,然后再次编译。

我真的不想走那条路,所以如果可以通过修改启动脚本、链接器等方式来完成,那就太好了。

AVR IC 基本上是哈佛架构(虽然经过修改),那么它们是否有不同的东西可供我们学习?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)