Programování mikroprocesor AVR v jazyce C. Ji í Bourek 16. kv tna 2007



Podobné dokumenty
Skalární sou in. Úvod. Denice skalárního sou inu

e²ení systém lineárních rovnic pomocí s ítací, dosazovací a srovnávací metody

Vektor náhodných veli in - práce s více prom nnými

C++ Akademie SH. 2. Prom nné, podmínky, cykly, funkce, rekurze, operátory. Michal Kvasni ka. 20. b ezna Za áte níci C++

Limity funkcí v nevlastních bodech. Obsah

Integrování jako opak derivování

Kompilace Makele C++ Zadání úlohy. Kompilace a Makele. OSD. O. Fi²er. April 18, O. Fi²er Kompilace, Makele

P íklad 1 (Náhodná veli ina)

Vektory. Vektorové veli iny

IPCorder KNR-100 Instala ní p íru ka

Cílem kapitoly je seznámit studenta se strukturou programu a jeho překladem.

Sazba zdrojových kód. Jakub Kadl ík

2. Ur íme sudost/lichost funkce a pr se íky s osami. 6. Na záv r na rtneme graf vy²et ované funkce. 8x. x 2 +4

Derivování sloºené funkce

T i hlavní v ty pravd podobnosti

Modelování v elektrotechnice

SRF08 ultrazvukový dálkoměr

Nastavení vestav ného p evodníku Ethernet -> sériová linka ES01

Státní maturita 2010 Maturitní generálka 2010 Matematika: didaktický test - základní úrove obtíºnosti MAGZD10C0T01 e²ené p íklady

ízení Tvorba kritéria 2. prosince 2014

Mikroprocesor Intel 8051

Rovnice a nerovnice. Posloupnosti.

Jevy, nezávislost, Bayesova v ta

Sbírka úloh pro elektronickou stavebnici. Stručný popis programovacího jazyka Bascom AVR

DeepBurner (testování UI)

Binární operace. Úvod. Pomocný text

3 Vývojová prostředí, základní prvky jazyka Java, konvence jazyka Java

Návod na obsluhu Pípáku verse V0.51 (PŘEDBĚŽNÝ NÁVOD).

PARADIGMATA PROGRAMOVÁNÍ 2A MAKRA I

Pr b h funkce I. Obsah. Maxima a minima funkce

INTERNETOVÝ TRH S POHLEDÁVKAMI. Uživatelská příručka

Algoritmizace a programování

MATLB: p edná²ka 1. Prom nné, indexování a operátory. TECHNICKÁ UNIVERZITA V LIBERCI Fakulta mechatroniky, informatiky a mezioborových studií

Fyzikální praktikum 3

Prezentace. Ing. Petr V elák 6. b ezna 2009

Pravd podobnost a statistika - cvi ení. Simona Domesová místnost: RA310 (budova CPIT) web:

ALLEX FX Programovatelný logický automat. Katalogový list. říjen Programovatelné logické automaty

P EHLED FUNKCÍ BRICX. Jan Mare²

Specifikace systému ESHOP

ZÁPISKY Z ANALYTICKÉ GEOMETRIE 1 SOUŘADNICE, BODY

P íklady k prvnímu testu - Pravd podobnost

19 Jednočipové mikropočítače

Základní praktikum laserové techniky

Informace a návod k pouºití ablony pro BP student FZS v Plzni. Ing. Petr V elák 20. únor 2012

Teorie her. Klasikace. Pomocný text

Autodesk Inventor 8 vysunutí

Státnice - Rekurzivní a rekurzivn spo etné mnoºiny

Vzorové e²ení 4. série

Kelvin v kapkový generátor

Obsah. Pouºité zna ení 1

IMTEE Přednáška č. 11

Uložené procedury Úvod ulehčit správu zabezpečení rychleji

Manuál uživatele čipové karty s certifikátem

8. Struktura údaj na LCD displeji

Databázovéa informačnísystémy NÁVRH IMPLEMENTACE 2 KONZISTENCE DATABÁZE

Algoritmizace a programování

C/C++ projekt v programu NetBeans

Programování 1. hodina. RNDr. Jan Lánský, Ph.D. Katedra informatiky a matematiky Fakulta ekonomických studií Vysoká škola finanční a správní 2015

TRANSFORMACE. Verze 4.0

BOZP - akcepta ní testy

NÁVOD K OBSLUZE. Obj. č.:

Provoz a poruchy topných kabelů

Prostory jmen. #include<iostream.h> namespace RadimuvProstor { int secti(int a, int b); class Trida { private: int Atribut; public: void metoda();

W H I R L P O O L M Y Č K Y N Á D O B Í

Uºivatelská p íru ka k programu SlaFoR verze 1.0

Digitální tlakoměr PM 111

1. (18 bod ) Náhodná veli ina X je po et rub p i 400 nezávislých hodech mincí. a) Pomocí ƒeby²evovy nerovnosti odhadn te pravd podobnost

Základní stavební prvky algoritmu

Modul řízení otáček stejnosměrného motorku

21. Číslicový měřicí systém se sběrnicí IEEE 488 (základní seznámení)

Transak ní zpracování I

Team Engineering. New in V13. TIA Portal news. Restricted / Siemens AG All Rights Reserved.

PARADIGMATA PROGRAMOVÁNÍ 2 KORUTINY, NEDETERMINISMUS

Objektov orientované programování. C++ Akademie SH. 7. Objektov orientované programování. Michal Kvasni ka. Za áte níci C++ 2.

Mikromarz. CharGraph. Programovatelný výpočtový měřič fyzikálních veličin. Panel Version. Stručná charakteristika:

Zadání. Založení projektu

Tutoriál Volné plošné zatížení

WordBase Postup pro zpracování dokumentů

1.2.5 Reálná čísla I. Předpoklady:

10 je 0,1; nebo taky, že 256

IP kamerový systém Catr - uºivatelský návod k obsluze

Nová "dimenze"! První univerzální stmívač pro všechny stmívatelné zdroje

Cvi ení 1. Modelování systém a proces. Mgr. Lucie Kárná, PhD. March 2, Organizace cvi ení 2 Matlab Za ínáme Základní operace Základní funkce

Moderní technologie ve studiu aplikované fyziky CZ.1.07/2.2.00/ Reálná čísla

Seriál: Management projektů 7. rámcového programu

Cvi ení 1. Cvi ení 1. Modelování systém a proces. Mgr. Lucie Kárná, PhD. March 2, 2018

Zkouška z předmětu Počítačové systémy

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

WEBDISPEČINK NA MOBILNÍCH ZAŘÍZENÍCH PŘÍRUČKA PRO WD MOBILE

SNÍMAČ T2114. Programovatelný snímač barometrického tlaku s výstupem 4-20 ma. Návod k použití

Návod pro vzdálené p ipojení do sít UP pomocí VPN pro MS Windows 7

e²ení 1. série Úvodní gulá² autor: Kolektiv org

( x ) 2 ( ) Další úlohy s kvadratickými funkcemi. Předpoklady: 2501, 2502

Příloha č. 54. Specifikace hromadné aktualizace SMS-KLAS

4. Připoutejte se, začínáme!

Jméno: P íjmení: Datum: 17. ledna 2018 Nechci zápo et p i hodnocení niº²ím neº (nezávazné): vadí mi vystavení mého hodnocení na internetu.

PARADIGMATA PROGRAMOVÁNÍ 2A MAKRA III

Quido USB 0/ Spínač síťového napětí 230 V ovládaný z PC přes USB rozhraní. 28. února 2011 w w w. p a p o u c h. c o m

IPCorder Uºivatelský manuál

Transkript:

Programování mikroprocesor AVR v jazyce C Ji í Bourek 16. kv tna 2007 1

1 Úvod Oproti b ºným procesor m pouºívaným v osobních po íta ích jsou mikroprocesory vcelku jednoduchá za ízení a je tedy moºné je vcelku snadno programovat p ímo v assembleru. Takto napsané programy bývají velice rychlé, ale vývoj jako takový trvá p íli² dlouho. Z toho d vodu se mikroprocesory b ºn programují v jazyce C. 2 Knihovna avr-libc 2.1 P eklada avr-gcc a projekt WinAVR Aby nemuseli d lat v²echnu práci odznova, vývojá i p eklada e jazyka C pro architekturu AVR pouºili jako základ p eklada gcc (GNU C Compiler) a ostatní utility pouºívané pro vývoj na opera ním systému Linux a dal²ích unixových systémech. P eklada gcc jako takový byl pozd ji portován i na Windows, takºe i avr-gcc je moºné v tomto OS pouºívat a dokonce ho i integrovat do vývojového prost edí AVR Studio od rmy Atmel. Pro snadnou instalaci a pouºití p eklada e avr-gcc vznikl projekt WinAVR (http://winavr.sourceforge.net/), který obsahuje p eklada, ostatní utility a dal²í software. Pro architekturu AVR byla portována i knihovna libc. Tuto knihovnu je moºné voln pouºít pro vývoj jak uzav ených, tak open source program. Je obsaºena v balíku WinAVR, ale lze ji stáhnout i samostatn ze stránek projektu (http://savannah.nongnu.org/projects/avr-libc/) Poznámka: Tento dokument je psán podle sou asné verze avr-libc; pokud je n kde uvedeno, jak p eklada p eloºí kód, platí to pro avr-gcc verze 4.1.0. 2.2 Vybrané hlavi kové soubory - <avr/io.h> Tato hlavi ka umoº uje práci s hardwarem mikroprocesoru, zp ístup uje I/O registry. Protoºe se po et a jména registr li²í podle typu, obsahuje tento hlavi kový soubor pouze ty registry, které jsou spole né pro v²echny procesory AVR, které se dají programovat v C. P i p ekladu dostává avr-gcc jako parametr typ mikroprocesoru, pro který se program p ekládá. P i preprocesingu denuje makro, které tomuto parametru odpovídá, toto makro se pouºije p i podmín ném p ekladu a p i vloºení <avr/io.h> se automaticky vloºí dal²í hlavi kový soubor, který odpovídá konkrétnímu za ízení. K port m je moºné p istupovat jménem, které je uvedné v manuálu. Následující p íklad p epne celý port A do reºimu výstup a výstupní piny nastaví do logické 1. #include <avr/io.h> DDRA = 0xff; PORTA = 0xff; 2.3 <avr/interrupt.h> Tento hlavi kový soubor vkládá funkce a makra slouºící k obsluze p eru²ení. Funkce, která obsluhuje p eru²ení, je deklarována takto: ISR (p eru²ení) { Místo p eru²ení je pot eba zadat jméno vektoru p eru²ení, nap íklad obsluha vn j²ího p eru²ení je pojmenována INT0_vect 1. Po startu procesoru je v registru p íznak vynulován bit I (globální povolení p eru²ení). Ten je moºné z programu nastavit zavoláním funkce sei() a vynulovat voláním cli() 2. Pokud n jaké p eru²ení eká na obslouºení, po povolení p eru²ení funkcí sei() se vykoná je²t jedna instrukce a poté procesor sko í do obsluºné funkce. 1 Kompletní seznam je vypsán v dokumentaci avr-libc na webu na adrese http://www.nongnu.org/avr-libc/usermanual/group avr interrupts.html 2 sei() ani cli() ve skute nosti nejsou funkce, ale makra, která na dané místo kódu vloºí instrukci sei (cli) 2

Následuje nástin programu, který bude reagovat na vn j²í p eru²ení: #include <avr/interrupt.h> ISR (INT0_vect) { // n jaká akce // inicializace - povolení vn j²ího p eru²ení sei(); loop: // hlavní smy ka programu goto loop; V obsluze p eru²ení je pot eba uloºit na zásobník hodnoty registr a registr p íznak - to automaticky zajistí p eklada. P i vstupu do obsluºné funkce procesor automaticky vynuluje bit I v registru p íznak a tím zabra uje obsluze dal²ího p eru²ení do doby, neº je obslouºeno p eru²ení první. Po návratu z obsluhy p eru²ení je p íznak I znovu nastaven a m ºe být zavolána dal²í obsluºná funkce. Pokud je ºádoucí, aby obsluha n jakého p eru²ení mohla být p eru²ena, lze to p eklada i oznámit atributem interrupt: ISR (INT0_vect) attribute ((interrupt)); ISR (INT0_vect) { // obsluha p eru²ení Tento atribut zp sobí, ºe p eklada p ed první instrukci v obsluze p eru²ení vloºí instrukci sei a tím op t povolí p eru²ovací systém. Pokud tedy na obsluhu eká dal²í p eru²ení, vykoná se jedna instrukce (zpravidla push r1) a procesor sko í do ekající obsluºné funkce. Vektory p eru²ení, pro které nejsou denovány ºádné obsluºné funkce, dodenuje p eklada tak, ºe procesor sko í na programovou adresu 0 a vyresetuje se. Tomuto chování lze zabránit denováním prázdného p eru²ení: EMPTY_INTERRUPT (INT1_vect); Prázdné p eru²ení obsahuje po p eloºení pouze instrukci reti. 2.4 <avr/sleep.h> Procesory AVR disponují n kolika reºimy spánku, ve kterých procesor spot ebovává mén energie. Pokud je pot eba procesor uspat, je nutné postupovat v t chto krocích. 1. Nastavit typ reºimu spánku - procesor má podle typu n kolik reºim spánku, které se li²í tím, kolik energie se u²et í, jak dlouho trvá probuzení a jaké události mohou probuzení zp sobit. Jednotlivé reºimy jsou denovány t mito makry: SLEEP_MODE_ADC SLEEP_MODE_IDLE SLEEP_MODE_STANDBY SLEEP_MODE_EXT_STANDBY SLEEP_MODE_PWR_DOWN SLEEP_MODE_PWR_SAVE Do kterého reºimu procesor p ejde, je nastaveno funkcí set_sleep_mode (), jméno reºimu se jí p edává jako parametr. 2. Povolit uspání procesoru - i kdyº je nastaveno, do jakého reºimu má procesor p ejít, stále není moºné ho uspat, protoºe po resetu to není povoleno. Povolení reºimu spánku se provede zavoláním funkce sleep_enable(), op tovné zakázání tohoto reºimu funkcí sleep_disable() 3 3. Zavolat funkci pro uspání - pokud je uspávání povoleno, procesor se do reºimu spánku p epne voláním funkce sleep_cpu() 4. Poznámka: Procesor se probouzí, pokud nastane p eru²ení. P ed voláním sleep_cpu() je tedy nutné volat funkci sei(). 3 Tyto funkce jsou ve skute nosti makra, která nastaví nebo vynulují I/O registr, kterým se reºim slánku ovládá. 4 Ve skute nosti jde o makro, které na místo funkce vloºí assemblerovskou instrukci sleep 3

2.5 <stdlib.h> Poznámka: Z této knihovny jsou vybrány jenom n které funkce. 2.5.1 malloc(), free() Jak pí²í auto i dokumentace, implementovat dynamické alokace pam ti na procesorech, které mají minimum pam ti, není nic jednoduchého. Standardní rozvrºení pam ti je takové, ºe na za átek se umis ují sekce.data a.bss. Za t mito sekcemi se nachází halda, zásobník za íná na konci pam ti a roste sm rem k niº²ím adresám. To znamená, ºe pokud je alokováno hodn dynamické pam ti (ale také pokud dojde k fragmentaci pam ti) a zárove je pot eba uloºit p íli² mnoho dat na zásobník, m ºe dojít ke kolizi. Pokud je k dispozici vn j²í pam, je moºné rozvrºení m nit, napríklad lze vyhradit vnit ní RAM pouze pro zásobník a v²echny prom nné umístit do pam ti vn j²í. Návod je k dispozici v dokumentaci - http://www.nongnu.org/avrlibc/user-manual/malloc.html Parametrem funkce malloc() je, kolik pam ti je pot eba alokovat; vrací ukazatel na alokované místo nebo NULL. Funkce free() má jako parametr ukazatel. 2.5.2 exit() Volání funkce exit() ukon í program. Protoºe v mikroprocesoru není nad azené prost edí, do kterého by bylo moºné se vrátit, program je ukon en nekone nou smy kou. Parametrem funkce je celé íslo, které je ignorováno. P eklada automaticky vloºí nekone nou smy ku na konec programu - pokud je funkce main() n jak p eru²ena (b h programu dojde na konec nebo pouºitím p íkazu return), program sko í na tuto nekone nou smy ku. 3 Programování a p eklad v t²ích projekt 3.1 Jednoduchý program Následující jednoduchý p íklad pouºije pin 1 na portu A jako výstupní a st ídá na n m logickou 0 a 1. #include <avr/io.h> unsigned int a; DDRA = (1 < < DDA1); loop: PORTA = (1 < < PORTA1); PORTA &= ~(1 < < PORTA1); goto loop; Kód uloºíme do souboru prvni.c a p eloºíme z p íkazové ádky (musíme být v adresá i, ve kterém je zdrojový kód uloºen): avr-gcc -g2 -Wall -mmcu=atmega16 -o prvni.elf prvni.c Parametry p edávané p eklada i v tomto p ípad zajistí, ºe výstup bude obsahovat ladící informace (-g2), p i p ekladu budou vypisována v²echna varování (-Wall), p ekládáme pro procesor AtMega 16 (-mmcu). Pokud se pokusíme p eloºit program pro procesor, který nemá port A, p eklada vrátí chybové hlá²ení: error: 'DDRA' undeclared (first use in this function) error: (Each undeclared identifier is reported only once error: for each function it appears in.) V tuto chvíli bychom rádi pro kontrolu vid li, jaký assemblerovský kód p eklada vygeneroval. K tomu slouºí dal²í utilita - avr-objdump avr-objdump -h -S prvni.elf >prvni.lst 4

Tímto p íkazem vygenerujeme soubor prvni.lst, který obsahuje hlavi ky sekcí a disassemblovaný kód, který je tam, kde je to moºné, uvozen C kódem, který k n mu pat í 5. Kdyº si soubor prohlédneme, zjistíme, ºe po spu²t ní programu p eklada vloºil kód, který jsme nepsali. V n m zaji² uje zkopírování dat uloºených v programové pam ti (konstanty, et zce) do pam ti opera ní a inicializuje globální prom nné. Protoºe ani jedno z toho v tomto p íkladu není pouºito, kód se p esko í. Poté uº následuje ná² program: 8e: cd e5 ldi r28, 0x5D ; 93 90: d4 e0 ldi r29, 0x04 ; 4 92: de bf out 0x3e, r29 ; 62 94: cd bf out 0x3d, r28 ; 61 unsigned int a; Jako první p eklada inicializuje ukazatel zásobníku (stack pointer, SP) tém na konec pam ti (p idáváním dat na zásobník se hodnota v SP sniºuje). Nad ukazatelem nechává 2B místa pro prom nnou a. DDRA = (1 < < DDA1); 96: aa e3 ldi r26, 0x3A ; 58 98: b0 e0 ldi r27, 0x00 ; 0 9a: ea e3 ldi r30, 0x3A ; 58 9c: f0 e0 ldi r31, 0x00 ; 0 9e: 80 81 ld r24, Z a0: 82 60 ori r24, 0x02 ; 2 a2: 8c 93 st X, r24 Tato sekce nastaví pin 1 na portu A jako výstupní. Na výstupu je logická nula. loop: PORTA = (1 < < PORTA); a4: ab e3 ldi r26, 0x3B ; 59 a6: b0 e0 ldi r27, 0x00 ; 0 a8: eb e3 ldi r30, 0x3B ; 59 aa: f0 e0 ldi r31, 0x00 ; 0 ac: 80 81 ld r24, Z ae: 82 60 ori r24, 0x02 ; 2 b0: 8c 93 st X, r24 Zde program p e te hodnotu aktuáln zapsanout v PORTA, logicky ji se te s dvojkou (piny se íslují od nuly, pin 1 tedy odpovídá bitu 2) a výsledek znovu zapí²e do PORTA. Tím na výstupu nastaví logickou 1. b2: 81 e0 ldi r24, 0x01 ; 1 b4: 90 e0 ldi r25, 0x00 ; 0 b6: 9a 83 std Y+2, r25 ; 0x02 b8: 89 83 std Y+1, r24 ; 0x01 ba: 05 c0 rjmp.+10 ; 0xc6 <main+0x38> bc: 89 81 ldd r24, Y+1 ; 0x01 be: 9a 81 ldd r25, Y+2 ; 0x02 c0: 01 96 adiw r24, 0x01 ; 1 c2: 9a 83 std Y+2, r25 ; 0x02 c4: 89 83 std Y+1, r24 ; 0x01 c6: 89 81 ldd r24, Y+1 ; 0x01 c8: 9a 81 ldd r25, Y+2 ; 0x02 ca: 00 97 sbiw r24, 0x00 ; 0 cc: b9 f7 brne.-18 ; 0xbc <main+0x2e> Aby se logická hodnota na výstupu nem nila p íli² rychle, vloºíme do programu ekací smy ku. Na za átku cyklu uloºí do prom nné a jedni ku a v kaºdé iteraci cyklu program na te hodnotu prom nné a z pam ti, zvý²í ji o 1 a znovu ji uloºí. Kdyº hodnota p ete e z 65535 zpátky na 0, program z cyklu vysko í. 6. 5 Ne vºdy se to poda í - ve sloºit j²ím kódu se asto stane, ºe v souboru najdeme nejprve dlouhý blok C kódu a teprve potom dlouhý blok assemblerovských instrukcí - v takovém p ípad se dost t ºko ur uje, co k emu pat í a obtíºn se hledají p ípadné chyby. 6 V jazyce C neexistuje prom nná typu logická hodnota - nenulová hodnota znamená TRUE, nula je FALSE. V tomto p ípad tedy cyklus b ºí tak dlouho, dokud hodnota v a není nulová. 5

PORTA &= ~(1 < < PORTA1); ce: ab e3 ldi r26, 0x3B ; 59 d0: b0 e0 ldi r27, 0x00 ; 0 d2: eb e3 ldi r30, 0x3B ; 59 d4: f0 e0 ldi r31, 0x00 ; 0 d6: 80 81 ld r24, Z d8: 8d 7f andi r24, 0xFD ; 253 da: 8c 93 st X, r24 Nyní pin nastavíme zp t do logické nuly. Program na te hodnotu v PORTA, logicky ji vynásobí s hodnotou, ve které jsou v²echny bity krom bitu 2 v logické 1, a výsledek uloºí zp t. dc: 81 e0 ldi r24, 0x01 ; 1 de: 90 e0 ldi r25, 0x00 ; 0 e0: 9a 83 std Y+2, r25 ; 0x02 e2: 89 83 std Y+1, r24 ; 0x01 e4: 05 c0 rjmp.+10 ; 0xf0 <main+0x62> e6: 89 81 ldd r24, Y+1 ; 0x01 e8: 9a 81 ldd r25, Y+2 ; 0x02 ea: 01 96 adiw r24, 0x01 ; 1 ec: 9a 83 std Y+2, r25 ; 0x02 ee: 89 83 std Y+1, r24 ; 0x01 f0: 89 81 ldd r24, Y+1 ; 0x01 f2: 9a 81 ldd r25, Y+2 ; 0x02 f4: 00 97 sbiw r24, 0x00 ; 0 f6: b9 f7 brne.-18 ; 0xe6 <main+0x58> goto loop; f8: d5 cf rjmp.-86 ; 0xa4 <main+0x16> ƒekací cyklus je stejný, kdyº dob hne, program sko í na za átek smy ky a v²e se opakuje 7. Tento kód je na první pohled velice neefektivní - jenom nastavení I/O registru DDRA zabere dev t hodinových cykl a pouºívá se p itom p t registr. V ekacím cykl se prom nná a zbyte n ukládá do pam ti, p itom by mohla z stat v registrech a b h programu by se tím zrychlil 8. Proto program p eloºíme je²t jednou a tentokrát zapneme optimalizace: avr-gcc -g2 -Wall -O2 -mmcu=atmega16 -o prvni.elf prvni.c avr-objdump -h -S prvni.elf >prvni.lst Disassemblovaný program bude vypadat takto: 8e: cf e5 ldi r28, 0x5F ; 95 90: d4 e0 ldi r29, 0x04 ; 4 92: de bf out 0x3e, r29 ; 62 94: cd bf out 0x3d, r28 ; 61 unsigned int a; DDRA = (1 < < DDA1); 96: d1 9a sbi 0x1a, 1 ; 26 loop: PORTA = (1 < < PORTA1); 98: d9 9a sbi 0x1b, 1 ; 27 PORTA &= ~(1 < < PORTA1); 9a: d9 98 cbi 0x1b, 1 ; 27 9c: fd cf rjmp.-6 ; 0x98 <main+0xa> V nastavení registru DDRA je vid t zna né zlep²ení: p eklada pouºil instrukci sbi - nastavení bitu v I/O registru 9, 7 V kaºdé knize o programování po íta se pí²e, ºe p íkaz goto by se m l pouºívat omezen, nebo lépe v bec, protoºe zp sobí, ºe procesor nem ºe vyuºít pipelining a program se zpomaluje. P i programování mikroprocesor tomu tak není a pouºití goto je (pokud je pot eba n kam sko it) naprosto regulérní. 8 Dalo by se íct, ºe kdyº vyrábíme ekací smy ku, n jaká pomalost nám nevadí. V tomto p ípad ne, ale pokud bychom pot ebovali ekat n jaký p esný as, je vhodné, aby doba prob hnutí jednoho cyklu byla co nejkrat²í, protoºe ji násobíme celým íslem - ím krat²í doba cyklu, tím p esn j²í asování m ºeme získat. 9 Pro tuto instrukci nepouºívá automaticky? Instrukce sbi a cbi nefungují pro v²echny I/O registry, takºe je nutné zkoumat kód a zjistit, jaký registr se nastavuje, coº spadá pod optimalizace. 6

stejnou instrukci pouºil pro manipulaci s registrem PORTA. Nicmén je také vid t, ºe se n co nepovedlo - p eklada analyzoval kód a zjistil, ºe hodnota prom nné a se nikde nepouºívá, proto zcela vylou il oba ekací cykly a pro samotnou prom nnou ani nealokoval místo v pam ti. Abychom tomu zabránili, musíme deklarovat prom nnou a jinak: volatile unsigned int a; Slovo volatile íká p eklada i, ºe hodnota prom nné a se m ºe kdykoliv v b hu programu zm nit, aniº by o tom v d l. To se vztahuje nap íklad na prom nné, se kterými pracujeme jak v hlavní smy ce programu, tak v obsluze p eru²ení. P eklada nijak nezkoumá, jestli se hodnota v a opravdu m ºe zm nit a jestli ji opravdu pouºíváme v n jaké obsluze p eru²ení (zde se zm nit nem ºe, ºádné p eru²ení neobsluhujeme), proto kód, ve kterém s touto prom nnou pracujeme, neodstraní (to chceme), ale na druhou stranu po kaºdé zm n novou hodnotu uloºí do pam ti. 3.2 Jednoduchý Makele Neustálé vypisování avr-gcc..., kdyº pot ebujeme program p eloºit, se po n kolika opakováních zna n omrzí, takºe vyuºijeme utilitu make, která nám zna n u²et í práci. V adresá i, ve kterém máme uloºen program, vytvo íme soubor Makele 10, který bude obsahovat následující: PRG OBJ MCU_TARGET = prvni = prvni.o = atmega16 CC OBJCOPY OBJDUMP override CFLAGS = avr-gcc = avr-objcopy = avr-objdump = -g2 -Wall -O2 -mmcu=$(mcu_target) $(DEFS) program: $(PRG).elf lst all: $(PRG).elf lst $(PRG).elf: $(OBJ) $(CC) $(CFLAGS) -o $@ $^ $(LIBS) lst: $(PRG).lst %.lst: %.elf $(OBJDUMP) -h -S $< > $@ D leºitá poznámka - ádky, které jsou odsazené (nap. $(OBJDUMP) -h -S $< > $@), jsou odsazené dv ma tabulátory. Pokud zvolíte jiný zp sob, Makele nebude fungovat. Nyní program p eloºíme prostým zadáním p íkazu make na p íkazové ádce v adresá i, ve kterém je uloºen zdrojový kód a Makele. 3.3 Program sloºený z více soubor P edpokládejme, ºe máme sloºit j²í program a chceme ho rozd lit do n kolika men²ích celk. Tuto situaci m ºeme demonstrovat na p edchozím programu odd lením ekacího cyklu. Vytvo íme nový adresá a hlavní program uloºíme do souboru druhy.c: 10 Tento Makele je zjednodu²ená verze p íkladu, který je uveden na webových stránkách projektu avr-libc - http://www.nongnu.org/avrlibc/user-manual/group demo project.html 7

#include <avr/io.h> #include "cekani.h" DDRA = (1 < < DDA1); loop: PORTA = (1 < < PORTA1); wait(); PORTA &= ~(1 < < PORTA1); wait(); goto loop; Vytvo íme hlavi kový soubor cekani.h a implementaci v n m deklarovaných funkcí cekani.c: /* cekani.h */ #ifndef _CEKANI_H #define _CEKANI_H void wait(void); #endif /* cekani.c */ #include "cekani.h" void wait(void) { volatile unsigned int a; Z p edchozího p íkazu zkopírujeme Makele a nahradíme první dva ádky takto: PRG OBJ = druhy = druhy.o cekani.o Poté spustíme make, program se p eloºí a výsledek si m ºeme prohlédnout v souboru druhy.lst 3.4 Projekt psaný v C i v assembleru V n kterých p ípadech narazíme na to, ºe kód vygenerovaný z jazyka C je p íli² pomalý. V p edchozích p íkladech se to projevilo v ekací funkci, která je bu pomalá kv li neustálému ukládání do pam ti a na ítání, nebo ji p eklada odstraní p i optimalizaci. Tuto funkci tedy napí²eme v assembleru. Vytvo íme nový adresá a z p edchozího p íkladu zkopírujeme Makele a druhy.c (p ejmenujeme na treti.c) Struktura hlavi kového souboru cekani.h je ur ena tím, ºe ho pouºívá jak p eklada assembleru, tak p eklada C - je tedy nutné rozli²it, která ást pat í komu. /* cekani.h */ #ifndef _CEKANI_H #define _CEKANI_H #ifdef ASSEMBLER #define waitl r24 #define waith r25 #else void wait (void); #endif #endif Pokud tento soubor pouºije p eklada assembleru, zapamatuje si makra, která pojmenovávají registry r24 a r25. Pokud ho pouºije p eklada jazyka C, najde deklaraci funkce wait(). Samotnou assemblerovskou implementaci ekací funkce uloºíme do souboru cekani.s 8

/* cekani.s */.nolist #include "cekani.h".list.global wait.func wait wait: eor waitl, waitl eor waith, waith ; vynulování ítacích registr wait_loop: adiw waitl, 1 or waitl, waith brne wait_loop ; pokud nejsou oba nulové, opakování cyklu ret Je vid t, ºe práce s pam tí odpadá a v²echno probíhá ist v registrech. Pouºitím této ekací funkce dosáhneme v t²í p esnosti neº s tou funkcí, kterou vygeneruje p eklada jazyka C. P izp sobíme nastavení Makele sou asné situaci: PRG = treti OBJ = treti.o cekani.o V tuto chvíli make program nep eloºí, neví totiº, jak p eloºit kód psaný v assembleru; na konec Makele proto p idáme následující instrukce 11 : ASFLAGS ALL_ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs = -mmcu=$(mcu_target) -I. -x assembler-with-cpp $(ASFLAGS) %.o : %.S $(CC) -c $(ALL_ASFLAGS) $< -o $@ 3.5 Zásady pro kombinování assembleru a C P i psaní funkcí v assembleru je nutné zachovávat n které konvence, s jejichº dodrºováním po ítá p eklada jazyka C. 3.5.1 Datové typy Pokud se funkci p edávají n jaké parametry, pop ípad se odebírá návratová hodnota, je nutné zachovat délku prom nných - char má 8 bit, int 16 bit, long 32 bit, long long 64 bit, oat a double jsou 32 bitové, ukazatele mají 16 bit. 3.5.2 Vyuºívání registr P eklada rozli²uje registry podle toho, jak se k nim chovají volané funkce, na: Nezachovávané p i volání funkce (call-used) (r18-r27, r30-r31) - funkce tyto registry m ºe voln pouºívat; pokud je program, který volá funkci, pouºívá, musí si jejich hodnoty odloºit jinam. Zachovávané p i volání funkce (call-saved) (r2-r17, r28-r29) - pokud chce funkce pouºít tyto registry, musí uloºit hodnoty v nich obsaºené a p ed návratem je zase obnovit. Pevné registry (r0, r1) - r0 je do asný registr, ve funkcích je moºné jeho hodnotu libovoln m nit (hodnotu zachovávají pouze obsluhy p eru²ení). r1 je nulový registr, p i vykonávání kódu v C vºdy obsahuje nulu. V assemblerovských funkcích je moºné ho pouºít i jinak, ale v takovém p ípad je nutné ho p ed návratem op t vynulovat. 3.5.3 Konvence pro p edávání parametr Parametry se p ednostn p edávají v registrových párech r25 aº r8 (parametry, které zabírají lichý po et byt, nad sebou mají vºdy jeden nevyuºitý registr). Pokud v registrech není pro v²echny parametry dostatek místa, zbylé se p edají p es zásobník. V následujícím p íkladu se parametr i p edá v registrech r24:r25 (v po adí niº²í byte - vy²²í byte) a parametr c v registru r22. void funkce (int i, unsigned char c) 11 P evzato z Makele projektu Avrt 9

Návratové hodnoty funkce se ukládají do registr od nejvy²²ího: int funkce (); /* vrací návratovou hodnotu v registrech r24:r25 */ long funkce2 (); /* vrací návratovou hodnotu v registrech r22:r25 */ 3.6 Kopírování programu do mikroprocesoru P eloºený program p eklada uloºí ve formátu ELF (Executable Linux Format), který ale není moºné nahrát do mikroprocesoru. Proto ho pot ebujeme nejprve zkonvertovat do souboru ve formátu Intel HEX. K tomu vyuºijeme utilitu avr-objdump, do Makele p idáme následující ádky: hex: $(PRG).hex %.hex: %.elf $(OBJCOPY) -j.text -j.data -O ihex $< $@ Soubor HEX potom vytvo íme zavoláním p íkazu make hex. Podobn m ºeme za ídit i nahrávání programu do mikroprocesoru - necháme make, aby zavolal program avrdude - do Makele p idáme: install: hex avrdude -c programátor -p kód_mcu -U flash:w:$(prg).hex:i Slovo programátor je pot eba nahradit jménem programátoru, který avrdude zná (nap. dapa, bsd), kód_mcu je kód, kterým avrdude identikuje procesor - nap íklad m16 pro Atmega 16. 4 Záv r Programování v t²ího projektu v assembleru je v podstat nemyslitelné - kód se velmi rychle stává nep ehledným, programování trvá dlouho a to výsledný program prodraºuje. Pouºít n jaký vy²²í jazyk je tedy nezbytnost. Dne²ní mikroprocesory mají navíc dostatek výpo etního výkonu, aby si mohly dovolit vykonat n které instrukce, které p eklada generuje navíc. Na druhou stranu je pot eba dávat pozor na to, co p eklada vygeneruje tam, kde záleºí na asování. V takových p ípadech bývá výhodn j²í p epsat kód do assembleru. Reference [1] Webové stránky projektu Avr-libc: http://www.nongnu.org/avr-libc/ 10