www.elektronik.si Seznam forumov www.elektronik.si
Forum o elektrotehniki in računalništvu
 
 PomočPomoč  IščiIšči  Seznam članovSeznam članov  SkupineSkupine  StatisticsStatistika  AlbumAlbum  DatotekeFilemanager DokumentacijaDocDB LinksPovezave   Registriraj seRegistriraj se 
  PravilaPravila  LinksBolha  PriponkePriponke  KoledarKoledar  ZapiskiZapiski Tvoj profilTvoj profil Prijava za pregled zasebnih sporočilPrijava za pregled zasebnih sporočil PrijavaPrijava 

Spreminjanje internega sklada na AVR-u

 
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> AVR, LPC900, x51
Poglej prejšnjo temo :: Poglej naslednjo temo  
Avtor Sporočilo
clownfish
Član
Član



Pridružen-a: Pet 05 Avg 2005 13:05
Prispevkov: 765
Aktiv.: 3.23
Kraj: Povir / Ljubljana

PrispevekObjavljeno: Ned Jun 28, 2009 10:26 am    Naslov sporočila:  Spreminjanje internega sklada na AVR-u Odgovori s citatom

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
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Slemi
Član
Član



Pridružen-a: Pet 29 Okt 2004 13:29
Prispevkov: 386
Aktiv.: 1.63
Kraj: Hrastnik

PrispevekObjavljeno: Ned Jun 28, 2009 12:11 pm    Naslov sporočila:   Odgovori s citatom

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
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo AIM - AOL Instant - naslov MSN Messenger - naslov
dragoon
Član
Član



Pridružen-a: Čet 03 Maj 2007 21:51
Prispevkov: 452
Aktiv.: 2.05
Kraj: Trojane

PrispevekObjavljeno: Ned Jun 28, 2009 2:15 pm    Naslov sporočila:   Odgovori s citatom

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.


pr_rtx.zip
 Opis:

Download
 Ime datoteke:  pr_rtx.zip
 Velikost datoteke:  17.01 KB
 Downloadano:  9 krat


_________________
LP, Mitja
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo MSN Messenger - naslov
GJ
Član
Član



Pridružen-a: Čet 02 Nov 2006 15:51
Prispevkov: 946
Aktiv.: 4.17
Kraj: Ljubljana

PrispevekObjavljeno: Ned Jun 28, 2009 2:20 pm    Naslov sporočila:  Re: Spreminjanje internega sklada na AVR-u Odgovori s citatom

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
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Silvo
Moderator
Moderator



Pridružen-a: Pon 24 Feb 2003 17:09
Prispevkov: 14673
Aktiv.: 61.93
Kraj: Koroška-okolica Dravograda

PrispevekObjavljeno: Ned Jun 28, 2009 3:39 pm    Naslov sporočila:   Odgovori s citatom

"Š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
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
clownfish
Član
Član



Pridružen-a: Pet 05 Avg 2005 13:05
Prispevkov: 765
Aktiv.: 3.23
Kraj: Povir / Ljubljana

PrispevekObjavljeno: Ned Jun 28, 2009 5:44 pm    Naslov sporočila:  Re: Spreminjanje internega sklada na AVR-u Odgovori s citatom

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
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
GJ
Član
Član



Pridružen-a: Čet 02 Nov 2006 15:51
Prispevkov: 946
Aktiv.: 4.17
Kraj: Ljubljana

PrispevekObjavljeno: Ned Jun 28, 2009 6:30 pm    Naslov sporočila:  Re: Spreminjanje internega sklada na AVR-u Odgovori s citatom

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
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
clownfish
Član
Član



Pridružen-a: Pet 05 Avg 2005 13:05
Prispevkov: 765
Aktiv.: 3.23
Kraj: Povir / Ljubljana

PrispevekObjavljeno: Pon Jun 29, 2009 10:01 am    Naslov sporočila:  Re: Spreminjanje internega sklada na AVR-u Odgovori s citatom

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.. Brick wall
Nazaj na vrh
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
GJ
Član
Član



Pridružen-a: Čet 02 Nov 2006 15:51
Prispevkov: 946
Aktiv.: 4.17
Kraj: Ljubljana

PrispevekObjavljeno: Pon Jun 29, 2009 1:41 pm    Naslov sporočila:  Re: Spreminjanje internega sklada na AVR-u Odgovori s citatom

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
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
clownfish
Član
Član



Pridružen-a: Pet 05 Avg 2005 13:05
Prispevkov: 765
Aktiv.: 3.23
Kraj: Povir / Ljubljana

PrispevekObjavljeno: Sre Jul 01, 2009 10:28 pm    Naslov sporočila:  Re: Spreminjanje internega sklada na AVR-u Odgovori s citatom

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
Odsoten Poglej uporabnikov profil Pošlji zasebno sporočilo
Pokaži sporočila:   
Objavi novo temo   Odgovori na to temo   Printer-friendly version    www.elektronik.si Seznam forumov -> AVR, LPC900, x51 Časovni pas GMT + 2 uri, srednjeevropski - poletni čas
Stran 1 od 1

 
Pojdi na:  
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