Hallo Hallo,
ich hänge mal wieder an Pointern rum..
Habe da noch so meine schwierigkeiten.
Es gibt aber bestimmt wieder jemand der Helfen kann :)
Ich möchte gerne Daten die als Struct im Flash abgelegt sind an eine
Funktion übergeben. Je nachdem welche Daten ich verwenden möchte.
Das ganze soll auf einem XMega mit dem AVR Studio laufen.
So habe ich es mal jetzt Probiert.
Das ist das Struct und die Daten.
Ich bekomme es so kompiliert, aber die Daten was ich bekomme sind
falsch.
Wenn ich das filter_array.x direkt mit _50_Hz_TP.x ersetze funktioniert
es.
Jetzt bin ich halt gerade an einem Punkt wo ich nicht mehr weiterkomme
und die Hilfe was mich weiterbringt konnte ich nicht finden.
Danke schön fürs Helfen
Gruß Tobias
Du hast die ganze Struktur als Übergabeparameter definiert. Beim
Funktionsaufruf werden daher die ganzen Bytes, aus denen die Struktur
physikalisch besteht, auf den Stack kopiert.
Aber: Dieser Kopiervorgang funktioniert nur, wenn denn die Quelldaten im
RAM liegen. Tun sie aber nicht.
Deswegen, und auch aus Performancegründen solltest du einen Pointer
übergeben. Des weiteren musst du den Programmspeicher mit
pgm_read_byte() lesen.
1
void write_dsp_hp(Filter *filter_array) {
2
uint8_t temp[4];
3
temp[0]=pgm_read_byte(&(filter_array.B2[0]));
4
temp[1]=pgm_read_byte(&(filter_array.B2[1]));
5
temp[2]=pgm_read_byte(&(filter_array.B2[2]));
6
temp[3]=pgm_read_byte(&(filter_array.B2[3]));
7
Sigma_block_write(..., temp);
8
temp[0]=pgm_read_byte(&(filter_array.B1[0]));
9
temp[1]=pgm_read_byte(&(filter_array.B1[1]));
10
temp[2]=pgm_read_byte(&(filter_array.B1[2]));
11
temp[3]=pgm_read_byte(&(filter_array.B1[3]));
12
Sigma_block_write(..., temp);
13
temp[0]=pgm_read_byte(&(filter_array.B0[0]));
14
temp[1]=pgm_read_byte(&(filter_array.B0[1]));
15
temp[2]=pgm_read_byte(&(filter_array.B0[2]));
16
temp[3]=pgm_read_byte(&(filter_array.B0[3]));
17
Sigma_block_write(..., temp);
18
temp[0]=pgm_read_byte(&(filter_array.A2[0]));
19
temp[1]=pgm_read_byte(&(filter_array.A2[1]));
20
temp[2]=pgm_read_byte(&(filter_array.A2[2]));
21
temp[3]=pgm_read_byte(&(filter_array.A2[3]));
22
Sigma_block_write(..., temp);
23
temp[0]=pgm_read_byte(&(filter_array.A1[0]));
24
temp[1]=pgm_read_byte(&(filter_array.A1[1]));
25
temp[2]=pgm_read_byte(&(filter_array.A1[2]));
26
temp[3]=pgm_read_byte(&(filter_array.A1[3]));
27
Sigma_block_write(..., temp);
28
}
29
30
int main() {
31
write_dsp_hp(&_50_Hz_HP);
32
}
Der Punkt ist, dass die normalen Speicherzugriffe von C sich immer auf
das RAM beziehen. Der Programmspeicher wird jedoch über einen anderen
Bus angesprochen, mit anderen Maschinen-Instruktionen, die C nicht
beherrscht. Die avr C library stellt daher in avr/pgmspace.h spezielle
Funktionen zum Lesen des Programmspeichers bereit, die in Assembler
implementiert wurden. Leider können diese Funktionen nur einfache
Datentype (byte, integer, etc) lesen. Deswegen musst du den
Programspeicher "zu fuß" byteweise auslesen und daraus ein neues
temporäres Array im RAM basteln.
Wenn du denn Quelltext von Sigma_block_write() ändern kann, würde ich
das dort machen. Eventuell kannst du dann den Kopiervorgang in das
temporäre Array weg optimieren.
Lesestoff dazu: http://www.nongnu.org/avr-libc/user-manual/pgmspace.html
Stefan Us schrieb:> Der Punkt ist, dass die normalen Speicherzugriffe von C sich immer auf> das RAM beziehen.
Was n das n für Quatsch? C kennt kein RAM oder ROM.
Du spielst hier auf die Harvard Architektur an, oder?
Bshit schrieb:> Was n das n für Quatsch? C kennt kein RAM oder ROM.
C ursprünglich nicht, AVRs jedoch schon und die Implementierung von GCC
auf AVRs mittlerweile auch. Daher kein Quatsch.
> Du spielst hier auf die Harvard Architektur an, oder?
Ja.
Stefan Us schrieb:> Mir ist gerade noch eingefallen, dass man die vier Bytes auch am Stück> mit memcp_P() kopieren kann.
Man könnte auch die komplette Struktur mittels memcpy_P in einem Rutsch
vom Flash ins SRAM kopieren. Nur fürs Protokoll, das würde dann
beispielsweise so aussehen
Aber egal wie man es dreht und wendet, es muss einen Kopiervorgang vom
Flash ins SRAM geben. Die von A.K angesprochene Variante mit dem 'neuen'
__flash Schlüsselwort ist die deutlich eleganteste Lösung dafür. Zum
einen macht der Compiler dann den Kopiervorgang, wenn auf die
tatsächlichen Werte zugegriffen wird und zum anderen kann der Compiler
auch die Weitergabe von Pointer an Funktionen besser überwachen, da
__flash anders ins Sprachkonzept von C eingebunden ist als die alte
PROGMEM Lösung, die die Hauptverantwortung für die korrekte Verwendung
im Code ausschliesslich an den Programmierer abgetreten hatte. Letzters
ging dann schon auch mal schief.
Karl Heinz schrieb:> Man könnte auch die komplette Struktur mittels memcpy_P
Man könnte auch die PROGMEM Krücke in Würde sterben lassen und
konsequent nur noch __flash verwenden. (Von legacy Projekten mal
abgesehen).
Und Anfänger auch zur Benutzung dieses auffordern, anstatt ihnen
Workarounds für den Workaround anzubieten.
le x. schrieb:> Und Anfänger auch zur Benutzung dieses auffordern, anstatt ihnen> Workarounds für den Workaround anzubieten.
Mit welchem Teil meines Postings, das die von A.K. angesprochene und von
dir propagierte Lösung ebenfalls als die deutlichst bessere Variante
hervorhebt, bist du nicht einverstanden?
Eventuell benutzt er ja noch (so wie ich) eine gcc Version, die __flash
noch nicht kann. Spätestens dann muss er wissen was da dahinter steckt,
so wie es nicht schadet, wenn er auch weiss, dass __flash vom Compiler
eine andere Behandlung erfordert und es daher zb nicht egal ist, wenn er
es (so wie manchmal bei einem volatile) einfach wegcastet, bzw. das
__flash nicht ohne einen Laufzeit-Penalty daher kommt und worin dieser
besteht.
Karl Heinz schrieb:> dann muss er wissen was da dahinter steckt,> so wie es nicht schadet, wenn er auch weiss, dass
... die Havard Architektur getrennte Adressräume für Code und Daten hat.
Und gleiche Adressen auf unterschiedliche Speicherzellen zeigen (Code /
Daten). Und dass Variablen ersteinmal im Datenbereich liegen. Und der µC
auf (konstante) Variblen im Codebereich nicht einfach so zugreifen kann.
Und ...
http://www.netzmafia.de/skripten/mikrocomputer/harvard.gifhttp://de.wikipedia.org/wiki/Harvard-Architektur