cancel
Showing results for 
Search instead for 
Did you mean: 

STM32N6 : Appli project w/o warning: LOAD segment with RWX permissions

tjaekel
Lead

FYI,

you can build, load, start and debug also the "Appli" project (not just as FSBL).

The linker script (selected as default) "STM32N657XOHXQ_LRUN.ld" loads and executes in the same way.

In order to avoid this warning about "LOAD segment with RWX permissions" you can modify this linker script as (see below).
Modifications:

  • split the SRAM into a "rx" and "rwx" part (helps later to place code in R/O memory)
  • use READONLY on the sections just loaded, never written (and avoid the warning)

 

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM2) + LENGTH(RAM2); /* end of "RAM" Ram type memory */
_sstack = _estack - _Min_Stack_Size;

_Min_Heap_Size  = 0x200;  /* required amount of heap */
_Min_Stack_Size = 0x800; /* required amount of stack */

/* Memories definition */
MEMORY
{
  /* 0x34000400, LENGTH 2047K */
  RAM    (rx)     : ORIGIN = 0x34000400,   LENGTH = 63K
  RAM2   (rwx)    : ORIGIN = 0x34010000,   LENGTH = 1984K
}

/* Sections */
SECTIONS
{
  /* The startup code into "RAM" Ram type memory */
  .isr_vector (READONLY):
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >RAM

  /* The program code and other data into "RAM" Ram type memory */
  .text (READONLY):
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)
    *(.RamFunc)        /* .RamFunc sections */
    *(.RamFunc*)       /* .RamFunc* sections */

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >RAM

  /* Constant data into "RAM" Ram type memory */
  .rodata (READONLY):
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >RAM

  .ARM.extab (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
   {
     . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  } >RAM

  .ARM (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
   {
     . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  } >RAM

  .preinit_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  } >RAM

  .init_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >RAM

  .fini_array (READONLY) : /* The READONLY keyword is only supported in GCC11 and later, remove it if using GCC10 or earlier. */
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  } >RAM

  /* Used by the startup to initialize data */
  _sidata = LOADADDR(.data);

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

  } >RAM2

  .noncacheable :
  {
    . = ALIGN(8);
    __snoncacheable = .;/* create symbol for start of section */
    KEEP(*(noncacheable_buffer))
    . = ALIGN(8);
    __enoncacheable = .;  /* create symbol for end of section */
  } >RAM2

  .gnu.sgstubs (READONLY):
  {
    . = ALIGN(4);
    *(.gnu.sgstubs*)   /* Secure Gateway stubs */
    . = ALIGN(4);
  } >RAM

  /* Uninitialized data section into "RAM" Ram type memory */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM2

  /* User_heap_stack section, used to check that there is enough "RAM" Ram  type memory left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM2

  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}

 

 But how to link and build a FW project so that:

  • all is stored in external QSPI
  • it is executed as code in QSPI memory (no need to copy code to internal SRAM)
  • but initialize SRAM (startup code)
  • and I can still debug (step through the code) when code remains in QSPI memory - does not seem possible

This linker script loads all still to internal SRAM and also executes out of SRAM (therefore you can debug).

BTW:
Why do we have to start entire code at address 0x34000400 (1KB after SRAM start)?
Why is the first 1KB of SRAM unusable (so that we have just 2047KB available (2MB - 1KB) - what is this used for)?

And: we do not use really all the 4.2MB SRAM (just 2MB - 1KB, in linker script). How to use all 4.2KB?
Are the memories in a linear address range?
NO: 32KB are in AHB_SRAM (not linear addresses) and the main memory as linear address range is just 0x34000000...343C0000 = 3840KB.
So, 4.2MB just with a linker script and using different sections.

1 REPLY 1
RomainR.
ST Employee

Hello @tjaekel 

You wrote:

Why do we have to start entire code at address 0x34000400 (1KB after SRAM start)?
Why is the first 1KB of SRAM unusable (so that we have just 2047KB available (2MB - 1KB) - what is this used for)?

The offset of 0x400 (1.024 bytes) is applied during the STM32_SigningTool.exe. This is why the App linker configuration uses this address. Note also, the FSBL is in charge to jump at this AXISRAM1 address by setting the PC counter.

And: we do not use really all the 4.2MB SRAM (just 2MB - 1KB, in linker script). How to use all 4.2KB?
Are the memories in a linear address range? 

You are free to extend your application to use AXISRAM3, 4, 5 and 6 (4x 448kB) but you need to enable it by firmware before use. 
Best regards,

Romain,

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.