Optmalizacja pod względem czasu.pdf

(85 KB) Pobierz
Programowanie optymalne
http://www.easy-soft.tsnet.pl/
Programowanie zoptymalizowane pod względem
wykorzystania czasu procesora
1. Wstęp.
W artykule chcę przedstawić moje sposoby na programowanie mikrokontrolerów
jednoukladowych (8051, PIC i podobne) w języku asemblera - ze szczególnym
zwróceniem uwagi na jak najmniejsze obciążenie procesora przez dużą liczbę
podprogramów (współdzielenie czasu procesora). Takie podejście sprawia, że układ
mikroprocesorowy staje się jakby układem wielozadaniowym, a przy okazji zostaje
zminimalizowane niebezpieczeństwo zawieszania się programów i utknięcia całości w
martwym punkcie. Z pewnością wiele z przedstawionych poniżej sposobów i sposobików
będzie Wam znanych, część być może bedzie nowych - generalnie chodzi jednak o
całościowe uświadomienie sobie takiej koncepcji programowania tak, aby później można
ją było świadomie stosować w praktyce (programowanie: od koncepcji do realizacji).
Opisane tu sposoby będą przydatne zwłaszcza przy pisaniu większych programów, gdzie
się "wiecej dzieje jednocześnie", ale mogą być również stosowane przy prostszych
programach. Tyle tytułem wstępu - chciałbym jednocześnie zachęcić wszystkich
programujących do opisywania własnych sposobów na programowanie - zwłaszcza o
opisy koncepcji, podejścia do problemu i jego rozwiązania, bo dostępne jest mnóstwo
przykładów, fragmentów procedur, etc ,etc, ale brak jest bardziej ogólnych zasad
programowania, a wydaje mi się że zapotrzebowanie na tego rodzaju literaturę jest
bardzo duże.
2. Uświadomienie sobie problemu to już połowa sukcesu.
Przeważnie piszący programy skupiają się na sposobie rozwiązania problemu - jak
najprościej (jeśli nie "jak w ogóle") napisać programik, który będzie realizował
przewidziane przez nich zadanie. Jest to podejście słuszne, aczkolwiek "mikroskopowe".
Trochę na zasadzie: " bierze się procedurę obsługi I2C, do tego dodaje obsługę
klawiatury, wyświetlacza LCD, łączy sie razem i mamy programik". Potrzebne jest
również myślenie "makroskopowe", które będzie nadrzędne, będzie obejmowało całość
koncepcji programu. Jednym słowem - planowanie. Oczywiście ma to szczególnie sens
przy większych programach, gdzie łatwo się jest pogubić w gąszczu procedurek, etykiet,
skoków, itp...
Częstokroć skupiając się na problemie bieżącym zapominamy o całości programu i o tym
jaki wpływ na pozostałe procedury i programy bedzie miala opracowywana przez nas
procedura. W skrajnym przypadku może to prowadzić do powstania sytuacji, kiedy
napisane przez nas programy - każdy oddzielnie, działają prawidłowo, ale kiedy
połączymy je wszystkie razem, to okazuje się, ze wzajemnie zakłócaja sobie pracę. W
rezultacie program nie działa albo działa "skokowo", gubiąc po drodze dane. Jak temu
przeciwdziałać - poniżej.
- strona 1/11 -
305451994.003.png
http://www.easy-soft.tsnet.pl/
3. Wizualizacja koncepcji działania procesora. Martwe pętle.
Dla ułatwienia zrozumienia działania procesora przygotowałem przykład opisowy - tzw.
"przedstawienie łopatologiczne".
Jednym z głównych zadań jakie wykonuje procesor jest tzw. pętla główna. Wyobraźmy ją
sobie jako dośc duży, kwadratowy pokój. Pośrodku pokoju stoi człowieczek, który jest
odpowiednikiem bieżącego procesu wykonywanego przez procesor.
Na początku naszych rozważań nasza pętla głowna jest pusta:
petla_glowna:
nop
goto petla_glowna
Wlączamy zasilanie procesora - teraz nasz czlowieczek zaczyna chodzic sobie wokól
pokoju zupelnie nic nie wykonując - po prostu chodzi w kólko.
Aby dać mu jakieś zajęcie wprowadzamy do akcji podprogramy. Wyobraźmy je sobie
jako pokoje umieszczone wokól naszego głownego pomieszczenia. Nasz czlowieczek
idąc wokół scian, gdy napotyka pokój, wchodzi do niego i wykonuje znalezione tam przez
niego zadanie. Po czym wraca do pokoju głownego, idzie dalej wzdłóż sciany, do
nastepnego pokoju i wykonuje następne zadanie....I tak dalej w kółko...
petla_glowna:
podprogram_1
podprogram_2
podprogram_3
podprogram_4
...
podprogram_n
goto petla_glowna
Na razie sytuacja jest prosta, ale jak to w życiu bywa, zaczynaja sie utrudnienia.:-))
Okazuje się bowiem, że nie zawsze jest możliwa natychmiastowa realizacja zadania
przez procesor (czyli naszego czlowieczka). Nie dowieźli danych i nasz człowieczek musi
czekać na nie ;-). Siada więc sobie gdzieś na krzeselku albo chodzi w kólko po pokoiku
podprogamu.
Wyglada to tak:
petla_glowna:
podprogram_1
podprogram_2
podprogram_3
podprogram_4
...
podprogram_n
goto petla_glowna
podprogram_1:
sprawdz_czy_sa_dane
jesli_nie - goto podprogram_1
jesli_tak - wykonaj podprogram
- strona 2/11 -
305451994.004.png
http://www.easy-soft.tsnet.pl/
i powroc z podprogramu
Jak widzimy nasz czlowieczek uzależniony jest od przeplywu danych, musi siedzieć w
pokoiku i czekać na nie.
A przecież ma do wykonania prace takze w innych pokojach. Może akurat w ktorymś z
nich są juz wszystkie potrzebne dane, a on siedząc tutaj marnuje tylko czas, podczas gdy
moglby wykonać inne zadania.
I tu dochodzimy do własciwego problemu. Sa to wlaśnie tzw. martwe petle podczas
ktorych procesor testuje jakis warunek i czekajac na niego nie wykonuje nic wiecej.
Wprowadzmy wiec usprawnienie. Nasz czlowieczek po wejsciu do kazdego pokoju
bedzie sprawdzal czy sa dla niego dane - jesli beda - wykona zadanie, jesli zas nie -
opusci on pokoj i pojdzie sprawdzac nastepne pokoje. Jesli w ktorymś z nich bedą dane,
bedzie wykonywał swoje tam zadanie.
Tak to wyglada w praktyce:
petla_glowna:
podprogram_1
podprogram_2
podprogram_3
podprogram_4
...
podprogram_n
goto petla_glowna
podprogram_1:
sprawdz_czy_sa_dane
jesli_nie - wyskocz z podprogramu
jesli_tak - wykonaj podprogram
i powroc z podprogramu
W ten sposób nie mamy blokady podprogamów w oczekiwaniu na dane... Nawet gdyby
z jakiś powodów dana ta nie nadeszła nigdy, to program nie zawiesi się w martwej pętli -
pozostałe podprogramy będą się dalej wykonywać bez zakłoceń.
Oczywiście - bywają pewne krytyczne czasowo operacje, które muszą zangażowac całą
moc obliczeniowa procesora, gdyż obsługa w tym czasie innych zadań spowodowałaby
utratę części danych. W tej sytuacji rozsądnym rozwiązaniem tego problemu jest
wykorzystanie przerwań - zwłaszcza gdy dane przychodzą zupelnie asynchroniczne.
- strona 3/11 -
305451994.005.png
http://www.easy-soft.tsnet.pl/
Przekazywanie informacji przez
flagi.
Najprostszym sposobem na sygnalizacje czy wazne dane nadeszly sa flagi. Flaga jest
bitem, ktorego ustawienie lub wyzerowanie informuje procesor o stanie danych. W
postaci programu wyglada to nastepująco:
podprogram_1:
sprawdz_czy_flaga_ustawiona
jesli_nie - wyskocz z podprogramu
jesli_tak - wykonaj podprogram
i powroc z podprogramu
Flaga moze byc ustawiana przez inny podprogram (ten ktory zbiera dla nas dane), jak i
przez nasz wykonawczy podprogram (gdy np. chcemy zasygnalizowac innym
podprogramom, ze wykorzystalismy juz dane i moga one ladowac następną porcję)
podprogram_1:
sprawdz_czy_flaga_ustawiona
jesli_nie - wyskocz z podprogramu
jesli_tak - wykonaj podprogram
zeruj_flage
i powroc z podprogramu
podprogram_2:
sprawdz_czy_flaga_wyzerowana
jesli_nie - wyskocz z podprogramu
jesli_tak - pobierz_dane_i_umiesc_je_w_zmiennych
ustaw_flage
i powroc z podprogramu
W ten sposob jak widzimy następuje dwustronna wymiana informacji pomiedzy
podprogramami - jednocześnie są one na tyle niezależne, że nawet w przypadku blędu
(brak w doplywie nowych danych do programu 2) nie następuje zawieszenie pracy
programu głównego (tak czy tak podprogram zawsze wyskakuje). To pozwala na np.
stworzenie dodatkowego podprogramu monitorujacego, ktory w przypadku wystąpienia
błedu - przywraca normalną pracę systemu (reset programowy - czyszczenie zmiennych,
ponowna inicjalizacja otoczenia, itp)
Flagi mogą być sprawdzane, ustawiane, bądź zerowane przez kilka programów jeśli
korzystają one z tych samych danych.
Czasami zdarza się, że chcielibyśmy mieć kontrolę nad wykonywaniem sie pewnych
podprogramów w odniesieniu do innych
podprogramów. Np. taka sytuacja: jeśli wykonuje sie poprogram nr 1, to w tym czasie
nie powinien sie wykonywać podprogram nr 2, bo oba korzystaja ze wspolnych
zmiennych i moga wystąpic błedy. Taka sytuacja zdarza sie w momencie kiedy jeden z
podprogramów wykonuje się w pętli głównej, a drugi w przerwaniu. Podczas obsługi
przerwania, program z pętli głownej zostaje przerwany "w trakcie" i jest wykonywany
program z przerwania. Jesli istnieje niebezpieczenstwo zamazania danych przez
program z przerwania, nalezy również uzyć flag dla zasygnalizowania tego faktu.
- strona 4/11 -
4.
305451994.006.png 305451994.001.png
http://www.easy-soft.tsnet.pl/
podprogram_2: ; wykonywany w pętli głównej
ustaw_flage_wykonywania_programu
wykonaj_podprogram
wyzeruj_flage_wykonywania_programu
i powroc z podprogramu
podprogram_3: ; wykonywany w przerwaniu
sprawdz_czy_flaga_wykonywania_podprogramu_2_ustawiona
jesli_tak - wyskocz z podprogramu
jesli_nie - wykonaj podprogram
i powroc z podprogramu
W ten sposób jeden podprogram jest zsynchronizowany z drugim - sa wzajemnie
powiazane i nie nastapi nigdy "zderzenie danych".
Za pomoca flag mozna też przekazywac programom informacje o upływie czasu - są to
tzw. znaczniki czasowe.
Zasada jest prosta - jeden z programów (najczęściej jest to program obsługi przerwania,
wywoływany cyklicznie co określony odcinek czasu) po obliczeniu zadanego odcinka czasu
ustawia flage informującą pozostałe programy, ze "czas upłynął".
Podprogram z pętli głównej, testuje cały czas tą flagę i gdy wykryje jej ustawienie -
wykonuje określoną sekwencję działan.
Oto przykład:
podprogram_1: ; wykonywany w przerwaniu
sprawdz_czy_uplynal_zadany_czas
jesli_nie - wyskocz z podprogramu
jesli_tak - ustaw flage TimeOn
i powroc z podprogramu
podprogram_2: ; wykonywany w pętli głównej
sprawdz_flage_TimeOn
jesli nie ustawiona - wyskocz z podprogramu
jesli ustawiona - wykonaj_podprogram i wyzeruj_flage
i powroc z podprogramu
W ten sposob nasz podprogram z pętli głownej wykonuje się np. co 1s, zamiast
wielokrotnie szybciej - nie obciąża to nadmiernie procesora i pozwala na wykonywanie
innych podprogramów w tym czasie. Tego typu zwolnione wykonywanie się programów
ma sens w przypadku np.odczytu pomiarow, gdy nie zalezy nam na duzej ilosci próbek/s
- zwlaszcza gdy do tego dochodzą opóźnienia związane z czasem konwersji wyników
przez urządzenia zewnętrzne.
- strona 5/11 -
305451994.002.png
Zgłoś jeśli naruszono regulamin