cancel
Showing results for 
Search instead for 
Did you mean: 

Help on linker script modifications for use of external SDRAM and LCD driver

Chao
Senior II

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:

Chao_0-1760182377760.png

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:

Chao_0-1760186291719.png

/* 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 */
  } >MEM3MAP

I 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

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Super User

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:

TDK_0-1760243304576.png

which, from your attached project, only has the RAM and FLASH sections defined.

TDK_1-1760243360466.png

 

Looks like you've modified the *_RAM.ld file, but aren't using it:

TDK_2-1760243422256.png

 

 

Delete the linker script you aren't using so the system can't use it.

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

View solution in original post

7 REPLIES 7
TDK
Super User

Look in the map file to see what is taking up so much space.

Probably the mem2mapbase section needs to be marked as NOLOAD.

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

Thanks for reply!

Add NOLOAD and build, it does not make difference:

Chao_0-1760205854956.png

Here I include the map file, could you please have a look at it, as I don't have experience on it, I could only read it intuitively.

 

TDK
Super User

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.

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

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:

Chao_0-1760239193221.png

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_BUF

The .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 = .;
  } >RAM

Therefore, 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 ?

TDK
Super User

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:

TDK_0-1760243304576.png

which, from your attached project, only has the RAM and FLASH sections defined.

TDK_1-1760243360466.png

 

Looks like you've modified the *_RAM.ld file, but aren't using it:

TDK_2-1760243422256.png

 

 

Delete the linker script you aren't using so the system can't use it.

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

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

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.

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