Kan inte skriva till en global variabel i ISR. C. ATMega48.

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Kan inte skriva till en global variabel i ISR. C. ATMega48.

Inlägg av StRob »

Varför kan jag inte skriva till en global "unsigned char" i avbrottet för TIMER1 Capture?
Jag har variabeln, MeasurementStatus, som flaggregister, där bit0 falggar för fel i mätningen, bit1 flaggar för att en ny mätning gjorts. Och i ISR (Interrupt Service Routine) vill jag sätta just biten som flaggar för att en ny mätning gjorts.
Så här ser de relevanta delarna av koden ut:

Kod: Markera allt

//Globala variabler och definitioner
#define NEW_MEASUREMENT 0b00000010
unsigned char MeasurementStatus = 0;

//ISR:
ISR(TIMER1_CAPT_vect)	//Rising edge on ICP1-pin (Flow Sensor Pulses) detected
{
	TCNT1 = 0;	//Clear Timer1 (16bit) for the following measurment
	MeasurementStatus |= NEW_MEASUREMENT;		//Flag for a complete period time measurment
//	PORTB ^= (1<<PORTB2);			             //BARA TESTRAD FÖR FELSÖKNING!! FUNGERAR DOCK!
}

//I main():
	if(MeasurementStatus & NEW_MEASUREMENT)			//Is the NEW_MEASUREMENT flag bit set from ISR?


Jag har provat att sätta en annan global variabel (unsigned char temp) temp = 1; i ISR och sedan bara kollat if(temp) i main, men den köper inte det heller!
Jag ser ju på togglingen (det som är bortkommenterat i ISR) att avbrotten fungerar fint, exakt när de ska, så ISR körs ju uppenbarligen!
Och jag har testat att sätta en negation i if(!temp) och då körs den ju så jag tycker att det är uppenbart att det är skrivningen av variabeln i ISR som inte fungerar, men varför???
Vad missar jag?? Jag har läst i databladet för ATM48 om interrupt och jag hittar iaf inget om detta..
Användarvisningsbild
E85
Inlägg: 1274
Blev medlem: 29 maj 2007, 16:24:19
Ort: Övik

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av E85 »

Prova deklarera den som volatile, dvs "volatile unsigned char variabel;"
Användarvisningsbild
jesper
Inlägg: 722
Blev medlem: 12 juni 2006, 16:04:08
Ort: Laem Mae Phim, Thailand

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av jesper »

StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av StRob »

på länken ovan kan man läsa: "The problem is that the compiler has no idea that etx_rcvd can be changed within an ISR. As far as the compiler is concerned, the expression !ext_rcvd is always true, and, therefore, you can never exit the while loop. Consequently, all the code after the while loop may simply be removed by the optimizer." Men tittar man i lss-filens assemblerkod så hittar man i ISR:

Kod: Markera allt

	MeasurementStatus |= INVALID_MEASUREMENT;		//Flag for lost contact to sensor (Sensor freq to low)
  bc:	80 91 05 01 	lds	r24, 0x0105
  c0:	81 60       	ori	r24, 0x01	; 1
  c2:	80 93 05 01 	sts	0x0105, r24
Så den har alltså inte tagit bort koden iaf.. Skall givetvis testa ändå!
Och bra att det nämndes, för det hade jag glömt sen skoltiden :wink:
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av sodjan »

Att optimera bort kod syftade nog på main(), inte på en ISR.
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av StRob »

Jaha, just det. Så lär det nog vara ja..
Det fungerade med volatile iaf!
i ISR ändrade den adressen från 0x0105 till 0x0100. Main tittade jag inte på då jag fått för mig att det var själva skrivningen av variabeln som inte fungerade. Så artade sig ju felet. Men ack så galet det kan bli.
Nyttig läxa hur som! :)
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av StRob »

Jag fick samma fel när jag försökte skriva in en define i en global variabel. denna kodrad låg alltså i main() direkt efter initieringen:
unsigned int i = TIMER1_FLOW_LIMIT;
men la jag till volatile innan så fungerar det utmärkt. Ska jag alltid ha volatile på mina variabler alltså?

I texten i länken vi tidigare nämnde står det:
"C's volatile keyword is a qualifier that is applied to a variable when it is declared. It tells the compiler that the value of the variable may change at any time--without any action being taken by the code the compiler finds nearby."

Jag tolkar det som att variabeln kan då ändras när som helst utan att kompilatorn ska bry sig om närliggande kod. Är inte det vanliga kriterier för en global variabel? Kan någon komma med någon bra tumregel om när den ska deklareras som volatile? Kan man alltid använda volatile, eller vad får det för konsekvenser?
Användarvisningsbild
AndLi
Inlägg: 18271
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av AndLi »

En global variabel kan inte ändra sig hur som helst, om den inte påverkas via en interrupt (eller via någon form av DMA, eller mappar en HW port) och då ska den vara volatile deklarerad.

Kompilatorn borde kunna ha rätt bra koll på hur den kommer ändras om den inte styrs via interrupt. Har du två funktioner som använder samma globala variabel kan ju kompilatorn räkna ut när den kommer att ändra sig och den behöver lägga in den i något register för att använda den till något. Så att volatile deklarera i onödan kan leda till sämre optimering då kompilatorn varje gång den ska använda den måste kopiera den från minnet.
StRob
Inlägg: 167
Blev medlem: 15 maj 2007, 09:30:47
Ort: Karlstad

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av StRob »

Okej. Låter logiskt.
Det sista problemet jag beskrev är endast relaterat till när man stegar genom programmet utan hänsyn till hårdvara. JAg kan inte se registret om jag inte skriver volatile. tycker det borde gå eftersom jag bara skriver in ett värde till det och det är en global char så "Watch-funktionen" borde se den. men "location not valid" får jag i value-fältet. trist men det är ju en värdslig sak.

Off topic: Kan någon rekomendera en bra debugger för AVR? Mega48 i huvudsak.
Användarvisningsbild
AndLi
Inlägg: 18271
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av AndLi »

Det låter som att kompilatorn har optimerat runt med din globala variabel...

HW eller SW delen av debuggern? Kör själv Win AVR kitet och en jtagicemkII
SvenW
Inlägg: 1156
Blev medlem: 24 april 2007, 16:23:10
Ort: Göteborg

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av SvenW »

[JAg kan inte se registret om jag inte skriver volatile.
unsigned char MeasurementStatus = 0;
Kompilatorn vet alltså att MeasurementStatus alltid är noll och därmed kan den optimeras bort. Kompilatorn är smart.
Men kompilatorn tar en funktion i taget och vet inget om att variabeln ändras i IRS när main() kompileras och vice versa.
Variabeln finns alltså inte heller i debuggern.
rekomendera en bra debugger för AVR? Mega48 i huvudsak.
Jag kör med avr-gdb och gnu toolchain. Fungerar alltid perfekt, i alla fall i Linux.
Senast redigerad av SvenW 12 oktober 2010, 14:06:08, redigerad totalt 1 gång.
Användarvisningsbild
AndLi
Inlägg: 18271
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av AndLi »

SvenW: det stämmer om variabeln inte används i koden, men även en rad som "unsigned char MeasurementStatus;" hade blivit borttagen av kompilatorn om den inte används i koden...

Man kan ju lägga till några MeasurementStatus++ och -- också och den blir fortfarande bortplockad... När den börjar användas i div if statement och dylikt kan man vara ganska säker på att den finns kvar.. Så att använda MeasurementStatus och bara sätta vilket mode den är i just nu och sen försöka använda den vid debugging lär inte ge önskat resultat...
SvenW
Inlägg: 1156
Blev medlem: 24 april 2007, 16:23:10
Ort: Göteborg

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av SvenW »

AndLi,
Nja, jag har för mig att kompilatorn brukar plocka bort det mesta som inte har verkan. Men det kan bero på kompilator och version och givetvis vilken optimeringsflagga man använder.

Jag ville bara betona att kompilatorer ofta är smartare än man kan föreställa sig, vilket många gånger leder till problem både för nybörjare och andra.
Speciellt vid debuggning.
Användarvisningsbild
AndLi
Inlägg: 18271
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av AndLi »

svenW. Ja, debugging med optimerad kod kan vara spännande, ofta försöker jag köra utan optimering påslagen då, vilket såklart ibland fixar buggen då det påverkar hela timeingen i koden...
Användarvisningsbild
vfr
EF Sponsor
Inlägg: 3515
Blev medlem: 31 mars 2005, 17:55:45
Ort: Kungsbacka

Re: Kan inte skriva till en global variabel i ISR. C. ATMega

Inlägg av vfr »

Precis så! Får man problem med kod genererad av en kompilator (i motsats till assembler), så ska man alltid prova att kompilera utan optimeringar först. Får man då skillnader, så är det läge att kolla närmare på såna saker.
Skriv svar