Interrupt frågor, AVR

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
Fagge
Inlägg: 3930
Blev medlem: 27 maj 2003, 13:59:51
Ort: Blekinge

Interrupt frågor, AVR

Inlägg av Fagge »

Vad är inte tillåtet att göra i en interrupt rutin?.

Jag har nämligen problem med att interruptrutinen ibland slumpvis fördärvar data i huvud programmet.

Och då frågar ni givetvis…
Har du initierat Stackpekaren = Jepp
Programkoden startar en liten bit in i minnet, eftersom interrupt vectorerna ligger i början av minnet. = Jepp

Register som används under interrupt rutinen Ska först PUSH,as ner i stacken
& POP,as ur precis innan avslut med RETi. = Jepp

Har jag missat något utöver det?.

Är det ok att hoppa till subrutiner, som ligger i huvudprogrammet, förutsatt att alla register som kan tänkas påverkas push,as innan?.

Är det ok att använda hopp & jämförelse instruktioner i interrupt rutinen?.
t.ex.

push r16
push r17
...
CPI r16, r17
BREQ blabla ; om lika hoppa till blabla
reti

blabla:
Inc r16
...
Pop r17
Pop r16
reti


För när man gör sånna jämförelser, så sätts väll olika flaggor.?
Kan man sabba flaggorna i fall interruptet skulle komma mitt i en av huvudprogrammets jämförelse instruktion. & sen utför interrupt rutinen samma instruktion fast med annan data.
Och då när interrupt rutinen är avklarad & programmet återgå, så har flaggorna ändrat sig & fel beslut tas?.
Användarvisningsbild
vfr
EF Sponsor
Inlägg: 3515
Blev medlem: 31 mars 2005, 17:55:45
Ort: Kungsbacka

Inlägg av vfr »

Statusregistret skall inte vara några problem om det är rätt skrivet. Det finns två sätt att hantera det på. Vissa processorarkitekturer sparar automatiskt statusregistret på stacken vid avbrott och återställer vid retur (dom flesta). På andra så får man fixa det själv (PIC16 t.ex). Nu vet jag inte hur AVR gör men det borde finnas exempel på det att utgå ifrån.

Är det ok att hoppa till subrutiner, som ligger i huvudprogrammet, förutsatt att alla register som kan tänkas påverka push,as innan?.

Ja, registerna måste sparas innan eller efter anropet.

Är det ok att använda hopp & jämförelse instruktioner i interrupt rutinen?.
t.ex.


Ja, om statusregistret tas omhand enligt ovan så är det inga problem.
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Som tumregel bör man göra så absolut lite som möjligt i en interruptrutin. Helst bara spara undan data och flagga för det, och sedan låta mainloopen ta hand om och behandla datat.

Du kan väl klistra in hela interruptkoden så kanske nån upptäcker något buggartat?
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Notera att för en mikrokontroller (bör gälla både PIC och AVR) så finns
det igentligen inget "huvudprogram" eller "interruptrutin". Det är bara något
som vi som programmerar dom tror. Processorn "vet" inte hurvida den
ligger i det ena eller det andra.

Ett interrupt är i princip ett CALL som sker asynkront och till en fast adress.
Dessutom manipuleras ofta ett par flaggor, men det är mindre intressant.

Så en fråga som "Är det ok att hoppa till subrutiner, som ligger i huvudprogrammet ?"
alltså inte är riktigt rellevant. Processorn ser igen skillnad. Det finns inget "...ligger i..." .

Det som däremot är rellevant är om du använder *samma* subrutin *både*
från din vanliga kod och från den kod som körs vid ett interrupt. Alltså :

""Är det ok att anropa till subrutiner, som *också* anropas från huvudprogrammet ?"

Ett problem är om denna subrutin "tål" att anropas ytterligare en gång
efter att den redan har anropats en gång ("re-entrance")? Det är väldigt
lätt att inte tänka på t.ex en "temp" variabel som man tycker är helt lokal
till subrutinen. Det kan t.ex vara så att man *vet* att den inte används
någon annanstans i koden, och alltså behövs ingen push/pop av just den!
Men, denna kan lätt skrivas över vid den andra anropet till subrutinen!

Om den inte tål flera anrop så finns det i princip två lösningar :

1. Gör en kopia av subrutinen som enbart anropas från interruptkoden.
2. Stäng av interrupt innan din huvudkod anropar den.

Om man läser ditt inlägg så är dte just det ovan som du beskriver,
men du skriver "interrupt" där det borde stå "subrutin" b.l.a.
Den kod du visar som exempel ligger alltså i en subrutin som du både
anropar från din huvudkod och från din interruptkod, eller hur ?
Och då har ju just det problemet som jag beskrev. Sen så beror ju
ditt exempel lite på var r16 och r17 kommer från från början.

Sen så tror jag inte att koden "slumpvis fördärvar data", du har bara inte
sett mönstret än... :-)
Användarvisningsbild
Fagge
Inlägg: 3930
Blev medlem: 27 maj 2003, 13:59:51
Ort: Blekinge

Inlägg av Fagge »

Oki, ska posta interrupt koden senare i kväll när jag kommit hem.

Ang anrop av subrutiner inifrån en interrupt rutin var bara en fråga i förbifarten.
Det är inget som jag gör nu, utan bara några data jämförelse mellan register & eventuella hopp inom rutinen.

Nej denna rutinen anropas inte av huvudprogrammet, utan bara då ett interrupt inträffar.

Sen så tror jag inte att koden "slumpvis fördärvar data", du har bara inte
sett mönstret än...

Det låter rimligt, med tanke på att huvudkoden börjar bli gigantisk stor. :wink:
Användarvisningsbild
Icecap
Inlägg: 26659
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Kan bara hålla med sodjan.

Jag har som regel att en "main"-rutin och en ISR aldrig får använda samma variabler på något tidpunkt. Det fungerar inte alltid och vissa fall är omöjliga att klara av utan att det blir så men då är regeln: den ena får bara läsa och den andra får båda läsa och skriva.

Jag har en specifik grej där jag har en interruptdriven UART-kommunikation och "alla" kan skicka till sändaren. Kruxet är att sändarerutinen kollar om UART'en redan har fullt upp att göra, om det är lugnt skickas byten direkt, annars läggs den i en buffer.

När UART'en har skickat färdig den "nuvarande" byte exekveras en interrupt och nästa byte hämtas. Detta ger dock problem då jag använder en ringbuffer med en ingångs- och en utgångs-pekare och BÅDA sänd-rutinen OCH ISR'n måste uppdatera dom. Så i rutinen stänger jag av interrupts (globalt), uppdaterar pekarna och enabler interrupt globalt igen, allt för att det inte ska krocka.

När man jobbar med interrupt ska man tänka som så:
Kan denna rutin avbrytas "mitt i" och anropas ytterligare en gång utan att det blir problem? Är svaret "ja" kan man anropa den hur som helst, är svaret "nej" får BARA ISR eller main anropa den!
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Ang anrop av subrutiner inifrån en interrupt rutin var bara en fråga i förbifarten.

Och det är naturligtsvis inget problem alls. Generellt sätt.
Problemet är som sagt om *samma* subrutin anropas både från din
interruptkod och från din huvudkod.

> Nej denna rutinen anropas inte av huvudprogrammet, utan bara då ett interrupt inträffar.

Jahaja, men då misstolkade jag din fråga helt.
Är det om anrop av subrutiner i största allmänhet ? För det är ingen
som helst skillnad oasvett om din kod ligger i ett interrupt eller inte.

För övrigt så är i princip hela ISR'en bara en "subrutin" som
kan anropas automatisk... :-)
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Och måste man dela på variabler mellan "huvudprogrammet" och ISR:er så bör man använda sig av små korta atomiska block i huvudprogrammet, motsvarande mutex i flertrådsmiljö. Såg att AVR Libc har stödrutiner för atomiska block.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

Och "atomiska block" = "stänga av interrupt" på vanlig svenska... :-)
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4750
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Inlägg av Swech »

Du MÅSTE spara statusregistret
Du har säkert glömt detta.....
Användarvisningsbild
vfr
EF Sponsor
Inlägg: 3515
Blev medlem: 31 mars 2005, 17:55:45
Ort: Kungsbacka

Inlägg av vfr »

Atomiskt block = ett block kod som kan ses som helhet utan möjlighet att avbrytas (delas). Därav namnet.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Inlägg av sodjan »

> Du MÅSTE spara statusregistret

Det gäller alla interrupt (i princip), om det nu var det som var frågan.
Problemen vid delade subutiner mellan "main" och "ISR" är mer komplexa än så...

> Atomiskt block = ett block kod som kan ses som helhet utan möjlighet att avbrytas (delas). Därav namnet.

Självklart, för oss som kan "större" processorarkitekturer är det solklart vad det betyder.
I mikrokontrollervärlden betyder det dock vanligtsvis bara "stäng av interrupt"... :-)

Sen, med dagens kunskap om atomen, så kanske inte namnet är helt perfekt valt. :-)
Användarvisningsbild
vfr
EF Sponsor
Inlägg: 3515
Blev medlem: 31 mars 2005, 17:55:45
Ort: Kungsbacka

Inlägg av vfr »

Det var bara ett försök till en förklaring i generella termer och med en koppling till namnet.

Nää, namnet är väl, i dagens situation, inte helt lämpligt. Men när det sattes så sågs atomen som odelbar. :)
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Fast det finns i vissa arkitekturer atomiska instruktioner som kollar en flagga, och om den inte är satt sätter den och hoppar in i ett block. Då får man mutex-stöd även utan att stänga av interrupt.

Fast oftast går det naturligtvis bra att stänga av interrupten också... :)
Användarvisningsbild
Fagge
Inlägg: 3930
Blev medlem: 27 maj 2003, 13:59:51
Ort: Blekinge

Inlägg av Fagge »

Swech: Okej, i så fall så är problemet löst. :)
Jag antar att push & pop fungerar direkt ihop med SREG?

Edit...
Googlade runt lite på SREG & interrupt
& man måste tydligen gå en liten omväg & skriva såhär i stället

in r16, sreg
push r16
…
…
…
Pop r16
out sreg, r16

Härligt, då kan man köra vidare nu. :)
Tack för hjälpen!.
Skriv svar