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

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: lite undringar om AVR progrannering i C

Inlägg av sodjan »

Hur sätter kompilatorn igentligen in koden om du gör två separata asm anrop på det där sättet ?
Om man har ett stycke inline-asm så ska det normalt inte påverkas alls av eventuell optimering av C-koden.
Och det "normala" är väl att man sätter in en hel sekvens asm utan separata anrop på det där sättet...

(Sen är det en helt annan sak att jag inte fattar det där med "två gånger", men det spelar mindre roll...)
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: lite undringar om AVR progrannering i C

Inlägg av bearing »

Fundera över om inte någon variabel måste vara volatile.

Exempel:

Kod: Markera allt

while(v1 != v2)
{
...
kod som inte påverkar v1
...
}
v1 och v2 är inte volatile.

Den här koden kan optimeras till att v1 laddas till ett register innan loopen, och sedan görs testet hela tiden mot registret. Men om v1 ändras i någon annan funktion/interrupt så påverkar det ju inte värdet på registret.
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: lite undringar om AVR progrannering i C

Inlägg av jesse »

Sodjan skrev:Och det "normala" är väl att man sätter in en hel sekvens asm utan separata anrop på det där sättet...
Jo, så tänkte jag också men jag lyckades av nån anledning inte få den att fatta mer än en instruktion per anrop ... orkade inte utforska vidare just då utan löste det med två separata, viket blev OK; de sattes direkt efter varandra i koden. Det var alltså inte de raderna som inte fungerade utan dessa rader i C:

MCUCR = 0x80;
MCUCR = 0x80;

(två gånger ska det skrivas i MCUCR. Det togs kanske ur sitt sammanhang när jag bara klippte ut en bit av koden.)

bearing: aha, ja, så kan det vara... jag sätter bl.a. en flagga i en interruptrutin när det kommer in ett tecken på UART. Denna flagga läses sedan av i main()... ska testa att göra den till volatile och samtidigt kolla att jag inte har fler sådana fällor. (har inte kompilatorn här just nu så det får bli senare). Tack för tipset! (börjar förstå mer och mer nu varför volatile används ibland)
:jimmyhacker: <== (Det är så jag ser ut när jag försöker programmera :) )

EDIT: en rättelse: ovanstående instruktioner handlar om att avaktivera jtag-interfacet, inte CPU-frekvensen som jag skrev innan. Men samma problem uppstår när jag ska ändra "clock-prescalern"...
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

pekare till arrayer i funktioner

Inlägg av jesse »

pekare till arrayer i funktioner

Nu har jag fått det att fungera - utskrift från EEPROM till uart, men jag fattar ändå inte exakt vad jag gör! Hur man skriver för att skicka pekare är fortfarande lite av en chansning.

Koden:

Kod: Markera allt


uint8_t EEMEM welcome[]="Välkommen!"; // definierar sträng i EEPROM som slutar med '0'
                                                        // "welcome" är en pekare till första positionen
// strängen består av uint_8t istället för char eftersom ReadEEprom tar [i]unsigned[/i] char som argunent.

    // skriv ut texten string[] EEPROM
    //  sista tecknet måste vara 0 ( \000)

void uaprint_EE(const uint8_t * string) {
    /* argumentet string är en pekare till en adress innehållande
     * uint8_t som inte får skrivas över.
     * skriver man till *string så skrivar man på en plats i SRAM = fel! */

	uint8_t i,tecken;
	for (i=0;i<128;i++) {
		tecken = eeprom_read_byte(string+i); // funktion i <avr/eeprom.h>
		if (tecken==0) break;
		uartSend(tecken);
	}
}

int main (void){
	uaprint_EE(welcome); // welcome är en pekare...
}
Den här raden fungerar oavsett om jag skriver string med eller utan stjärna:
tecken = eeprom_read_byte(*string+i);
tecken = eeprom_read_byte(string+i);


Jag hade först med stjärnan, men fick en varning och testade att ta bort den. Jag trodde det skulle vara en stjärna där eftersom string är en pekare, men det var visst fel tänkt? Varningen jag fick var:
warning: passing argument 1 of 'eeprom_read_byte' makes pointer from integer without a cast

så jag misstänker att det är fel, även om det råkar fungera i just det här fallet ändå?

hmmm... (tänker efter...)

skriver jag bara string så får jag minnesadressen?
skriver jag *string så får jag värdet i SRAM på den adress pekaren string pekar på?

Så *string blir tokigt fel här, antar jag för jag vill bara skicka en adress som argument, inte ett datavärde. :roll:
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: lite undringar om AVR progrannering i C

Inlägg av sodjan »

En "pekare" är ju i princip någonting som innehåller en adress till något annat.
I ditt fall är "welcome" igentligen inte en pekare, utan det är adressen till
själva variablen direkt, så att säga. Annars hade "welcome" inte pekat direkt
till texten, utan till en adress där det i sin tur låg en adress till texten...

Så att "welcome" är en pekare till första positionen" stämmer igentligen inte riktigt...
SvenW
Inlägg: 1156
Blev medlem: 24 april 2007, 16:23:10
Ort: Göteborg

Re: lite undringar om AVR progrannering i C

Inlägg av SvenW »

Jo, det blir en pekare, men det här är en av de punkter där språket med rätta har kriticerats för att vara ologiskt.
I språket 'd', efterföljaren till 'c', försöker man komma till rätta med sånt här, har jag för mig. Återstår att c om d blir populärt :)
sodjan
EF Sponsor
Inlägg: 43251
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping

Re: lite undringar om AVR progrannering i C

Inlägg av sodjan »

Nja...

Om man i C deklarerar en variabel t.ex som :

int varA;

Så är ju varA inte en "pekare". Dock så innehåller naturligstvis symbolen
"varA" i alla fall en adress som "pekar" till platsen där det lagras en int.

Alltså varA => int. Men det är inte en pakare på det sätt som C definierar det.

Men om man istället säger :

int *VarA;

så är varA en pekare till en int. D.v.s att varA är en symbol i kompilatorn som
innehåller en adress som pekar till en plats i minnet där det ligger en adress till en int.

Alltså varA => adress => int.

I fallet med koden i tråden så har symbolen "welcom" redan adressen direkt till
den aktuella variablen (strängen), och alltså är "welcome" *INTE* en pekare.

Med din logik så skulle alla symboler som innehåller en adress till en variabel vara
"pekare", men så är det ju inte. Bara de symboler som innehåller en adress till
en adress till något är "pekare".
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: lite undringar om AVR progrannering i C

Inlägg av jesse »

nu är ju welcome[] en array, och så här står det i boken "Snygg grundläggande C++ med Dev-C++" av Fredrik Vallbo:
sidan 67: skrev:Om vi deklarerar en array med
datatyp variabelnamn[antal fack];
så kommer den dels att reservera utrymme ... men kommer också att deklarera en pekare ungefär som om vi hade skrivit:
datatyp* variabelnamn;
och tilldela denna pekare minesadressen där första elementet ligger lagrat.
...
Faktum är att skrivsättet
variabelnamn [index]
bara är ett förkortat skrivsätt för
* (variabelnamn+index)
(där "variablenamn" är en pekare och "index" är en integer).

det betyder att
tecken = welcome[ i ];
är detsamma som
tecken = *(welcome + i);

jag skickar ju pekaren welcome som parameter i funktionen uaprint_EE, där den kallas string. Sedan läser jag tecken för tecken med
tecken = eeprom_read_byte(string+i);
så visst är welcome en pekare.

Men det gäller bara arrayer förstås, inte andra variabler.

--------spekulation:-------
(Kanske jag hade kunnat skriva tecken = eeprom_read_byte(string[ i ]); och det hade betytt samma sak?)
(EDIT: Nej, det går inte... funktionen eeprom_read_byte ska ju inte ha själva tecknet som argument (vilket hade lästs ur en odefinierad plats i SRAM) utan adressen så att den kan läsa eepromet... så det var fel,fel,fel!)
SvenW
Inlägg: 1156
Blev medlem: 24 april 2007, 16:23:10
Ort: Göteborg

Re: lite undringar om AVR progrannering i C

Inlägg av SvenW »

Det är precis som jesse citerar ovan, och som sodjan påpekar är det inte logiskt.

eeprom_read_byte() deklareras så här i avr-libc <avr/eeprom.h>:

Kod: Markera allt

static __ATTR_PURE__
__inline__ uint8_t 	eeprom_read_byte (const uint8_t *__p)
Det betyder att den skall ha en pekare som argument.
Man kan skriva på olika sätt:

Kod: Markera allt

tecken = eeprom_read_byte(string+i); 
tecken = eeprom_read_byte(&string[i]); 
tecken = eeprom_read_byte(&string[0] + i ); 
Det är alltid svårt att hålla reda på vad som är pekare och det tar lång tid att träna in.
Användarvisningsbild
Icecap
Inlägg: 26658
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: lite undringar om AVR progrannering i C

Inlägg av Icecap »

Problemet är att om man deklarerar en sträng (kan kalla den "String") är den egentligen en array av char och när man anger den som argument gör kompilern om den till en pekare som pekar på första char i array'n.

Om man istället anger String[6] uppfattar kompilern inte det som en pekare till en sträng men som en pekare till en char så det finns en del "oskrivna regler" (som nog är skrivit ner någonstans) som är bra att känna till. Själv sker det att jag vill skriva till ett visst ställe i en sträng och då skriver jag "&String[3]" som mål.
Mr M
Inlägg: 165
Blev medlem: 20 januari 2006, 21:35:14

Re: lite undringar om AVR progrannering i C

Inlägg av Mr M »

Vill bara säga det att ibland så kanske inte C-koden funkar som den skall bara för att man inte har slagit på kodoptimeringen.

Ett exempel är då man skall skriva till internt EEPROM. Då ska man enabla skrivningen genom att ettställa en bit i ett register och sen inom 4 cykler ska man ettställa en annan bit i samma register.

Om man inte optimerar koden så blir det för mycket instruktioner mellan dessa operationer och då funkar inte skrivning till EEPROMet.

:D
Användarvisningsbild
Icecap
Inlägg: 26658
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Re: lite undringar om AVR progrannering i C

Inlägg av Icecap »

Och just sådana saker använder man ASM-direktiv till...
Mr M
Inlägg: 165
Blev medlem: 20 januari 2006, 21:35:14

Re: lite undringar om AVR progrannering i C

Inlägg av Mr M »

Ja, då slipper man vara beroende av hur effektiv kod kompilatorn genererar.

Eftersom jag inte är så bra på assembler på AVR så kollade jag vad kompilatorn genererade för assemblerkod vid optimering. Sen klippte jag in de assembler raderna i C-koden. :D
bearing
Inlägg: 11676
Blev medlem: 2 mars 2006, 01:01:45
Ort: Ängelholm

Re: lite undringar om AVR progrannering i C

Inlägg av bearing »

Varför lät du dem inte vara C?
bos
Inlägg: 2314
Blev medlem: 24 februari 2007, 23:29:15
Kontakt:

Re: lite undringar om AVR progrannering i C

Inlägg av bos »

Mr M skrev:Sen klippte jag in de assembler raderna i C-koden. :D
Till vilken nytta?
Skriv svar