Ne, interapt ne cuva STATUS (ni ostale registre) automatski niti (bar u 16F seriji) ih moze sacuvati na steku, vec se za njihovo cuvanje i povracaj uglavnom primenjuje sledeci kod:
Code:
cblock 0x70 ; definisanje pocetka registara - registri zajednicki za sve banke
W_TEMP ; W_TEMP sa ovakvim algoritmom mora biti deljiv izmedju svih banki
STATUS_TEMP ; STATUS_TEMP moze se nalaziti bilo gde u Bank 0.
PCLATH_TEMP ; PCLATH_TEMP se takodje moze nalaziti bilo gde u Bank 0
endc ; kraj imenovanja registara
_interrupt
MOVWF W_TEMP ;Copy W to W_TEMP register
SWAPF STATUS,W ;Swap status to be saved into W
CLRF STATUS ;bank 0, regardless of current bank, Clears IRP,RP1,RP0
MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register
MOVF PCLATH, W ;Only required if using pages 1, 2 and/or 3
MOVWF PCLATH_TEMP ;Save PCLATH into PCLATH_TEMP register
CLRF PCLATH ;Page zero, regardless of current page
;
;(ISR) ;(Insert user code here)
;
MOVF PCLATH_TEMP, W ;Restore PCLATH
MOVWF PCLATH ;Move W into PCLATH
SWAPF STATUS_TEMP,W ;Swap STATUS_TEMP register into W
;(sets bank to original state)
MOVWF STATUS ;Move W into STATUS register
SWAPF W_TEMP,F ;Swap W_TEMP
SWAPF W_TEMP,W ;Swap W_TEMP into W
retfie ; return from interrupt
On se samo iskopira, i to je to. Cela filozofija. Interapti ni ne mogu predstavljati problem (osim ako njihov kod nije duzi od 2Kb) jer se uglavnom stavljaju na pocetku memorije, a pocetak glavnog programa pocinje nakon njihovog kraja.
16F serija ima samo dve specijalne flash adrese, a to su reset vektor (adresa 0x00) i interapt vektor (0x04). Uglavnom se odmah od pocetka interapt vektora postavlja interapt rutina, a na njenom kraju nadovezuje se glavni program. To izgleda otprilike ovako:
Code:
ORG 0x000 ; processor reset vector
goto _main ; go to beginning of program
ORG 0x004 ; interrupt vector location
; Ovde odmah pocinje interapt rutina
_interrupt ; sa gornjim snimanjem i povracajem registara
MOVF PCLATH_TEMP, W ;Restore PCLATH
...
retfie ; povratak iz interapta
_main ; pocetak glavnog programa
...
Cela 16F serija uopste nema instrukcija za pristup steku. On se spolja ne moze videti, a koriste ga jedino interapt i CALL instrukcija (i naravno, odgovarajuce instrukcije povratka) za cuvanje adrese povratka. 16F serija ima samo 8 nivoa steka.
Harvardski set instrukcija podrazumeva da se unutar instrukcije nalazi kod instrukcije (po kome se CALL instrukcija razlikuje od GOTO), i operand sa kojim se radi (adresa, registar, bajt, bit, odrediste rezultata). Postoje i instrukcije sa vise operanda.
CALL instrukcija izgledala bi ovako:
kod . . operand - apsolutna adresa skoka
100 . kkkkkkkkkkk
Od GOTO instrukcije ona se razlikuje jedino po kodu instrukcije koji je za GOTO 101
Instrukcija povratka iz potprograma RETURN koja nema ikakav operand izgleda ovako:
. . . . kod
00000000001000
Instrukcija za brisanje registra CLRF (upis vrednosti 0x00) izgleda ovako:
. kod . . . operand - RAM adresa
000001 . . fffffff
Ono sto je svim instrukcijama zajednicko je fiksna duzina instrukcija (14 bitova). Kako su za kod CALL i GOTO instrukcija utrosena 3 bita, ostaje ih samo 11 za adresiranje apsolutne adrese. 11 bitova = 2Kb. Sve sto prelazi ovakvu stranicu (Program Counter je trinaestobitni, pa moze adresirati do 8Kb flasha sto je maksimum za 16F seriju) mora updatovati PCH preko PCLATH registra.
Ukoliko se pogleda CLRF instrukcija, primecuje se da je kod instrukcije zauzeo 7 bitova, tako da ih je ostalo samo 7 za adresiranje RAM memorije. 7 bitova = 128 bajtova. Sve preko toga resava se preko banaka (4 banaka * 128 bajtova je maksimalna RAM memorija za 16F seriju).
Za pointere unutar RAM memorije najprakticnije je koristiti njeno indirektno adresiranje. Medjutim, tu veliko ogranicenje predatavljaju banke, jer se RAM ne moze samo tako nadovezati iz jedne u drugu banku. Ovo ogranicenje postoji jer je unutar svake banke pocetni deo (0x00 - 0x1F ili 0x00 - 0x0B u zavisnosti od tipa mikrokontrolera) svake banke rezervisan za registre specijalne namene. Kako se njima direktno upravlja integrisanim hardverskim modulima, kompajler bi za pointere morao ili koristiti neprekidan RAM unutar jedne banke (najbrzi i najoptimizovaniji metod), ili koristiti komplikovanije procedure za virtuelno spajanje ovako izdeljene RAM memorije.
Jos jedna stvar koja je nezgodna kod PIC16 serije je upotreba instrukcija grananja. Naime, one preskacu narednu instrukciju (samo narednu instrukciju, nema relativnog +- skoka) u slucaju da je odgovarajuci uslov ispunjen. To se pak moze resiti upotrebom dve GOTO instrukcije odmah nakon instrukcija grananja, a jos bolje bi bilo da kompajler prepozna ovu situaciju i da u cilju bolje optimizacije koda stavi samo jednu GOTO instrukciju (neposredno nakon instrukcije grananja - onu koja ce biti preskocena ako je uslov ispunjen) i da odmah nakon nje nastavi sa drugim delom (koji se izvrsava ukoliko je uslov ispunjen).
[Ovu poruku je menjao Stojan Trifunovic dana 24.07.2008. u 23:06 GMT+1]
[Ovu poruku je menjao Stojan Trifunovic dana 24.07.2008. u 23:13 GMT+1]