Listing 154 Wypisywanie informacji o pamięci // Rozmiar strony (w bajtach)
r3_puL((SPM_PAGESIZE)40xff) |
rs~put((SPM_PAGESIZE)»8);
// Ilość stron
rs_put((BOOTSTART/2/SPM_PAGESIZE)JrOxff); C3_puL<(BOOTSTART/2/SPM_PAGESrZE)»8);
// Ilość stron eeprom rs_put(C(E2ENC+I)/2/SPM_PAGESIZE)&0xff); re_put C((E2EMC+1)/2/£PM_PAGESI ZE)»8) ;
się funkcja_init(), kompilator umieszcza ją
w taki sposób, że będzie ona wywołana zaraz po rcsccic procesora (patrz tabela 11). Koniecznie musi to być lunkcja z atrybutem naked (goła). Brak tego atrybutu powoduje dodanie przez kompilator dodatkowego kodu, który powoduje zawieszenie aplikacji. Jeśli aplikacja korzysta z WDT, w przypadku wystąpienia jego przerwania ważne jest, aby jak najszybciej powrócić do wykonywanego programu. Ponadto, często w tego typu aplikacji stosuje się zmienne umieszczone w sekcji .noinit, gdzie ważne jest zapamiętanie wartości w chwili wystąpienia zerowania. W miejscu gdzie aplikacja ma takie dane, bootloader może mieć zmienne inicjowane. W takim przypadku gdyby uruchamianie było kontynuowane, wartości zmiennych aplikacji uległyby straceniu. Rozwiązanie z listingu 153 sprawia, że cały bootloader jest bardziej „przezroczysty” dla aplikacji.
Samo przejście w tryb programowania przedstawiam w szarej ramce „Komunikacja z bootloaderem”. Nie będę omawiał tego fragmentu kodu ze względu na to, że nic wnosi on nic nowego. Tak samo pominiemy obsługę komend: „q”, „i” oraz „v”. Są one łatwe do zrozumienia na podstawie udostępnionych kodów.
Ciekawy drobiazg występuje w odpowiedzi na komendę „m" - wypisanie informacji
ABC... GCC
Deklaracja stałych dla preprocesora C z poziomu pliku makefile
Listing 155 Dejiniowome stałych dla kompilatora C
w pliku makefile
# Place D or U optiors here CDEFS = -DF_CPU=$(F_CPU)UL CDEF5 4= -DBOOTSTART=:$ (BOOTSTART)
-Dnazwa=ci ag_znakow odpowiada umieszczeniu w każdym kompilowanym pliku definicji:
#define nazwa ciag_znakow
o organizacji pamięci. Jej zasadniczą część pokazuje listing 154. Interesujący punkt zaznaczyłem kolorem. Obliczanie ilości dostępnych dla aplikacji stron odbywa się na podstawie informacji o miejscu w którym umieszczony został bootloader. Zauważ, że zmienna BOOTSTART została utworzona w pliku makefile i kompilator C nic o mej me wic. Jak więc umożlwić jej wykorzystanie? Rozwiązania są dwa:
1. Zdeklarować zupełnie niezależnie stałą BOOTSTARI w pliku harddef.h.
2. Przesłać wartość zmiennej BOOTSTART do kompilatora C z poziomu pliku makefile.
O ile pierwsze rozwiązanie nie wymaga wyjaśnień, z drugiego jeszcze nie korzystaliśmy. Opis znajduje się, razem z listingiem 155, w niebieskiej ramce.
Ponieważ program był pisany w najprostszy możliwy sposób, dane do zapisu do pamięci są wysyłane w postaci ciągu liczb binarnych. Brak jest jakiegokolwiek zabezpieczenia przed przekłamaniami. Dlatego został wprowadzony mechanizm umożliwiający odczytanie zapisanej strony. Po wysłaniu strony programu a jeszcze przed jej zapisem, program może dokonać sprawdzenia poprawności danych. Praktyczne próby wykazały, że mimo tak prostego rozwiązania, przekłamania podczas transmisji są bardzo rzadkie.
Listing 156 pokazuje część kodu wykonywaną na komendę „F\ Zwróć szczególną uwagę na sposób wykorzystania funkcji z pliku <avr/boot.h>. Takie napisanie bootloadera jest wygodne i bardzo poglądowe.
ABC... OCC
Wsparcie bootloadera
przez aur-libc 1.4
Gdy postanowimy do naszego programu dołączyć plik nagłówkowy <avr/boot.h>, uzyskamy dostęp do wygodnych funkcji umożliwiających napisanie programu ładującego. Dla nas najważniejsze są następujące funkcje:
boot_page_erase(adres) - przygotowuje kasowanie strony. Adres jest adresem bajtowym.
b°ot_page_fill(adres, dana) - wpisuje 16-bitową daną do bufora strony. bo°t_page_write(adres) - zapisuje bufor strony do pamięci FLASH. boot_rw>v_enablc() - odblokowanie zajętej sekcji RWW.
boot_spm_busyO ~ sprawdza, czy instrukcja SPM jest zajęta.
boot_spm_busy_wait() - czeka na zakończenie działania instrukcji SPM.
Program możesz wypróbować razem ze znajdującym się na Elportalu programem służącym do wysyłania kodu programu. Będziesz miał wtedy okazję zauważyć, ze program jest ładowany wyraźnie szybciej niż przez prosty interfejs ISK
Bootloader jest programem, na który mamy niewiele miejsca. Jest to dobre miejsce do wypróbowania swoich możliwości w napisaniu dużego fragmentu kodu w asemblerze. Przepiszemy teraz na asembler funkcję zapisującą bufor do pamięci FLASH.
Rys. 54 Zmiana ustawień dotycząca plików .S
Listing 156 kod komendy ..f uintlG_t page*
// oczekiwanie na potwirdzenie rs_put(‘f’);
if(‘8* != rs_get O)
continue;
// pobranie adresu
page * rs_get();
page 1= (jintl6_t)rs_g«t ()«8 ;
// przesłanie adresu dc kontroli rs_put(page & Oxff); rs_put(paqe » 8):
1* rs_getO) continue;
/////////////////////////////////
// Procedura zapisu
uintI6_t i;
uint3_t* pbufl — y_pdgebufC;
eeprom_busy_waitO; fcoot_paqc_crooc(page)J // Oczekiwanie na skasowanie paaiięci fcoot spra busy wait();
// wypełnianie bufora strony for Ci—0 • i<SPM_PACESIZE; 14-0 {
uintI6 t w = *pbuff++; w +ss (*ph iff44-) « 8; fcoot_pace_fill(page 4 i» w);
)
H zapisanie bufora do-pamięć'
fcoot_page_write(page)i
// Oczekiwanie na zakończenie operacji
toot_spra_busy_waitO;
// Aktywacja sekcji rww
fcoot_rww_enafcleO\
// Koniec zapisu
muitiu/mm/fui/nn/um
// Potwierdzenie dokonania zapisu ta
Elektronika dla Wszystkich Październik 2006 43