Interrupt frågor, AVR
Interrupt frågor, AVR
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?.
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?.
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.
Ä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.
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...
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...

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.
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.

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!
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!
> 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...
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...

> 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.
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.

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!.

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!.