2025-10-11 5:41 AM - last edited on 2025-10-13 2:37 AM by Andrew Neil
Follow-on from: Help for porting from MDK to CubeIDE.
Hi
I am now working on porting an MDK example to CubeIDE on an F767-based customized board with 32MB SDRAM and an LCD interface.
At the moment, the build of the ported example in CubeIDE gives following erorr message:
The following is the original code of the example targeting on ARM compiler:
static __align(64) uint8_t mem1base[160*1024];
static __align(64) uint8_t mem2base[28912*1024] __attribute__((at(0XC01F4000)));
static __align(64) uint8_t mem3base[60*1024] __attribute__((at(0X20000000)));
static uint32_t mem1mapbase[160*1024/64];
static uint32_t mem2mapbase[28912*1024/64] __attribute__((at(0XC01F4000 + 28912*1024)));
static uint32_t mem3mapbase[60*1024/64] __attribute__((at(0X20000000 + 60*1024))); Now after the porting, the code is changed to:
/* mem1 (internal RAM) (64 bytes alignment) */
__attribute__((section(".mem1base.mem1_base"))) static uint8_t mem1base[160 * 1024] = { 0 };
// mem2 (32MB external SDRAM)
// 64 bytes alignment, start address = 0XC01F4000
// the first 2MB is used by LTDC (1280*800*2)
__attribute__((section(".mem2base.mem2_base"))) static uint8_t mem2base[28912 * 1024] = { 0 };
// mem3 (CCMRAM, 64KB, used only by MCU)
// 64 bytes alignment, start address = 0X20000000
__attribute__((section(".mem3base.mem3_base"))) static uint8_t mem3base[60 * 1024] = { 0 };
__attribute__((section(".mem1mapbase.mem1map_base"))) static uint32_t mem1mapbase[160 * 1024 / 64] = { 0 };
__attribute__((section(".mem2mapbase.mem2map_base"))) static uint32_t mem2mapbase[28912 * 1024 / 64] = { 0 };
__attribute__((section(".mem3mapbase.mem3map_base"))) static uint32_t mem3mapbase[60 * 1024 / 64] = { 0 };
__attribute__((section(".ltdc_lcd_framebuf.lcd_framebuf"))) uint16_t ltdc_lcd_framebuf[1280][800];
I have no previous experiences on modifying a linker script, all I learned was from STM32CubeIDE User Guide, and the following are my modifications:
address calculations for those in the following script:
/* Memories definition */
/*
********************************************************
** Original Memories definition
MEMORY
{
RAM (xrw) : ORIGIN = 0X20000000, LENGTH = 512K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
}
********************************************************
*/
MEMORY
{
MEM3BASE (xrw) : ORIGIN = 0X20000000, LENGTH = 60K
MEM3MAP (xrw) : ORIGIN = 0x2000F000, LENGTH = 1K
MEM1BASE (xrw) : ORIGIN = 0x2000F400, LENGTH = 160K
MEM1MAP (xrw) : ORIGIN = 0x20037400, LENGTH = 3K
RAM (xrw) : ORIGIN = 0x20038000, LENGTH = 512K-224K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
LCD_BUF (xrw) : ORIGIN = 0XC0000000, LENGTH = 2000K
MEM2BASE (xrw) : ORIGIN = 0XC01F4000, LENGTH = 28912K
MEM2MAP (xrw) : ORIGIN = 0XC1E30000, LENGTH = 452K
}
/* Initialized data sections into "RAM" Ram type memory */
.data :
{
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
*(.data) /* .data sections */
*(.data*) /* .data* sections */
. = ALIGN(4);
_edata = .; /* define a global symbol at data end */
} >RAM
/* Place array mem1base into internal memory MEM1 region */
.mem1base :
{
. = ALIGN(64);
_smem1base = .; /* create a global symbol at data start */
*(.mem1base) /* .mem1base sections */
*(.mem1base*) /* .mem1base* sections */
. = ALIGN(64);
_emem1base = .; /* define a global symbol at data end */
} >MEM1BASE
/* Place array mem1mapbase into internal memory MEM1 region */
.mem1mapbase :
{
. = ALIGN(4);
_smem1mapbase = .; /* create a global symbol at data start */
*(.mem1mapbase) /* .mem1mapbase sections */
*(.mem1mapbase*) /* .mem1mapbase* sections */
. = ALIGN(4);
_emem1mapbase = .; /* define a global symbol at data end */
} >MEM1MAP
/* Place array mem2base into external SDRAM memory MEM2 region */
.mem2base :
{
. = ALIGN(64);
_smem2base = .; /* create a global symbol at data start */
*(.mem2base) /* .mem2base sections */
*(.mem2base*) /* .mem2base* sections */
. = ALIGN(64);
_emem2base = .; /* define a global symbol at data end */
} >MEM2BASE
/* Place array mem2mapbase into external SDRAM memory MEM2 region */
.mem2mapbase :
{
. = ALIGN(4);
_smem2mapbase = .; /* create a global symbol at data start */
*(.mem2mapbase) /* .mem2mapbase sections */
*(.mem2mapbase*) /* .mem2mapbase* sections */
. = ALIGN(4);
_emem2mapbase = .; /* define a global symbol at data end */
} >MEM2MAP
/* Place array ltdc_lcd_framebuf into external SDRAM memory LTDC_FRAME_BUF region */
.ltdc_lcd_framebuf :
{
. = ALIGN(4);
_sltdc_lcd_framebuf = .; /* create a global symbol at data start */
*(.ltdc_lcd_framebuf) /* .ltdc_lcd_framebuf sections */
*(.ltdc_lcd_framebuf*) /* .ltdc_lcd_framebuf* sections */
. = ALIGN(4);
_eltdc_lcd_framebuf = .; /* define a global symbol at data end */
} >LCD_BUF
/* Place array mem3base into CCMRAM memory MEM3 region */
.mem3base :
{
. = ALIGN(64);
_smem3base = .; /* create a global symbol at data start */
*(.mem3base) /* .mem3base sections */
*(.mem3base*) /* .mem3base* sections */
. = ALIGN(64);
_emem3base = .; /* define a global symbol at data end */
} >MEM3BASE
/* Place array mem3mapbase into CCMRAM memory MEM3 region */
.mem3mapbase :
{
. = ALIGN(4);
_smem3mapbase = .; /* create a global symbol at data start */
*(.mem3mapbase) /* .mem3mapbase sections */
*(.mem3mapbase*) /* .mem3mapbase* sections */
. = ALIGN(4);
_emem3mapbase = .; /* define a global symbol at data end */
} >MEM3MAPI must have done something wrong in this script, so please point them out to me, it would be highly appreciated!
Many thanks in advance!
Chao
Solved! Go to Solution.
2025-10-11 9:32 PM
Still think you're modifying one linker script but using another.
From your screenshot, it looks like you're using the *_FLASH.ld linker script file:
which, from your attached project, only has the RAM and FLASH sections defined.
Looks like you've modified the *_RAM.ld file, but aren't using it:
Delete the linker script you aren't using so the system can't use it.
2025-10-11 9:32 AM
Look in the map file to see what is taking up so much space.
Probably the mem2mapbase section needs to be marked as NOLOAD.
2025-10-11 11:15 AM
2025-10-11 4:39 PM
If I declare a new section like you are and mark it as NOLOAD, the program compiles for me. I'm not sure what you are doing differently. Are you sure you're modifying the right linker script? Check the linker script listed in the log file to the one you are modifying.
2025-10-11 9:12 PM
I created a very simple F767 project, specificly for this test.
The project only enabled Serial Wire, selected LSE and HSE, added all variables with __attribute__ declaration in the main.c, also initialized these variables in the main, modified linker script as in previous project, and finally build the project, and the build failed:
I found, if I don't do the initializations on these variables by commenting out the USE_VARS definition, the build is okay. Please find attached file for the whole project.
Because the modification of linker script for different variables are in the same way as shown below, could you please confirm whether or not it is correct:
In the code:
__attribute__((section(".ltdc_lcd_framebuf"))) uint16_t ltdc_lcd_framebuf[1280][800];
In the script:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20038000, LENGTH = 512K-224K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
LCD_BUF (xrw) : ORIGIN = 0XC0000000, LENGTH = 2000K
}
/* Place array ltdc_lcd_framebuf into external SDRAM memory LTDC_FRAME_BUF region */
.ltdc_lcd_framebuf (NOLOAD):
{
. = ALIGN(4);
_sltdc_lcd_framebuf = .; /* create a global symbol at data start */
*(.ltdc_lcd_framebuf) /* .ltdc_lcd_framebuf sections */
*(.ltdc_lcd_framebuf*) /* .ltdc_lcd_framebuf* sections */
. = ALIGN(4);
_eltdc_lcd_framebuf = .; /* define a global symbol at data end */
} >LCD_BUFThe .ltdc_lcd_framebuf section was copied from the .data section and renamed it though I don't understand the following syntax at all:
*(.ltdc_lcd_framebuf)
*(.ltdc_lcd_framebuf*)
I did s search on the net for defining a variable in a gcc linker script, the following is answered by AI:
.myvars:
{
my_var = .;
} >RAMTherefore, for my case, could I just do the following:
/* in the script: */
.lcd_buf (NOLOAD):
{
. = ALIGN(4);
ltdc_lcd_framebuf = .;
} >LCD_BUF
/* in the code: */
__attribute__((section(".lcd_buf "))) uint16_t ltdc_lcd_framebuf[1280][800];Does the section name have to be different from the name of the specified variable ?
2025-10-11 9:32 PM
Still think you're modifying one linker script but using another.
From your screenshot, it looks like you're using the *_FLASH.ld linker script file:
which, from your attached project, only has the RAM and FLASH sections defined.
Looks like you've modified the *_RAM.ld file, but aren't using it:
Delete the linker script you aren't using so the system can't use it.
2025-10-12 5:41 AM
You are absolutely right!!!
I was not aware of that. I thought the compiler would use the both!
Now it builds ok.
Thank you so ...... much, really appreciate it!
Chao
2025-10-12 9:23 AM
It's confusing. In my opinion, CubeMX should only generate the *_FLASH.ld one, since that's what they use. But it's been like that for so long, unlikely to change now. Glad you got it solved.