Reputation: 111
I have a simulator of a custom-designed CPU, that has the memory mapped as follows:
MEMORY
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 16384K /* KiB */
RAM (rw) : ORIGIN = 0x20000000, LENGTH = 512K /* KiB */
}
From what I've tested, everything in the CPU works as expected, apart from malloc() (and similar memory allocation functions). The malloc
function will return a pointer to the FLASH memory (i.e. not respecting the RAM origin).
This is the test code:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
extern uint32_t _sidata; /* Start of .data in FLASH */
extern uint32_t _sdata; /* Start of .data in RAM */
extern uint32_t _edata; /* End of .data in RAM */
extern uint32_t _sbss; /* Start of .bss in RAM */
extern uint32_t _ebss; /* End of .bss in RAM */
void initialize_memory(void) {
// Copy initialized variables from FLASH to RAM (.data section)
uint32_t *src = &_sidata;
uint32_t *dest = &_sdata;
while (dest < &_edata) {
*dest++ = *src++;
}
// Zero-initialize the .bss section in RAM
dest = &_sbss;
while (dest < &_ebss) {
*dest++ = 0;
}
}
int main(void){
initialize_memory();
int *ptr1 = (int*)malloc(4*sizeof(int));
__asm__("nop"); // just for locating this line in assembly
__asm__("lui t0, 0x80000"); // Destination address
__asm__("mv t1, a5");
__asm__("sw t1, 0(t0)"); // Storing the returned value
__asm__("nop");
}
The __asm__
part is used for my evaluation - I can see the output of 0x80000000 and it is 8. The malloc is returning a number 8. -> that is not correct, at least it should be 0x20000008 to point into RAM.
This is the risc-v assembly part (.lss) from where I found out the register I wanted to inspect (a5 in this case):
000000bc <main>:
bc: fe010113 addi sp,sp,-32
c0: 00112e23 sw ra,28(sp)
c4: 00812c23 sw s0,24(sp)
c8: 02010413 addi s0,sp,32
cc: f4dff0ef jal 18 <initialize_memory>
d0: 01000513 li a0,16
d4: 038000ef jal 10c <malloc>
d8: 00050793 mv a5,a0
dc: fef42623 sw a5,-20(s0)
e0: 00000013 nop
e4: 800002b7 lui t0,0x80000
e8: 00078313 mv t1,a5
ec: 0062a023 sw t1,0(t0) # 80000000 <_estack+0x5ff80004>
f0: 00000013 nop
f4: 00000793 li a5,0
f8: 00078513 mv a0,a5
fc: 01c12083 lw ra,28(sp)
100: 01812403 lw s0,24(sp)
104: 02010113 addi sp,sp,32
108: 00008067 ret
To see if the malloc is actually doing something, I've tested this code. The result of the second malloc is 0x20:
...
int *ptr1 = (int*)malloc(4*sizeof(int));
__asm__("nop");
__asm__("lui t0, 0x80000");
__asm__("mv t1, a5");
__asm__("sw t1, 0(t0)");
__asm__("nop");
int *ptr2 = (int*)malloc(4*sizeof(int));
__asm__("nop");
__asm__("lui t0, 0x80000");
__asm__("mv t1, a5");
__asm__("sw t1, 0(t0)");
__asm__("nop");
}
Linker script:
.data :
{
. = ALIGN(4);
_sdata = .;
*(.data)
*(.data*)
*(.*data*)
. = ALIGN(4);
_edata = .;
} >RAM AT> FLASH
/* } AT> FLASH */
/* } >FLASH AT>RAM */
_sibss = LOADADDR(.bss);
. = ALIGN(4);
.bss :
{
_sbss = .;
__bss_start__ = _sbss;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
__bss_end__ = _ebss;
/* } >RAM */
/* } >RAM */
} >RAM AT> FLASH
._user_heap_stack :
{
. = ALIGN(8);
PROVIDE ( __heap_start__ = . );
. = . + 0x1000;
PROVIDE ( __heap_end__ = . );
} >RAM
The question is, why the output of the malloc is not respecting the origin of the RAM, on the other hand - how do I even know if that returned number is correct in the first place - wouldn't it "collide" with the data preloaded from FLASH?
Toolchain used: xpack-riscv-none-elf-gcc-14.2.0-2
Upvotes: 1
Views: 128