我试着在RISCV处理器上运行一些c程序,我得到了这个:
/foss/tools/riscv-gnu-toolchain-rv32i/217e7f3debe424d61374d31e33a091a630535937/lib/gcc/riscv32-unknown-linux-gnu/11.1.0/../../../../riscv32-unknown-linux-gnu/bin/ld: test_la.elf section `.data' will not fit in region `dff'
/foss/tools/riscv-gnu-toolchain-rv32i/217e7f3debe424d61374d31e33a091a630535937/lib/gcc/riscv32-unknown-linux-gnu/11.1.0/../../../../riscv32-unknown-linux-gnu/bin/ld: region `dff' overflowed by 1624 bytes
collect2: error: ld returned 1 exit status
根据this线程中的一个注解,这可能是由于声明了一些大型的全局数组引起的。对我来说也是如此,我在全局(main函数之外)有这些数组:
int sig_A [Bits] = { 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1};
int sig_B [Bits] = { 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
int sig_C [Bits] = { 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0};
int data_i [Bits] = { 0, 0, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 2, 3, 2, 2, 2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 2, 3, 2, 3, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 6, 0, 0};
我需要这些数据从RISCV发送到一些数字电路。我如何才能使这种情况发生(如果有一种方法)。谢谢。
- 连接器档案**
/* Copyright lowRISC contributors.
Licensed under the Apache License, Version 2.0, see LICENSE for details.
SPDX-License-Identifier: Apache-2.0 */
INCLUDE ../generated/output_format.ld
OUTPUT_ARCH(riscv)
/*******
MEMORY
{
Change this if you'd like different sizes. Arty A7-100(35) has a maximum of 607.5KB(225KB)
BRAM space. Configuration below is for maximum BRAM capacity with Artya A7-35 while letting
CoreMark run (.vmem of 152.8KB).
ram : ORIGIN = 0x00100000, LENGTH = 0x30000 * 192 kB *
stack : ORIGIN = 0x00130000, LENGTH = 0x8000 * 32 kB *
}
**********/
_entry_point = _vectors_start + 0x80;
ENTRY(_entry_point)
/* The tohost address is used by Spike for a magic "stop me now" message. This
is set to equal SIM_CTRL_CTRL (see simple_system_regs.h), which has that
effect in simple_system simulations. Note that it must be 8-byte aligned.
We don't read data back from Spike, so fromhost is set to some dummy value:
we place it just above the top of the stack.
*/
tohost = 0x20008;
fromhost = _stack_start + 0x10;
SECTIONS
{
.vectors :
{
. = ALIGN(4);
_vectors_start = .;
KEEP(*(.vectors))
_vectors_end = .;
} > flash
.text : {
. = ALIGN(4);
*(.text)
*(.text.*)
} > flash
.rodata : {
. = ALIGN(4);
/* Small RO data before large RO data */
*(.srodata)
*(.srodata.*)
*(.rodata);
*(.rodata.*)
} > flash
.data : {
. = ALIGN(4);
/* Small data before large data */
*(.sdata)
*(.sdata.*)
*(.data);
*(.data.*)
} > dff AT > flash
.bss :
{
. = ALIGN(4);
_bss_start = .;
/* Small BSS before large BSS */
*(.sbss)
*(.sbss.*)
*(.bss)
*(.bss.*)
*(COMMON)
_bss_end = .;
} > dff
}
PROVIDE(_stack_start = ORIGIN(sram) + LENGTH(sram));
2条答案
按热度按时间aiazj4mn1#
你能不能给我一个链接,让我自己理解链接器脚本?-temp1445
我在
"linker script" documentation
上做了一个网络搜索,得到了(在120万中):https://wiki.osdev.org/Linker_Scripts我下载了你链接到的回购协议[全部14 GB; - )].在repo中,我们有几个文件:
除了源地址
RAM
之外,它们是相似的。这意味着您 * 只有1 KB内存!
但是,你的例子引用了
dff
。有一个python脚本引用了一个同名的链接器脚本,但是它必须是[auto-]生成的,因为树中没有dff.lds
。AFAICT,
caravel
是一个针对riscv FPGA或ASIC实现的 * 门 * 级verilog/VHDL设计。我 * 已经 * 完成了[linux] S/W内核移植到一个新的ASIC CPU设计[20年前],使用 * 门 * 级模拟器。
但是,这可能会非常缓慢。
例如,在启动过程中,linux将进入一个旋转循环来计算CPU速度(即BogoMIPS)。在真实的硬件上,这个测试只需要一小部分秒(例如1ms)。在模拟器上,这个测试需要一整天。
因此,我用NOP替换了该环路,并将频率硬连线(使用(e.g.)):
然后,我们必须为[建议的]硬件开发软件设备驱动程序。某些硬件的verilog代码不完整。
但是,我们确实有硬件的功能规格。
我们的解决方案是在以下平台上进行大部分软件开发:
1.一个 * 功能 * 仿真器(类似于
qemu
),我们在其中添加了硬件设备的仿真。1.用户空间代码,在运行x86代码的开发机器(例如x86 PC)上运行,并具有允许我们调用H/W仿真函数的库。
1.具有类似硬件的真实硬件SDK板
1.门级模拟器
我们将软件配置为能够在这些环境中使用条件编译工作。
我们使用(2)和(1)进行了大部分软件开发工作。当我们99.44%确定没有 * 软件 * 错误(例如UB等)时,我们才使用(3)进行全面验证。
这样,我们就不会浪费 * 小时 * 的模拟器时间来查找一个在SDK板或模拟器上5秒内发现的[微不足道的]软件错误。
这也允许程序员能够独立于硬件设计者的verilog代码(通常比软件有 * 更多 * 的错误)调试软件。
您没有指定您的主要目标是什么,但是我强烈推荐这样的构建环境。
如果您只是想在汇编级试验riscv架构,那么我会使用
qemu
或等效的代码。如果您尝试编写软件来驱动当前/提议的硬件设备,我仍然建议采用与我们所采用的策略类似的策略。
wfauudbj2#
你的程序定义了一些大的数组,它们比可用的RAM大。错误信息显示(用链接器的路径去掉前缀):
.data
部分收集所有可写的static * 变量,其中包括数组。由于该部分被分配在dff
区域中,它将溢出。现在你至少有两个选择。
1.减小数组的大小
您在注解中说数组中的所有值都如图所示一样小,范围在0到6之间。元素数据类型为
int
,大小似乎为4个字节。这对于存储小值来说太大了。您可以发明一些方法,只将所需的位压缩到可用空间中,但这需要在运行时使用一些解压缩代码,具体取决于值的用途。
一个更简单的方法是使用尽可能小的合适的数据类型,比如
uint8_t
。但是,一旦你在程序中添加更多的变量,同样的问题就会再次出现,因此,我建议使用第二种方法。
根据值的使用情况,您还可以将这两个选项结合使用,从而最大限度地减少ROM中数组的占用空间。
2.将阵列移动到ROM
正如你在注解中确认的那样,你的程序只读取这些数组的值,它们的内容是固定的。
给它们加上修饰符
const
。这会把它们放到.rodata
部分,意思是"只读数据"。因为这个部分是在flash
区域中分配的,所以它不会填满你稀缺的RAM。无论如何,你应该总是使用修饰符来显示这些特征。初学者的课程很少涉及到这一点,在PC上他们也不需要。但在嵌入式世界中,总是用
const
来修改只读变量。下面是检查内存使用情况的提示:让链接器生成一个Map文件。对于基于GNU的工具链,查找the option
-Map
。例如,如果你通过前端"gcc"运行链接器,你可以在命令行中添加-Wl,-Map=output.map
。