I have created a minimal example of my problem. In the c file I initialize an array with 16 elements. Then I call a function with the array pointer and its size as parameter. The function itself works, I've verified that with the disassembly file. Also the stackpointer initialisation works fine. The problem is that the function parameter of the array pointer is wrong. I checked it and the origin of failure is at the very beginning of the main section. Here the pointer gets stored on the stack.
What I don't understand: The array values are stored in the .rodata section. This section begins at 0x1000. So the pointer to the array should also be 0x1000. In the disassembly 0x1000 gets loaded into a5 (the right value). But then it loads the value of address a5 into a4. So 0x1000 represents a pointer to a pointer to the array, which makes no sense imho. Has anyone a idea what I'm doing wrong?
Here is all the information needed:
c program:
void test(uint8_t *array, int size){
for(int i=0; i<size; ++i){
LED_ADDR = array[i];
}
}
int main(){
uint8_t buf[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
test(buf, 16);
}
linker script:
OUTPUT_ARCH( "riscv" )
ROMSIZE = 0x1000;
ROM_OFFSET = 0x0000;
RAMSIZE = 0x1000;
RAM_OFFSET = 0x1000;
/* provide variables for startup code (stack init) */
STACK_TOP = ( RAMSIZE + RAM_OFFSET - 4 );
ENTRY (start)
MEMORY {
rom (rx) : ORIGIN = ROM_OFFSET, LENGTH = ROMSIZE
ram (!rx) : ORIGIN = RAM_OFFSET, LENGTH = RAMSIZE
}
SECTIONS {
.reset : { <PROJECTPATH>/obj/startup.o } > rom /* startup code */
.text : { *(.text) } > rom /* executable data */
.rodata : { *(.rodata) } > ram /* read only data */
.sdata : { *(.sdata) } > ram /* init vars */
.bss (NOLOAD) : { *(.bss) FILL(0x0f); } > ram /* uninit data */
}
disassembly file important parts: -in .text, beginning of main(): Pointer of array should be stored on stack I assume:
80: 000017b7 lui a5,0x1 # a5 = first ram addr: begin of .rodata
84: 0007a703 lw a4,0(a5) # a4 = content of this addr?!?!?!
88: fee42023 sw a4,-32(s0) # a4 gets stored on stack
-.rodata, contains values of array:
Disassembly of section .rodata:
00001000 <.rodata>:
1000: 0100
1002: 0302
1004: 0504
...
100e: 0f0e
EDIT:
My CPU is a havard architecture and it can't access data from the ROM directly. So .rodata and .data have to be in the RAM. My approach is that the program process writes the instructions into the ROM, but also writes the .rodata and .data into the RAM. My implementation of the Hardware facilitates this. (A script of mine separates these two datablocks of the binary and transcode it in a protocol my program unit can handle.)
And in the binary at first glance it works: .text is in the address space of the ROM and the .rodata and .data are in the address space of RAM. But the addresses to the .rodata, the linker calculates, are wrong.
This program of mine is only to test the functionality of this, I wouldn't write code like this otherwise. (The optimization flag is also -o0.)
So first of all, I'd like to understand the lines at the beginning of main(), that should put the array pointer onto the stack.
80: 000017b7 lui a5,0x1 # a5 = first ram addr: begin of .rodata
84: 0007a703 lw a4,0(a5) # a4 = content of this addr?!?!?!
88: fee42023 sw a4,-32(s0) # a4 gets stored on stack
Why is the linker treating the beginning of .rodata as a pointer to the array and not like the actual address of the array?