31. julija, 2007

Kaj narediti, ko zmanjka RAM-a v mikrokontrolerju?

Slike BTPP BTPP 87 - Kaj narediti, ko zmanjka RAM-a v mikrokontrolerju?Vendar so se mi kmalu začeli javljati tudi drugi – sedaj pa je bilo že potrebno preveriti zadevo! Nekje se je moj Bascom moral razlikovati od ostalih … Po analizi različnih postavk sem zasledil našega “krivca” – skrival se je v meniju: Options -> Compiler -> Misc, v okencu Byte End (slika 2). Tukaj vpisano vrednost je bilo potrebno povečati na 60H. Po tem ni bilo več težav s prevajanjem programa. Do podobnih težav lahko naletite tudi pri drugih programih, če uporabljate večje število spremenljivk, posebej tipa long ali stringove. Seveda 60H v Byte End ni čarobna vrednost in jo je potrebno prilagoditi konkretnim zahtevam programa; za vsak primer vedno izberite najmanjšo številko, s katero se prevajanje še izvaja brez napak.

Slike BTPP BTPP 87a - Kaj narediti, ko zmanjka RAM-a v mikrokontrolerju?Ko smo se že dotaknili te tematike, bi bilo škoda ne zvedeti nekaj več o načinu, v katerem Bascom uporablja razpoložljivih 128 B RAM-a. Po izvršenem prevajanju programa poglejmo nakratko v Bascom Report (File -> Show Result, slika 3). Tu lahko zasledimo veliko uporabnih informacij, med ostalim tudi o razmestitvi v programu določenih spremenljivk znotraj RAM-a. Prostor do 1FH je dodeljen registrom R0-R7 (procesor pozna skupno 4 skupine teh registrov, kar pomeni, da ima skupno 32 registrov). Od 20H naprej Bascom najprej razmešča bitne spremenljivke (bitno naslovljivi so le pomnilniški naslovi do 2FH), zatem pa rezervira nekaj bytov za svoje potrebe – v ta prostor se shranjujejo začasni rezultati, kazalci ipd. Koliko prostora bo rezerviranega, je odvisno od nabora instrukcij, ki jih v programu uporabljamo. Nato sledijo spremenljivke, določene v programu, in na koncu še vse ostale. V našem primeru se začenja prva spremenljivka Stevec na naslovu 32H. Odvisno od tipa zavzemajo spremenljivke en (byte), dva (word) ali štiri (long) byte, kar je lepo razvidno iz izpisa na sliki 3. Stringi zavzemajo po 1 byte več od svoje dejanske dolžine.

Slike BTPP BTPP 87b - Kaj narediti, ko zmanjka RAM-a v mikrokontrolerju?Naslovni prostor nad zadnjo spremenljivko pa vse do konca RAM-a je rezerviran za sklad (stack). Na sklad procesor shranjuje naslove vrnitve pri skoku v podprogram ali pa vsebine registrov pri izvršitvi prekinitvenih rutin. Sklad se polni po načelu LIFO (last in – first out, kar pomeni, da bo prvi shranjeni podatek uporabljen zadnji in obratno). Če malo bolj razmislimo o načinu uporabe sklada, se bo to pokazalo povsem logično. Predpostavimo, da npr. podprogram AA kliče podprogram BB, podprogram BB pa podprogram CC. V tem primeru bo na sklad najprej zapisan naslov vrnitve v glavni program, potem naslov vrnitve v podprogram AA in na koncu, v podprogram BB. Povratni naslovi se bodo s sklada jemali v obrnjenem vrstnem redu: najprej naslov vrnitve v podprogram BB, potem v AA in na koncu v glavni program. Očitno mora sklad biti čim globlji (višji?), da bi lahko uporabljali čim več nivojev podprogramov. Če se vrnemo k našemu primeru je zadnja spremenljivka Disp$$ (na sliki 3 se je ne vidi). V programu je določena kot string dolžine 10 znakov in zavzema skupno 11 bytov, 4AH–54H. Prva nezasedena lokacija RAM-a je torej 55H in tu se zares začenja sklad. Poglejte vrstico:

StackStart : &H55

Glede na vse povedano, bi meja Byte End = 54H morala zadostovati; zaradi rezerve smo nastavili vrednost 60H. Ostaja dejstvo, da sta Byte End in StackStart vezana; če dodate še kako spremenljivko ali spremenite dolžino stringov, se bo to pokazalo na StackStart, ko pa ta preseže določeno vrednost, bo potrebno spremeniti tudi Byte End, kot smo že zapisali. Kako Bascom javlja procesorju začeten naslov pomnilnika, rezerviranega za sklad? Inicializacija sklada se iz Bascoma ne vidi, temveč je potrebno pogledati v prevedeno HEX-kodo (slika 4). Na sliki vidimo rezultat prevajanja enega praznega programa, vpisan je samo ukaz: Dim Aa As Byte. Zanimiv je rezultat prevajanja:

75 81 22

koda je pravzaprav inicializacija sklada na začetni naslov, v tem primeru na 22H (na naslovu 21H se nahaja spremenljivka Aa).

Slike BTPP BTPP 87c - Kaj narediti, ko zmanjka RAM-a v mikrokontrolerju?Koliko prostora na skladu potrebujemo, je odvisno od skupnega števila verižno vezanih podprogramov (klicanje podprograma znotraj podprograma). Vsak klic zavzema po dva byta na skladu, vendar se moramo zavedati tudi tega, da mnogi Bascom ukazi pravzaprav pomenijo skok v eno izmed notranjih Bascom rutin, tako da je niz ponavadi daljši, kot se nam to zdi pri analizi Bascom programa. Običajno ne gremo globlje kot do 3. ali 4. nivoja in če k temu prištejemo še 2–3 nivoje, ki jih Bascom uporablja za klicanje svojih rutin, se bomo ustavili na globini sklada 10–14 bytov. Tudi pri precej kompleksnih programih, če so pazljivo napisani, globina sklada ne bo bistveno večja.

Vendar pa moramo biti pazljivi pri uporabi prekinitvenih rutin. Ena takih prekinitvenih rutin se začenja z nizom Push instrukcij, s pomočjo katerih se vsebine vseh registrov začasno shranijo na sklad, konča pa z nizom Pop instrukcij, s katerimi se vsebine registrov zajemajo s sklada nazaj. To je nujno zaradi zaščite samega programa; prekinitvena rutina se lahko zgodi v katerem koli trenutku, Bascom pa si mora zapomniti trenutno stanje, da bi lahko po končanju prekinitvene rutine nadaljeval z izvajanjem glavnega programa.

Tak varnostni mehanizem ima tudi neželjene posledice. Prva je ta, da shranjevanje registrov na sklad in ponovno obnavljanje njihove vsebine upočasnjuje izvajanje prekinitvene rutine in programa nasplošno; gre za približno 50 izgubljenih mikrosekund. Druga posledica je znatno zasedanje RAM-a, rezerviranega za sklad, in sicer po 13 bytov za eno prekinitveno rutino. Če k temu dodamo še zasedanje sklada, povzročeno z uporabo podprograma, in če se zgodita še dve prekinitvi istočasno, bo sklad presegel razpoložljiv RAM, kar pomeni rušenje programa.