K U R S
AVR GCC: kompilator C dla
mikrokontrolerów AVR, część 13
Obsługa obszarów pamięci
mikrokontrolerów AVR, część 1
Pamięci te są umieszczone w od- Jedną z wielkich zalet mikrokontrolerów AVR (podobnie
dzielnych obszarach adresowych
zresztą jak układów wielu innych rodzin) jest integracja
i wyposażone w oddzielne sprzętowe
w jednym układzie wszystkich potrzebnych rodzajów
mechanizmy dostępu (architektura
pamięci (SRAM, EEPROM i Flash), co pozwala na znaczne
typu Harvard) obsługiwane różny-
mi instrukcjami maszynowymi
uproszczenie budowanych urządzeń. Ich obsługa nie zawsze
rys. 30. W obszarze RAM dodatko-
jest jednoznaczna, co sprawia duże trudności programistom,
wo wydzielone są sekcje rejestrów
zwłaszcza tym, którzy są przyzwyczajeni do korzystania z pełni
roboczych i rejestrów wejść/wyjść
wyposażone w odrębny sposób ob- możliwości języka C.
sługi (m.in. występuje adresowanie
bitowe) rys. 31. ci wewnętrznej adreso-
Wszystko to jest chlebem po- wanej pośrednio, xdata
wszednim dla konstruktorów dobrze zewnętrzną pamięć
zaznajomionych z budową mikrokon- RAM, zaś code ozna-
trolerów i programowaniem w assem- cza umieszczenie stałej
blerze. Jednak z punktu widzenia ję- (wyłącznie do odczytu)
zyka C sprawy się komplikują. Język ulokowanej w pamię-
ten pochodzi ze świata dużych ma- ci programu. Przypisa-
szyn o całkowicie odmiennej organi- nie zmiennej lub stałej
zacji pamięci (jeden obszar o wspól- określonego klasyfikato-
nym sposobie adresowania i dostępu ra pozwala kompilatoro-
czyli architektura von Neumanna) wi w momencie jej uży-
i nie posiada żadnych standardo- cia na generację kodu
wych mechanizmów wspierających odpowiedniego dla za-
powyższe zróżnicowanie. deklarowanego obszaru
Kompilatory C tworzone dla kon- pamięci (np. zastoso-
kretnych rodzin mikrokontrolerów są wanie instrukcji MOVX
od razu wyposażane w specyficzne w przypadku zewnętrz-
rozszerzenia obsługi różnych pamię- nej pamięci '51). Na Rys. 31. Struktura wewnętrznej pamięci RAM mikro-
ci. Na przykład w SDCC dla rodzi- ogół jest modyfikowana kontrolerów AVR
ny '51 klasyfikator data identyfikuje też budowa wskazników
podstawową pamięć danych, idata tak, aby mieściły one dodatkową in- jest to mocno uciążliwe, ale potrafi
oznacza obszar rozszerzonej pamię- formację o typie pamięci dla aktual- zaskoczyć programistów przyzwycza-
nie wskazywanego obiektu. jonych do PC lub innych kompilato-
Niestety AVR GCC nie jest na- rów C dla AVR.
rzędziem od podstaw dedykowanym
rodzinie AVR, ale jedynie jednym Obsługa SFR oraz obszaru I/O
z wielu portów uniwersalnego zesta- Ten temat był już wielokrotnie
wu kompilatorów GNU GCC. GCC omawiany w poprzednich odcinkach.
natomiast tak samo jak nadmienio- Obecnie AVR GCC oferuje pełne
no powyżej o języku C jest przy- wsparcie dla takich operacji. Nie
stosowany do ciągłego modelu pa- są konieczne dawniejsze dodatkowe
mięci. Skłonienie go do współpracy makra typu inp czy outp stosu-
z tak nietypową dla niego platformą jemy zwyczajne instrukcje przypisa-
sprzętową wymagało wielu wysiłków nia. Przy tym optymalizator potrafi
Rys. 30. Rodzaje pamięci w AVR. Każ- i kompromisów. Nie udało się nieste- samodzielnie określić możliwości
da z nich jest liniowym obszarem ad- ty do tej pory uzyskać pełnej wy- zaadresowania danego rejestru i wy-
resowanym od zera. Stałe RAMEND, gody użytkowania spotykanej w ko- brać najprostsze i najkrótsze instruk-
E2END i FLASHEND są zdefiniowane mercyjnych narzędziach AVR GCC cje (in, out, cbi, sbi) pokazywali-
w plikach nagłówkowych poszczegól- wymaga dodatkowo poznania kilku śmy to na różnych przykładach. Je-
nych typów mikrokontrolerów specyficznych dla niego technik. Nie dynym mankamentem tego postępu
Elektronika Praktyczna 3/2006
107
K U R S
Wl, section start=.data=adres_ opisany w dokumentacji avr libc)
startowy na ogół wykorzystujemy prze-
Wl, section start=.bss=adres_ znaczoną dla użytkownika sekcję
startowy init1. Umieszczenie funkcji w okre-
Wl, section start=.noinit=adres_ ślonej sekcji realizuje atrybut sec-
startowy tion(nazwa). Dodatkowo zastosu-
albo (dla sekcji.data i.bss) wer- jemy znany juz atrybut naked,
Rys. 32. Przemieszczanie sekcji da- sje skrócone: który pozbawi funkcję samoczyn-
nych do zewnętrznej pamięci Wl, Tdata=adres_startowy nie tworzonego prologu i epilogu.
Wl, Tbss=adres_startowy W efekcie uzyskujemy bezpośred-
jest częściowy brak kompatybilności W AvrSide wprowadzamy je nie wstawienie kodu w potrzebnym
ze starszymi projektami jednak w polu edycyjnym dodatkowych miejscu, np. tak (przykład dla
dla rozpoczynających naukę nie bę- opcji w zakładce Linker okna kon- Atmega 128):
void EnableExtRam(void) __attribu-
dzie to żadną przeszkodą. figuracji projektu ale bez pre-
te__ ((naked)) __attribute__ ((section
( .init1 )));
fiksu Wl, AvrSide dodaje go
Obsługa pamięci danych automatycznie (czyli np. wpisuje- void EnableExtRam(void)
{
Sposób zarządzania pamięcią da- my po prostu: Tdata=adres). Je- XMCRA = _BV(SRW00);
XMCRB = _BV(XMBK);
nych także był już dość dokładnie śli używamy makefile dodajemy
MCUCR = _BV(SRE);
}
przedstawiony (podział na sekcje, potrzebną opcję do LDFLAGS. Na-
lokalizacja stosu itp.). Kompilator leży tylko pamiętać, że przesu- Sprawdzmy, że rzeczywiście od-
posługuje się tą pamięcią jako do- nięcie sekcji przemieszcza samo- powiedni kod pojawił się zaraz za
myślnym obszarem nie musimy czynnie wszystkie znajdujące się wektorami przerwań. Zwróćmy też
stosować żadnych dodatkowych kla- za nią z zachowaniem domyślnej uwagę, że w tym przypadku wy-
syfikatorów (oprócz wynikających kolejności (rys. 32). Korzyść z ta- starcza sama deklaracja i definicja
z zastosowanej sekcji jak NOINIT, kiego przemieszczenia jest podwój- funkcji nigdzie w programie jej
czy wynikających ze struktury pro- na: otrzymujemy do dyspozycji jawnie nie wywołujemy byłoby
gramu jak static czy volatile). dużą przestrzeń na dane a zarazem to wręcz błędem, gdyż spowoduje
Także zawartość wskazników do- nie musimy się kłopotać o wiel- skok z powrotem do sekcji .init1
myślnie wskazuje na adresy w pa- kość stosu i potencjalne nadpisanie praktycznie resetując program. Je-
mięci danych (z wyjątkiem wskaz- przez stos części danych. Moż- śli zrobimy kilka eksperymentów
ników na funkcje odnoszących się liwa jest także oczywiście ope- stwierdzimy także, że w sekcji .init1
do adresów w obszarze kodu). Nie- racja odwrotna: przeniesienie do można spowodować błąd jawnym
które układy z rodziny ATmega są zewnętrznej pamięci stosu (słu- przypisaniem zera (np. XMCRA=0).
wyposażone w sprzętowy interfejs ży do tego dyrektywa kompilatora Kompilator użyje rejestru zerowe-
zewnętrznej pamięci danych. Do- minit stack=nnnn albo zamien- go r1 (sts 0x006D, r1), który tutaj
stęp do zewnętrznej pamięci jest nie bezpośrednie zadeklarowanie może mieć jeszcze wartość przy-
zorganizowany bardzo prosto: od- początku stosu dyrektywą linke- padkową gdyż jest inicjalizowany
wołanie się programu do adresu ra defsym, __stack=nnnn). Ale dopiero w ustawiającej stos sekcji.
RAM wykraczającego poza pojem- w praktyce nie ma to większego init2. W razie konieczności przenie-
ność wbudowaną w kostkę powo- sensu, gdyż dostęp do stosu po- śmy więc nasz kod do następnej
duje samoczynne wygenerowanie przez zewnętrzną magistralę będzie startowej sekcji użytkownika .init3.
odpowiedniej sekwencji sygnałów znacznie wolniejszy, co pogorszy Można też zamiennie dołączyć
na magistrali ext ram. Nie są więc efektywność całego programu. do projektu mały moduł assemblero-
potrzebne (w przeciwieństwie do Przy takim przemieszczeniu wy, który realizuje tylko to zadanie:
// uruchomienie ext ram:
np. '51) żadne oddzielne instrukcje sekcji danych musimy samodziel-
#include
maszynowe. Wynika stąd od razu, nie zadbać o odpowiednio wcze-
.global MemInit
że AVR GCC może taką pamięć sne uruchomienie magistrali ext .section.init1, ax ,@progbits
obsługiwać na zwykłych zasadach, ram musi być ona aktywna
MemInit:
ldi r24,0x80
bez żadnych dodatkowych adapta- już w momencie inicjalizacji da-
out _SFR_IO_ADDR(MCUCR),r24
ldi r24,_BV(SRW00)
cji. Jeśli jednak przypomnimy oma- nych .data oraz zerowania ob-
sts XMCRA,r24
ldi r24,_BV(XMBK)
wiany wcześniej schemat domyślne- szaru .bss. Zwykłe wpisanie kon-
sts XMCRB,r24
go podziału RAM na sekcje (.data, figuracji magistrali na początku
.bss, .noinit, stos) od razu stwier- naszego programu nie wystarczy, ale tu już musimy sami pamię-
dzimy, że obszar zewnętrzny jest gdyż (jak widzieliśmy w podglą- tać o rozmieszczeniu SFR w prze-
ulokowany poza stosem i nie będzie dzie assemblera) kod inicjalizacji strzeniach IO oraz extended sfr
mógł być bezkolizyjnie wykorzysta- (__do_copy_data oraz __do_cle- i stosować odpowiednie instrukcje
ny przez linker. Mamy do dyspo- ar_bss) wykonywany jest przed (out albo sts).
zycji kilka sposobów uniknięcia wejściem do funkcji main. Musi- Jerzy Szczesiul, EP
tej przeszkody. Jeden z najczęściej my zmodyfikować jedną z sekcji jerzy.szczesiul@ep.com.pl
stosowanych to poinstruowanie lin- startowych (podział samoczynnie
kera o nowym, pasującym do przy- tworzonych sekwencji rozpoczyna- UWAGA!
Środowisko IDE dla AVR GCC opracowane
gotowanego sprzętu rozmieszczeniu jących i kończących program na
przez autora artykułu można pobrać ze
sekcji. Służą do tego odpowiednie sekcje startowe init0...init9 i zamy-
strony http://avrside.ep.com.pl.
opcje linii komend AVR GCC: kające fini0...fini9 jest dokładnie
Elektronika Praktyczna 3/2006
108
Wyszukiwarka
Podobne podstrony:
kolo 03 2006
LBB9600 15 03 2006 PA PL F
LBC3483 15 03 2006 PA PL F
LBC3011 x1 15 03 2006 PA PL F
LBC3482 15 03 2006 PA PL F
LBC3086A 15 03 2006 PA PL F
LB1 UW06x x 15 03 2006 PA PL F
LBC1227 15 03 2006 PA PL F
LBC1256 15 03 2006 PA PL F
LB1 BW12 x 15 03 2006 PA PL F
LA1 UW24 x 15 03 2006 PA PL F
LBC1080 15 03 2006 PA PL F
LBC340x 15 03 2006 PA PL F
LB1 UW06 Fx 15 03 2006 PA PL F
LB1 CW06 x 15 03 2006 PA PL F
LBB1949 15 03 2006 PA PL F
więcej podobnych podstron