STM32 prosty skrypt linkera

Skrypt jest rzeczywiście prosty. Zaprezentuję go w całej okazałości, żeby był bardziej zrozumiały. Jest to generalnie kompilacja działających i niedziałających przykładów z internetu. Minimum jest bardzo proste. Na początku w pamięci flash musi znaleźć się tablica wektorów przerwań (tablica wskaźników do funkcji obsługujących przerwania). Opisuje go sekcja oznaczona jako isr_vectors. KEEP jest konieczny, gdyż inaczej linker może chcieć wyrzucić coś, co jest nieużywane. Następnie w sekcji .text (chociaż można ją nazwać dowolnie) umieszczamy kod wykonywalny, który kompilator oznacza jako .text lub .text.* (* oznacza dowolny ciąg znaków). Po kodzie wykonywalnym umieszczamy stałe, które kompilator oznacza jako .rodata*. Teraz występuje kolejna sekcja. Zmienne zainicjowane. Musimy na nie utworzyć nową sekcję, gdyż wartości inicjujące muszą być zapisane w pamięci flash ( AT (_flash_data_start) umieszczamy sekcję po stałych), a adresy będą mapowane w pamięci RAM ( >RAM) .

Tutaj dorzuciłem małą ciekawostkę pod tytułem .ramsection. Gdy jakiejś funkcji dodamy atrybut .ramsection, np tak:

__attribute__ ((long_call, section (".ramsection")))

wtedy funkcja zostanie zmapowana do pamięci ram. Oczywiście kod startowy musi zadbać o to, aby została kod takiej funkcji został przekopiowany do pamięci RAM na starcie. Dlatego .ramsection jest w sekcji data. Podczas startu kopiujemy całą sekcję data od _data_start do _data_end na początek pamięci RAM.

Ostatnia sekcja to zmienne niezainicjowane. Są one mapowane do pamięci RAM. Dobra praktyka inżynierska nakazuje w kodzie startowym przejechać się zerami po obszarze pamięci od _bss_start do _bss_end. Oczywiście dobra praktyka inżynierska sobie, a realia sobie. Nie trzeba inicjować tego obszaru, ale podczas używania tych zmiennych należy pamiętać, że ich pierwsza wartość będzie w sumie losowa.

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

SECTIONS
{
    .  = 0x0;        
    .isr_vectors : 
    {
     . = ALIGN(4);
     KEEP(*(.isr_vectors))
     . = ALIGN(4);
    } >FLASH
    
    .text :
    {
        *(.text)   
 *(.text.*) 
        *(.rodata)
        *(.rodata*)   
        . = ALIGN(4);
        _flash_data_start = .;
    } >FLASH
    
    .data : AT (_flash_data_start)
    {
     . = ALIGN(4);
     _data_start = .;
        *(.data)
        *(.data.*)
        *(.ramsection)
        _data_end = .;
    } >RAM

    .bss :
    {
     . = ALIGN(4);
     _bss_start = .;
        *(.bss)       
        _bss_end = .;
    } >RAM
    
}

Na koniec dorzucę:
Mój skrypt linkera – GitHub
Mój kod startowy – GitHub