Strul med AVR (avr-gcc)
Strul med AVR (avr-gcc)
Jag har ett problem med min AVR (mega128) jag har ett par rutiner för att skicka ut saker på serieporten:
putc(char ch) lägger ut tecken på serieporten
puts(char *c) lägger ut en sträng:
for(; *c; c++) putc(*c);
att bara köra
putc('M'); putc('a'); .... fungerar
Kör man puts("Mange"); kommer det bara skit ut.
Om man deklarerar en char-array: char str[]={"Mange"}; Så innehåller den inte "Mange" utan skräp.
Jag gissar att någon kompilatorflagga eller att länkstyrfilen är trasig, nån som har några bra tips?
Eller att det bara är något annat som är knäppt...
putc(char ch) lägger ut tecken på serieporten
puts(char *c) lägger ut en sträng:
for(; *c; c++) putc(*c);
att bara köra
putc('M'); putc('a'); .... fungerar
Kör man puts("Mange"); kommer det bara skit ut.
Om man deklarerar en char-array: char str[]={"Mange"}; Så innehåller den inte "Mange" utan skräp.
Jag gissar att någon kompilatorflagga eller att länkstyrfilen är trasig, nån som har några bra tips?
Eller att det bara är något annat som är knäppt...
Det har med att vissa strängar lagras i flash. Strängen "Mange" representeras som en pekare, och vissa fall mellanlagrar kompilatorn i ram-minnet och låter då pekaren vara adressen dit. I andra fall avses flash-adressen och råkar efter det tolkas som en ram-adress, vilket gör att bara "skit" kommer ut.
Såhär är det:
Att deklarera:
char str[]={"Mange"}; // hmmm, er du også dansk?
betyder egentligen bara att du deklarerar:
char str[strlen("Mange")+1];
Ska dessa data stå kvar ska den deklareras:
const char str[]= "Mange";
eller
const char * str = "Mange";
Resultatet blir det samma: str pekar på strängen "Mange". I teorin kommer själva strängen då att sparas i flashen (någonstans SKA den ju vara om den är en konstant) och 'str' är då enbart en adress till den sträng.
Hur det är specifikt med AVR vet jag inte men detta är standart C.
Att deklarera:
char str[]={"Mange"}; // hmmm, er du også dansk?
betyder egentligen bara att du deklarerar:
char str[strlen("Mange")+1];
Ska dessa data stå kvar ska den deklareras:
const char str[]= "Mange";
eller
const char * str = "Mange";
Resultatet blir det samma: str pekar på strängen "Mange". I teorin kommer själva strängen då att sparas i flashen (någonstans SKA den ju vara om den är en konstant) och 'str' är då enbart en adress till den sträng.
Hur det är specifikt med AVR vet jag inte men detta är standart C.
Icecap> Jag håller inte riktigt med. Ditt exempel är givetvis klockrent rätt och genererar en konstantsträng direkt i flashen. Men även gilles exempel borde fungerat. I hans fall är det en initierad strängvariabel och startupkoden till C:n skall initiera den från data i flashen vid boot. Detta skall kompilern ta hand om, eller är det ett undantag i den här miljön?
http://www.nongnu.org/avr-libc/user-manual/index.html
Kolla där. Där står hur man läser från flashen.
Se även faq:en på den siten. Där står iaf om hur man sparar i flash..kanske även hur man sparar i ram??
Happy hunting[/url]
Kolla där. Där står hur man läser från flashen.
Se även faq:en på den siten. Där står iaf om hur man sparar i flash..kanske även hur man sparar i ram??
Happy hunting[/url]
Jag har testat det sätt i ett annat inbyggnadsmiljö och där fungerar det rakt av inte att deklarera en variabel i RAM och ladda den direkt. Jag har å andra sidan slagit av att konstanter kopieras från flash till RAM så den biten är ju logisk.
Min anledning till att göra detta är att jag, i mina projekter, inte har enorma mängder med RAM, faktisk har jag bara 6Kb utan extern RAM-krets så jag håller hårt i vad som används av minne osv. Dessutom kan ett värde man behöver som konstant skrivas över (vid fel) om det kopieras och används från RAM och jag har ingen overhead eller hastighetsbegränsning i flashen så jag har ett välfungerande sätt utan att slöa ner processorn.
Vad som fungerar gcc (eller vad det är) kan jag inte svara på.
Rent programmeringsteknisk tycker jag att det är fel att deklarera en variabel med ett visst värde, ska det värde stå fast är det en 'const' eller om det är en variabel som ska ha en viss startvärde grejer man det under uppstartssekvensen. Med variabel menar jag i detta fall ändringsbar.
Alltså hade jag (om jag behövde en variabel sträng med ett visst startinnehåll) deklarerat:
Detta sätt hade för mig varit tydligt och klart, båda vad angår variablens typ och vad man sätter som initial sträng.
Men programmeringsstil är ofta personlig...
Min anledning till att göra detta är att jag, i mina projekter, inte har enorma mängder med RAM, faktisk har jag bara 6Kb utan extern RAM-krets så jag håller hårt i vad som används av minne osv. Dessutom kan ett värde man behöver som konstant skrivas över (vid fel) om det kopieras och används från RAM och jag har ingen overhead eller hastighetsbegränsning i flashen så jag har ett välfungerande sätt utan att slöa ner processorn.
Vad som fungerar gcc (eller vad det är) kan jag inte svara på.
Rent programmeringsteknisk tycker jag att det är fel att deklarera en variabel med ett visst värde, ska det värde stå fast är det en 'const' eller om det är en variabel som ska ha en viss startvärde grejer man det under uppstartssekvensen. Med variabel menar jag i detta fall ändringsbar.
Alltså hade jag (om jag behövde en variabel sträng med ett visst startinnehåll) deklarerat:
Kod: Markera allt
char str[6];
const char * strConst1 = "Mange";
void main(void)
{
memcpy(&str,&strConst1,sizeof(strConst1));
... // Nog en massa annat grejs
while(1)
{
... // här kör det av bara fan
}
}
Men programmeringsstil är ofta personlig...
Icecap> Då är vi överens! Har man ställt in att den inte skall intiera saker så gör den förhoppningsvis inte det. Tyckte bara att en standard-C utan andra inställningar borde klara det.
Sedan håller jag inte riktigt med dig ang. sättet att göra initiering. Givetvis är det effektivare och bättre att göra en konstant direkt av det i flashen om den inte skall ändras. Däremot för en initierad variabel så tycker jag det är lika tydligt med direktinitiering. Det lilla extra förtydligande som erhålles av att göra en memcpy tycker jag äts upp av att man kluddar ner koden med extra såna istället. Ser renare och mer rakt på sak utan memcpy.
Det är säkert väldigt personligt och det är så jag är van att jobba.
Sedan håller jag inte riktigt med dig ang. sättet att göra initiering. Givetvis är det effektivare och bättre att göra en konstant direkt av det i flashen om den inte skall ändras. Däremot för en initierad variabel så tycker jag det är lika tydligt med direktinitiering. Det lilla extra förtydligande som erhålles av att göra en memcpy tycker jag äts upp av att man kluddar ner koden med extra såna istället. Ser renare och mer rakt på sak utan memcpy.
Det är säkert väldigt personligt och det är så jag är van att jobba.
Jovisst kan du ha ett poäng där, anledningen till mitt val är att jag vill ha absolut kontroll över vad som händer. Jag har tillbragt på tok för mycket tid med att debugga saker som blev klarat automatisk för mig, saker jag inte vill skulle hända osv.
Själva memcpy-delen har jag alltid i en separat rutin (void Initialize_Variables(void)) som jag slänger i *.h-filen, funktionen utförs ju antingen dold eller via mitt bevåg och jag hatar att ordna andras problem.
Men jag tror att det är just beroende på person vad man gillar, mitt sätt eller ditt sätt är lika "riktiga"....men de behöver inte passa andra än just oss.
gille: bra att du fick det till att rulla.
Själva memcpy-delen har jag alltid i en separat rutin (void Initialize_Variables(void)) som jag slänger i *.h-filen, funktionen utförs ju antingen dold eller via mitt bevåg och jag hatar att ordna andras problem.
Men jag tror att det är just beroende på person vad man gillar, mitt sätt eller ditt sätt är lika "riktiga"....men de behöver inte passa andra än just oss.
gille: bra att du fick det till att rulla.