• Nie Znaleziono Wyników

Jacek Augustyn, dr inż. Krzysztof Janik PROGRAMOWANIE MIKROKONTROLERÓW RODZINY AVR W JĘZYKU JAGASMSesja: Kształcenie w dziedzinie elektroniki i telekomunikacji.Akademia Górniczo - Hutnicza

N/A
N/A
Protected

Academic year: 2021

Share "Jacek Augustyn, dr inż. Krzysztof Janik PROGRAMOWANIE MIKROKONTROLERÓW RODZINY AVR W JĘZYKU JAGASMSesja: Kształcenie w dziedzinie elektroniki i telekomunikacji.Akademia Górniczo - Hutnicza"

Copied!
4
0
0

Pełen tekst

(1)www.pwt.et.put.poznan.pl. Jacek Augustyn Krzysztof Janik Akademia Górniczo-Hutnicza w Krakowie, Katedra Automatyki 30-059 Kraków, al. Mickiewicza 30, paw. B1 Jacek.Augustyn@agh.edu.pl Krzysztof.Janik@agh.edu.pl. 2005. Poznańskie Warsztaty Telekomunikacyjne Poznań 8 - 9 grudnia 2005. PROGRAMOWANIE MIKROKONTROLERÓW RODZINY AVR W JĘZYKU JAGASM W referacie przedstawiono język programowania JagAsm, będący makroasemblerem służącym do programowania procesorów rodziny AVR i stanowiącym efektywne narzędzie wspomagające nauczanie w ramach kursów o tematyce związanej z systemami starowania czasu rzeczywistego. Zaprezentowano podstawowe informacje dotyczące składni języka JagAsm oraz wskazano na jego zalety dydaktyczne w porównaniu z klasycznymi asemblerami mnemonicznymi.. 1. Wprowadzenie Nauczanie programowania w języku asembler jest jednym z ważnych aspektów kształcenia w zakresie studiów inżynierskich i magisterskich na kierunkach obejmujących zagadnienia automatyki przemysłowej i robotyki. Programowanie w asemblerze pozwala na szczegółowe poznanie faktycznych możliwości oferowanych przez dany procesor. Podczas zajęć laboratoryjnych studenci przyswajają zagadnienia związane z architekturą mikrokontrolera, a w szczególności liczbą i przeznaczeniem rejestrów, trybami adresowania, operacjami arytmetycznymi, sposobami obsługi błędów i zasadami funkcjonowania systemu przerwań. Równie istotne jest opanowanie metodologii programowania urządzeń peryferyjnych takich jak porty komunikacyjne, przetworniki analogowo-cyfrowe i układy czasowo-licznikowe. Znajomość języka asembler pomaga również w zrozumieniu wielu mechanizmów przyjętych w językach wysokiego poziomu (zwłaszcza w języku C/C++) takich jak: wykorzystywania wskaźników, tworzenia zmiennych automatycznych, obsługi stosu. Wiele publikacji z dziedziny informatyki postuluje opanowanie asemblera jako bardzo pomocną umiejętność przed przystąpieniem do pisania programów w języku C/C++. Ułatwia także tworzenie oprogramowania w taki sposób, aby lepiej wykorzystać możliwości procesora poprzez właściwą organizację struktur danych i lepszą optymalizację kodu wynikowego. Programowanie w języku asembler znajduje zastosowanie w aplikacjach, w których wymagania wobec szybkości działania programu i minimalizacji obszaru zajmowanej pamięci są szczególnie ostre. Dotyczy to szczególnie aplikacji dedykowanych dla systemów wbudowanych o znacznie ograniczonej pojemności pamięci, takich jak systemy sterowania automatycznego, gdzie dodatkowym wymaganiem jest gwarantowany czas reakcji na zdarzenie zewnętrzne.. PWT 2005 - POZNAŃ 8-9 GRUDNIA 2005. 2. Problemy podczas programowania z użyciem klasycznych asemblerów mnemonicznych Obok oczywistych korzyści wynikających ze stosowania języków niskopoziomowych należy zwrócić uwagę na szereg niedogodności występujących podczas tworzenia kodu w asemblerze. Kod źródłowy jest mało czytelny i zazwyczaj stosunkowo obszerny. Jest także znacznie trudniejszy do modyfikacji niż kod w językach wysokopoziomowych, a proces tworzenia kodu źródłowego jest czasochłonny, żmudny i podatny na błędy. Powszechnie stosowane asemblery mnemoniczne są dość trudne do praktycznego opanowania. W takich asemblerach rozkazy procesora przedstawiane są za pomocą tzw. mnemoników. Mnemonik jest 2-4 literowym skrótem pochodzącym od pełnej nazwy rozkazu. Jeśli procesor posiada bogatą listę rozkazów, duża liczba mnemoników utrudnia opanowanie języka asembler. Dla przykładowych procesorów ATMego rodziny AVR lista mnemoników obejmuje 114 pozycji [1,2,3]. Przykładowe mnemoniki z jednej tylko grupy rozkazów przesłań przedstawiono w poniższej tabeli. Tabela 1. Mnemoniki rozkazów przesłań w procesorach rodziny ATMega oraz ich rozwinięcie. Mnemonik. Rozwinięcie mnemonika. MOV MOVW LDI LDS STS LD ST LDD STD IN OUT LPM SPM ELPM ESPM PUSH POP. Move (copy) register Move (copy) register pair Load immediate Load direct from data space Store direct to data space Load indirect Store indirect Load indirect with displacement Store indirect with displacement In from IO location Out to IO location Load program memory Store program memory Extended load program memory Extended store program memory Push register on stack Pop register from stack. Inne grupach rozkazów także posiadają dużą liczbę mnemoników. Przykładowo, w grupie rozkazów operujących na bitach znajduje się 28 mnemoników, a rozkazy skoków posiadają 38 mnemoników. Studenci poświęcają stosunkowo dużo czasu na opanowanie listy rozkazów. Podobnie brzmiące. 1/4.

(2) www.pwt.et.put.poznan.pl. mnemoniki są przyczyną powstawania częstych pomyłek (np. LD/LDI/LDS). Może to prowadzić do znaczącego wydłużenia czasu tworzenia i uruchamiania programu. Drugim głównym problemem związanym z programowaniem w języku asembler jest wykorzystywanie instrukcji skoków i etykiet. Nawet podczas tworzenia niewielkich programów, programista jest zmuszony do używania obszernego zestawu etykiet, których nazwy muszą być unikalne. Ponadto bloki programu wykonywane warunkowo nie posiadają czytelnej prezentacji. Niedoświadczeni programiści łatwo mogą doprowadzić do powstania tzw. „spagetti code” – zagmatwanego układu skoków trudnego do interpretacji, śledzenia i poprawiania.. 3. Propozycje ulepszeń Znaczące przyspieszenie procesu kształcenia w zakresie programowania w języku asembler można uzyskać odchodząc od klasycznej mnemonicznej notacji publikowanej przez producenta procesora [4]. W opracowanym makroasemblerze JagAsm do zapisu instrukcji procesora stosuje się notację algebraiczną, polegającą na użyciu operatorów występujących w językach wysokopoziomowych (C/C++). Każde wyrażenie zawierające taki operator jest tłumaczone na jeden rozkaz procesora, co pozwala zachować zalety dydaktyczne związane z programowaniem w asemblerze. Każda instrukcja bądź wyrażenie w języku JagAsm jest zakończone znakiem średnika. W jednej linii można umieścić wiele instrukcji, co pozwala na skrócenie liczby linii kodu źródłowego. Instrukcje mogą być także zapisywane w oryginalnej notacji mnemonicznej. Wówczas możliwe jest umieszczenie tylko jednej instrukcji w danej linii. 3.1. Rozkazy przesłań danych oraz rozkazy nadawania wartości W asemblerze JagAsm do zapisu rozkazów przesłań danych przyjęto operator „=” (podstawienie). Kierunek przesłania (załaduj/zapisz) określany jest na podstawie kolejności zapisu operandów. Adres operandu źródłowego bądź docelowego umieszczany jest pomiędzy znakami „[ ]”. Dla niektórych rozkazów, uszczegółowienie ich działania odbywa się za pomocą odpowiednich sufiksów precyzujących ich znaczenie. W grupie rozkazów przesłań zdefiniowano następujące sufiksy: (io) – dla przesłań z/do portów wejścia-wyjścia, (p) – dla przesłań z/do pamięci programu, (ep) – dla przesłań z/do pamięci programu z użyciem adresowania rozszerzonego, (w) – dla przesłań o szerokości słowa16-bit. W grupie rozkazów obejmujących ustawienie, wyzerowanie bądź przesłanie pojedynczego bitu operacja jest również oznaczana operatorem „=” oraz symbolizującym operację na sufiksem „(b)” pojedynczym bicie. Wybrane rozkazy przesłań i rozkazy bitowe oraz ich notację w asemblerze JagAsm dla procesorów rodziny ATMega przestawiono w tabeli 2.. PWT 2005 - POZNAŃ 8-9 GRUDNIA 2005. Tabela 2. Wybrane i pojedynczych bitów. Mnemonik MOV MOVW LDI LDS / STS LD / ST LDD / ST IN /OUT LPM SPM ELPM ESPM. rozkazy. przesłań. danych. Wybrane przykłady rozkazów w notacji JagAsm Rx=Ry Rx+1:Rx=Ry+1:Ry (w) Rx=k8 Rx=[k16] Rx=[XYZ] Rx=[XYZ+] Rx=[–XYZ] Rx=[YZ+q6] Rx=P (io) Rx=[Z] (p) [Z]=R0:R1 (p) Rx=[RAMP:Z/Z+] (ep) [RAMP:Z]=R0:R1 (ep). Rozkazy bitowe BST / BLD SBI / CBI SEx / CLx BSET / BCLR. T=Rx.b (b) P.b=0 (b) / P.b=1 (b) C=0 (b) / C=0 (b) Dla pozostałych flag statusu: N,Z,I, S,V,T,H stosuje się analogiczną notację sreg.b=0/1 (b). 3.2. Operacje arytmetyczne i logiczne Operacje arytmetyczne i logiczne zapisywane są przy użyciu jedno lub dwuznakowych operatorów arytmetycznych jak „*”, „+”, „+=”, „–=”, „&=”, itd. Dodatkowo sufiksy precyzują znaczenie niektórych rozkazów: (w) – operacja na słowach 16-bitowych, (u2) – negacja arytmetyczna, (u) – mnożenie ze znakiem, (s) – mnożenie ze znakiem, (su) – mnożenie w którym pierwszy argument traktowany jest jako liczba ze znakiem, drugi jako liczba bez znaku . Tabela 3. Wybrane rozkazy arytmetyczne i logiczne. Mnemonik ADD ADC SUB SBC SUBI SBCI ADIW SBIW NEG INC DEC CLR SER MUL / MULS / MULSU CP CPC CPI Rozkazy logiczne AND / ANDI OR / ORI EOR COM. Wybrane przykłady rozkazów w notacji JagAsm Rx +=Ry Rx +=Ry+CY Rx –=Ry Rx –=Ry–CY Rx –=k8 Rx –=k8–CY Rd+=k6 (w) Rd –=k6 (w) –Rx (u2) Rx++ Rx– – Rx=0 Rx=$FF R0:1 = Rx*Ry (u/s/su) cmp(Rx,Ry) cmp(Rx,Ry) (CY) cmp(Rx,k8) (CY) Rx &= Ry / Rx &= k8 Rx |= Ry / Rx |= k8 Rx ^= Ry ~Rx. 2/4.

(3) www.pwt.et.put.poznan.pl. 3.3. Wyrażenia strukturalne Dalsze poprawienie czytelności kodu źródłowego w makroasemblerze JagAsm możliwe jest dzięki wyrażeniom strukturalnym. Pozwalają one na znaczącą redukcję liczby etykiet w kodzie źródłowym. Wyrażenie strukturalne .IF wykorzystuje istniejące rozkazy skoków warunkowych i rozkazy warunkowego pominięcia następnej instrukcji. Podczas asemblacji generowany jest jeden, odpowiedni rozkaz warunkowy. Początek bloku kodu wykonywanego warunkowo oznaczany jest nawiasem otwierającym „{”. Koniec tego bloku oznaczany jest nawiasem zamykającym „}” - jest on odpowiednikiem etykiety w asemblerze mnemonicznym. Zestawienie możliwych wyrażeń warunkowych przedstawiono w tabeli 5. Przyjęto 4 zasadniczo różne typy notacji dla wyrażenia .IF stosownie do istniejących w rodzinie ATMega rozkazów. Tabela 5. Wyrażenia warunkowe Mnemonik BREQ / BRNE BRCS / BRCC BRSH / BRLO BRMI / BRPL BRGE / BRLT BRHS / BRHC BRTS / BRTC BRVS / BRVC BRIE / BRID. Notacja JagAsm. .If (COND) { }. Gdzie COND : EQ / NE CS / CC SH / LO MI / PL GE / LT HS / HC TS / TC VS / VC IE / ID. Tabela 6. Wyrażenie .DO .WHILE Mnemonik Skoki warunkowe patrz tabela 5 Skoki warunkowe patrz tabela 5. .IF(sreg.b=0/1) {. RJMP. } .IF(Rx.b=0/1) <jedna_instrukcja> .IF(IO.b=0/1) (iob) <jedna_instrukcja> .IF (Rx<>Ry) <jedna_instrukcja>. Skoki warunkowe patrz tabela 5 Skoki warunkowe patrz tabela 5 RJMP. BRBC / BRBS SBRC / SBRS SBIC / SBIS CPSE. Innym wyrażeniem strukturalnym występującym w makroasemblerze JagAsm jest pętla .DO .WHILE. Konstrukcja pętli .DO .WHILE także wykorzystuje istniejące rozkazy skoków warunkowych. Wyrażenie .WHILE jest zastępowane jedną instrukcją procesora. W przypadku pętli nieskończonej użyty jest rozkaz RJMP (zobacz tabela 6). Pętla rozpoczyna się wyrażeniem .DO oraz otwierającym nawiasem „{”. Blok instrukcji zakończony jest zamykającym nawiasem „}” oraz wyrażeniem .WHILE. Wyrażenie .DO nie jest tłumaczone na żadną instrukcję procesora. Jest ono odpowiednikiem etykiety w asemblerze mnemonicznym. Blok instrukcji zawarty między nawiasami „{}” wykonywany jest wielokrotnie aż do czasu, gdy wyspecyfikowany warunek przestanie być prawdziwy. Treść pętli zostanie wykonana przynajmniej jeden raz. Pętle mogą być zagnieżdżane. Do wcześniejszego przerwania pętli można użyć wyrażenia .BREAK. Jego dozwolone argumenty są takie same jak wyrażenia .WHILE.. Możliwe jest zagnieżdżanie wyrażeń warunkowych. Odpowiadające im etykiety generowane są automatycznie. .IF (COND) { … blok kodu wykonywany warunkowo .IF (COND) { … blok kodu wykonywany warunkowo } … blok kodu wykonywany warunkowo }. W celu realizacji alternatywnych gałęzi programu możliwe jest użycie wyrażenia „.ELSE” oraz odpowiednio umieszczonych nawiasów ograniczających „{„ oraz „}”. Zawarty między tymi nawiasami blok kodu zostanie wykonany w przypadku, gdy wyrażenie warunkowe .IF będzie fałszywe. .IF (COND) { … blok kodu wykonywany warunkowo } .ELSE { … blok kodu wykonywany w przypadku, gdy warunek (COND) nie jest spełniony }. Wyrażenie .ELSE możliwe jest do zastosowania jedynie z pierwszymi dwoma formami wyrażenia .IF i jest tłumaczone na rozkaz RJMP.. PWT 2005 - POZNAŃ 8-9 GRUDNIA 2005. Notacja JagAsm .DO { } .WHILE (COND); .DO{ }.WHILE (sreg.b=0/1); .DO{ }.WHILE(1); .BREAK (COND); .BREAK (sreg.b); .BREAK;. 4. Przykład programu w języku JagAsm Poniżej przestawiono przykładowy program obsługujący port szeregowy w procesorze ATMega8 [3]. Program konfiguruje nadajnik portu, a następnie wysyła ciąg znaków z tablicy o nazwie „bufor” aż do momentu napotkania wartości 0. R16=71; UBRRH=r16 (io); // konfiguracja prędkości portu UCSRB.TXEN=1 (b); // włączenie nadajnika portu // ustawienie adresu początku bufora zawierającego znaki R26=low(bufor); R27=high(bufor); R1=0; .do{ R0=[X]+; // pobierz następny znak do wysłania cmp (R0,R1); .break (EQ); // gdy znak równy zero, to przerwij .do{ // czekaj na zwolnienie nadajnika .IF (UCSRA.UDRE=1)(iob) .BREAK; }.while(1); UDR=r1 (io); }.while (1);. Komentarze oznaczane ukośnika „//”.. są. znakiem. podwójnego. 3/4.

(4) www.pwt.et.put.poznan.pl. 5. Podsumowanie Pomimo podobieństwa składni do języków wysokopoziomowych JagAsm jest makroasemblerem. Każdemu wyrażeniu odpowiada dokładnie jedna instrukcja procesora. Programowanie w asemblerze JagAsm pozwala na znacznie szybsze tworzenie kodu źródłowego, znacząco poprawia jego czytelność oraz zmniejsza liczbę popełnianych błędów. Pozwala to na realizację szerszego zakresu materiałowego w krótszym czasie. Studenci biorący udział w kursie wykazują większe zrozumienie zagadnień programowania niskopoziomowego. Zaobserwowano wzrost zainteresowania kursem w porównaniu z kursami prowadzonymi w poprzednich latach tylko z użyciem asemblerów mnemonicznych. Podczas zajęć wykładowych i laboratoryjnych, zalecane jest wykonanie jednego bądź dwóch wstępnych ćwiczeń wprowadzających z klasycznego asemblera memonicznego. Mają one na celu zapoznanie studentów z oryginalną listą instrukcji publikowaną przez producenta mikrokontrolerów. Obecnie przygotowywany jest asembler JagAsm dla mikrokontrolerów 32-bitowych.. 6. Literatura [1] 8-bit AVR Instruction Set, Atmel Corporation, 2005 [2] AVR Assembler User Guide, Atmel Corporation, 1998 [3] 8-bit AVR with 8KB In-System Programmable FLASH. ATMega 8, Atmel Corporation, 2004 [4] J. Augustyn, A. Lisowska-Lis: “New educational concept in study course of the assembly language applied to microcontrollers”, 9-th Baltic Region Seminar on Engineering Education, Gdynia, 2005. PWT 2005 - POZNAŃ 8-9 GRUDNIA 2005. 4/4.

(5)

Cytaty

Powiązane dokumenty

Artykuł prezentuje zastosowanie algorytmu świetlika do optymalizacji niezawodności dwóch systemów: mostkowego i 10-elementowego, z wykorzystaniem metod zbioru

Zawarta w niej analiza stanu instytucji trudniących się świadczeniem usług związanych z niesieniem pomocy lu- dziom w podeszłym wieku, zagrożonym wykluczeniem społecznym bądź

Wydział Elektrotechniki, Automatyki, Informatyki i

Sól magnezowa tego kwasu zawiera 16.9% magnezu, natomiast produktem utleniania alkoholu B jest kwas identyczny jak kwas A.. Podaj nazwę

Udowodniono tym samym główną tezę niniejszej rozprawy, że bez konieczności wyznaczania elementów macierzy funkcji przenoszenia kanału radiowego, a wykorzystując jedynie proste

Możliwe jest opracowanie bardziej wydajnego – od obecnie stosowanych – algorytmu wyboru trybu pracy stacji abonenckiej w bezprzewodowej sieci lokalnej WLAN standardu IEEE

Typowe modele kierowców (Rysunek 3.1a) konstruowane są głównie z przeznaczeniem na potrzeby symulacji (algorytm symulacyjny, model środowiska i model kierowcy tworzą

4) elektorzy spośród studentów i doktorantów, którzy stanowią nie mniej niż 20% składu kolegium; liczbę studentów i doktorantów ustala się proporcjonalnie do liczebności obu