Atmel AT91SAM7S i Open Source
AT91SAM7S?
Atmel AT91SAM7S jest mikrokontrolerem firmy Atmel z obsługą dużej ilości zabawek, m.in. USB. Poniżej opiszę, jak udało mi się zaprogramować go poprzez interface JTAG (konkretnie Wiggler) za pomocą jedynie opensource'owych narzędzi.
Kompilator
Jeśli kompilator i otwarte źródła, to oczywiście GCC. Tutaj nie było problemu, ze strony gnuarm.com można pobrać stosowny toolchain dla Linuxa, Windowsa i MacOS. Instalacja jest bezproblemowa, należy sobie jedynie dodać do PATH ścieżkę dostępu do katalogu GNUARM/bin. Podczas kompilacji, należy do GCC podać argument określający architekturę: -mcpu=arm7tdmi
oraz tryb THUMB: -mthumb
. Samo GCC, podobnie jak pozostałe narzędzia, powinny być wywoływane z prefiksem arm-elf
, czyli np.:
arm-elf-gcc.exe -mcpu=arm7tdmi -mthumb -O2 -c testproj\test.c -o testproj\test.o
arm-elf-gcc.exe -mcpu=arm7tdmi -mthumb -o testproj\test testproj\test.o -lc
Po zlinkowaniu plików .o
przez GCC powstaje plik typu ELF
. Do zaprogramowania urządzenia potrzeba pliku w formacie Intel HEX lub czystych danych binarnych (dalej będę używał postaci binarnej, ponieważ tylko taka jest w pełni obsługiwana przez dostępne programy). Konwersji dokonuje się narzędziem objcopy
. Wywołuje się je następująco:
arm-elf-objcopy -O binary plikwejściowy plikwyjściowy
Opcjonalnie można również podać parametr -I, który określa format pliku wejściowego. Domyślnie jest to właśnie ELF. arm-elf-objcopy obsługuje następujące typy plików:
- elf32-littlearm
- elf32-bigarm
- elf32-little
- elf32-big
- srec
- symbolsrec
- tekhex
- binary
- ihex
Narzędziem bez którego można się co prawda obyć, ale w które warto się zaopatrzyć, jest make.
Biblioteki
Atmel dostarcza zestaw dobrych bibliotek, jednak niestety dostępne są one tylko dla komercyjnego kompilatora IAR. Na szczęście, wszystkie one zostały przeportowane także dla GCC, można je (wraz z ciekawymi przykładami) ściągnąć ze strony Martina Thomasa. Można tam też znaleźć różne warianty kodu startowego, który nie jest dostarczany z GNUARM.
W środowisku przygotowanym tak, jak to opisałem powyżej, dla przykładów z w/w strony wystarcza wykonanie make
w katalogu, w którym znajduje się plik Makefile
. Aby otrzymać plik binarny zdatny do procesu programowania, konieczna jest edycja Makefile'a:
# Output format. (can be srec, ihex, binary) FORMAT = binary
Programowanie
Po skompilowaniu wielu programów w jeszcze większej ilości wariantów, GFY podpowiedział, że z ARMami7 radzi sobie OpenOCD. Dla Windowsa jest do pobrania wersja instalacyjna, dla Linuxa jest to nieco bardziej skomplikowane. Proces budowy programu opisano w wiki projektu, dla kompletności zamieszczę poniżej:
mkdir openocd cd openocd svn checkout http://svn.berlios.de/svnroot/repos/openocd/trunk cd cd trunk ./bootstrap ./configure --enable-parport --enable-parport_ppdev makePonieważ po skonfigurowaniu programu w ten sposób nie mogłem połączyć się z JTAGiem, konieczna była edycja pliku config.h:
#define PARPORT_USE_PPDEV 0
Oryginalnie była tam wartość 1. Prawdopodobnie podobny efekt dałoby usunięcie parametru
--enable-parport_ppdev
z ./configure
.
Następnie, należy przygotować odpowiedni plik konfiguracyjny, przykłady są zamieszczone w katalogu doc/configs. Mój wygląda następująco:
#daemon configuration telnet_port 4444 gdb_port 3333 #interface interface parport parport_port 0x378 parport_cable wiggler jtag_speed 0 #use combined on interfaces or targets that can't set TRST/SRST separately reset_config trst_and_srst srst_pulls_trst #jtag scan chain #format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE) jtag_device 4 0x1 0xf 0xe #target configuration daemon_startup reset #target <type> <startup mode> #target arm7tdmi <reset mode> <chainpos> <endianness> <variant> target arm7tdmi little run_and_halt 0 arm7tdmi-s_r4 target_script 0 reset h2294_init.script run_and_halt_time 0 30 working_area 0 0x40000000 0x40000 nobackup #flash configuration flash bank lpc2000 0x0 0x40000 0 0 lpc2000_v1 0 14765 calc_checksum flash bank cfi 0x80000000 0x400000 2 2 0
Program uruchomiłem następująco:
cd src
Parametr -d 3 można pominąć, służy do wyświetlania większej ilości informacji. Jeśli wystąpił błąd, program wyjdzie do linii poleceń, jeśli uda mu się połączyć z kontrolerem - przestanie wyświetlać w konsoli wiadomości i zacznie nasłuchiwać na portach 4444 oraz 3333. Ponieważ nie interesuje nas w tej chwili debugowanie, a zwykłe zaprogramowanie flasha, łączymy się jakimś klientem telneta (polecam Putty) pod port 4444 komputera na którym jest uruchomiony OpenOCD. W przypadku kiedy program jest uruchomiony na komputerze lokalnym, jego adresem będzie 127.0.0.1 . Po połączeniu powinien pojawić się prompt:
./openocd -f config.cfg -d 3
Open On-Chip Debugger
>
Wpisując help
, można otrzymać listę poleceń (dokładniejsza dokumentacja znajduje się na wiki OpenOCD). Najpierw można sprawdzić, czy połączenie na pewno działa (polecenie flash info 0
). Powinna się pojawić informacja na temat pamięci flash dostępnej w układzie:
#1: at91sam7 at 0x00100000, size 0x00040000, buswidth 4, chipwidth 0 at91sam7 information: Chip is AT91SAM7S256 cidr: 0x270d0940, arch: 0x0070, eproc: ARM7TDMI, version:0x000, flashsize: 0x00040000 master clock(estimated): 32kHz pagesize: 256, lockbits: 16 0x0000, pages in lock region: 64 securitybit: 0, nvmbits: 0x0Właściwe flashowanie odbywa się za pomocą komendy:
flash write 0 plik.bin 0