You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

RISCV处理器运行C程序遇.data段无法放入dff区域错误求助

解决RISC-V中全局数组导致的链接器内存溢出问题

问题详情

链接器报错如下:

/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

报错原因是声明了多个大型全局初始化数组,占用过多.data段空间,超出dff区域容量。数组声明如下:

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};

当前使用的链接器脚本:

/* 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));

需求是将这些数据从RISC-V发送到数字电路,以下是可行的解决方法:

解决方法

1. 将数组改为只读常量,移至Flash存储区

这些数组是初始化好的固定数据,不需要运行时修改,直接用const修饰,编译器会将其放入.rodata段,而链接器脚本中.rodata映射到flash区域(通常Flash空间远大于片内RAM),不会占用dff的空间。

修改后的数组声明:

const int sig_A [Bits] = { ... };
const int sig_B [Bits] = { ... };
const int sig_C [Bits] = { ... };
const int data_i [Bits] = { ... };

读取这些只读数据发送到数字电路的逻辑不受影响,因为只是读取操作,不需要修改数组内容。

2. 调整链接器脚本,扩大dff区域容量

检查链接器脚本中包含的output_format.ld文件,找到dff区域的定义,增大其LENGTH值,只要不超过硬件实际的RAM容量即可。如果dff就是注释中提到的ram区域,可以取消注释并调整ram的LENGTH:

MEMORY
{
    ram         : ORIGIN = 0x00100000, LENGTH = 0x38000 /* 增大到224KB,根据硬件实际情况调整 */
    stack       : ORIGIN = 0x00138000, LENGTH = 0x8000  /* 32KB栈空间 */
}

同时要确保SECTIONS中.data和.bss的> dff改为> ram(如果dff是ram的别名),或者直接修改dff的定义。

3. 动态分配内存存储数组

将全局数组改为在main函数中通过malloc动态分配堆内存,这样数据会放在堆区,不占用全局.data段空间:

#include <stdlib.h>
#include <string.h>

int main() {
    // 分配内存
    int *sig_A = malloc(Bits * sizeof(int));
    int *sig_B = malloc(Bits * sizeof(int));
    int *sig_C = malloc(Bits * sizeof(int));
    int *data_i = malloc(Bits * sizeof(int));
    
    // 初始化数据(可以把原数组内容作为const数组放在.rodata,然后memcpy)
    const int sig_A_init[] = { ... };
    memcpy(sig_A, sig_A_init, sizeof(sig_A_init));
    // 其他数组同理
    
    // 发送数据到数字电路的逻辑...
    
    // 释放内存(如果不再需要)
    free(sig_A);
    free(sig_B);
    free(sig_C);
    free(data_i);
    
    return 0;
}

注意:需要确保链接器脚本配置了足够的堆空间,或者使用的libc支持动态内存分配。

4. 外部存储加载数据(适合超大数据)

如果数据量超过片内存储的最大容量,可以将数组数据存储在外部Flash、SD卡等存储设备中,程序启动后通过硬件总线读取数据到内存,再发送到数字电路。这种方法需要硬件支持外部存储,同时编写对应的驱动代码实现数据读取。

内容的提问来源于stack exchange,提问作者temp1445

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 01:45:35