Hi,
für ein Verschlüsselungsverfahren muss ich riesige Matrizen speichern.
Wenn ich versuche sie per:
1
constuint8_tmatrix[]PROGMEM={0x11,0x22,...,0x11};
in den Flash legenzu lassen, bekomme ich immer den Fehler:
"Größe der Variablen "matrix" ist zu hoch."
Ich benutze einen atmega128 und die matrix ist 81Kbyte( ja 81*1024
bytes)
gross, sollte also in den Flash passen.
G++gle und Forumssuche hat leider nicht erbracht.
Was läuft da schief?
Danke
Stefan
Der avr-gcc adressiert Arrays über 16-bit-Pointer, damit ist die Größe
auf 32kB begrenzt. Warum es nicht 64kB sind, wurde hier mal diskutiert,
wenn du das genauer wissen willst, musst du mal danach suchen. 81kB
funktiert auf keinen Fall.
Oliver
Ah, das erklärt es natürlich.
Aber wenn ich die Matrix in ein 2-dimensionales Array mit 81 Zeilen und
1024 Spalten zerlege, dann sollte das funktionieren, oder? Jeder Pointer
für sich muss dann ja weniger als 32kbyte "überstreichen" können.
Danke für die schnelle Antwort
Stefan
@ Stefan H. (Firma privat) (schnufff)
>Aber wenn ich die Matrix in ein 2-dimensionales Array mit 81 Zeilen und>1024 Spalten zerlege, dann sollte das funktionieren, oder?
NEIN! Weil das auch als zusammenhängendes Objekt verwaltet wird. Du
braucht getrennte Arrays kleiner gleich 32kB.
MfG
Falk
an das Element in Zeile,Spalte?
Nur zur Info: Ich habe mehrere Matrizen die in Summe knapp 200Kbyte
gross sind und 3 davon sind grösser als 64K.Alle Matrizen sind statisch
und werden nur gelesen. Ich weiss das ich besser auf einen kleinen ARM7
umsteigen kann, aber das ist nunmal nicht die Zielplattform.
danke
Stefan
Du kannst das Array ja auch mit Assembler füllen und in C nur einen
Zeiger darauf verwalten. Arrayzugriffe erfolgen in C per definitionem
(gemäß dem Standard) immer mit dem Typ "signed int", daher sind
diese hier ungeeignet.
Danke Jörg, aber die Matrizen werden auf einem PC mit einem
CoputeralgebraProgramm vorberechnet und dann etwas formatiert und in
meiner config.c eingebunden. Sie sind also zur kompletten Laufzeit des
Programms fest.
Ich hatte mittlerweile versucht das Beispiel aus dem libc manual
nachzubauen:
Allerdings meckert er jetzt" pointer targets in init differ in
signedness".
Selbst wenn der pointer "signed int" ist, muss er doch immer noch
+32Kbyte adressieren können.Also sollte das für eine Zeile der MAtrix
reichen, oder hab ich was flasch verstanden?
Gruss
Stefan
Stefan H. wrote:
> Danke Jörg, aber die Matrizen werden auf einem PC mit einem> CoputeralgebraProgramm vorberechnet und dann etwas formatiert und in> meiner config.c eingebunden. Sie sind also zur kompletten Laufzeit des> Programms fest.
Ja, eben, daher kannst du sie ja genauso gut durch eine Folge von
.byte-Anweisungen in einer Assemblerdatei anlegen lassen.
Ok, asm für avr hab ich schon programiert, aber noch nie c und asm
gemischt.
Ich hab grad 2 probleme. wie binde ich die *.asm datei ein und wie
greife ich dann über C auf die bytes/words zu?
So, ich hab jetzt alle Array in Stücke kleiner 32K aufgeteilt und will
mit pgm_read_byte/word_far drauf zugreifen.
Definiert sind die Array wie gehabt per
1
constuint8_tMatrix0[]PROGMEM={0x01,...};
aber keine der heir gefunden Möglichkeiten auf die hexwerte in
Matrix[i]zuzugreifen scheint richtig zu funktionierten:
1
myByte=pgm_read_byte_far(FAR(Matrix[i]);
2
myByte=pgm_read_byte_far(FAR(Matrix+i));
3
myByte=pgm_read_byte_far(FAR(Matrix)+i));
liefern entweder nur 00 oder FF.
Bin ich denn so blöd?
Ich will einfach nur konsistent auf den kompletten flash eines Mega256
zugreifen können und mir auf ewig konstante bytes/words auslesen können.
Gruss
Stefan
Stefan H. wrote:
> Ich hab grad 2 probleme. wie binde ich die *.asm datei ein und wie> greife ich dann über C auf die bytes/words zu?
Die Assemblerdatei benennst du mit einer auf .S (großes S) versehenen
Endung und gibst sie einfach dem Compiler mit. Der kann damit dann
was anfangen.
In der Assemblerdatei musst du die extern bekannt zu machenden Symbole
mit .global deklarieren:
1
.section .progmem.data,"a",@progbits
2
.global bigarray
3
bigarray:
4
.byte 42, 23, 1, 5, 18
In der C-Datei deklarierst du dies einfach als externes Array:
1
externuint8_tbigarray[];
*Aber*:
Du kannst nicht mit normalen Array- oder Zeigerzugriffen darauf
zugreifen, denn dann stolperst du ja sofort wieder darüber, dass
ein Zeiger im AVR-GCC nur 16 bits groß ist und dass der Arrayindex
per definitionem vom Typ signed int ist. Du musst stattdessen per
Typecast vom Arraynamen einen uint32_t-Wert bilden und den an Stelle
eines Zeigers benutzen. Die ganze Adressrechnung, die dir sonst
der Compiler abnimmt, musst du also zu Fuß erledigen. Die sich
ergebende uint32_t-Zahl kannst du dann als Adresse an ein
pgm_read_byte_far() übergeben.