Hallo Zusammen!
Ich habe in meinem Programm in einem Header ein ca. 6kbyte Array
gespeichert.
Direkt ins Flash also so:
const uint8_t rawData[7668] PROGMEM = {...}
In meinem main will ich nun verschiedene Werte abfragen, was sich etwas
schwierig gestaltet.
Wenn ich nun rawData[1] verwende, so kann ich diesen Wert auslesen.
Wenn ich z.B. rawData[x] verwende und x in meinem Hauptprogramm
deklariere (globale Variable), so funktioniert der Zugriff nicht.
Wenn ich in meinem Header diese Zeile einfüge:
prog_uint16_t x = 0;
Dann funktioniert zwar der Zugriff aus dem Main, allerdings hat ein x++,
Beispielsweise kein Ereignis zur Folge.
Was mich also interessieren würde, wie kann ich eine Variable, die im
Flash gespeichert ist überschreiben?
Ich hoffe das Problem ist verständlich erklärt.
Gruss
Electronics'nStuff schrieb:> Was mich also interessieren würde, wie kann ich eine Variable, die im> Flash gespeichert ist überschreiben?
Gar nicht.
ROM = Read Only Memory.
mfg.
> prog_uint16_t x = 0;> Dann funktioniert zwar der Zugriff aus dem Main, allerdings hat ein x++,> Beispielsweise kein Ereignis zur Folge.
Ist ja logisch, ein Pointer im Programm Speicher ist read-only.
b=rawData[x] Addiert x zum Pointer auf rawdata. Dann wird die RAM(!)
Zelle gelesen, auf die der Pointer Zeigt. Die Daten liegen aber gar
nicht im RAM.
Lies Dir mal diese Seite durch:
http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
Für den Zugriff auf dem Programmspeicher brauchst Du die dort
beschriebenen Funktionen.
Thomas Eckmann schrieb:> Electronics'nStuff schrieb:>> Was mich also interessieren würde, wie kann ich eine Variable, die im>> Flash gespeichert ist überschreiben?> Gar nicht.> ROM = Read Only Memory.>> mfg.
Das ist nicht richtig.
---
Schau' im Datenblatt deines Controllers in das Kapitel "Flash
Programming". Bei einigen Controllermn ist es möglich aus der Anwendung
den Flashspeicher zu verändern. Ist aber nur sinnvoll für seltene
Änderungen, da der Flash-Speicher z. B. nur 10.000 mal neu beschrieben
werden kann.
Hmm..
Also wenn ich das so habe:
const uint8_t rawData[7668] PROGMEM = {..};
uint16_t y = 0;
uint16_t x = 0;
spalte1[x] =pgm_read_word(rawData[y]);
Dann bekomme ich in spalte1[x] eig. nur Schrott.
Wie muss ich die Variable y deklarieren? Mit dem ROM habt ihr natürlich
recht, aber wohin kommt die dann?
Gruss
Quatschkopf schrieb:> spalte1[x] =pgm_read_byte(rawData + y);
Wow, super, danke!
Ehrlich gesagt habe ich aber keine Ahnung was das für ein Unterschied
macht?
Kann ich das irgendwo nachlesen? Diese Schreibweise habe ich nämlich
noch nie gesehen.
Gruss & nochmals Danke!
Electronics'nStuff schrieb:> Quatschkopf schrieb:>> spalte1[x] =pgm_read_byte(rawData + y);>> Wow, super, danke!> Ehrlich gesagt habe ich aber keine Ahnung was das für ein Unterschied> macht?>> Kann ich das irgendwo nachlesen?
In jedem noch so grindigem C-Buch
Electronics'nStuff schrieb:> Quatschkopf schrieb:>> spalte1[x] =pgm_read_byte(rawData + y);> Kann ich das irgendwo nachlesen? Diese Schreibweise habe ich nämlich> noch nie gesehen.
Dann wird's aber Zeit. Das heisst Pointerarithmetik.
Quatschkopf schrieb:> Das ist nicht richtig.
Das ist zu 100% richtig.
Das ist und bleibt ein ROM. Völlig unabhängig davon, ob man das mit
irgendeinem Verfahren löschen und neu beschreiben kann.
Funktioniert das: i++? Nein. Also Nur Lesen.
mfg.
Electronics'nStuff schrieb:> Quatschkopf schrieb:>> spalte1[x] =pgm_read_byte(rawData + y);>> Wow, super, danke!> Ehrlich gesagt habe ich aber keine Ahnung was das für ein Unterschied> macht?
der Name eines Arrays für sich alleine steht für seine Startadresse.
D.h. du nimmst
rawData die Startadresse von rawData im Speicher
rawData + y und zählst da noch dazu, wieviele Array-
Elemente die Adresse weiter gesetzt werden
soll
-> Ergebnis: du hast die Speicheradresse an der das y-te Element von
rawData gespeichert ist.
Und diese Adresse übergibst du an pgm_read_byte, welches das dort
gespeicherte Byte besorgt und liefert.
Die Indexoperation ist in C so definiert
a[i] <==> *( a + i )
d.h. das unterscheidet sich nur dadurch, dass nach der Adressberechnung
durch den * dann auch gleich noch der Wert geholt wird. Was ja auch
sinnvoll ist, in
j = a[i];
denn da will man ja den Wert haben und in j speichern.
Nur bei dir geht das natürlich nicht, weil ja der * den Wert aus dem
SRAM holen würde, deine Daten aber nicht im SRAM sind sondern im Flash.
D.h. du musst die ganze Operation
j = a[i];
2-teilen. Da
a[i]
identisch ist zu
*(a+i)
und du den * durch einen Aufruf der Funktion pgm_read_byte ersetzen
musst, ergibt sich ganz zwanglos
j = pgm_read_byte( a + i );
Das pgm_read_byte übernimmt ganz einfach den Part der Dereferenzierung.
Alternativ hätte man auch
j = pgm_read_byte( &a[i] );
schreiben könnnen. Wenn man das auflöst, dann zeigt sich, dass auch das
wieder auf dasselbe hinausläuft, denn & und * sind komplementäre
Operationen. Ein
&(*(a+i))
ist dasselbe wie a+i
Wie gesagt: In jedem noch so grindigem C-Buch, wenn es um Arrays geht
und wie die intern behandelt werden. Das ist nämlich wichtig, weil es
auch reinspielt, wie eigentlich Arrays an Funktionen übergeben werden.
Und natürlich hängt damit aufs Engste auch das ganze Kapitel
Pointerarithmetik zusammen.
wenn dir also bei
const uint8_t a[20] PROGMEM = {...}
j = pgm_read_byte( a + i );
nicht auf Anhieb klar ist, was bei den Funtkionsargumenten passiert,
dann hast du ein enormes Defizit in deinem C-Sprachverständnis. Und das
musst du beheben! Mit dem Durcharbeiten eines C-Buchs.
Thomas Eckmann schrieb:> Quatschkopf schrieb:>> Das ist nicht richtig.> Das ist zu 100% richtig.> Das ist und bleibt ein ROM. Völlig unabhängig davon, ob man das mit> irgendeinem Verfahren löschen und neu beschreiben kann.> Funktioniert das: i++? Nein. Also Nur Lesen.>> mfg.
Du hast geschrieben: Zitat (siehe
Beitrag "Re: PROGMEM Problem"):
"Gar nicht."
Und das ist falsch!
@ Karl Heinz, vielen Dank für deine sehr ausführliche Erklärung!
Karl Heinz Buchegger schrieb:> a[i] <==> *( a + i )Karl Heinz Buchegger schrieb:> rawData die Startadresse von rawData im Speicher
Das sind die zwei Dinge, die ich einfach nicht wusste.
Gruss
Quatschkopf schrieb:> Und das ist falsch!
Ich habe dir doch schon mitgeteilt, daß es zu 100% richtig ist.
Man kann im Flash keine Variablen überschreiben, sondern nur im RAM.
1. gibt es im Flash keine Variablen
2. muss die Speicherstelle erst gelöscht werden und kann dann neu
beschrieben werden.
Du versuchst hier Zusammenhänge herzustellen, die einfach nicht
existieren.
mfg.
Electronics'nStuff schrieb:> @ Karl Heinz, vielen Dank für deine sehr ausführliche Erklärung!>> Karl Heinz Buchegger schrieb:>> a[i] <==> *( a + i )>> Karl Heinz Buchegger schrieb:>> rawData die Startadresse von rawData im Speicher>> Das sind die zwei Dinge, die ich einfach nicht wusste.
Und genau das musst du abstellen.
Denn das erste ist der Grund dafür, warum man in C schreiben kann
1
int*a=malloc(anzahl*sizeof(int));
2
3
a[i]=5;// a[i] <--> *(a+i) a ist ein Pointer
4
// der Rest ist Pointerarithmetik (+)
5
// bzw. Dereferenzierung (*)
und das zweite ist der Grund dafür, warum
1
voidfoo(int*k)
2
{
3
k[0]=8;
4
}
5
6
intmain()
7
{
8
inta[5];
9
10
foo(a);// a ist die Startadresse des Arrays
11
// und foo will eine Adresse haben - passt also
12
}
genau so funktioniert, wie es funktioniert.
Das sind also ziemliche Basis-Dinge in C, sobald man mit Arrays
arbeitet.
Karl Heinz Buchegger schrieb:> Das sind also ziemliche Basis-Dinge in C, sobald man mit Arrays arbeitet.
Ich muss zugeben, ich habe Arrays bis jetzt nur sehr oberflächlich
benutzt und noch nie für grössere Datenmengen.
Bis jetzt habe ich sie eig. ausschliesslich für Ausmaskierungen etc.
verwendet. Also zwei, drei Werte und gut ist.
Ein gutes Buch wäre allerdings bestimmt nicht verkehrt!
Electronics'nStuff schrieb:> Ein gutes Buch wäre allerdings bestimmt nicht verkehrt!
Allerdings.
Denn das ist nur die Spitze des Eisbergs (wenn auch ein sehr wichtiger).
Da wartet noch vieles darauf entdeckt zu werden.
@ Electronics'nStuff (Gast)
>Ist es korrekt, dass der Zugriff auf's Flash vehältnismässig eeeewig>dauert?
Nö. Beim Lesen 3 Takte, RAM-Zugriffe brauchen 2.
Schreiben dauert natürlich eher lang, im Bereich von einigen
Millisekunden pro Page.
Nö. Da im Flash auch das Programm liegt, wird darauf mit voller
Prozessorgeschwindigkeit zugegriffen. Die avrlib Routinen (z.B.
'pgm_read_byte()') dauern ein klein wenig, aber kannste eigentlich
vergessen. EEPROM ist eigentlich das langsamste wegen der ganzen
Registervorbereitung.
@ Matthias Sch. (Firma: Matzetronics) (mschoeldgen)
>Prozessorgeschwindigkeit zugegriffen. Die avrlib Routinen (z.B.>'pgm_read_byte()') dauern ein klein wenig,
Nö, das sind schon lange INLINE Funktionen.
Falk Brunner schrieb:> Messfehler? DIV 8 Fuse gesetzt? AVR Fuses falsch eingestellt?
DIV 8 kann ich definitiv ausschliessen. Ist zwar der interne Oszillator
aber der sollte ja wohl trotzdem so um die 8MHz haben.
Messfehler?
Hmm.. habe einfach einen Pin getoggelt am Anfang und am Ende des
Programms.. mit DSO gemessen (das ist eig. ziemlich genau sonst).
Gruss
@ Electronics'nStuff (Gast)
>Hmm.. habe einfach einen Pin getoggelt am Anfang und am Ende des>Programms..
Togglen kann schief gehen, dann misst man Mist. Du must definert am
Anfang setzen und am Ende löschen.
Electronics'nStuff schrieb:> Das Array aus dem Flash habe ich über einen Header eingebunden, das> sollte eig. keinen Einfluss haben nehme ich an?
Das ist egal.
Electronics'nStuff schrieb:> knapp 220µs dauert bei einer Taktrate von 8Mhz?
Für die ganze Schleife?
Ein Durchlauf ca. 30 Takte. Finde ich bei der Rechnerei da drin nicht so
erstaunlich.
mfg.
Harun schrieb:> Welchen Wert hat "spalte_position"?
Wird von 0-60 heraufgezählt also ein 60 Durchläufe.
Thomas Eckmann schrieb:> Ein Durchlauf ca. 30 Takte. Finde ich bei der Rechnerei da drin nicht so> erstaunlich.
Dauert die echt so lange?
Gibt es da noch was einfacheres?
Ich will z.B. aus 0xBE zwei Variabeln kreieren -> 0x0B und 0x0E.
Funktioniert auf diese Weise ohne Probleme aber geht es auch einfacher?
Gruss
> Wird von 0-60 heraufgezählt also ein 60 Durchläufe.
Kein Wunder.
> Gibt es da noch was einfacheres?
Da ungerade & gerade immer nacheinander folgen: Ja.
Electronics'nStuff schrieb:> Dauert die echt so lange?
Das ist das, was du gemessen hast.
Electronics'nStuff schrieb:> Ich will z.B. aus 0xBE zwei Variabeln kreieren -> 0x0B und 0x0E.
Das verstehe ich jetzt nicht so ganz.
mfg.
Naja.. ich habe in meinem Array (rawData) lauter 8-Bit "Worte" in hex
gespeichert.
Also irgendwie 0x45, 0xBE, 0x75 etc.. ich möchte diese nun umwandeln.
Im Array spalte[] sollen die gleichen Werte vorkommen, allerdings
"aufgeteilt".
Also so: 0x45 -> 0x04 und 0x05
0xBE -> 0x0B und 0x0E
0x75 -> 0x07 und 0x05
Ich will quasi die 8-Bit Worte einfach auftrennen und dann in meinem
Array unterbringen.
Gruss
Electronics'nStuff schrieb:> Ich will quasi die 8-Bit Worte einfach auftrennen und dann in meinem> Array unterbringen.
Also aus rawdata[0] = 0x45
soll spalte[0] = 0x04 und spalte[1] = 0x05 werden?
mfg.
Electronics'nStuff schrieb:> Ich will quasi die 8-Bit Worte einfach auftrennen und dann in meinem> Array unterbringen.
Dafür hast du dieses Monster PROGMEM aufgezogen? Glaub ich jetzt mal
nicht.