Jak przenieść projekt ze środowiska IAR Embedded Workbench do Atollic TrueSTUDIO – poradnik migracyjny

Zmiany kodu asemblerowego

Mimo że zestaw instrukcji i obsługiwane tryby adresowania pozostają przy migracji na inne środowisko programistyczne bez zmian, jest jeden aspekt zestawu narzędziowego nie podlegający standaryzacji. Chodzi o składnię obsługiwaną przez asembler.

Patrząc na najniższy poziom, asemblery pozwalają na tworzenie kodu aplikacji poprzez dokładne określenie jakie instrukcje zostaną wykonane. W celu uproszczenia zadania programistom, asemblery są wyposażone w dodatkowe funkcje, w tym:

  • Obsługę symboli i etykiet do adresowania symbolicznego;
  • Obsługę preprocesora, umożliwiającą warunkową asemblację skrośną oraz użycie makr;
  • Obsługę włączania plików zewnętrznych, pozwalającą na współdzielenie wspólnych definicji;
  • Obsługę wyrażeń arytmetycznych i łańcuchów znakowych;
  • Obsługę niektórych cech wysokopoziomowych (np. struktur).

Niestety, niektóre asemblery różnią się nie tylko jeśli chodzi o funkcje dodatkowe, ale również jeśli chodzi o symbole użyte do opisu instrukcji (np. symbole używane do rozróżniania trybów adresowania lub definicje stałych numerycznych). Różnice tego typu pomiędzy zestawami narzędziowymi można jednak łatwo obejść stosując proste mapowanie.

WSKAZÓWKA

Narzędzia GNU są zgodne z dyrektywą mówiącą, że składnia instrukcji powinna być taka, jak zdefiniowano w referencyjnej liście instrukcji ARM Instruction Set. Narzędzia IAR również są z nią zgodne, co znacznie ułatwia przenoszenie projektów. Aby włączyć tryb zgodności wystarczy do pliku z kodem źródłowym dodać linię:

Zapewnia to, że instrukcje i rejestry użyte w pliku będą spójne z każdym innym zestawem narzędzi zgodnym z ARM Instruction Set.

W poniższej tabeli zestawione są najważniejsze różnice w składni asemblera między dwoma omawianymi zestawami narzędziowymi. Trzeba zaznaczyć, że dyrektyw jest zbyt wiele, by wszystkie je tu wymienić. W większości przypadków istnieje dokładny odpowiednik, ale trzeba to weryfikować korzystając z podręcznika użytkownika.

 

Tab. 16. Różnice w składni asemblera

Obszar GNU IAR
Nazewnictwo dyrektyw <nazwa> <NAZWA>
Komentarze wielowierszowe /* … */ /* … */
Komentarze jednowierszowe # lub @ // lub ;
Zakończenie wyrażenia ; lub nowa linia tylko nowa linia
Stałe binarne 0bnnn lub 0Bnnn b’nnn lub nnnb
Stałe ósemkowe 0nnn q’nnn lub nnnq
Stałe dziesiętne Nnn nnn lub d’nnn
Stałe szesnastkowe 0xnnn lub 0Xnnn 0nnnh lub 0xnnn lub h’nnn

 

Kod startowy

Przy starcie systemu – także po resecie – wykonany powinien zostać kod startowy (startup code), inicjalizujący system wspomagania przetwarzania (runtime system). W proces ten wliczają się: inicjalizacja stosu, sterty i sekcji danych oraz wykonanie konstruktorów globalnych w aplikacjach C++. Funkcja ta jest automatycznie obsługiwana przez środowisko wspomagania języka C dostarczane z każdym zestawem narzędziowym.

  • Tablica wektorów przerwań powinna być ustawiona tak, by połączyć reset, wyjątki i wpisy tablicy przerwań z odpowiednimi funkcjami obsługującymi.
  • Przeprowadzone powinny zostać także inne inicjalizacje, specyficzne dla mikrokontrolera (np. inicjalizacja systemu zegarowego i pamięci).

W większości systemów modyfikacji wymaga tylko kod specyficzny dla sprzętu, istnieje zwykle funkcja wywoływana jako część kodu startowego, przed funkcją main, którą można wykorzystać do ustawienia zegarów, pętli PLL i kontrolerów pamięci.

Funkcja specyficzna dla sprzętu (w przypadku GCC i mikrokontrolerów z rdzeniem ARM nazwana SystemInit) jest napisana w C i dostarczana w postaci kodu źródłowego, który można modyfikować według potrzeb.

Częścią kodu startowego są także tablica wektorów przerwań i funkcje obsługujące przerwania. W narzędziach GNU, tablica wektorów jest rozpowszechniana z odnośnikami do domyślnych funkcji obsługujących, które są wykorzystywane o ile użytkownik nie włączy funkcji o takiej samej nazwie do swojego kodu źródłowego. Rozwiązanie to wykorzystuje symbole słabe.

Symbol słaby (oraz dana lub funkcja z nim skojarzona) zostaną włączone do wynikowego pliku wykonywalnego, o ile inny (nie-słaby) symbol o takiej samej nazwie nie zostanie włączony przy konsolidacji. Mechanizm ten pozwala na zdefiniowanie domyślnego zachowania w kodzie niskopoziomowym oraz na wprowadzenie kodu nadpisującego je w wysokopoziomowych plikach użytkownika.

Poniższa tabela zestawia funkcje i symbole używane w narzędziach IAR EmbeddedWorkbench oraz GNU w kodzie startowym.

 

Tab. 17. Funkcje i symbole w kodzie startowym

Własność GNU IAR
Plik startowy startup_xxx_c1.s (np. startup_stm32f10x_c1.s) cstartup_M.s
Punkt startowy ResetHandler __iar_program_start
Inicjalizacja sprzętu SystemInit __low_level_init
Funkcje obsługi przerwań xxHandler (np. USART2_IRQHandler) xxHandler
Domyślna funkcja obsługi IRQ Default_Handler Nieskończona pętla dla każdej xxHandler
Szczyt stosu _estack sfe(CSTACK)
Dół sterty _end sfb(HEAP)
Początek BSS _sbss
Koniec BSS _ebss
Początek wartości inicjalizacyjnych dla danych _sidata
Początek danych _sdata
Koniec danych _edata

 

O autorze