从内存中的特定地址开始初始化数组 - C编程

时间:2015-02-11 21:47:01

标签: c arrays shared-memory

您是否知道如何从内存中的特定地址(非虚拟,物理DDR内存)开始初始化结构数组。我正致力于在SoC(ARM-FPGA)上实现TxRx。基本上ARM(PS)和FPGA(PL)通过使用共享RAM存储器相互通信。目前我正在处理发送器端,所以我需要不断加载从MAC层到内存的数据包,然后我的Tx读取数据并将其发送到空中。为了实现这一点,我想在(ARM)端实现循环FIFO缓冲,以便我可以将最多6个数据包存储到缓冲区并逐个发送,同时在已发送的包的位置加载其他数据包。因为我需要使用特定的内存地址,我感兴趣的是可以初始化将存储在内存中特定地址的结构数组。 例如,我希望我的数组从地址0x400000开始,到地址0x400000结束+ MaximumNumberOfPackets x SizeOfPackets 我知道如何为结构的一个实例化执行此操作,例如: buffer_t * tmp =(struct buffer_t *)234881024;

但是如何为结构数组做到这一点?

3 个答案:

答案 0 :(得分:6)

指向单个结构(或int,float或其他任何东西)的指针本质上是指向它们数组的指针。指针类型为数组条目提供sizeof()值,从而允许指针算法工作。

因此,给定struct buffer你可以简单地做

static struct buffer * const myFIFO = (struct buffer *) 0x40000

然后只需将myFIFO作为数组

进行访问
for (size_t i = 0; i < maxPackets; ++i)
{
    buffer[i].someField = initialValue1;
    buffer[i].someOtherField = 42;
}

这就像你期望的那样。

不能做什么(使用纯标准C)是在特定地址声明一个数组,如下所示:

struct buffer myFIFO[23] @ 0x400000;

但是,您的编译器可能具有允许它的扩展名。许多嵌入式编译器(毕竟,它们通常是如何声明内存映射设备寄存器),但对于每个编译器供应商而言都是不同的,并且可能对于每个芯片都是不同的,因为它是供应商扩展。

GCC允许通过属性将其用于AVR处理器,例如

volatile int porta __attribute__((address (0x600)));

但它似乎不支持ARM。

答案 1 :(得分:2)

一般来说@kdopen是正确的,但是对于arm,你应该在MEMORY部分链接器脚本中创建一个条目,向链接器显示你的内存:

MEMORY
{
    ...
    ExternalDDR (w) : ORIGIN = 0x400000, LENGTH = 4M
}

而且,当您声明变量时,只需使用

__attribute__((section("ExternalDDR")))

答案 2 :(得分:1)

我找到了怎么做的方法。我可以这样做吗?我将其设置为链接器脚本:

MEMORY { 
        ps7_ddr_0_S_AXI_BASEADDR : ORIGIN = 0x00100000, LENGTH = 0x1FF00000          
        ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0x00000000, LENGTH = 0x00030000 
        ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0xFFFF0000, LENGTH = 0x0000FE00 
        DAC_DMA (w) : ORIGIN = 0xE000000, LENGTH = 64K 
       }

.dacdma : {
   __dacdma_start = .;
   *(.data)
   __dacdma_end = .;
} > DAC_DMA

然后我将其设置为代码

static buffer_t __attribute__((section("DAC_DMA"))) buf_pool[6];