Request for Linker Script to Place Code/Data in TCM (Cortex-M7, i.MX8MP)

I am currently working on the Cortex-M7 core of the i.MX8MP platform and am trying to place all the code and data sections into TCM (ITCM and DTCM) to ensure optimal performance. However, I have not been successful in modifying the linker script accordingly, as the existing memory configuration and placement logic are a bit unclear to me.

Could you kindly provide a working linker script or an example configuration that correctly places all code and data segments into the TCM regions for the Cortex-M7 on this platform?

This would greatly help me proceed with development and ensure the application runs from the fastest available memory.

Thank you in advance for your support.

Thanks & regards,
Prem0919

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

Did you like my answer? :+1: :-1:


Hello Prem0919,

Thank you for your question! I understand you want to ensure that all code and data for the Cortex-M7 are placed in ITCM and DTCM on the Verdin iMX8M Plus for the best performance.

Below is a template for a GNU ld (linker script) file that will place your code (.text), read-only data (.rodata), initialized data (.data), and zero-initialized data (.bss) into the appropriate TCM regions:

/* Verdin iMX8M Plus M7 TCM linker script example */

/* ITCM: 128KB at 0x00000000 - 0x0001FFFF (for code) */
/* DTCM: 128KB at 0x20000000 - 0x2001FFFF (for data) */

MEMORY
{
  ITCM (rx) : ORIGIN = 0x00000000, LENGTH = 128K
  DTCM (rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}

SECTIONS
{
  /* Place code and read-only data in ITCM */
  .text :
  {
    KEEP(*(.isr_vector))
    *(.text*)
    *(.rodata*)
    *(.glue_7)
    *(.glue_7t)
    *(.eh_frame*)
  } > ITCM

  /* Initialized data in DTCM */
  .data : AT(__data_load_addr)
  {
    __data_start__ = .;
    *(.data*)
    . = ALIGN(4);
    __data_end__ = .;
  } > DTCM
  __data_load_addr = LOADADDR(.data);

  /* Uninitialized data (BSS) in DTCM */
  .bss (NOLOAD) :
  {
    __bss_start__ = .;
    *(.bss*)
    *(COMMON)
    . = ALIGN(4);
    __bss_end__ = .;
  } > DTCM

  /* Stack can also be allocated in DTCM if required */
  __StackTop = ORIGIN(DTCM) + LENGTH(DTCM);
  __StackLimit = __StackTop - 0x400; /* Example: 1KB stack */

  /* ... other sections as necessary ... */
}

/* Provide symbols for startup code */
PROVIDE(__stack = __StackTop);

Notes:

  • Modify sizes if your application is getting close to the 128KB limits.
  • Make sure your startup (crt0) code copies the .data section from flash/ROM/load address to DTCM at startup.
  • The actual section labels (.text, .data, .bss) should match what is used by your toolchain/startup code.

For more details regarding addresses, refer to the memory regions described here:

It is also advisable to review MCUXpresso SDK examples for the i.MX8MP, as they include linker scripts tailored for this platform:

Let me know if you need further clarification or help customizing the script for your project!

Best regards, Toradex AI Assistant.

Hi @prem0919!

NXP already provides linker scripts on their MCUXpresso examples:

~/boards/evkmimx8mp/demo_apps/hello_world/armgcc$ ls *.ld
MIMX8ML8xxxxx_cm7_ddr_ram.ld  MIMX8ML8xxxxx_cm7_flash.ld  MIMX8ML8xxxxx_cm7_ram.ld

The flash.ld is for external flash (like an SD card), the ddr_ram.ld is for the DDR, and, if I’m not mistaken, the ram.ld uses the TCM, but only for code. If you want to use the TCM for data, you may customize the linker script. Since we are not experienced in customizing such a script, I recommend that you ask on NXP’s community, where you will be able to get more efficient help.

That being said, you may use one of its examples as a starting point and then start to customize it with your changes.

About the Toradex AI answer, I was not able to test, but feel free to try it and let us know if it worked or not.

Best regards.