Initialize array starting from specific address in memory - C programming

elem picture elem · Feb 11, 2015 · Viewed 10.3k times · Source

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?

Answer

kdopen picture kdopen · Feb 11, 2015

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.