Janez Puhan
posodobljeno 9.11.2011 |
Primer uporabe preprostega operacijskega sistemaIzvorna koda je napisana za Philipsov mikrokrmilnik LPC2138, ki temelji na centralnem procesnem jedru ARM7TDMI-S. Prikazuje primer regulacije svetlosti žarnice. Svetlost žarnice se povečuje s povečevanjem kota odprtja, in zmanjšuje z zmanjševanjem kota odprtja triaka v pomožnem vezju (slika 1). Mikrokrmilnik ves čas pregleduje stanje treh tipk T0, T1 in T3, ki se nahajajo na osnovni plošči učnega razvojnega sistema Šarm. Ob pritisku na tipko T0 se prične svetlost zmanjševati, ob pritisku na T1 pa povečevati. Zmanjševanje, oziroma povečevanje traja toliko časa, dokler ni pritisnjena tipka T3, ki pomeni zaustavitev trenutnega ukaza. Tako mikrokrmilnik skrbi za pravilne trenutke odprtja triaka.
Inicializacija mikrokrmilnikaOb zagonu se izvrši ukaz na naslovu 0x00000000. Izvajati se prične koda, ki se nahaja na naslovu reset: v datoteki crt0.s. Najprej se koda programa prepiše iz pomnilnika flash v pomnilnik RAM, kar kasneje omogoči hitrejše delovanje. Vsa programska koda, ki se ne nahaja v datoteki crt0.s, bo tekla iz pomnilnika RAM. Da je to mogoče, morajo biti temu ustrezno napisana navodila povezovalniku (datoteka iSLPC2138_WinIDEA.ld). Če količina pomnilnika RAM ne zadostuje, mora programska koda pač teči iz pomnilnika flash. Da to dosežemo, je potrebno malce spremeniti navodila prevajalniku. In sicer je potrebno vse .text odseke izven datoteke crt0.s preseliti v pomnilnik flash. Spremenjen del datoteke iSLPC2138_WinIDEA.ld bi v tem primeru izgledal takole:
Koda v datoteki
crt0.s se ne spremeni. Po prepisovanju programske kode je na vrsti
postavljanje začetnih vrednosti kazalcev sklada. V našem primeru so postavljeni
kazalci za vse načine delovanja, čeprav bomo uporabljali le irq in uporabniški
način delovanja. Kazalci sklada v ostalih načinih delovanja so sicer
inicializirani, vendar v našem primeru nikdar uporabljeni. Sledi skok v
funkcijo
start_up(), ki se nahaja v datoteki
startup.c. S tem smo zapustili zbirnik in se preselili v programski
jezik C.
Inicializacija mikrokrmilnika se nadaljuje s klicem funkcije init(). Argumenti funkcije podajajo želene hitrosti vodil, oziroma želeno frekvenco urinega signala, ter uporabljene vhodne in izhodne pine. Koda je parametrizirana, tako da lahko uporabnik omenjene parametre nastavlja na enem mestu v glavi datoteke.
Funkcija
init() se nahaja v datoteki
init.c in kliče ostale funkcije, ki inicializirajo posamezne sklope
mikrokrmilnika (PLL - Phase Locked Loop, VPB - VLSI Peripherial Bus, MAM -
Memory Acceleration Module in GPIO - General Purpose Input Output). Po končani
inicializaciji se ob klicu funkcije
sch_on() dvigne mehanizem operacijskega sistema, ki bo opisan v
nadaljevanju. Sledi glavni program, ki pa ga v našem primeru pravzaprav ni.
Namesto njega imamo neskončno zanko
saj se funkcija
start_up() nikdar ne konča.
Preprost operacijski sistem v realnem časuKoda operacijskega sistema se nahaja v datoteki rtos.c. Jedro sistema predstavlja enostaven razvrščevalnik, ki je napisan v funkciji sch_int(). Razvrščevalnik je klican v enakomernih časovnih intervalih s pomočjo prekinitev Timer0. Zagotavlja, da je vsako opravilo (opravila so funkcije navedene v urniku sch_tab) klicano enkrat v določenem časovnem intervalu. To pomeni, da naš operacijski sistem deluje v realnem času. Zaradi preprostosti sistema veljajo zanj štiri omejitve:
rtos_tasks.h:
rtos_tasks.c:
Operacijski sistem
ne teče sam od sebe. Zagon operacijskega sistema se izvrši ob klicu funkcije
sch_on(), ki je klicana iz funkcije
start_up() v datoteki
startup.c. Funkcija
sch_on() z ustreznimi klici drugih funkcij poskrbi za nastavitve
časovnika Timer0 in vektorskega nadzornika prekinitev (VIC - Vector Interrupt
Controller). Morda najpomembnejše pa je, da s tem postavimo tudi dolžino ene
časovne rezine, ki jo je mogoče nastavljati v glavi datoteke
startup.c s parametrom
V našem primeru je dolžina časovne rezine torej
10ms. Ker imamo dve opravili, je vsako
na vrsti enkrat na
Dt =
20ms.
OpraviliImamo dve opravili, in sicer sta to funkciji keys() in turn_on(). Njuna koda se nahaja v datoteki main.c. Dolžina časovne rezine omejuje dožino opravil. Funkciji keys() in turn_on() se morata zato tudi v najslabšem primeru končati vedno prej kot v 10ms.Funkcija keys() vsakič odčita stanje tipk T0, T1 in T3. Glede na zadnjo pritisnjeno tipko poveča, ali zmanjša vrednost globalne spremenljivke turn_on_level, ki določa kot odprtja triaka. Če je bila zadnja pritisnjena tipka T3, potem ostane spremenljivka turn_on_level konstantna. Da se kot odprtja nebi prehitro spreminjal, se povečevanje oziroma zmanjševanje zgodi le na vsakih keys_counter_stop klicev opravila (v našem primeru je keys_counter_stop = 500, opravilo pa je klicano na vsakih 20ms, torej se turn_on_level spremeni na vsakih 500 * 20ms = 10ms). Drugo opravilo turn_on() na vhodnem pinu p0.4 zazna prehod omrežne napetosti preko ničle. Prehod preko ničle sproži začetek štetja števca turn_on_counter, ki šteje klice opravila. Torej se poveča za ena na vsakih 20ms. Ko števec doseže vrednost spremenljivke turn_on_level, funkcija s postavitvijo pina p0.5 na ena odpre triak, ki seveda ostane odprt do konca polperiode. Razmere ponazarja slika 3.
|