Strona główna Artykuły ARM ARM toolchain - tutorial
ARM toolchain - tutorial
Ocena użytkowników: / 299
SłabyŚwietny 
Wpisany przez Freddie Chopin   
Niedziela, 17 Maj 2009 16:36
Spis treści
ARM toolchain - tutorial
ARM toolchain
Debugger
Edytor (IDE)
Eclipse + OpenOCD + GDB
Epilog
Wszystkie strony

Eclipse + OpenOCD + GDB

Do sprzęgnięcia wszystkich elementów w jedną całość brakuje jeszcze dwóch pluginów do Eclipse. Pluginy owe - jak i wszelkie uaktualnienia samego pakietu - można pobrać poprzez menu Help > Software updates.

Pierwsza wtyczka - Eclipse C/C++ GDB Hardware Debugging - należy do palety dodatków "firmowych", więc jedyne co należy zrobić, to w zakładce Available Software z dostępnego drzewa wybrać http://download.eclipse.org/tools/cdt/releases/ganymede > CDT Optional Features > Eclipse C/C++ GDB Hardware Debugging i kliknąć Install. Proces instalacji wtyczki może trochę potrwać - zależnie od aktualnego obciążenia serwerów i łącza.

Drugi z potrzebnych komponentów - Zylin Embedded CDT - wymaga kilku kliknięć więcej. Ponieważ wtyczka ta nie jest częścią standardowo dostępnej palety, należy dodać stronę macierzystą wtyczki do dostępnych źródeł aktualizacji. Aby tego dokonać, w zakładce Available Software należy wybrać opcję Add Site... i wprowadzić adres http://opensource.zylin.com/zylincdt . Po kliknięciu OK z drzewa będzie można wybrać http://opensource.zylin.com/zylincdt > Uncategorized > Zylin Embedded CDT. Po kliknięci w Install wtyczka zostania pobrana i zainstalowana.

W tym momencie warto dla pewności zresetować Eclipse, aby być pewnym, że zainstalowane właśnie wtyczki zostaną poprawnie uruchomione.

Do celów debuggowania aplikacji w Eclipse przewidziany jest inny układ okien. Predefiniowane układy okien w Eclipse zwane są Perspectives. Kod tworzony jest w C/C++ Perspective, natomiast debuggowanie możliwe jest w Debug Perspective. Otworzenie nowego układu możliwe jest przez menu Window > Open Perspective > Other... . Układy które już zostały otwarte można zmieniać w prawym górnym rogu okna Eclipse oraz w menu Window > Open Perspective.

Do Debug Perspective warto dodać zakładkę deassemblacji - menu Window > Show View > Disassembly. Zakładkę tą można umieścić według uznania w dowolnej z ramek Debug Perspective.

Pierwszym krokiem w sprzęgnięciu Eclipse ze sprzętem jest uruchomienie za jego pośrednictwem OpenOCD. Opcje umożliwiające uruchamianie dowolnych zewnętrznych aplikacji poprzez Eclipse znaleźć można w menu Run > External Tools. Ikonka tej grupy dostępna jest również standardowo na pasku narzędziowym. W celu uruchomienia OpenOCD wybieramy więc Run > External Tools > External Tools Configurations... i ikonką New launch configuration (po lewej na pasku narzędzi nad pustą obecnie listą) (lub opcja New z menu kontekstowego listy) tworzymy nowy element. W zakładce Main wprowadzić należy ścieżkę dostępu do OpenOCD - dla wersji 0.1.0 będzie to C:\Program Files\OpenOCD\0.1.0\bin\openocd.exe - oraz argumenty z którymi wywołany zostanie program, które zależne są od konfiguracji sprzętowej. W moim przypadku (JTAG-lock-pick + makieta z LPC2103) argumenty mają postać -f interface/jtagkey.cfg -f target/lpc2103.cfg . Wprowadzoną konfigurację warto nazwać w sposób jednoznaczny w polu Name na górze okna - niech będzie to na przykład "OpenOCD + jtagkey + lpc2103". Tak przygotowaną konfigurację można zatwierdzić przyciskiem Apply, a następnie uruchomić przyciskiem Run. Raz uruchomiona konfiguracja będzie później dostępna w sposób szybszy, a mianowicie bezpośrednio poprzez menu Run > External Tools (lub pod ikoną na pasku narzędzi).

Uruchomione OpenOCD pojawi się w zakładce Debug, a komunikaty OpenOCD powędrują do zakładki Console związanej z tym elementem.

Finalny krok na drodze do ujarzmienia debuggowania w Eclipse to wprowadzenie parametrów dla GDB. Opcje powiązane z debuggerem dostępne są w menu Run > Debug Configurations... . Dostęp do tej grupy opcji możliwy jest też poprzez przycisk Debug, który standardowo znajduje się na pasku narzędzi.

W oknie Debug Configurations wśród dostępnych na liście elementów powinna się znaleźć opcja GDB Hardware Debugging - po jej dwukrotnym kliknięciu stworzona zostanie nowa konfiguracja powiązana z tym typem debuggowania.

Konfiguracje powiązane są z projektami, więc pierwszą czynnością musi być przypisanie jednego z otwartych projektów do tej konfiguracji - można to zrobić bezpośrednio - wpisując nazwę projektu do pola Project - lub wybierając projekt z listy aktualnie otwartych przyciskiem Browse... . Po wybraniu projektu konieczne jest wybranie pliku wykonywalnego, który będzie debuggowany. Ponownie - względną ścieżkę do pliku można podać bezpośrednio w polu C/C++ Aplication, lub wybrać jeden z dostępnych dla danego projektu plików poprzez przycisk Search Project... .

W następnej zakładce - Debugger - znajdują się ustawienia samego GDB. W zakładce tej należy przede wszystkim wprowadzić ścieżkę do samego pliku wykonywalnego GDB - w przypadku standardowej instalacji pakietu CodeSourcery będzie to C:\Program Files\CodeSourcery\Sourcery G++ Lite\bin\arm-none-eabi-gdb.exe . Drugim parametrem który należy zmienić w tej zakładce jest numer portu za pomocą którego GDB będzie komunikował się ze sprzętem - w przypadku OpenOCD standardowo jest to port o numerze 3333.

Ostatnią porcję zmian należy wprowadzić w zakładce Startup, która odpowiada za - zgodnie z nazwą zresztą - zachowanie GDB po podłączeniu do sprzętu. Pierwszą ramką która powinna budzić szczególne zainteresowanie jest ramka Initialization Commands. Opcje Reset and Delay oraz Halt najlepiej zostawić w spokoju - nie działają one prawidłowo z toolchainami dla ARMów. W dużym oknie tekstowym możemy wprowadzać różne komendy które zostaną wykonane po uruchomieniu GDB. Najciekawszą opcję jest możliwość wydawania komend bezpośrednio dla OpenOCD - uzyskać to można poprzez poprzedzenie komendy słówkiem monitor (lub w skrócie mon). Zestaw komend jaki należy wydać jest ściśle zależny od używanego układu docelowego oraz od efektu jaki chce się osiągnąć. Zasadniczo po uruchomieniu GDB resetuje się układ docelowy (a więc monitor reset) i zatrzymuje rdzeń (poprzez - na przykład - monitor halt lub monitor soft_reset_halt w przypadku np. LPC2000). Jeśli w kodzie zaszły jakieś zmiany konieczne jest załadowanie do pamięci układu nowego obrazu. Kusi aby użyć do tego celu opcji z ramki Load Image and Symbols, niemniej jednak i te opcje niezbyt dobrze współpracują z ARMami. Do załadowania obrazu można więc wykorzystać bezpośrednio komendę GDB - load - którą wpisać należy do pola w ramce Initialization Commands. Przedostatnia ramka - Runtime Options - pozwala na ustawienie "jednorazowego" breakpointa w dowolnym miejscu i odpalenie programu po tych wszystkich operacjach. Warto więc podejść do sprawy standardowo - zatrzymać program na początku funkcji main, gdyż zwykle nie ma potrzeby debuggowania assemblerowych startupów. W tym celu wystarczy zaznaczyć opcję Set breakpoint at i w pole tekstowe wpisać main oraz zaznaczyć opcję Resume.

W tym momencie warto może napisać parę słów na temat Initialization Commands. Ponieważ toolchain dla ARMów nie obsługuje opcji resetowania przez GDB, warto stworzyć sobie dwa "zestawy" konfiguracji debuggowania - jedna konfiguracja umożliwiać będzie załadowanie do procesora nowego obrazu programu, a druga wykorzystywać będzie obraz znajdujący się już w pamięci układu. Różnić będą się tylko obecnością komendy load.

Przykładowe komendy inicjalizujące dla LPC2103 i ładujące program do pamięci RAM:

monitor reset
monitor soft_reset_halt
monitor mww 0xE01FC040 0x0002
load

Zauważyć można dodatkową komendę mww 0xE01FC040 0x0002, która powoduje zapis (Memory Write Word) wartości 0x0002 pod adres 0xE01FC040, który - w ARM7 - odpowiada rejestrowi MEMMAP - wartość ta w tym rejestrze oznacza zmapowanie początku pamięci RAM w obszar wektorów przerwań, co odpowiada sytuacji gdy cały załadowany program znajduje się w pamięci RAM.

W tym momencie gotową konfigurację warto jakoś ładnie nazwać (na przykład LPC2103 + load) przy pomocy pola na górze okna i zatwierdzić całość przyciskiem Apply. Jeśli w tle wciąż uruchomione jest OpenOCD można od razu nacisnąć przycisk Debug i przejść do debuggowania programu! Po pierwszym uruchomieniu danej konfiguracji będzie ona dostępna w wygodniejszy sposób, a mianowicie bezpośrednio w menu Run > Debug History lub pod przyciskiem Debug na pasku narzędzi.

Jeśli wszystko się udało, po krótkiej chwili w zakładce Debug poniżej uruchomionego OpenOCD powinien pojawić się proces o ustalonej przez nas nazwie odpowiedzialny za GDB Hardware Debugging, a w nim zatrzymany pojedynczy wątek Thread [0]. Sukces!

Warto w tym momencie wspomnieć o kwestii konsol dla uruchomionych aplikacji. Wprawne oko podczas uruchamiania GDB zauważy kilkanaście linijek przewijających się przez zakładkę Console i znikających po pełnym uruchomieniu. Otóż każda z uruchomionych w tle aplikacji ma swój własny zestaw zakładek i danych, a więc i konsol. Jeśli w zakładce Debug klikniemy na proces OpenOCD (dokładniej - na element C:\Program Files\OpenOCD\0.1.0\bin\openocd.exe) to w zakładce Console pojawi się aktualna zawartość konsoli przyporządkowanej dla tego właśnie procesu. Konsola ta zaraz po odpaleniu GDB powinna zawierać mniej więcej taki tekst:

Open On-Chip Debugger 0.1.0 (2009-01-21-21:15) Release

BUGS? Read http://svn.berlios.de/svnroot/repos/openocd/trunk/BUGS

$URL: https:// Adres poczty elektronicznej jest chroniony przed robotami spamującymi. W przeglądarce musi być włączona obsługa JavaScript, żeby go zobaczyć. /svnroot/repos/openocd/tags/openocd-0.1.0/src
/openocd.c $
1000 kHz
Info : JTAG tap: lpc2103.cpu tap/device found: 0x4f1f0f0f (Manufacturer: 0x787,
Part: 0xf1f0, Version: 0x4)
Info : JTAG Tap/device matched
Warn : no telnet port specified, using default port 4444
Warn : no gdb port specified, using default port 3333
Warn : no tcl port specified, using default port 6666
Info : accepting 'gdb' connection from 0
Error: timed out while waiting for target halted
Warn : acknowledgment received, but no packet pending
Warn : target not halted
Info : JTAG tap: lpc2103.cpu tap/device found: 0x4f1f0f0f (Manufacturer: 0x787,
Part: 0xf1f0, Version: 0x4)
Info : JTAG Tap/device matched
requesting target halt and executing a soft reset
target state: halted
target halted in ARM state due to debug-request, current mode: Supervisor
cpsr: 0x000000d3 pc: 0x00000000
Warn : memory write caused data abort (address: 0xe01fc040, size: 0x4, count: 0x1)
Runtime error, file "command.c", line 456:

Natomiast jeśli w zakładce Debug wybrany zostanie element odpowiadający procesowi GDB (czyli C:\Program Files\CodeSourcery\Sourcery G++ Lite\bin\arm-none-eabi-gdb.exe) naszym oczom ukaże się konsola samego GDB, której zawartość powinna wyglądać mniej więcej tak:

target remote localhost:3333
0x00000000 in ?? ()
monitor soft_reset_halt
load

Loading section .text, size 0x1adc lma 0x40000000
Start address 0x40000000, load size 6876
Transfer rate: 13 KB/sec, 6876 bytes/write.
tbreak main
Temporary breakpoint 1 at 0x400001a0: file src/main.c, line 258.
continue

Temporary breakpoint 1, main () at src/main.c:258
258 volatile unsigned int x,max=100000;

Warto zauważyć, że w zakładce Disassembly widać aktualną instrukcję C a pod nią odpowiadający jej zestaw instrukcji assemblerowych. W zakładce Variables zauważyć można wszystkie zmienne lokalne danej funkcji. Aby dodać zmienne globalne wystarczy kliknąć w obszar tej zakładki prawym przyciskiem myszy i skorzystać z opcji Add Global Variables... . W zakładce Registers po rozwinięciu elementu Main można natomiast podziwiać rejestry rdzenia.



Zmieniony: Piątek, 12 Czerwiec 2009 11:31