avbrottsrutiner i C
-
- Inlägg: 35
- Blev medlem: 2 februari 2005, 17:18:12
- Ort: Göteborg
avbrottsrutiner i C
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;
}
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;
}
-
- Inlägg: 35
- Blev medlem: 2 februari 2005, 17:18:12
- Ort: Göteborg
> 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...
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...
-
- Inlägg: 35
- Blev medlem: 2 februari 2005, 17:18:12
- Ort: Göteborg
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.
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.
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...
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...
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.
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.
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);
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);
> 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 ?
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 ?
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 =)
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 =)
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
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.

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

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.