# Linker
Le code linker sert à guider le compilateur (plus précisément le linker, comme ld dans GCC) pour assembler toutes les sections d’un programme en un fichier binaire unique.

Sur un microcontrôleur comme le **STM32F410RB**, il faut indiquer où chaque partie du code et des données doit être placée dans la **mémoire du MCU**.

- Où commence le code executable, son point d'entrée ;
- Définit chaque region de la memoire qui existe sur le microcontrolleur et leur taille ;
- Où placer les sections differentes du code en memoire (exemple : interruption, etc...).

Dans l'idée on peut le faire à la main ou récuperer celui générer automatiquement par le logiciel STM32IDE. 

## MEMORY 
Pour realiser un linker on doit preciser la SRAM et sa flash.
Cette partie décrit les zones mémoire physiques du STM32F410RB.
Il faut se fier au plan memoire de la datasheet p.40/763

![alt text](./img/memoryMap.png)

Sur celui-ci nous constatons que SRAM est à 32kB et commence à 0x2000 0000
et que la fash commence à 0x0800 0000 et sa taille est de 128kB (donné à la figure 1 page 37/763)

On peut alors placer dans le linker :

```c
MEMORY
{
  FLASH (rx): ORIGIN = 0x08000000, LENGTH = 128K
  SRAM (rwx): ORIGIN = 0x20000000, LENGTH = 32K
}
```
(rx) → read et execute, donc on peut lire et exécuter du code dedans.

(rwx) → read, write, execute (en pratique, on n’exécute pas depuis la RAM, mais certains MCU le permettent).

## SECTIONS
Chaque programme compilé contient plusieurs sections générées par le compilateur. L'ordre à laquelle ils sont cris découle de la convention utilisé dans CMSIS (fichier startup fournis par ARM).

Tous les compilateurs suivent la même idée :

- Sections nécessaires au CPU d’abord (vecteurs, code)
- Sections de données ensuite (initialisées, non initialisées)
- Mémoire dynamique à la fin (heap, stack)

### ISR_VECTOR
Indique les vecteurs d'interruptions :

```c
isr_vector :
{
    KEEP(*(.isr_vector))
} >FLASH
```

".isr_vector" : C'est la section qui contient le vecteur d'interruptions (ISR - Interrupt Service Routine). Les vecteurs d'interruptions sont des adresses de fonction qui seront appelées lorsque des interruptions spécifiques se produisent.

"KEEP" : Cette directive indique au linker de conserver cette section dans le binaire final, même si elle semble inutilisée par le programme. Cela est crucial pour les vecteurs d'interruptions qui doivent absolument être présents dans le binaire.

">FLASH" : Cela indique que cette section doit être placée en mémoire Flash, qui est généralement de la mémoire non-volatile, utilisée pour stocker le programme.

Elle est placée en Flash pour être disponible dès le reset.

### TEXT
Contient le code de notre programme :

```c
 .text :
  {
    . = ALIGN(4);
		
    *(.text)
    *(.rodata)
		
    . = ALIGN(4);
    _etext = .;
  } >FLASH
```
.text = code exécutable (fonctions, instructions machine).

.rodata = données constantes (const int, chaînes de caractères, etc.).

_etext marque la fin de la zone code, utile pour copier ensuite la section .data au démarrage.

```c
    . = ALIGN(4);
```
Permet d'aligner l'adresse courante sur une frontière de 4 octets.

Cela garantit que le code est correctement aligné en mémoire, ce qui peut être nécessaire pour des performances optimales ou des restrictions matérielles.

### DATA
Variables initialisées :
```c
 .data :
  {
    . = ALIGN(4);
    _sdata = .;
		
    *(.data)

    . = ALIGN(4);
    _edata = .;
  } >SRAM AT> FLASH
```
.data contient les variables globales initialisées (ex: int x = 5;).

Ces valeurs sont stockées dans la Flash au moment de la programmation, mais copiées dans la RAM lors du démarrage (d’où >SRAM AT>FLASH).

_sdata et _edata servent au code d’initialisation (startup.s) pour savoir quoi copier et combien d’octets.

### BSS
Variables non initialisées : 
```c
  .bss :
  {
    . = ALIGN(4);
    _sbss = .;
		
    *(.bss)
		
    . = ALIGN(4);
    _ebss = .;
  } >SRAM
```

.bss contient les variables globales non initialisées (ex: int counter;).

Ces variables ne sont pas stockées en Flash, car elles ne contiennent pas de valeur initiale.

Au démarrage, le startup code remplit cette zone avec des zéros (memset), d’où “zeroed during startup”.