So ist es.Man lernt halt nie aus!
Ich denke, der eine oder andere könnte was helfen, aber dann müßtest Du das Programm postenHabt ihr noch weitere Tipps auf Lager?
Gruß Sebastian
Hallo,
Ich danke euch für die Informationen. Jetzt versteh ich auch was izaseba gemeint hat.
Ich habe ein
uint8_t FONT_6X8[659] = {....}
Dass man da das PROGMEM dazwischen schreiben muss hab ich nicht gewusst. Ich hab hier mal gelesen, dass Variablen erst im SRAM sind,
wenn sie innerhalb der main funktion deklariert werden. Das hat sich aber
schon anhand von versuchen wiedersprochen......
Man lernt halt nie aus! Und ich programmier ja erst seit nem Jahr ^^
Wie man dann dieses array ausliest muss ich mir dann noch erarbeiten.
Ich danke euch erstmal vielmals für diese Informationen!
Habt ihr noch weitere Tipps auf Lager? denn ich weiß nicht wo die restlichen ~1300 Bytes herkommen.
Ich hab eigentlich nur eine billige menüführung.... Das sind echt nur ein paar wenige Variablen... zusammen höchstens 50Bytes...
Naja und die Funktionen, aber die sind auch nicht so krass.....
Gruß,
Franz
So ist es.Man lernt halt nie aus!
Ich denke, der eine oder andere könnte was helfen, aber dann müßtest Du das Programm postenHabt ihr noch weitere Tipps auf Lager?
Gruß Sebastian
Linus TorvaldSoftware is like s e x: its better when its free.
Schau mal im avr-gcc-Artikel, da hab ich was dazu geschrieben:
13 Optimierungen, Tipps & Tricks
11.3 SRAM, Flash, EEPROM: Datenablage am Beispiel Strings
In Hallo Welt für AVR (LED blinken) gibt es einen Unterabschnitt "Mapfile erstellen". Im MapFile stehen alle Lokatierungs-Infos.
Disclaimer: none. Sue me.
Okey, danke!
Da werd ich mich am Wochenende mal durchackern.
Dankeschön und Gute Nacht!
Gruß,
Franz
Hallo,
Hat doch ein bisschen länger gedauert, musste für ne Prüfung lernen...
Also wenn ich das richtig verstanden habe, dann muss ich das machen:
Kurze Fragen noch:Code:// Headerdatei inportieren #include <avr/pgmspace.h> // mein Array Definieren const uint8_t FONT[] PROGMEM = { 1,2,3,4,5,6,7,8,9,10.... }; // Und so frägt man ein einzelnes Byte aus dem Array ab: data = pgm_read_byte(&FONT[i]);
1. Frage
Bei einer Normalen Deklaration, definiert der AVR wenn er die
Deklaration durchläuft einfach eine Variable im RAM, und der bleibt dann da im Rahmen des Geltungsbereiches?
2. Frage
Muss bei der definition einer "Flashvariable" immer das const davor stehen?
3. Frage
Bei Funktionen wird man zwahr eher weniger solche festen Arrays und
daten definieren, aber ich würde gerne verstehen warum da dann static
davor steht. Werden die dann im Flash geschrieben, und nach der
Funktion wieder gelöscht?
4. Frage
Obiges warscheinlich nur wenn man was großes Bearbeiten möchte...
Danke schon im Voraus für eure Antworten!
Gruß,
Franz
(ad 1)
Der Gültigkeitsbereich einer Variablen ist etwas anderes als ihre Lebensdauer! Die Lebensdauer bezieht sich auf ein Objekt (im Sinne von C), während "Gültigkeitsbereich" im Hinblick auf ein Symbol (über welches ein Objekt referenziert wird) zu verstehen ist.
(ad 2)
Ja.
(ad 3)
Nein. Im [wiki="C-Tutorial"] steht dazu was unter Speicherklassen bzw. Gültigkeitsbereich. Daß der Gültigkeitsbereich einer Variablen verlassen wird bedeutet nicht unbedingt, daß diese zerstört wird! Ebenso werden diese Variablen nicht vom Startup-Code ins Flash gelegt (wo sollten ihre Werte denn herkommen?) sondern in eine Section gelegt, die im Flash landet und eben nicht im RAM (oder im EEPROM). Das static kann gebraucht werden, wenn man lokale Labels in einer Flash-Tabelle halten will. Ein Beispiel findet sich am Ende der "State-Machine" im [wiki="Sourcevergleich"]
(ad 4) ???
Disclaimer: none. Sue me.
Hallo,
Danke für deine Antworten! Übrigens, netter Artikel!
Eines wäre noch offen,
Ich speichere ja nun mein Font-Array in den Flash.
Um ein Zeichen darzustellen, benötige ich 7Bytes aus dem Array.
Das bedeutet, wenn ich einen Satz schreibe, greift er ziemlich oft auf
den Flash zu.
Frage:
Wie sieht das ganze dann zeitlich aus? Dauert es recht viel länger,
Bytes aus dem Flash zu lesen, als vom RAM?
Ich denke mal, dass es dann in meinem Fall sinnvoller ist, gleich das
ganze Zeichen aus dem Flash zu lesen (die 7Bytes), und nicht jedesmal
Einzelzugriffe zu machen.
Gruß,
Franz
section size addr
.text 900 0
.data 0 8388704
.bss 0 8388704
.noinit 0 8388704
.eeprom 0 8454144
.stab 1020 0
.stabstr 1940 0
Total 3860
data + bss = 0.... Ich würde sagen, Problem gelöst!
Danke vielmals für eure Hilfe!
Das 650Byte Font liegt jetzt schön brav im Flash!
FAZIT: Man lernt nie aus!
Gruß,
Franz
Von der Zugriffszeit tun sich SRAM und Flash nicht viel, was etwas teurer sein kann ist die Adressberechnung und weil der Flash nur via Z-Reg gelesen werden kann.
Um aus dem Flash ein Byte zu lesen gibt es in avr/pgmspace.h das Makro
pgm_read_byte (addr)
in dem addr ein C-Ausdruck ist, der zu einer Adresse auswertet (bzw. unsigned int).
Beim Zugriff auf zwei aufeinanderfolgende Adressen muss die Adresse immer wieder neu berechnet werden. Ist die Adresse jedoch ein Lvalue, könnte sie im Z gehalten werden und der Zugriff dementsprechend effizienter gestaltet werden.
Ja kannst du dann wählen, was du haben willst: minimale Laufzeit oder kleinster Code:Code:#include <avr/pgmspace.h> #if defined (__AVR_ENHANCED__) #define pgm_read_byte_inc(addr) \ ({ \ uint8_t __result; \ __asm__ \ ( \ "lpm %0, Z+" \ : "=r" (__result), "=z" (addr) \ : "1" (addr) \ ); \ __result; \ }) #endif /* __AVR_ENHANCED__ */ uint8_t sram[7]; const uint8_t flash[10][7] PROGMEM = { }; void foo (uint8_t num) { uint8_t i; for (i=0; i<7; i++) sram[i] = pgm_read_byte (& flash[num][i]); } void foo2 (uint8_t num) { uint8_t i; const void * addr = flash[num]; for (i=0; i<7; i++) sram[i] = pgm_read_byte_inc (addr); } void foo3 (uint8_t num) { const void * addr = flash[num]; sram[0] = pgm_read_byte_inc (addr); sram[1] = pgm_read_byte_inc (addr); sram[2] = pgm_read_byte_inc (addr); sram[3] = pgm_read_byte_inc (addr); sram[4] = pgm_read_byte_inc (addr); sram[5] = pgm_read_byte_inc (addr); sram[6] = pgm_read_byte_inc (addr); }
Code:.global flash .section .progmem.data,"a",@progbits .size flash, 70 flash: .skip 70,0 /*************************************************/ .text .global foo foo: ldi r25,lo8(7) ; tmp48, mul r24,r25 ; num, tmp48 movw r30,r0 ; tmp54 clr r1 ldi r26,lo8(sram) ; tmp53, ldi r27,hi8(sram) ; tmp53, subi r30,lo8(-(flash)) ; tmp54, sbci r31,hi8(-(flash)) ; tmp54, ldi r25,lo8(6) ; i, .L161: lpm r24, Z ; __result st X+,r24 ; sram, __result subi r25,lo8(-(-1)) ; i, adiw r30,1 ; tmp54, sbrs r25,7 ; i, rjmp .L161 ; ret /*************************************************/ .global foo2 foo2: ldi r25,lo8(7) ; tmp45, mul r24,r25 ; num, tmp45 movw r30,r0 ; addr clr r1 subi r30,lo8(-(flash)) ; addr, sbci r31,hi8(-(flash)) ; addr, ldi r26,lo8(sram) ; tmp51, ldi r27,hi8(sram) ; tmp51, ldi r25,lo8(6) ; i, .L168: lpm r24, Z+ ; __result st X+,r24 ; sram, __result subi r25,lo8(-(-1)) ; i, sbrs r25,7 ; i, rjmp .L168 ; ret /*************************************************/ .global foo3 foo3: ldi r25,lo8(7) ; tmp45, mul r24,r25 ; num, tmp45 movw r30,r0 ; addr clr r1 subi r30,lo8(-(flash)) ; addr, sbci r31,hi8(-(flash)) ; addr, lpm r24, Z+ ; __result sts sram,r24 ; sram, __result lpm r24, Z+ ; __result sts sram+1,r24 ; sram, __result lpm r24, Z+ ; __result sts sram+2,r24 ; sram, __result lpm r24, Z+ ; __result sts sram+3,r24 ; sram, __result lpm r24, Z+ ; __result sts sram+4,r24 ; sram, __result lpm r24, Z+ ; __result sts sram+5,r24 ; sram, __result lpm r24, Z+ ; __result sts sram+6,r24 ; sram, __result ret /*************************************************/ sram: .skip 7,0
Disclaimer: none. Sue me.
Hallo,
erstmal besten Dank für Deine Bemühungen!
Ich werd gleich mal damit rumexperimentieren! Danke!
Gruß,
Franz
Lesezeichen