0
0
Power-electronicsHow-ToBeginner · 4 min read

How to Use Linker Script in Embedded C: Syntax and Example

In embedded C, a linker script controls how the program's sections are placed in memory. You write a .ld file defining memory regions and section placement, then pass it to the linker during build to customize your program's memory layout.
📐

Syntax

A linker script typically defines memory regions and section placement. The basic syntax includes:

  • MEMORY block: Defines physical memory areas with start address and size.
  • SECTIONS block: Maps program sections like .text, .data, and .bss to memory regions.
  • Symbols: You can define symbols to mark addresses or sizes.
ld
MEMORY
{
  FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
  RAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 40K
}

SECTIONS
{
  .text :
  {
    *(.text*)
    *(.rodata*)
  } > FLASH

  .data :
  {
    *(.data*)
  } > RAM

  .bss :
  {
    *(.bss*)
  } > RAM
}
💻

Example

This example shows a simple embedded C program with a linker script that places code in FLASH and variables in RAM. It demonstrates how to define memory and sections, then build and run the program.

c
#include <stdint.h>

// Variable in RAM
int counter = 0;

// Function in FLASH
void increment_counter(void) {
    counter++;
}

int main(void) {
    increment_counter();
    return counter; // Should return 1
}

/* Linker script (simple.ld):
MEMORY
{
  FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
  RAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 40K
}

SECTIONS
{
  .text : { *(.text*) *(.rodata*) } > FLASH
  .data : { *(.data*) } > RAM
  .bss : { *(.bss*) } > RAM
}
*/
Output
Program returns 1
⚠️

Common Pitfalls

Common mistakes when using linker scripts include:

  • Not matching memory sizes with actual hardware, causing linker errors or runtime faults.
  • Forgetting to place initialized data (.data) in RAM and code (.text) in FLASH.
  • Missing or incorrect section names causing sections to be discarded or misplaced.
  • Not aligning sections properly, which can cause crashes on some processors.

Always verify your memory map matches your device datasheet and test the program on hardware.

ld
/* Wrong: placing .data in FLASH (read-only) */
SECTIONS
{
  .data : { *(.data*) } > FLASH
}

/* Correct: place .data in RAM */
SECTIONS
{
  .data : { *(.data*) } > RAM
}
📊

Quick Reference

Key points to remember when writing linker scripts:

  • MEMORY: Define all physical memory regions with correct addresses and sizes.
  • SECTIONS: Map program sections to these memory regions.
  • Symbols: Use symbols to mark important addresses if needed.
  • Alignment: Align sections properly for your CPU architecture.
  • Build: Pass the linker script to the linker with -T yourscript.ld.

Key Takeaways

A linker script controls how program sections are placed in memory for embedded systems.
Define MEMORY regions and map SECTIONS like .text, .data, and .bss to them.
Always match memory sizes and addresses to your hardware specifications.
Place executable code in FLASH and writable data in RAM to avoid runtime errors.
Pass the linker script to the linker using the -T option during build.