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