2025-10-17 1:44 AM - last edited on 2025-10-17 2:27 AM by Andrew Neil
Hi
Just hours ago, I updated the IDE from 1.14.0 to the latest version 1.19.0, a build on the project I have been working on fails by RAM and Flash overflow. This issue has been resolved before the IDE update.
Check the 2 map files, I found the (NOLOAD) in the linker script has no effect in the new IDE.
The error message from the linker:
The F767 board is customized with 32MB external SDRAM, memory map and sections are defined as below:
MEMORY
{
MEM3BASE (xrw) : ORIGIN = 0X20000000, LENGTH = 60K
MEM3MAP (xrw) : ORIGIN = 0x2000F000, LENGTH = 4K
MEM1BASE (xrw) : ORIGIN = 0x20010000, LENGTH = 160K
MEM1MAP (xrw) : ORIGIN = 0x20038000, LENGTH = 10K
RAM (xrw) : ORIGIN = 0x2003A800, LENGTH = 512K-234K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 1024K
LCD_BUF (xrw) : ORIGIN = 0XC0000000, LENGTH = 2000K
MEM2BASE (xrw) : ORIGIN = 0XC01F4000, LENGTH = 28912K
MEM2MAP (xrw) : ORIGIN = 0XC1E30000, LENGTH = 1807K
MEM4BASE (xrw) : ORIGIN = 0xC1FF3C00, LENGTH = 49K
}
/* After the .data section: */
.mem1_base (NOLOAD):
{
. = ALIGN(64);
mem1base = .; /* create a global symbol at data start */
} >MEM1BASE
/* Place array mem1mapbase into internal memory MEM1 region */
.mem1_map (NOLOAD):
{
. = ALIGN(4);
mem1mapbase = .; /* create a global symbol at data start */
} >MEM1MAP
/* Place array mem2base into external SDRAM memory MEM2 region */
.mem2_base (NOLOAD):
{
. = ALIGN(64);
mem2base = .; /* create a global symbol at data start */
} >MEM2BASE
/* Place array mem2mapbase into external SDRAM memory MEM2 region */
.mem2_map (NOLOAD):
{
. = ALIGN(4);
mem2mapbase = .; /* create a global symbol at data start */
} >MEM2MAP
/* Place array ltdc_lcd_framebuf into external SDRAM memory LTDC_FRAME_BUF region */
.lcd_buffer (NOLOAD):
{
. = ALIGN(4);
ltdc_lcd_framebuf = .; /* create a global symbol at data start */
} >LCD_BUF
/* Place array mem3base into internal memory MEM3 region */
.mem3_base (NOLOAD):
{
. = ALIGN(64);
mem3base = .; /* create a global symbol at data start */
} >MEM3BASE
/* Place array mem3mapbase into internal memory MEM3 region */
.mem3_map (NOLOAD):
{
. = ALIGN(4);
mem3mapbase = .; /* create a global symbol at data start */
} >MEM3MAP
/* Place array mem2base into external SDRAM memory MEM2 region */
.mem4_base (NOLOAD):
{
*(.mem4_base*); /* create a global symbol at data start */
} >MEM4BASE
In C files:
__attribute__((section(".lcd_buf"))) uint16_t ltdc_lcd_framebuf[1280][800];
// mem1base (internal RAM,160KB,64 bytes alignment) address = 0x20010000 ~ 0x20037FFF
__attribute__((section(".mem1_base"))) static uint8_t mem1base[160 * 1024] = { 0 };
// mem2base (external SDRAM,30MB,address = 0xC01F4000 ~ 0xC1E2FFFF,64 bytes alignment )
// the first 2MB is used by LTDC (1280*800*2)
__attribute__((section(".mem2_base"))) static uint8_t mem2base[28912 * 1024] = { 0 };
// mem3base (internal RAM, 60KB, address = 0x20000000 ~ 0x2000EFFF,64 bytes alignment)
__attribute__((section(".mem3_base"))) static uint8_t mem3base[60 * 1024] = { 0 };
/* memory management tables */
// mem1mapbase (internal RAM,10KB,address = 0x20038000 ~ 0x2003A7FF,64 bytes alignment)
__attribute__((section(".mem1_map"))) static uint32_t mem1mapbase[160 * 1024 / 64] = { 0 };
// mem2mapbase (external SDRAM,1807K,address = 0xC1E30000 ~ 0xC1FF3BFF,64 bytes alignment )
__attribute__((section(".mem2_map"))) static uint32_t mem2mapbase[28912 * 1024 / 64] = { 0 };
// mem3mapbase (internal RAM,4KB,address = 0x2000F000 ~ 0x2000FFFF,64 bytes alignment)
__attribute__((section(".mem3_map"))) static uint32_t mem3mapbase[60 * 1024 / 64] = { 0 };
mem4_based region is used for absolute addressing for some variables, such as:
/* variable definitions for a circular buffer placed in the external SDRAM: */
/* byte and uint are defined as uint8_t and uint32_t */
byte* powerOn;
byte* buffer;
uint* numBytesLeft;
uint* rdAddr;
uint* wrAddr;
byte* status;
/* initializations */
void BufferX::Init()
{
powerOn = (byte*) POWER_ON_FLAG_ADDR; /* SDRAM Location: 0xC1FF3C00 */
buffer = (byte*) DBG_PRINT_BUFFER_START_ADDR; /* SDRAM Location: 0xC1FF5000 */
rdAddr = (uint*) DBG_BUFFERX_READ_ADDR; /* SDRAM Location: 0xC1FF3C30 */
wrAddr = (uint*) DBG_BUFFERX_WRITE_ADDR; /* SDRAM Location: 0xC1FF3C34 */
status = (byte*) DBG_BUFFERX_STATUS_ADDR; /* SDRAM Location: 0xC1FF3C0C */
numBytesLeft = (uint*) DBG_BUFFERX_NUM_BYTES_LEFT_ADDR; /* SDRAM Location: 0xC1FF3C38 */
if (*powerOn != 0xAA)
{ // MCU power on
*rdAddr = 0;
*wrAddr = 0;
*status = BUFFER_EMPTY;
*numBytesLeft = 0;
}
overflowPrintable = true;
}
Map file by CubeIDE V1.14.0:
.mem1_base 0x0000000020010000 0x28000
0x0000000020010000 . = ALIGN (0x40)
0x0000000020010000 mem1base = .
.mem1_base 0x0000000020010000 0x28000 ./ThirdParty/MALLOC/malloc.o
.mem1_map 0x0000000020038000 0x2800
0x0000000020038000 . = ALIGN (0x4)
0x0000000020038000 mem1mapbase = .
.mem1_map 0x0000000020038000 0x2800 ./ThirdParty/MALLOC/malloc.o
.mem2_base 0x00000000c01f4000 0x1c3c000
0x00000000c01f4000 . = ALIGN (0x40)
0x00000000c01f4000 mem2base = .
.mem2_base 0x00000000c01f4000 0x1c3c000 ./ThirdParty/MALLOC/malloc.o
.mem2_map 0x00000000c1e30000 0x1c3c00
0x00000000c1e30000 . = ALIGN (0x4)
0x00000000c1e30000 mem2mapbase = .
.mem2_map 0x00000000c1e30000 0x1c3c00 ./ThirdParty/MALLOC/malloc.o
.lcd_buffer 0x00000000c0000000 0x0
0x00000000c0000000 . = ALIGN (0x4)
0x00000000c0000000 ltdc_lcd_framebuf = .
.mem3_base 0x0000000020000000 0xf000
0x0000000020000000 . = ALIGN (0x40)
0x0000000020000000 mem3base = .
.mem3_base 0x0000000020000000 0xf000 ./ThirdParty/MALLOC/malloc.o
.mem3_map 0x000000002000f000 0xf00
0x000000002000f000 . = ALIGN (0x4)
0x000000002000f000 mem3mapbase = .
.mem3_map 0x000000002000f000 0xf00 ./ThirdParty/MALLOC/malloc.o
.mem4_base
*(.mem4_base*)
0x000000002000ff00 . = ALIGN (0x4)
Map file by CubeIDE V1.19.0:
.mem1_base 0x2003a8b0 0x28000 load address 0x0801c6f4
.mem1_base 0x2003a8b0 0x28000 ./ThirdParty/MALLOC/malloc.o
.mem2_base 0x200628b0 0x1c3c000 load address 0x080446f4
.mem2_base 0x200628b0 0x1c3c000 ./ThirdParty/MALLOC/malloc.o
.mem3_base 0x21c9e8b0 0xf000 load address 0x09c806f4
.mem3_base 0x21c9e8b0 0xf000 ./ThirdParty/MALLOC/malloc.o
.mem1_map 0x21cad8b0 0x2800 load address 0x09c8f6f4
.mem1_map 0x21cad8b0 0x2800 ./ThirdParty/MALLOC/malloc.o
.mem2_map 0x21cb00b0 0x1c3c00 load address 0x09c91ef4
.mem2_map 0x21cb00b0 0x1c3c00 ./ThirdParty/MALLOC/malloc.o
.mem3_map 0x21e73cb0 0xf00 load address 0x09e55af4
.mem3_map 0x21e73cb0 0xf00 ./ThirdParty/MALLOC/malloc.o
.mem1_base 0x20010000 0x0
0x20010000 . = ALIGN (0x40)
0x20010000 mem1base = .
.mem1_map 0x20038000 0x0
0x20038000 . = ALIGN (0x4)
0x20038000 mem1mapbase = .
.mem2_base 0xc01f4000 0x0
0xc01f4000 . = ALIGN (0x40)
0xc01f4000 mem2base = .
.mem2_map 0xc1e30000 0x0
0xc1e30000 . = ALIGN (0x4)
0xc1e30000 mem2mapbase = .
.lcd_buffer 0xc0000000 0x0
0xc0000000 . = ALIGN (0x4)
0xc0000000 ltdc_lcd_framebuf = .
.mem3_base 0x20000000 0x0
0x20000000 . = ALIGN (0x40)
0x20000000 mem3base = .
.mem3_map 0x2000f000 0x0
0x2000f000 . = ALIGN (0x4)
0x2000f000 mem3mapbase = .
.mem4_base
*(.mem4_base*)
0x2000f000 . = ALIGN (0x4)
I wonder why this happens, I would like to receive anyone's suggestions, and especially to invite @TDK to have a look at this issue as you resolved this issue in IDE version 1.14.0.
Chao
Solved! Go to Solution.
2025-10-17 12:17 PM
By doing some experiments, the following section definitions will pass the project build:
.mem2_base (NOLOAD):
{
. = ALIGN(64);
*(.mem2_base)
} >MEM2BASE
/* and */
.mem2_base (NOLOAD):
{
. = ALIGN(64);
*(.mem2_base*)
} >MEM2BASE
Then what are the difference between *(.mem2_base) and *(.mem2_base*) ? What do they exactly mean ?
2025-10-17 1:46 AM
I missed a warning message from the linker just after the link errors:
../../../arm-none-eabi/bin/ld.exe: warning: Tunnel.elf has a LOAD segment with RWX permissions
2025-10-17 2:31 AM
Going from v1.14.0 to 1.19.0 is quite a jump, so not really surprising that things have changed - in particular, the GCC toolchain version will most likely have changed.
Quite a few previous posts on this "LOAD segment with RWX permissions" warning:
2025-10-17 5:55 AM
NOLOAD hasn't changed how it works. Recheck your assumptions. Probably a mismatch in the linker file you're using. Don't see anything wrong in the information you presented--issue is likely elsewhere.
2025-10-17 12:17 PM
By doing some experiments, the following section definitions will pass the project build:
.mem2_base (NOLOAD):
{
. = ALIGN(64);
*(.mem2_base)
} >MEM2BASE
/* and */
.mem2_base (NOLOAD):
{
. = ALIGN(64);
*(.mem2_base*)
} >MEM2BASE
Then what are the difference between *(.mem2_base) and *(.mem2_base*) ? What do they exactly mean ?
2025-10-18 1:20 AM - edited 2025-10-18 1:47 AM
I don't really know, but this would be general GCC linker stuff - not specific to STM32, so any general GCC resources would be applicable...
PS:
Where is the official documentation of gnu linker script command language?
Using ld, The GNU linker - Linker Scripts.
via a google search for "gcc linker script".
2025-10-18 6:48 AM
Thanks a lot for this.