Locate Heap in SDRAM Posted by FranzWegerer on 2016-02-08 13:49 Hello, I want to locate heap in SDRAM. I found some Keil samples, but ... SDRAM adress is 0xD0000000, size 8M. Thanks a lot
Posted by tarek bouchkati on 2016-02-08 16:07 Hello Franz, you need to specify SDRAM memory in your linker file (here I am using a linker for STM32L476RGTx with 1M FLASH and 96K RAM) /* Specify the memory areas */ MEMORY { FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1M RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96K SDRAM(xrw) : ORIGIN = 0x????????, LENGTH = 8M } /* Specify the memory areas */MEMORY{FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1MRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 96KSDRAM(xrw) : ORIGIN = 0x????????, LENGTH = 8M} And modify >RAM by >SDRAM /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { . = ALIGN(4); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(4); } >SDRAMxxxxxxxxxx /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { . = ALIGN(4); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(4); } >SDRAM Update: Do not forget to initialize you SDRAM before your application starts ! It should be done in Reset Handler (in startup file) in assembly. There are better solutions that writing in assembler 1- Start with the default STACK&HEAP location (RAM), initialize your SDRAM then switch to SDRAM as STACK&HEAP location 2- Separate Heap and stack locations (STACK in RAM and HEAP in SDRAM) in linker file, than initialize SDRAM in your main before any malloc usage
Posted by FranzWegerer on 2016-02-09 20:26 First - thank you very much! Yes I want only heap into SDRAM (the heap can use the whole SDRAM), but how can I split this? Sorry, but I am not very familiar with linker scripts
Posted by tarek bouchkati on 2016-02-10 13:37 We can also do that without big modifcations in linker script by defining the heap start/end in linker miscellaneous flags, ie : -Wl,--defsym=__heap_start=0xD0000000,--defsym=__heap_limit=0xD0800000xxxxxxxxxx -Wl,--defsym=__heap_start=0xD0000000,--defsym=__heap_limit=0xD0800000 Note: you have to change these values with yours and removing heap informations from linker (not necessary but good for your linker lisibility) 1- remove this line : _Min_Heap_Size = 0; /* required amount of heap */ 2- and replace this /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { . = ALIGN(8); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); } >RAMxxxxxxxxxx /* User_heap_stack section, used to check that there is enough RAM left */ ._user_heap_stack : { . = ALIGN(8); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); } >RAM with the following /* User_stack section, used to check that there is enough RAM left */ ._user_stack : { . = ALIGN(8); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Stack_Size; . = ALIGN(8); } >RAMxxxxxxxxxx /* User_stack section, used to check that there is enough RAM left */ ._user_stack : { . = ALIGN(8); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Stack_Size; . = ALIGN(8); } >RAM Edit: I forgot syscalls modifications You have to add syscalls.c to project (you can borrow it from another SystemWorkbench project) then replace _sbrk function by the following caddr_t _sbrk(int incr) { extern char __heap_start asm("__heap_start"); /* Defined by the linker. */ extern char __heap_limit asm("__heap_limit"); /* Defined by the linker. */ static char *heap_end; static char *heap_limit = &__heap_limit; char *prev_heap_end; if (heap_end == 0) heap_end = &__heap_start; prev_heap_end = heap_end; if (heap_end + incr > heap_limit) { errno = ENOMEM; // not enough memory return (caddr_t) -1; } heap_end += incr; return (caddr_t) prev_heap_end; }x caddr_t _sbrk(int incr){ extern char __heap_start asm("__heap_start"); /* Defined by the linker. */ extern char __heap_limit asm("__heap_limit"); /* Defined by the linker. */ static char *heap_end; static char *heap_limit = &__heap_limit; char *prev_heap_end; if (heap_end == 0) heap_end = &__heap_start; prev_heap_end = heap_end; if (heap_end + incr > heap_limit) { errno = ENOMEM; // not enough memory return (caddr_t) -1; } heap_end += incr; return (caddr_t) prev_heap_end;}
Posted by FranzWegerer on 2016-02-16 15:13 Thanks again. Works without any problems. I think it is easier to define the symbols in linker script. Attached the final code with all modifications code.zip (3.83 Kb)
Posted by Csongor on 2019-09-13 12:12 Hello guys! I have a similar problem. I want to locate heap in SDRAM in Nucleo144 H743ZI hardware. Your conversation and solution is very helpfully and interesting, but i have a lot of question about this topic. First question: Can I have to change something in the CubeMX FMC Mode & Configuration SDRAM 1? Because I don’t realize it is important to me. Nobody speaks about it. When I was searching on the internet for my problem solution, I only found about, how to change something in for example: STM32H743ZITx_FLASH.ld file. You guys are the first solution, who spoke about it, that I must to change something in the syscall.c file. Second question: What is the easiest way to test my SDRAM is working? Nowadays I use malloc function to see this. Is it correct or do you have any better idea? Thanks a lot! Csongor