Hallo Leut's;
ich habe einen ATTiny45 programmiert (im AVR Studio 4.13 mit GCC) um
mein Prog zu schreiben. Nach dem kompilieren steht unter Memory Usage:
Programm/ Data/ Eeprom - Speicher, dass mein Data Speicher zu 107,3%
genutzt wird.
Ich möchte natürlich diesen Speicher reduzieren auf unter 100%. Die
Frage ist: wie man generell Speicher-sparsam programmiert und auf
unnütze Variablen verzichten kann. Was trägt zur Speicherreduzierung
bei? Ich konnte in den Beiträgen zwar was über Speicher lesen, aber
nicht wie man sprsam damit umgeht.
Wie sieht es bezüglich des Speicherbedarfs aus mit globalen Variablen
oder mit Hilfsvariablen wei folgt:
1
uint8_tZeit_180ms=88;
2
uint8_tZeit_100ms=50;
3
uint16_tStrom_Nenn=420;
4
...
Ich habe mal versucht z.B. die 16 Bit Variable in eine 8 Bit Variable zu
verändern (natürlich auch die "420" auf unter 255 zu setzen) oder aber
die Hilfsvariablen auszukommentieren und die Zahlen direkt zu verwenden
oder globale Variablen in das Hauptprogramm zu verschieben. Aber
irgendwie hat es nicht wirklich viel gebracht außer das ich jetzt 272
byte (106,3%) verwenden.
Hat jemand Tipps oder einen Link zu einem Artikel wie man
Speichersparsam programmiert? Was sollte man im Hinterkopf behalten
während der Programmierung?
P.S.: Ich weiß, ich weiß. Wenn ich einen ATTiny 85 verwenden habe ich
keine Probleme mit dem Speicher. Es geht mir mit diesem Thread nicht um
die µC sondern wirklich um die tatsache der effizienten Progranmmierung
bezüglich des vorhandenen Speichers.
Wäre für konstruktive Antworten dankbar.
Hallo Janis,
kennst Du Dich mit Assembler aus? Du kannst Dir in AVRStudio, wenn Du
den Simulator benutzt, mit View/Disassembler ansehen, was der Compiler
aus Deinem Code gemacht hat. So kannst Du lernen, wann und wie RAM
belegt wird.
Mit uint8_t liegst Du schon recht gut gut. Vielleicht lassen sich in
Schleifen usw. auch "register" Variable benutzen. Was für
"Nebenwirkungen" die verschiedenen Compiler-Optimierungsstufen
hinsichtlich der RAM-Nutzung haben, habe ich noch nicht probiert. Wäre
vielleicht einen Versuch wert.
Gruß
Fred
P.S. Versuche möglichst wenige geschachtelte Funktionsausrufe zu
benutzen, da dafür immer RAM gebraucht wird.
Hallo Janis,
noch ein Idee: Hast Du "-mtiny-stack" in den Compiler Optionen
eingestellt? Falls nicht, verwendet der Compiler 16 bit für die
Stack-Addressierung, so dass diese Adressen als 2 Bytes im RAM (bzw. auf
dem Stack selbst) landen. Falls Du es probierst und dann später doch zum
Attiny85 wechseln solltest: vergiss dann nicht, diese Option wieder zu
entfernen!
Gruß
Fred
Jannis wrote:
> Ich habe mal versucht z.B. die 16 Bit Variable in eine 8 Bit Variable zu> verändern (natürlich auch die "420" auf unter 255 zu setzen) oder aber> die Hilfsvariablen auszukommentieren und die Zahlen direkt zu verwenden> oder globale Variablen in das Hauptprogramm zu verschieben. Aber> irgendwie hat es nicht wirklich viel gebracht außer das ich jetzt 272> byte (106,3%) verwenden.
Ja, das ist klar. Einzelne Variablen zu optimieren bringt fast nichts.
Besser ist es, überall da, wo globale Variablen unnötig sind, sie lokal
anzulegen.
Die größte Optimierung ist jedoch bei Arrays möglich, die schlagen ja in
voller Länge zu Buche.
Und beim GCC werden ohne spezielle Syntax auch alle Konstantenarrays im
SRAM abgelegt.
Peter
Ich nochmal,
Trägt folgender Code zu Speichernutzung bei?
1
uint8_tZeit_500=245;
2
[...]
3
if(Zeit>=Zeit_500)
4
[...]
Ich will damit den Code übersichtlich halten. Die Variable wird im Prog
nicht verändert und behält den Wert.
Kann ich das gleiche auch mit diesem Code erreichen?
1
#define Zeit_500 245;
2
[...]
3
if(Zeit>=Zeit_500)
4
[...]
Oder wird dann die Zahl 245 als Text 245 benutzt?
Wenn nicht, wird dadurch der Datenspeicher entlastet?
@Andreas Kaiser
>Der Compiler produziert ein Map-File, in dem die Speicherbelegung>aufgeschlüsselt wird. Das ist bei der Suche die erste Adresse.
Das kann ich nicht bestätigen. Bei mir werden folgende Files produziert:
*.elf, *.eep, *.hex; *.aps, *.aws
@Fred S.
>noch ein Idee: Hast Du "-mtiny-stack" in den Compiler Optionen>eingestellt?
nein habe ich nicht, kann ich aber ausprobieren...
Jannis wrote:
> Wie sieht es bezüglich des Speicherbedarfs aus mit globalen Variablen> oder mit Hilfsvariablen wei folgt:>
1
uint8_tZeit_180ms=88;
2
>uint8_tZeit_100ms=50;
3
>uint16_tStrom_Nenn=420;
4
>...
wenn sich diese Werte nie ändern, dann kannst du das ersetzen durch
#define Zeit_180ms 88
#define Zeit_100ms 50
#define Strom_Nenn 420
> Ich habe mal versucht z.B. die 16 Bit Variable in eine 8 Bit Variable zu> verändern (natürlich auch die "420" auf unter 255 zu setzen) oder aber> die Hilfsvariablen auszukommentieren und die Zahlen direkt zu verwenden
mit den #define machst du im Grunde nichts anderes, allerdings
in einer etwas besseren Form, als wie wenn die Zahlenwerte direkt
im Code stehen würden.
> oder globale Variablen in das Hauptprogramm zu verschieben.
Das bringt nicht viel.
Globale Variablen wirst du nur dann los, wenn sie nicht wirklich
global sein müssen und in Subfunktionen verfrachtet werden können.
Zeig mal dein Programm. Speichersparen ist meist eine
Gratwanderung, die man am realen Code machen muss.
PS: Selbst wenn du den Speicher auf knapp unter 100% bringen
kannst, reicht das noch nicht. Es muss schon deutlich unter
100% sein, da ja zur Laufzeit für Call/Return Stack und
lokale Variablen auch noch Speicher benötigt wird.
Jannis wrote:
> Das kann ich nicht bestätigen. Bei mir werden folgende Files produziert:> *.elf, *.eep, *.hex; *.aps, *.aws
Muss man möglicherweise im Studio in den Projekteigenschaften noch
einschalten.
>>noch ein Idee: Hast Du "-mtiny-stack" in den Compiler Optionen>>eingestellt?
Das spart ein paar Bytes Code, aber keine Daten.
Jannis wrote:
>>Der Compiler produziert ein Map-File, ...> Das kann ich nicht bestätigen. ...
Dann setze mal bei den Compiler-Optionen (erstes Fenster, wenn Du
"configuration options" im Studio anklickst) ein Häkchen vor "generate
map file"! Und den map file dann im Unterordner "default" (oder wohin
bei Dir der Compiler schreibt) suchen.
Gruß
Fred
Ich habe jetzt mal alle Werte die sich nicht ändern in defines
definiert. Hat nicht wirklich was gebracht.
Das Map-file ist jetzt im Anhang, (danke für die Info a-k)
Dir verhagelt der Floating-Point Fehler der aktuellen Version vom WinAVR
Code und Daten. Es wird am einfachsten sein, wenn du die WinAVR Version
von Mai 2007 verwendest.
>Dir verhagelt der Floating-Point Fehler der aktuellen Version vom WinAVR>Code und Daten. Es wird am einfachsten sein, wenn du die WinAVR Version>von Mai 2007 verwendest.
Vielen Dank für die Info, aber ich muss Windows Vista benutzen und bei
der Mai-Version gibt es da Probleme. Mein Administrator musste mir daher
die aktuelle Version aufspielen.
Shit - und nu?
ich führe zwei berechnungen it floating point durch:
1
I_Min=(wert*0.7);// untere Grenze
2
I_Max=(wert*1.3);// obere Grenze
ich brauche aber definitiv die Werte für +/- 30 Prozent, Kann ich anders
daran kommen?
Jannis wrote:
> Shit - und nu?>> ich führe zwei berechnungen it floating point durch:>
1
>I_Min=(wert*0.7);// untere Grenze
2
>I_Max=(wert*1.3);// obere Grenze
3
>
>> ich brauche aber definitiv die Werte für +/- 30 Prozent, Kann ich anders> daran kommen?
I_Min ist ein Integer?
Delta = ( wert + 5 ) * 3 / 10;
I_Min = wert - Delta;
I_Max = wert + Delta;
(Die + 5 sind die Hälfte von den 10 und sollen eine korrekte
Rundung sicherstellen)
Aufpassen musst du, dass die Berechnung zwischendurch nicht
überlaufen kann. Hängt von wert ab (Datentyp und Wertebereich).
>Dir verhagelt der Floating-Point Fehler der aktuellen Version vom WinAVR>Code und Daten. Es wird am einfachsten sein, wenn du die WinAVR Version>von Mai 2007 verwendest.
DEFINITIV
Wenn ich mit ganzen Zahlen rechne habe ich folgendes:
Data: 4 bytes (1.6% Full)
Also ganze 100% weniger
@a-k
Woran hast du das in dem map-file erkannt?
@kbuchegg
Danke für Dein Rechenbeispiel, damit komme ich und auch mein
Datenspeicher { ;-) } klar. Die Rundungsfehler sind in diesem Beispiel
nicht soooo wichtig!
Vielen Dank euch allen für eure ausführlichen Informationen.
Mir ist noch wichtig, wie man das im map-file erkennt und vielleicht
trotz euren Infos, wo man Artikel oder Infos über speicheroptimierte
Programmieren findet.
Denn ich interessieren mich generell für einen sauberen Programmierstil,
weil ich mehr oder weniger gerade erst anfange und von Anfang an grobe
Fehler vermeiden möchte, die sich sonst ins Hirn brennen und später nur
noch schlecht loszuwerden sind!
Jannis wrote:
> @a-k> Woran hast du das in dem map-file erkannt?
In diesem Fall an der Variablen __clz_tab aus der libgcc. Diesen Bug
hatte ich schon im Dezember gefunden. Siehe Thread kurz nach der Release
vom neuen WinAVR.