Jesses följetång om AVR programmering i C...

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

Men jag blir tokig:

Kod: Markera allt

/* å=\x86 ä=\x84 ö=\x94 Å=\x8f Ä=\x8e Ö=\x99 */
uint8_t EEMEM change2[] =	"\n\rBekr\x84fta \x84ndring:";
\x84 är 'ä', men bara det andra ä-et skrivs ut:

Kod: Markera allt

Bekr0ta ändring:
:shock: Jag har ju faktiskt skrivit exakt samma på båda ställena!
Användarvisningsbild
Icecap
Inlägg: 26658
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Jesses följetång om AVR programmering i C...

Inlägg av Icecap »

Du gör faktisk fel! Du har INTE skrivit samma båda ställen!
Jag har "boldat" de hexadecimala värden:
uint8_t EEMEM change2[] = "\n\rBekr\x84fta \x84ndring:";

För att få det rätt ska du skriva:
uint8_t EEMEM change2[] = "\n\rBekr\x84" "fta \x84ndring:";
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

Aha, trodde alltid den tog två "siffror" där. Inte tänkte jag att 'f' var en tredje siffra! :doh:

Jag kunde ju skrivit talet oktalt också. "Bekr\204fta" Sättet att dela upp strängen med " " hade jag inte kommit på själv även om jag ju gör så när jag ska ha den på flera rader.

Tack för snabb hjälp! :tumupp:
Användarvisningsbild
Icecap
Inlägg: 26658
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Jesses följetång om AVR programmering i C...

Inlägg av Icecap »

Jag har haft detta problem många gångar, min kompiler varnar dock för "för långt hexadecimalt tal". Då jag såg denna varning första gången blev jag MYCKET fundersam på vad tusan det kunde vara, det tog sin lilla tid innan jag fattade var och varför och hur man fixade det.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

ibland fattar jag inte vad kompilatorn gör... ofta är optimeringen så avancerad att den är nästan omöjlig att följa, men det här känns inte bra...

Källkod:

Kod: Markera allt

...
	while (!ADC_ready); // vänta
	adc  =  ADCL;
	adc |= (ADCH << 8);
	ADCSRA = ADCSRAset; // ADC-OFF
	MCUCR = MCUCRset;   // default = IDLE sleep mode
	return adc;	
}
Jag läser in ADC-värdet från ADCL+ADCH och ska returnera det.
Det returnerade värdet används sedan i en beräkning.

Jag kollade disassemblern, och såg detta:
192: while (!ADC_ready); // vänta
+000000F9: 91800090 LDS R24,0x0090 .......... Load direct from data space
+000000FB: 2388 TST R24 .......... Test for Zero or Minus
+000000FC: F3E1 BREQ PC-0x03 .......... Branch if equal
193: adc = ADCL;
+000000FD: B184 IN R24,0x04 .......... In from I/O location
194: adc |= (ADCH << 8 );
+000000FE: B185 IN R24,0x05 .......... In from I/O location
195: ADCSRA = ADCSRAset; // ADC-OFF
+000000FF: E086 LDI R24,0x06 .......... Load immediate
+00000100: B986 OUT 0x06,R24 .......... Out to I/O location
Läser alltså in ADCL och ADCH , båda till r24, och instruktionen efter så kommer en LDI R24, 0x06 .... den spolar alltså hela min analoga läsning! Nu blir jag sne.. :x

(ok, jag körde QUOTE här istället för CODE för att kunna göra källkodsraderna tjocka, vet inte om det blev mer eller mindre läsbart, :roll: )
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Jesses följetång om AVR programmering i C...

Inlägg av sodjan »

Varför bli sne ?
Den gör ju bara (så vitt jag kan se) precis det du ber om...
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

Jo, Sodjan, hittills har den faktiskt gjort det...

Jag vet vad jag vill , men uppenbarligen vet jag inte vad jag har skrivit.

Att den skiter i att returnera något värde från ADCL och ADCH så som jag har skrivit berodde på att det värdet i sin tur inte användes. (det syns ju i koden att jag vill returnera värdet i variabeln adc, men programmet som anropade funktionen skrev senare över resultatet). Resultatet var avsett att användas, men jag hade av misstag skrivit in en sats där jag skrev över mitt beräkningsresultat med ett annat värde... Hade jag inte sett att disassemblern spolade mina inläsningar hade jag nog inte upptäckt det på ett bra tag!
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Jesses följetång om AVR programmering i C...

Inlägg av sodjan »

Ja, det framgår ju inte hur "adc" är definierad, så det går ju inte att säga så mycket om det.
Så som det var nu så skrivs "adc" över två gånger, först med ADCH sedan med ADCSRAset.
Sen så framgick det ju inte heller hur varken ADCSRA eller ADCSRAset var definierade
så jag vet igentligen inte vad du ville säga med det hela. Att den skrev över adc i det ena
läget *kan* bero på någon optimering där den ser att adc i sig inte används.

> Hade jag inte sett att disassemblern spolade mina inläsningar hade jag nog inte upptäckt det på ett bra tag!

Om du inte använde det i alla fall, vad spelade det för roll ?
Och det är mycket möjligt att *om* du hade använt adc senare,
så kanske inte koden hade sett likadan ut, optimeringen hade fixad det.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

jo, som sagt, jag upptäckte ju orsaken. när jag väl tog bort den satsen som skrev över mitt resultat så blev koden riktig och "adc" returnerades på rätt sätt. ADCSRAset är bara en konstant. Det kan man se på assemblerkoden:

Kod: Markera allt

+000000FF: E086 LDI R24,0x06   .......... Load immediate
+00000100: B986 OUT 0x06,R24 .......... Out to I/O location
men den satsen borde ju inte påverkat värdet i adc i vilket fall som helst.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Jesses följetång om AVR programmering i C...

Inlägg av sodjan »

Nja, alltså. Eftersom kompilatorn ser att värdet i "adc" aldrig används till något,
så är det ju ingen fara att återanvända R24 heller. Det ser ju ut som att
kompilatorn bara använder R24 som en scratch varabel fär värden som
inte behövs. Samma sak med testen av (!ADC_ready) t.ex. Även där
används R24.

Jag gissar att om det hade framgått av koden att adc skulle användas till
annat, så hade inte R24 används på det där sättet...
Nerre
Inlägg: 27257
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Jesses följetång om AVR programmering i C...

Inlägg av Nerre »

Men adc används ju?

Kod: Markera allt

 return adc;   
Och efter han skrev att returvärdet används i en beräkning antar jag att returvärdet används också.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: Jesses följetång om AVR programmering i C...

Inlägg av sodjan »

OK, inget problem, det hade jag missat.
Då tar jag tillbaka precis allt jag sa... :-)
Trevlig helg !
Nerre
Inlägg: 27257
Blev medlem: 19 maj 2008, 07:51:04
Ort: Upplands väsby

Re: Jesses följetång om AVR programmering i C...

Inlägg av Nerre »

Jag såg det inte heller först.

Min första tanke var att OR-grejen inte behövdes för den fattar att de två adresserna (ADCH och ADCL) ligger efter varandra. Men sen sprack det ju då den även använde R24 för nästa rad... Och då tänkte jag att adc kanske inte används. Men så såg jag return...


En annan tanke var att det optimeras m.a.p. pipelining (d.v.s. läsningen sker egentligen nån klockcykel senare så värdet i R24 hinner användas innan det skrivs över). Men jag tror inte AVR har så avancerade pipelines.

Jag har hackat assembler på TMS 320C80 som exjobb för en massa år sen och där var det mycket sånt:-) Externa I/O-operationer tog t.ex. 11 cykler eller nåt sånt så man fick göra annat under tiden om man skulle slippa waitstates.


Jag skulle vilja se hur koden ser ut de följande raderna. Vad händer efter OUT 0x06,R24? Det är ju där "return" skall utföras.
Användarvisningsbild
Icecap
Inlägg: 26658
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: Jesses följetång om AVR programmering i C...

Inlägg av Icecap »

Orkar inte leta igenom alla sidor men hur är "adc" deklarerat?
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Jesses följetång om AVR programmering i C...

Inlägg av jesse »

Känns kanske inte så relevant längre , då problemet blivit löst, men adc är en 16-bitars unsigned int deklarerad inne i samma funktion:

Kod: Markera allt

int16_t ADCread(uint8_t kanal) {
	int16_t adc;
	....
	adc = ...
	...
	return adc;
Jag skulle vilja se hur koden ser ut de följande raderna. Vad händer efter OUT 0x06,R24? Det är ju där "return" skall utföras.
det är en väldans massa kod, som jag ville bespara er... (som jag nu inte kan återge längre, då jag rättat koden och kompilerat om). Det returnerades aldrig något värde förstås, eftersom det redan från början hade spolats. Men hela funktionen hade optimerats till en "line-in" så det fanns ingen return över huvud taget i den optimerade koden.

Orsaken till alltihop låg utanför adc-funktionen: Här är det också onödigt att ge er 100 rader kod, men i princip var det:

Kod: Markera allt

if (gain20) {
	current = ADCread(k[knr]);
	current = current*32/20;
}
...
(senare i koden:) 
current = ADCread(k[knr]);
eftersom den läser in ett nytt värde i current längst ner så skrivs gamla värdet över - det insåg kompilatorn och optimerade bort precis allt som hade med det att göra (förutom själva inläsningarna, adc = ADCL ... eftersom dessa påverkar processorns periferi, så kan dessa läsningar inte optimeras bort utan att få en oönskad påverkan.)

Den sista satsen skulle egentligen befinna sig i en villkorad sats (if), och när den väl gjorde det, så gick det inte längre att optimera bort den tidigare läsningen.
Senast redigerad av jesse 12 februari 2010, 23:01:22, redigerad totalt 2 gånger.
Skriv svar