building process, memory and Linker script

image.png

Memory Model

  1. Flash Memory :
    • Read-Only
    • Begins at address 0x08000000
    • Size depends on specific STM32 microcontroller
    • Program code is stored here.
    • Contains a vector table at address 0x08000004This consists of pointers to the various exception handlers
  2. SRAM :
    • Read and Write
    • Begins at 0x20000000
    • Size depends on specific STM32 microcontroller
    • Variables and Stack are stored here

Linker Script

The script has 4 features:

Memory

MEMORY
{
    name [(attr)] : ORIGIN = origin, LENGTH = len
    …
}

E.g.

MEMORY
{
    FLASH(rx) : ORIGIN = 0x08000000, LENGTH = 512K
    SRAM(rwx) : ORIGIN = 0x20000000, LENGTH = 128K
}

Sections

SECTIONS
{
    …
}

E.g.

SECTIONS
{
    .text :
    {
        *(.text)   /* merge all .text sections of input files */
    }> FLASH
}

Sections (cont.)

The 3 relevant sections:

Startup Code

Contains:

  1. Reset Handler
    • This function copies the initial values for variables from the FLASH where the linker places them to the SRAM.
    • It also zeros out the uninitialized data portion of the SRAM.
  2. Interrupt Vector Table
    • This is an array that holds memory address of interrupt handler functions
    • In order to allow application code to conveniently redefine the various interrupt handlers, every required vector is assigned an overrideable _weak alias to a default function which loops forever

VMA and LMA

Getting familiar with the script (cont.)

commands

Section Merging

image.png

example

/* Memories definition */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 128K
  FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 512K
  CUSTOM_MEMORY (rx) : ORIGIN = 0x800C000,	LENGTH = 64K
}

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

   /*Create this section in the RAM*/
   .custom_ram_block 0x20000100(NOLOAD) : 
   {
   
   /*Keep variables even if they are not referenced*/
    KEEP(*(.custom_ram_block))
   }>RAM
   
   .custom_flash_block 0x08004000 :
   {
   	KEEP(*(.custom_flash_block))
   }>FLASH
   
  .custom_section :
	 {
	 	KEEP(*(.custom_section))
	 } >CUSTOM_MEMORY

#define CUSTOM_FUNC  __attribute__((section(".custom_section")))
#define RAM_FUNC  __attribute__((section(".RamFunc")))

unsigned char __attribute__((section(".custom_ram_block"))) custom_ram_buff[10];   //10 bytes
unsigned char __attribute__((section(".custom_flash_block"))) custom_flash_buff[10];   //10 bytes

void RAM_FUNC _led_toggle(uint32_t dly_ms)
{
	GPIOA->ODR ^= LED_PIN;
    delay(dly_ms);
}

void CUSTOM_FUNC _led_toggle2(uint32_t dly_ms)
{
	GPIOA->ODR ^= LED_PIN;
    delay(dly_ms);
}

image.png

image.png