cancel
Showing results for 
Search instead for 
Did you mean: 

Build Fails after Updating STM32CubeIDE from 1.14.0 to 1.19.0

Chao
Senior II

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:

 

Chao_0-1760690285209.png

 

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

 

1 ACCEPTED SOLUTION

Accepted Solutions

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 ?

View solution in original post

6 REPLIES 6
Chao
Senior II

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

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:

https://community.st.com/t5/forums/searchpage/tab/message?advanced=false&allow_punctuation=false&q=LOAD%20segment%20with%20RWX%20permissions

 

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
TDK
Super User

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.

If you feel a post has answered your question, please click "Accept as Solution".

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 ?

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".

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

Thanks a lot for this.