Electronic – gcc __attribute__ section not working

clinkermemoryxilinxzynq

I'm working on a Zynq Ultrascale+ MPSoC and trying to play around with the on and off chip memories. In the following program, I'm trying to place only variable 'x' into OCM (on-chip-memory) where everything else is loaded into external DDR.

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"

volatile u32 x __attribute__ ((section ("psu_ocm_ram_0_MEM_0"))) = 10;
volatile u32 *p = &x;

int main()
{
    init_platform();

    xil_printf("x = %u\r\n", x);
    xil_printf("p = %p\r\n", p);

    cleanup_platform();
    return 0;
}

The output is:

x = 10
p = 2AB0

So it doesn't look like p is pointing to a variable in OCM memory according to the memory map below.

enter image description here

If I change to linker script to put the entire .data section into OCM (and get rid of the gcc attribute), then the output becomes as I expected:

x = 10
p = FFFC0130

The weird thing is that the .map file for the original program does show that the linker is trying to do something with the variable, I'm just not sure what:

                0x0000000000002ab0                __data_end = .

.tm_clone_table
                0x0000000000002ab0        0x0
 .tm_clone_table
                0x0000000000002ab0        0x0 
 .tm_clone_table
                0x0000000000002ab0        0x0 

.igot.plt       0x0000000000002ab0        0x0
 .igot.plt      0x0000000000002ab0        0x0 

psu_ocm_ram_0_MEM_0
                0x0000000000002ab0        0x4
 psu_ocm_ram_0_MEM_0
                0x0000000000002ab0        0x4 ./src/helloworld.o
                0x0000000000002ab0                x

So it looks like the variable is being placed at the end of the .data section, which is in DDR (for the original code), but I want the variable in OCM. Anybody know what's going on here?

Best Answer

It turns out I wasn't using the gcc attribute correctly. I was trying to place the variable directly into OCM using:

volatile u32 x __attribute__ ((section ("psu_ocm_ram_0_MEM_0"))) = 10;

as if the compiler is able to put individual variables into specific memory locations. Rather, it's the linker that's responsible for assigning all executable code (data and instructions) to physical memory. It order to make this work, I had to create a custom section in the linker script and assign this section to OCM:

.my_section : {
    KEEP(*(.my_section))
} > psu_ocm_ram_0_MEM_0

Then in my code:

volatile u32 x __attribute__ ((section (".my_section"))) = 10;

The output was then:

x = 10
p = FFFC0000

as expected.