11

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?

elem
  • 171
  • 1
  • 2
  • 12
  • What is your compiler & OS (if any)? – Grzegorz Szpetkowski Feb 11 '15 at 21:52
  • Hi, it is ARM gcc compiler – elem Feb 11 '15 at 21:54
  • Might help: http://stackoverflow.com/questions/4067811/how-to-place-a-variable-at-a-given-absolute-address-in-memory-with-gcc – Grzegorz Szpetkowski Feb 11 '15 at 21:55
  • Hi, I know how to do it for one instantiate of structure that is something similar like on that link. But I do not know how to do it for array of instantiates of structure. I do not know is it possible to do it. Something like: buffer_t buffer_pool[6] (and to force it start from specific address in memory for example 0x4000000). I found some advice on this link http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3750.html (second option is more interesting for me). But again it is just for one instantiate. – elem Feb 11 '15 at 22:07
  • Could you not just create 6 structs and place them adjacent to each other in memory? That's basically all an array is. Then you can have a pointer to the beginning of the buffer and use pointer addition to access the different structs. – mstbaum Feb 11 '15 at 22:08
  • mstbaum that is an option but I was thinking is there better way do do it, instead setting 6 structs and forcing them to specific memory. I will do like that if nobody gives better advice. – elem Feb 11 '15 at 22:11

3 Answers3

7

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.

kdopen
  • 8,032
  • 7
  • 44
  • 52
  • kdopen thank you for answer I will do it like that. Initialize buffer_pool at beginning and then fill up through for loop. – elem Feb 11 '15 at 22:23
3

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")))
Gaskoin
  • 2,469
  • 13
  • 22
  • Gaskoin I am not that experienced with linker scripts, but I will try to do it looks interesting. I will get to know how to write linker scripts. – elem Feb 11 '15 at 22:40
  • I do not know how do you build your code so I cannot provide you any details. If you have dedicated IDE for your ARM maybe you can find something in configuration. If you are using gcc you should have somewhere a file with ld extension -> that is what you need :) – Gaskoin Feb 11 '15 at 22:44
  • Dear I am using Xilinx SDK, it is based on eclipse. 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 } And then I set this into code static buffer_t __attribute__((section("DAC_DMA"))) buf_pool[6]; – elem Feb 11 '15 at 22:59
  • Gaskoin I do not get it work. When I try to print out address of variable I get some random value. Seems that linker doesn't take into account may memory section declaration. – elem Feb 11 '15 at 23:59
  • You should try to launch it, because sometimes debugger can show wrong addresses for external memories, have the same issue with CM4 but was working fine. I do not know xilinx sdk so I me not be able to help you more – Gaskoin Feb 12 '15 at 08:01
  • You can check also http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0474f/BABDJCAA.html – Gaskoin Feb 12 '15 at 08:13
  • 1
    Gaskoin I got it work. Except from declaring memory region in lscript.ld, also there should put memory region mapping for that region. So I added .dacdma : { __dacdma_start = .; *(.data) __dacdma_end = .; } > DAC_DMA where DAC_DMA is previously added region (in style like you explained), and the I call static buffer_t buf_pool[MAX_BUF_POOL_SIZE]__attribute__((section(".dacdma"))); – elem Feb 12 '15 at 10:30
2

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]; 
elem
  • 171
  • 1
  • 2
  • 12