 |
www.elektronik.si Forum o elektrotehniki in računalništvu
|
Poglej prejšnjo temo :: Poglej naslednjo temo |
Avtor |
Sporočilo |
clownfish Član

Pridružen-a: Pet 05 Avg 2005 13:05 Prispevkov: 765 Aktiv.: 3.23 Kraj: Povir / Ljubljana
|
Objavljeno: Ned Jun 28, 2009 10:26 am Naslov sporočila: Spreminjanje internega sklada na AVR-u |
|
|
Programiram v C-ju (ICC AVR) in bi rad v interuptni rutini pred zaključkom na sklad urinil naslov rutine kamor naj se program vrne po zaključku interupta.
Torej, da potegnem iz sklada originalen naslov za vračanje, vrinem naslov neke rutine in spet porinem nazaj originalen naslov za vračanje.
Primer ki bi ga rad izvedel:
Timer interupt dela RTC interupte vsake 1/64s. Z tem torej generiram RTC in neke interne timerje.
Vsake toliko pa bi moral ob določenem pogoju ki je odvisen od neke ure sprožiti nek program, ki traja nekaj časa. Več kot 1/64sekunde.
Torej če ga kličem iz interupta se zna zgoditi, da bo izvajanje le tega trajalo predolgo.
Tako pa bi na sklad vrinil naslov te rutine, ob zaključku interupta pa bi skočil v to rutino, medtem ko bi se naslednji interupt normalno izvedel.
Jasno lahko bi to izvedel tudi v Main programu a tam imam spet drug program ki včasih v raznih zankah čaka, da pritisneš tipko in podobno. Prav zato se mi izvajanje tega programa zamakne kar pa nočem.
V asemblerju na 8031 družini sem to včasih uporabil in je bila zelo praktična bližnjica.. na AVR-u pa tega še nisem počel..
Lahko bi se lotil tudi kakšnega multitasking AVR OS a mislim, da bi na ta način vse skupaj elegantno in funkcionalno rešil.
Kakšna ideja?
P.S: Sicer se skoraj isto vprašanje postavil že v temi:
http://www.elektronik.si/phpBB2/viewtopic.php?t=16179
a še sedaj nimam odgovora kako naj to izvedem.. torej vrivanje na sklad..
|
|
Nazaj na vrh |
|
 |
Slemi Član

Pridružen-a: Pet 29 Okt 2004 13:29 Prispevkov: 386 Aktiv.: 1.63 Kraj: Hrastnik
|
Objavljeno: Ned Jun 28, 2009 12:11 pm Naslov sporočila: |
|
|
Poskusi na tak način, da za vsak interupt RTC povečaš neko spremenljivko, potem pa v glavnem programu izvedeš kar pač mora interupt izvesti in zmanjšaš spremenljivko za ena. Tako lahko izvedeš kar moraš v interuptu in pač vrineš tisto kar imaš.
Upam da razumeš princip.
LP
|
|
Nazaj na vrh |
|
 |
dragoon Član


Pridružen-a: Čet 03 Maj 2007 21:51 Prispevkov: 452 Aktiv.: 2.05 Kraj: Trojane
|
Objavljeno: Ned Jun 28, 2009 2:15 pm Naslov sporočila: |
|
|
pripenjam primer RTOSa za avrje za CV in ICC. primer je skompajlan z CodeVisionom, je deloval ko sem se ukvarjal s tem, detajle pa sem od takrat že pozabil. mogoče ti kaj pomaga.
Opis: |
|
 Download |
Ime datoteke: |
pr_rtx.zip |
Velikost datoteke: |
17.01 KB |
Downloadano: |
9 krat |
_________________ LP, Mitja |
|
Nazaj na vrh |
|
 |
GJ Član


Pridružen-a: Čet 02 Nov 2006 15:51 Prispevkov: 946 Aktiv.: 4.17 Kraj: Ljubljana
|
Objavljeno: Ned Jun 28, 2009 2:20 pm Naslov sporočila: Re: Spreminjanje internega sklada na AVR-u |
|
|
teslo je napisal/a: |
Programiram v C-ju (ICC AVR) in bi rad v interuptni rutini pred zaključkom na sklad urinil naslov rutine kamor naj se program vrne po zaključku interupta. |
Pristop je popolnoma zgrešen!
teslo je napisal/a: |
Torej, da potegnem iz sklada originalen naslov za vračanje, vrinem naslov neke rutine in spet porinem nazaj originalen naslov za vračanje. |
Sklad oziroma stack deluje po načelu: LIFO
teslo je napisal/a: |
Torej če ga kličem iz interupta se zna zgoditi, da bo izvajanje le tega trajalo predolgo. |
Pa naj se izvede v več delih! V prekinitvi kličeš rutino, v rutini pa sprostiš prekinitve, seveda pa predhodno zagotoviš, da rutina ne kliče ponovno sama sebe, dokler ne konča svojega dela! Pa paziti moraš kako so shranjeni registri osnovnega programa, oziroma kako se restavrirajo ob izhodu prekinitve.
LP GJ
|
|
Nazaj na vrh |
|
 |
Silvo Moderator


 
Pridružen-a: Pon 24 Feb 2003 17:09 Prispevkov: 14673 Aktiv.: 61.93 Kraj: Koroška-okolica Dravograda
|
Objavljeno: Ned Jun 28, 2009 3:39 pm Naslov sporočila: |
|
|
"Šaranje" po skladu pri avr-jih v assemblerju ne predstavlja kakega večjega problema. Le točno moraš vedeti kaj bi rad. Kako bi to izvedel v višjenivojskem jeziku ne vem. Na hitro sem spisal eno testno rutino.
Ob vklopu se zaporedoma vklapljajo pini porta-a. Ko se izvede rutina "PisiSklad" le ta prebere trenutni SP ter popravi sklad. Rutino sem namreno pisal "nižje" (0x1AA), ter iz nje pognal še eno rutino. ret vrača iz sklada novo lokacijo PC-ja tako, tako da se program nadaljuje 0x19 namesto 0x22. Program nikoli ne pride do rjmp GZ.
Koda: |
;Pisanje v sklad
.include "tn26def.inc"
.def tmp=r16
.org 0x0
rjmp GlProg
.org 0x0C
GlProg:
ldi tmp,low(ramend)
out SP,tmp
ldi tmp,0xff
out DDRA,tmp
GZ:
sbi PORTA,0
rcall Pavza1S
in tmp,sp
sbi PORTA,1
rcall Pavza1S
sbi PORTA,2
rcall Pavza1S
sbi PORTA,3
rcall Pavza1S
NovSklad:
sbi PORTA,4
rcall Pavza1S
sbi PORTA,5
rcall Pavza1S
sbi PORTA,6
rcall Pavza1S
sbi PORTA,7
rcall Pavza1S
rcall PisiSklad
rjmp GZ
.org 0x1AA
PisiSklad:
clr XH
in XL,sp
inc XL
ldi tmp,High(NovSklad)
st X+,tmp
ldi tmp,low(NovSklad)
st X+,tmp
clr tmp
out PORTA,tmp
rcall Pavza1S
ret
;-----------------------------------------------------------
;Pavza 1S Oscilator 4Mhz
;-----------------------------------------------------------
Pavza1S:
push r20
push r21
push r22
ldi r20,185
ldi r21,75
ldi r22,21
P_zanka:
dec r20
brne P_zanka
dec r21
brne P_zanka
dec r22
brne P_zanka
pop r22
pop r21
pop r20
ret |
_________________ lp
Silvo |
|
Nazaj na vrh |
|
 |
clownfish Član

Pridružen-a: Pet 05 Avg 2005 13:05 Prispevkov: 765 Aktiv.: 3.23 Kraj: Povir / Ljubljana
|
Objavljeno: Ned Jun 28, 2009 5:44 pm Naslov sporočila: Re: Spreminjanje internega sklada na AVR-u |
|
|
GJ je napisal/a: |
Pristop je popolnoma zgrešen! |
Pristop je pravilen in zagotovo delujoč.
Vse poti vodijo v Rim.. Vendar je ena taka druga drugačna. Če že trdiš, da je pristop zgrešen bi bilo modro od tebe, da bi to tudi utemljil in navedel primer kako to drugače bolje elegantno rešiti..
Citiram: |
Sklad oziroma stack deluje po načelu: |
Hmm.. moja napaka.. res bi moral kar direktno na sklad poriniti dodaten naslov rutine in na koncu slednje ret, ki bi vrnil program spet na mesto kjer ga je interupt prekinil. Jasno bi moral zagotoviti, da bi bili vsi registri ohranjeni..
Citiram: |
Pa naj se izvede v več delih! V prekinitvi kličeš rutino, v rutini pa sprostiš prekinitve, seveda pa predhodno zagotoviš, da rutina ne kliče ponovno sama sebe, dokler ne konča svojega dela! Pa paziti moraš kako so shranjeni registri osnovnega programa, oziroma kako se restavrirajo ob izhodu prekinitve. |
Zanimiv pristop.. lahko malo bolj podrobno razložiš kako sprostiš prekinitev?
glede klica (sama sebe) bi že poskrbel..
ko se interupt sproži se na sklad porine PC, v sami interuptni rutini se pospravijo registri, ki se v sami rutini uporabijo, pred izhodom pa se povrnejo registri nazaj v prvotno stanje, RET oziroma RETI pa nazaj napolne PC in program se izvaja od tam od kjer ga je prekinitev ustavila.
Torej bi moral narediti tako, da bi iz interutne rutine klical to rutino, sprostil interupte?? signaliziral rutini, da se kliče enkrat, skočil vanjo izvedel program in ob koncu sprostil registre in se vrnil nazaj v program.. ??
|
|
Nazaj na vrh |
|
 |
GJ Član


Pridružen-a: Čet 02 Nov 2006 15:51 Prispevkov: 946 Aktiv.: 4.17 Kraj: Ljubljana
|
Objavljeno: Ned Jun 28, 2009 6:30 pm Naslov sporočila: Re: Spreminjanje internega sklada na AVR-u |
|
|
teslo je napisal/a: |
ko se interupt sproži se na sklad porine PC, v sami interuptni rutini se pospravijo registri, ki se v sami rutini uporabijo, pred izhodom pa se povrnejo registri nazaj v prvotno stanje, RET oziroma RETI pa nazaj napolne PC in program se izvaja od tam od kjer ga je prekinitev ustavila. |
Tako nekako...
Če tvoj prevajalnik vse registre shrani na sklad, si na konju! Če pa uporablja še kakšne interne prekinitvene variable, moraš zagotoviti tudi njihovo kopijo/restvariranje!
Algoritem je nekako takšen, če se vsi podatki spravijo na sklad!
1)V prekinitveni rutini preveriš potrebo, če moraš klicati tvojo dodatno rutino v prekinitvi.
2)Preveriš zastavico, ki si jo predhodno določil, če se trenutno ne izvaja.
3)Če je potreba in se ne izvaja, jo kličeš kot navadno proceduro, lahko pa je kar del prekinitvene rutine.
4)Na začetku te procedurem postaviš zastavico, da se rutina izvaja in pobrišeš I (interrupt) zastavico, da so prekinitve sproščene.
5)Ko opraviš delo v tej proceduri moraš na koncu procedure zopet postaviti I zastavico (izklopiš prekinitve), pobrišeš zastavico, da si v dadatni rutini in se vrneš nazaj v prekinitveno rutino.
P.S.
Ponavadi se preverja in kliče takšne procedure čisto na koncu prekinitvene rutine!
Sklad mora biti dovolj velik, da lahko v njem spraviš dvakrat vse podatke o prekinitvi!
LP GJ
|
|
Nazaj na vrh |
|
 |
clownfish Član

Pridružen-a: Pet 05 Avg 2005 13:05 Prispevkov: 765 Aktiv.: 3.23 Kraj: Povir / Ljubljana
|
Objavljeno: Pon Jun 29, 2009 10:01 am Naslov sporočila: Re: Spreminjanje internega sklada na AVR-u |
|
|
GJ je napisal/a: |
Tako nekako...
Če tvoj prevajalnik vse registre shrani na sklad, si na konju! Če pa uporablja še kakšne interne prekinitvene variable, moraš zagotoviti tudi njihovo kopijo/restvariranje! |
Jasno..
Bom pognal simulacijo programa v AVR studiu in videl kaj dela moj prevajalnik torej kako prevede kodo..
Citiram: |
Algoritem je nekako takšen, če se vsi podatki spravijo na sklad!
1)V prekinitveni rutini preveriš potrebo, če moraš klicati tvojo dodatno rutino v prekinitvi.
2)Preveriš zastavico, ki si jo predhodno določil, če se trenutno ne izvaja.
3)Če je potreba in se ne izvaja, jo kličeš kot navadno proceduro, lahko pa je kar del prekinitvene rutine.
4)Na začetku te procedurem postaviš zastavico, da se rutina izvaja in pobrišeš I (interrupt) zastavico, da so prekinitve sproščene.
5)Ko opraviš delo v tej proceduri moraš na koncu procedure zopet postaviti I zastavico (izklopiš prekinitve), pobrišeš zastavico, da si v dadatni rutini in se vrneš nazaj v prekinitveno rutino. |
I zastavica?
Kej jo najdem??
Predvidevam, da to procesor dela sicer sam ko se iz interuptne rutine vrne z RETI ukazom?
Če pa ročno pobrišem to I zastavico pred vračanjem iz interuptne rutine.. se bodo interupti spet redno "dogajali" vseeno pa je PC še vedno v rutini podaljšanega interupta.. ?
Citiram: |
P.S.
Ponavadi se preverja in kliče takšne procedure čisto na koncu prekinitvene rutine! |
jasno..
Citiram: |
Sklad mora biti dovolj velik, da lahko v njem spraviš dvakrat vse podatke o prekinitvi! |
poznam to.. drugače se dogajajo res čudne stvari.. programu se kar nekaj trga..
|
|
Nazaj na vrh |
|
 |
GJ Član


Pridružen-a: Čet 02 Nov 2006 15:51 Prispevkov: 946 Aktiv.: 4.17 Kraj: Ljubljana
|
Objavljeno: Pon Jun 29, 2009 1:41 pm Naslov sporočila: Re: Spreminjanje internega sklada na AVR-u |
|
|
teslo je napisal/a: |
I zastavica?
Kej jo najdem??
Predvidevam, da to procesor dela sicer sam ko se iz interuptne rutine vrne z RETI ukazom? |
Ukaz reti samodejno pobriše zastavico I.
Vendar se ta zastavica nahaja v nekem procesorskem registru, ponavadi tam kjer se nahajta tudi Carry in pa Zero zastavici. Poglej v datasheet od procesorja, oziroma mora biti zastavica I deklarirana v eni od C-jevskih datotek.
teslo je napisal/a: |
Če pa ročno pobrišem to I zastavico pred vračanjem iz interuptne rutine.. se bodo interupti spet redno "dogajali" vseeno pa je PC še vedno v rutini podaljšanega interupta.. ? |
Tako je!
Še nekaj zelo važnega moraš sedaj vedeti.
Ti boš imel sedaj tri programe! Glavni program je lahko prekinjen na poljubnem naslovu, da se izvede prekinitev.
Če bereš v glavnem programu variable od ostalih prekinitvenih rutin oziroma, če prekinitvene rutine berejo variable glavnega programa boš potreboval sinhronizacijo.
Pravzaprav je sinhronizacija potebna le pri variablah, ki so daljše od 1 byta.
Oziroma pri variablah, ki jih ne moreš z enim atomarnim cpu ukazom prebrati/vpisati.
Kje lahko občasno nastane problem?
Recimo, da bereš 16 bitni števec iz glavnega programa, ki ga vpisuje (povečuje) prekinitvena rutina. Ko glavni program prebere prvi byte se takoj za tem lahko zgodi prekinitev, ki spremeni vrednost te varible. Ko se glavni program nadaljuje prebere še drugi byte. Prebrani podatek je lahko povsem nepravilen.
PRIMER:
Recimo, da ima 16 bitni števec vrednost 0x00FF. Mi smo prebrali high byte in ima vrednost nič. Nakar se zgodi prekinitev in poveča števec za ena, nova vrednost je sedaj 0x0100. Ko se glavni program nadaljuje prebere še preostali byte in prebrana vrednost variablre je tako 0 namesto 256.
Sinhroniziraš branje ali pisanje takole:
1)V glavnem programu izklopiš prekinitve (I zastavica = 1).
2)Prekopiraš prvi byte 16 bitne variable.
3)Prekopiraš drugi byte 16 bitne variable.
4)V glavnem programu ponovno vklopiš prekinitve (I zastavica = 0).
P.S.
Nekateri procesorji imajo lahko tudi samostojne ukaze za vklapljanje/izklapljanje prekinitev, na primer CLI in pa STI.
LP GJ
|
|
Nazaj na vrh |
|
 |
clownfish Član

Pridružen-a: Pet 05 Avg 2005 13:05 Prispevkov: 765 Aktiv.: 3.23 Kraj: Povir / Ljubljana
|
Objavljeno: Sre Jul 01, 2009 10:28 pm Naslov sporočila: Re: Spreminjanje internega sklada na AVR-u |
|
|
Torej v timer interuptu najprej obnovim timer counter in takoj nato dam SEI saj z tem spet omogočim interupte. Kljub temu bo šel program naprej in se izvajal do konca dokler se ne bo vrnil nazaj iz interuptne rutine.
Sicer se bo vrnil nazaj v glavni program z RETI, ki prav tako omogoči interupte vendar ker smo jih že prej omogočili z SEI ukazom sam RETI ne bo vplival na izvajanje interuptov.
Torej se bo v tem primeru lahko za interuptno rutino izvajala "moja" dodatna rutina in tako se bo zagotovo izvedla za interuptom torej v sami interuptni rutini..
Če pa bo trajanje te podaljšane rutine vzelo preveč časa se bo vseeno vmes še enkrat generiral isti interupt s tem, da se "moj" podaljšek ne bo izvedel.
Po koncu tega vmesnega interupta se bo do konca izvedla podaljšana stara interuptna rutina torej z "mojim" dodatkom..
Edina stvar na katero je potrebno gledati je, da se zagotovi, da se sklad ne "povozi" saj se v tem primeru dogajajo "čudne" stvari...
|
|
Nazaj na vrh |
|
 |
|
|
Ne, ne moreš dodajati novih tem v tem forumu Ne, ne moreš odgovarjati na teme v tem forumu Ne, ne moreš urejati svojih prispevkov v tem forumu Ne, ne moreš brisati svojih prispevkov v tem forumu Ne ne moreš glasovati v anketi v tem forumu Ne, ne moreš pripeti datotek v tem forumu Ne, ne moreš povleči datotek v tem forumu
|
Uptime: 494 dni
Powered by phpBB © 2001, 2005 phpBB Group
|