Sida 1 av 1

avbrottsrutiner i C

Postat: 30 april 2006, 23:44:42
av tobbetabbe
Finns det några problem att använda sig av samma variabler i olika interrupt
har testat men funkar inte försöker spara w-registren mm
har någon nåt förslag


highpriorityinterrupt
{

//läser av tiden mellan externa pulser från pulsgivare

//TMR1 genererar avbrott,räknar 10 externa pulser sedan slår runt



TMR0L_temp=TMR0L;
TMR0H_temp=TMR0H;

}


lowpriorityinterrupt
{

//läser av senaste avläsningen 1mS

TMR0L_sample=TMR0L_temp;
TMR0H_sample=TMR0H_temp;

}

Postat: 30 april 2006, 23:59:08
av sodjan
Du tycker naturligtsvis inte att det har den minsta betydelse
vilken processor du använder ???

Postat: 1 maj 2006, 00:03:57
av tobbetabbe
PIC18F458 20MHz CC8e-demo komplilator

Postat: 1 maj 2006, 00:29:16
av sodjan
> Finns det några problem att använda sig av samma variabler i olika interrupt

Nej, inte om man tänker sig för. Annars, ja...

> har testat men funkar inte

Vad är testat och vad funkar inte ?

> försöker spara w-registren mm

"Försöker" ?

> har någon nåt förslag

I interrupt delen av databladet finns det exempel
på hur man ska hantera b.la WREG och STATUS när
man kör med dubbla prioriteter. Det är oklart vad du har
läst och vad du har gjort så...

Men vänta, du kör ju C !
Missade det...

Postat: 1 maj 2006, 01:00:56
av tobbetabbe
har följt de anvisningar från kompilatortillverkaren mde påstår
att man enbart behöver spara undan de register som man på verkar
i interruptrutinen.så jag undrar om det finns standardlösningar.

ex på sparande av register som gjort förut:

save_wreg=wreg
save_FSR=FSR
osv... , sedan återställer jag det när avbrottet är slut.


Det enda jag gör här är att avläsa timrar. jag har bara skrivit pseudokod
för att inte förvirra.

Postat: 1 maj 2006, 01:16:14
av sodjan
Jo, kompilatorn bör ju ta hand om de "vanliga" registren, d.v.s
W, STATUS och ett till. Man borde inte behöva göra det själv,
men jag vet inte säkert.


Men vad är det för symptom du ser ?
Vad får du för problem ?

En annan metod är att helt enkelt kolla på ASM koden
som kompilatorn spottar ur sig, och se själv om den
gör något konstigt...

Postat: 1 maj 2006, 07:56:00
av Icecap
Nu kör jag ju med MikroC till PIC men de C-kompilers jag har kommit över sparar alla nödvändiga registre automatisk, det är inget man ska pilla med själv.

Vad som däremot kan bli mer komplicerat är variabler, man ska tänka till ordentligt vilka delar av programmet som får göra vad med vilk variabler annars blir det mycket lätt pannkaka av det hela.

Postat: 7 maj 2006, 23:54:35
av pagge
Speciellt grisigt kan det bli om man har 16 eller 32 bitars variabler. Då tar alla updateringar av variabeln, te.ex.

min_16_bitars_variabel += 0xBEEF;

minst två instruktioner att utföra eftersom uCn bara arbetar med 8 bitar åt gången. Om ett interrupt sker i mitten av detta och interruptrutinen läser av variabeln så kan du få lite vad för skit som helst.

Man bör stänga av interrupt vid skrivning till delade variabler

disable(det_interrupt_som_läser_min_16_bitars_variabel);
min_16_bitars_variabel += 0xBEEF;
enable(det_interrupt_som_läser_min_16_bitars_variabel);

Postat: 8 maj 2006, 13:09:06
av sodjan
> Speciellt grisigt kan det bli om man har 16 eller 32 bitars variabler.

Vilket naturligtsvis inte är något specifikt för C eller något annat språk heller.
Det är exakt samma "problem" i assembler.

Men angående originalfrågan, man bör kanske, även om det sägs att
kompilatorn sparar unden register på rätt sätt, att det även fungerar OK
vid användning av dubbla prioritetsnivåer. Jag har för mig att *någon*
(minns inte vilken) C-kompilator har problem me det och man får
skriva sina funktionsdefinitioner på ett speciellt sätt för att komma runt det.

Saken är ju den att *normalt* på PIC18 med *en* int-prio nivå (så som
de flesta normalt kör), så sker context-saving automatiskt utan att man
behöver lägga till någon egen kod (och det ska naturligtsvis inte kompilatorn
heller göra, eftersom det är onödigt), men i något fall har de alltså missat
att detta inte fungerar om man kör med båda int-prio's. Low-prio
interruptet måste spara context "för hand", medans high-prio interruptet
kan köra med automatiken.

Kan det vara så att din kompilator missar på denna punkt ?

Postat: 8 maj 2006, 14:08:56
av pagge
Precis det problemet ramlade jag in i igår när jag programerade en PIC med skolans kompilator från CSS (http://www.ccsinfo.com/).

Man måste starta programmet med
#device HIGH_INTS=TRUE

och måste deklarera INT hanterarna med hög prioritet såhär


#int_ccp1 HIGH
min_hanterare(){
}

och inte som vanligt

#int_ccp1
min_hanterare(){
}

Ett eller två slitna hårstrån kan erkännas innan jag kom på det =)

Postat: 8 maj 2006, 14:31:48
av sodjan
Alltså för att du ville köra med båda nivåerna ?
För det behövs väl inte annars (d.v.s "normalt") ?

Postat: 8 maj 2006, 20:02:17
av pagge
Jepp. Kör man i kompabilitetsläge, dvs utan prioritet, så är det inga problem.

Postat: 8 maj 2006, 21:36:55
av sodjan
OK. Och det de kallar "kompabilitetsläge" vill jag kalla "normalläge"... :-)

Men den lösning som du visade är väll "as documented", antar jag,
eller var det verkligen något du "kom på" ? :-)

En annan sak, skall *alla* INT hanterarna ha "HIGH" ?

Vilken är då "low" ??

Postat: 9 maj 2006, 21:45:21
av pagge
Nä, naturligtvis skall bara de med hög prioritet deklareras som high :).
HIGH_INTS=TRUE är för att kompilatorn skall veta att man kör olika nivåer, sen deklarerar man de höga hanterarna som HIGH så den vet vilka som är high och low.

Jo, det var dokumenterat långt ner i C manualen, dock inte i labkompendiumet jag fick av läraren :evil:

Anledningen till att jag behövde olika prioriteter är att jag skall styra några servon och eftersom prollen bara har två PWM kanaler måste jag göra en mjukvarupwm av ena comparemodulen som styr flera servon. Eftersom jag har en massa anda interrupts från diverse givare så kan dessa störa mjukvarupwmen som är väldigt känslig. Man märkte att servot ryckte om man t.ex. körde A/Dn interruptdriven i maxfart. Men nu funkar det klockers då soft PWM en kör hög prioritet och alla andra interrupts kör låg.