Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize array starting from specific address in memory - C programming

Do you have idea how to initialize array of structs starting from specific address in memory (not virtual, physical DDR memory). I am working on implementation of TxRx on SoC (ARM-FPGA). Basically ARM (PS) and FPGA (PL) communicate to each other by using shared RAM memory. Currently I am working on transmitter side, so I need to constantly load packets that I get from MAC layer to memory, then my Tx reads data and sends it in air. To achieve this I want to implement circular FIFO buffer on (ARM) side, in way that I can store up to 6 packets into buffer and send them one by one, in same time loading other packets on places of already sent packages. Because I need to use specific memory addresses I am interested is it possible to initialize array of structure that will be stored on specific addresses in memory. For example I want that my array starts at adress 0x400000 and ends at address 0x400000 + MaximumNumberOfPackets x SizeOfPackets I know how to do it for one instantiate of structure for example like this: buffer_t *tmp = (struct buffer_t *)234881024;

But how to do it for array of structures?

like image 245
elem Avatar asked Feb 11 '15 21:02

elem


3 Answers

A pointer to a single struct (or int, float, or anything else) is inherently a pointer to an array of them. The pointer type provides the sizeof() value for an array entry, and thus allows pointer arithmetic to work.

Thus, given a struct buffer you can simply do

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

and then simply access myFIFO as an array

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

This works just the way you expect.

What you can't do (using pure standard C) is declare an array at a particular address like this:

struct buffer myFIFO[23] @ 0x400000;

However, your compiler may have extensions to allow it. Many embedded compilers do (after all, that's often how they declare memory-mapped device registers), but it will be different for every compiler vendor, and possibly for every chip because it is a vendor extension.

GCC does allow it for AVR processors via an attribute, for example

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

But it doesn't seem to support it for an ARM.

like image 56
kdopen Avatar answered Nov 06 '22 16:11

kdopen


Generally @kdopen is right but for arm you should create an entry in MEMORY section linker script that shows to linker where is your memory:

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

And than, when you are declaring variable just use the

__attribute__((section("ExternalDDR")))
like image 28
Gaskoin Avatar answered Nov 06 '22 17:11

Gaskoin


I found the way how to do it. So could I do it like this. I set this into linker script:

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

And then I set this into code

static buffer_t __attribute__((section("DAC_DMA"))) buf_pool[6]; 
like image 2
elem Avatar answered Nov 06 '22 17:11

elem