Kategorie | Linux

  

Programowanie mikrokontrolerów AVR w Linuksie

Opublikowano 24 maja 2011 przez Franek

Autorem wpisu jest Bartosz C., ten wpis bierze udział w konkursiepozostałe prace konkursowe.

Witam, tutorial ten to wprowadzenie w świat programowanie mikrokontrolerów (uC) AVR (chociaż za prezentowane tu wskazówki będą przydatne przy obsłudze innym rodzin uC) za pomocą języka c w Linuksie. Zakładam że czytelnik miał styczność z programowaniem za pomocą WinAVR pod Windowsem, chociaż nie jest to wymóg konieczny. Programowanie w assemblerze jest oczywiście także możliwe (kod z c jest zamieniany najpierw właśnie na asm, potem dopiero na binarny i wgrywany do układu), natomiast w Bascomie nie, nawet za użyciem Wine. Wykorzystywany będzie programator działający z interfejsem USB, czyli np. USBasp lub STK500 lub kompatybilny. Prezentowane tu polecenia były sprawdzane na ArchLinuksie, chociaż powinny działać na dowolnej dystrybucji.

 

NibyBlog.pl polceca Mikrokontrolery.BlogSpot.com

Obsługa programatora

Zaczniemy od prawidłowego podłączenia programatora. W linuksie wszystko jest plikiem tak więc nasz programator będzie takoż widoczny, a co dla nas ważne będzie miał takie same prawa dostępu jak reszta plików. Dlatego, aby czytać dane z uC musimy mieć prawo do odczytu, a jeżeli chcemy programować to także do zapisu. Przeważnie system prawidłowo nada prawa automatycznie, ale my zrobimy to w sposób bardziej pewny i pro :). Użyjemy do tego udev. Podłączamy nasz programator i wydajemy komendę:
lsusb
..
Bus 002 Device 003: ID 16c0:05df VOTI

dzięki temu znajdujemy nasze urządzenie i ścieżkę niego. W moim przypadku oznacza to plik: /dev/bus/usb/002/003.
Następne polecenie (oczywiście zmieniamy ścieżkę do pliku na tą przydzieloną przez system):
udevadm info -a -p $(udevadm info -q path -n /dev/bus/usb/002/003)
Powinna pojawić się długa lista z parametrami, numery seryjne, nazwa producenta itd dla naszego programatora. Teraz stworzymy plik z odpowiednią regułę udev.
sudo nano /etc/udev/rules.d/81-avr-programator.rules
i kopiujemy poniższy tekst, oczywiście zmieniając odpowiednie parametry na te uzyskane z polecenia udevadm:
ATTRS{idVendor}=="16c0", ATTRS{idProduct}=="05df", ATTRS{serial}=="0000:00:1d.0", MODE="0660", GROUP="users"
Od teraz (po restarcie) niezależnie do którego portu USB podłączymy nasz programator będzie on miał takie same prawa (660) i grupę (users), w tym przypadku użytkownik na którego jesteśmy zalogowani musi być w grupie “users”. Możemy oczywiście nadawać inne prawa np. 666, wtedy możemy pominąć grupę, ale odbywa się to kosztem bezpieczeństwa (nasz przypadek jest akurat bez sensu, ale zaznaczam sprawę jakbyśmy chcieli podłączyć inne urządzenie np. drukarkę sieciową tą metodą). Dzięki udev możemy zrobić sporo ciekawych rzeczy dzięk np.i uruchamianiu dowolnego skryptu gdy zostanie odnalezione dane urządzenie. Taki skrypt może przeprowadzić pewną akcję konfiguracyjną lub np. uruchomić powiadomienie o podłączeniu sprzętu. Więcej o udev pod tym linkiem.
Dla pewności sprawdzamy jeszcze ustawiania:
ls -l /dev/bus/usb/002/004
crw-rw---- 1 root users 189, 131 05-11 23:36 /dev/bus/usb/002/003

Teraz potrzebujemy narzędzia avrdude, powinieneś je znaleźć w domyślnym repozytorium swojej dystrybucji. Zapewne korzystałeś z niego pod Windowsem, składnia tutaj jest identyczna. Musisz wiec znać rodzaj swojego mikrokontrolera, rodzaj programatora i port do którego jest podłączony. Przykładowo dla popularnych stk500v2 lub urządzeń kompatybilnych parametry te to: stk500v2 i avrdoper, rodzaj uC zależy od tego jaki układ programujesz, a jest ich sporo. Przykładowo odczytamy fusebity by sprawdzić poprawność działania.
avrdude -p atmega162 -P avrdoper -c stk500v2 -U lfuse:r:-:h
Używany mikrokontroler to atmega162 i programator stk500v2. Jeżeli korzystasz z innego programatora potrzebne dane znajdziesz w instrukcji, na stronie www lub będziesz musiał popytać na forach poświęconych tej tematyce. Wszelkie możliwe wartości do wpisania są opisane w manualu avrdude, wyświetlisz go oczywiście poleceniem:
man avrdu

Zaczynamy programować
Potrzebujemy teraz środowiska programistycznego oraz kompilatora c. W Windowsie wszystko to zapewniał pakiet WinAVR, w Linuksie te same narzędzia są dostępne oddzielnie, ale działają bez problemu. Musimy zainstalować pakiety:

  • gcc-avr – zestaw kompilatorów przystosowanych do mikrokontrolerów AVR
  • avr-libc – biblioteka c przystosowana do mikrokontrolerów AVR
  • binutils-avr – narzędzia do operowania formatami plików, potrzebne do stworzenia plików hex
  • automake – obsługa plików makefile
  • geany – środowisko programistyczne, możemy używać dowolnego (np. Eclipse), ale osobiście polecam Geany i na nim będzie się koncentrowała reszta tutoriala
  • avr8-burn-o-mat – gui dla avrdude
  • gtkterm – konsola portu szeregowego

Stwórzmy zwykły plik tekstowy w dowolnym edytorze z odpowiednikiem ‘hello world’ dla mikrokontrolerów, czyli migającą diodą.

#include
#include
int main(void) {
DDRB  |= 1<<0;
while (1) {
PORTB ^= 1<<0;
_delay_ms(1000);
}
}

Uwaga! W Linuksie(Uniksach) w ścieżce do pliku stosuje się znak prawego ukośnika (“/”), natomiast w Windowsie lewego (“\”).
Jeżeli stosowałeś ten znak do includowania plików będziesz musiał zamienić go na ten właściwy dla jedynego słusznego systemu :). Ponadto format “avr/io.h” działa także pod Windowsem (przynajmniej w kompilatorze AVR-GCC z pakietu WinAVR) i innych systemach więc lepiej go stosować nawet jeżeli programujesz tylko na Windowsie i masz zamiar publikować kod.

Aby skompilować kod do pliku relokowalnego (*.o) wydajemy polecenie:
avr-gcc -mmcu=atmega162 -Os -DF_CPU=8000000UL -Wall tescik.c -o tescik.o
Używane opcje to:

  • -mmcu=atmega162 – rodzaj mikrokontrolera
  • -Os – rodzaj optymalizacji (zasadniczo nie zmieniamy)
  • -DF_CPU=8000000UL – taktowanie naszego uC, niektóre funkcje np nasza. _delay_ms zależą od tej wartości
  • -Wall – wyświetli więcej komunikatów
  • tescik.c -o tescik.o – plik wejściowy i wyjściowy

Następnie z takiego pliku trzeba wytworzyć plik hex w formacie IntelHex:
avr-objcopy -O ihex tescik.o tescik.hex
Nie pozostaje nam nic innego jak wgrać taki plik do naszego układu (pamięci flash):
avrdude -p atmega162 -P avrdoper -c stk500v2 -U flash:w:tescik.hex
Voila, jeżeli mamy prawidłowo zmontowany układ dioda powinna się włączać i wyłączać co 1 sekundę.

Makefile
Postaramy się teraz zautomatyzować proces kompilowania i wgrywania wsadu, pozwoli nam na to plik makefile. Jest to nic innego jak skrypt wykonywany przez program ‘make’ który uwalnia nas od ręcznego wpisywania komend. Skrypty te możemy napisać sami (jest dostępnych wiele kursów), ale lepiej skorzystać z gotowego szablonu dostępnego np. wraz z WinAVR dla Windowsa, zobaczysz że będzie działał on idealnie także pod Linuksem. Szablon dostępny jest tutaj.

Plik jest obszerny, ale na początku wystarczy zapoznanie się z poniższymi zmiennymi, są one dobrze skomentowane.
MCU = atmega162
F_CPU = 8000000
TARGET = helloworld
SRC = main.c
OPT = s
DEBUG = dwarf-2
AVRDUDE_PROGRAMMER = stk500v2
AVRDUDE_PORT = avrdoper

Większość z nich stosowaliśmy już wcześniej i bez problemu powinieneś je móc zmienić tak by wszystko działo z Twoim programatorem i układem.Z nowych wartości warto poznać:.TARGET to nazwa naszego ostatecznego pliku hex, czyli tutaj helloworld.hex, SRC to nazwa naszego pliku z kodem źródłowym, jeżeli mamy rozbity program na wiele plików musimy wszystkie je włączyć do tej zmiennej.

Zapisz plik pod nazwą ‘makefile’ lub ‘Makefile’ inne nazwy są niepoprawne. W skrypcie tym są zadeklarowane 3 podstawowe funkcje:

  • all – kompiluje wszystkie pliki (jeżeli zostały zmienione od poprzedniej kompilacji)
  • program – to samo co ‘all’, ale poza tym automatycznie wgrywa wsad do uC
  • clean – czyści folder z niepotrzebnych plików powstałych podczas kompilacji (pliki relokowalne, do debbugera etc.)
  • Aby wywołać którąś z tych funkcji wydajemy w terminalu:
  • avr-gdb – debugger dla AVR
  • avarice – debugowanie AVR za pomocą JTAGv
  • avra – asembler dla AVRv
  • tavrasm – kolejny asemblerv
  • kontrollerlab – środowisko programistyczne przystosowane dla AVR, niestety zdaje się że od 4 lat projekt jest nie rozwijanyv
  • simulavr – symulator AVR
  • arduino – temat rzeka, polecam notkę na wiki lub oficjalną stronę. Być może się zastanawiasz po co ten tekst skoro jest arduino, odpowiedź: cena, marnotrastwo cennych elementów (stosowanie całego zestawu ewaluacyjnego wraz z programatorem nawet do prostych projektów) i chęć dokładniejszego zrozumienia działania programów/układów.
  • avr-gdb – debugger dla AVR
  • avarice – debugowanie AVR za pomocą JTAGv
  • avra – asembler dla AVRv
  • tavrasm – kolejny asemblerv
  • kontrollerlab – środowisko programistyczne przystosowane dla AVR, niestety zdaje się że od 4 lat projekt jest nie rozwijanyv
  • simulavr – symulator AVR
  • arduino – temat rzeka, polecam notkę na wiki lub oficjalną stronę. Być może się zastanawiasz po co ten tekst skoro jest arduino, odpowiedź: cena, marnotrastwo cennych elementów (stosowanie całego zestawu ewaluacyjnego wraz z programatorem nawet do prostych projektów) i chęć dokładniejszego zrozumienia działania programów/układów.

make all
make program
make clean

Jak widzisz proces ten jest bardzo prosty i szybki. Polecam tworzyć każdy projekt w osobnym folderze i umieszczać w nim osobne pliki makefile. W przyszłości zapewne nauczysz się wykorzystywać bardziej zaawansowane możliwości tych plików jak np. uaktywnianie obsługi liczb zmiennoprzecinkowych w funkcjach typu printf, które zabierają sporo zasobów (jak na uC oczywiście) i są domyślnie wyłączone, ale czasami jednak przydatne.

 

Środowisko pracy Geany
Geany to średnio skomplikowane i szybkie środowisko programistyczne, słowem idealne dla mikrokontrolerów. Otwórzmy jakiś plik z kodem w c dla AVR. Jeżeli w folderze mamy plik makefile to, aby go uruchomić wystarczy wcisnąć kombinację Shift+Ctrl+F9 i wpisać nazwę funkcji, którą chcemy wykonać (all, program, clean). Jeżeli próbowalibyśmy kompilować program dla uC tylko poprzez wciśniecie F8(skompiluj) lub F9(zbuduj) niechybnie otrzymamy masę błędów, gdyż domyślnie Geany będzie używał kompilatora GCC dla komputerów PC, a nie dla AVR. Stosowanie makefile likwiduje ten problem, ponadto komunikaty o błędach/ostrzeżeniach pozwalają nam szybko za pomocą dwukliku przenosić się do właściwego miejsca w celu poprawy kodu. Sami Geany możemy naprawdę porządnie spersonalizować do swoich potrzeb, na początek warto zmienić kolorowanie składni (ja używam stylu oblivion) i czcionkę na przyjazną dla programisty (polecam consolas, co prawda czcionka jest z Windowsa, ale możemy używać jej legalnie na Linuksie).

 

avr8-burn-o-mat – gui dla AVRdude
Avrdude to najlepszy program do obsługi programatora, ma jednak tę wadę że jest dostępny w wersji konsolowej. W wielu przypadkach programy CLI są zdecydowanie lepszym rozwiązaniem, ale nie tutaj. Na szczęscie jest dostępna graficzna nakładka pod nazwą AVR8 Burn-O-Mat. Program jest napisany w Javie więc musimy ją zainstalować. W niektórych dytrybucjach nakładka ta jest dostępna w repozytoriach (np. w AUR dla ArchLinuksa), jeżeli u nas jej brak to pobieramy archiwum zip ze strony projektu w którym znajdujemy plik ‘AVR8_Burn_O_Mat.jar’ resztę plików możemy skasować. Program uruchamiamy poprzez dwuklik lub polecenie:
java -jar AVR8_Burn_O_Mat.jar
Po załączeniu programu musimy ustawić uC, rodzaj programatora i portu (tak jak poprzednio w wersji konsolowej) oraz ścieżkę do binarki z avrdude i pliku konfiguracyjnego. Ścieżki te znajdziemy po wywołaniu komendy ‘whereis’:
whereis avrdude
avrdude: /usr/bin/avrdude /etc/avrdude.conf /usr/share/man/man1/avrdude.1.gz

Za pomocą avr8-burn-o-mat możemy bezproblemowo wgrywać pliki hex (np. te pobrane z internetu bez kodu źródkowego), odczytywać fusebity (są one nawe opisane dla każdego uC co niesamowicie ułatwia sprawę i minimalizuje pomyłki) oraz robić wiele innych rzeczy.

 

Gtkterm – obsługa portu szeregowego
Na zakończenie krótko o obsłudze portu szeregowego (RS232) pod linuksem. Jest wiele programów do tego celu, ale ja wybrałem gtkterm. Możemy w nim łatwo zmienić ustawienia transmisji, prędkości, zmienić rodzaj kontroli przepływu danych (wyłączona, handshaking RTS/CTS lub handshaking programowy) etc. Sporą zaletą jest definiowanie własnych profili ustawień w pliku konfiguracyjnym (~/.gtktermrc), wówczas możemy zdefiniować różne tryby pracy dla urządzeń pracujących na różnych ustawieniach/prędkościach i łatwo między nimi się przełączać wpisują w konsoli:
gtkterm nazwa_profilu
np.
gtkterm gsm
gtkterm gps

Jeżeli korzystamy z konwertera RS<>USB to nasze urządzenie powinno być widoczne pod plikiem /dev/ttyUSB0, dla połączenia bluetooth będzie to /dev/rfcomm0. Jeżeli okaże się że nie mamy uprawnień do odczytu/zapisu do tego pliku/urządzenia będziemy musieli stworzyć podobne regułki jak dla naszego programatora.

Pamiętajmy że w Linuksie znak nowego wiersza to jeden znak ASCII , w przeciwieństwie do Windowsa i innych systemów, gdzie nowy wiersz składa się z dwóch znaków . Przy odbieraniu danych wszystko powinno być ok, ale przy wysyłaniu warto sprawdzić jak dokładnie działa odbiornik.

Zakończenie
Tutorial ten to oczywiście wstęp do programowania mikrokontrolerów pod Linuksem. Zauważ że całkowicie pominąłem temat debugowania programów, oczywiście istnieje taka możliwość, ale to temat dla bardziej zaawansowanych. Zasygnalizuję tylko że program AVRStudio powinien działać pod WINE (kwestia problematyczna, niektórym działa innym nie) i przedstawię listę dodatkowych programów które mogą ci się przydać:

  • avr-gdb – debugger dla AVR
  • avarice – debugowanie AVR za pomocą JTAGv
  • avra – asembler dla AVRv
  • tavrasm – kolejny asemblerv
  • kontrollerlab – środowisko programistyczne przystosowane dla AVR, niestety zdaje się że od 4 lat projekt jest nie rozwijanyv
  • simulavr – symulator AVR
  • arduino – temat rzeka, polecam notkę na wiki lub oficjalną stronę. Być może się zastanawiasz po co ten tekst skoro jest arduino, odpowiedź: cena, marnotrastwo cennych elementów (stosowanie całego zestawu ewaluacyjnego wraz z programatorem nawet do prostych projektów) i chęć dokładniejszego zrozumienia działania programów/układów.
  

8 Comments For This Post

  1. Bartosz C. Says:

    drobny błąd w składzie. Lista dodatkowych programów co ma być na końcu jest tutaj przy sekcji z makefile. Prosze o poprawe.

  2. Franek Says:

    Źle mi się coś ctr+v zrobiło ;)

  3. Mateusz Says:

    Witam, chciałem się zacząć bawić AVR'ami. Czy taki zestaw jest dobry http://sklep.avt.pl/go/_info/reviews.php?id=48509http://sklep.avt.pl/p/pl/486706/uklad+scalony+atm
    ??
    Z góry dziękuję za odpowiedź

  4. Marek Serwisant Says:

    Jeden z lepszych artów na temat AVR-ów pod linuksem w Polskiej sieci. Czekam na podobny na temat Raspberry Pi :)

  5. Mariusz Says:

    Mam pod ręką Raspberry Pi (Raspbian) oraz dwa programatory:

    ID 16c0:05e1 VOTI CDC-ACM class devices (modems)
    ID 16c0:05dc VOTI shared ID for use with libusb

    Potrzebuję zaprogramować Atmega32 po ISP (za pomocą któregoś z programatorów powyżej).

    Ktoś podpowie tak to zrobić, krok po kroku? (zero doświadczeń z programowaniem za pomocą Comand Line Interface, sterownikami do programatorów itp. Prośba o pomoc.

    Zainstalowałem avrdude:

    root@raspberrypi:/home/pi# avrdude
    Usage: avrdude [options]
    Options:
    -p <partno> Required. Specify AVR device.
    -b <baudrate> Override RS-232 baud rate.
    -B <bitclock> Specify JTAG/STK500v2 bit clock period (us).
    -C <config-file> Specify location of configuration file.
    -c <programmer> Specify programmer type.
    -D Disable auto erase for flash memory
    -i <delay> ISP Clock Delay [in microseconds]
    -P <port> Specify connection port.
    -F Override invalid signature check.
    -e Perform a chip erase.
    -O Perform RC oscillator calibration (see AVR053).
    -U <memtype>:r|w|v:<filename>[:format]
    Memory operation specification.
    Multiple -U options are allowed, each request
    is performed in the order specified.
    -n Do not write anything to the device.
    -V Do not verify.
    -u Disable safemode, default when running from a script.
    -s Silent safemode operation, will not ask you if
    fuses should be changed back.
    -t Enter terminal mode.
    -E <exitspec>[,<exitspec>] List programmer exit specifications.
    -x <extended_param> Pass <extended_param> to programmer.
    -y Count # erase cycles in EEPROM.
    -Y <number> Initialize erase cycle # in EEPROM.
    -v Verbose output. -v -v for more.
    -q Quell progress output. -q -q for less.
    -? Display this usage.

    avrdude version 5.11.1, URL: &lt ;http://savannah.nongnu.org/projects/avrdude/&gt;
    root@raspberrypi:/home/pi#

    Dwa programatory wpięte i widziane przez system:

    root@raspberrypi:/home/pi# lsusb
    Bus 001 Device 018: ID 16c0:05dc VOTI shared ID for use with libusb
    Bus 001 Device 017: ID 16c0:05e1 VOTI CDC-ACM class devices (modems)
    root@raspberrypi:/home/pi#

    Co dalej?

  6. Piotr Says:

    Zatrzymałem się na
    sudo nano /etc/udev/rules.d/81-avr-programator.rules

    Wywala mi błąd
    sudo: nano: nie znaleziono polecenia

    Linux openSUSE.
    Pomożecie ?

  7. Sylwek Says:

    nie masz zainstalowanego programu nano.
    niestety nie wiem jak się instaluje oprogramowanie w openSUSE.

    na wszeli wypadek zrób jeszcze
    sudo touch /etc/udev/rules.d/81-avr-programator.rules

  8. Mateusz Says:

    Dzięki za artykuł, bardzo mi się przydał.
    Miałem tylko jeden problem – chodzi konkretnie o ATTRS{serial}, który przybierał różne wartości w zależności od portu usb. Po zdefiniowaniu na dwóch portach programator działał a na trzecim nie. Usunąłem ten parametr z pliku .rules i hula jak powinno. ;) – mam nadzieję, że brak tego nie wypływa to jakoś negatywnie na cokolwiek?

    I jeszcze jedno małe ot. Po dodaniu .rules nie trzeba restartować systemu. Wystarczy:
    sudo udevadm control –reload-rules

Leave a Reply

Polityka komentarzy

     
     
Green Dog Says

MiniBlog