www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Datenspeicher überfüllt - wie effektiv nutzen / programmieren?


Autor: Jannis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
uint8_t Zeit_180ms = 88;
uint8_t Zeit_100ms = 50;
uint16_t 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 
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.

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Jannis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Fred,

ich kenne mich leider nicht mit Assembler aus, sondern nur mit C.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Compiler produziert ein Map-File, in dem die Speicherbelegung 
aufgeschlüsselt wird. Das ist bei der Suche die erste Adresse.

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jannis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich nochmal,

Trägt folgender Code zu Speichernutzung bei?
uint8_t Zeit_500 = 245;
[...]
if (Zeit >= Zeit_500)
  [...]

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?
#define Zeit_500 245;
[...]
if (Zeit >= Zeit_500)
  [...]
Oder wird dann die Zahl 245 als Text 245 benutzt?

Wenn nicht, wird dadurch der Datenspeicher entlastet?

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, kannst du so machen wenn du hinten beim #define noch das Semikolon 
rauswirfst.

Häng hier mal das Mapfile rein.

Autor: Jannis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jannis wrote:
> Wie sieht es bezüglich des Speicherbedarfs aus mit globalen Variablen
> oder mit Hilfsvariablen wei folgt:
>
uint8_t Zeit_180ms = 88;
> uint8_t Zeit_100ms = 50;
> uint16_t Strom_Nenn = 420;
> ...

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.

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Fred S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Jannis (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
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)

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Jannis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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:
 I_Min = (wert * 0.7); // untere Grenze
 I_Max = (wert * 1.3); // obere Grenze

ich brauche aber definitiv die Werte für +/- 30 Prozent, Kann ich anders 
daran kommen?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jannis wrote:

> Shit - und nu?
>
> ich führe zwei berechnungen it floating point durch:
>
>  I_Min = (wert * 0.7); // untere Grenze
>  I_Max = (wert * 1.3); // obere Grenze
> 
>
> 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).

Autor: Berti (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Integer arethemtik!
Da bleibt dann mehr oder weniger ein bisschen schieben übrig

Autor: Jannis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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!

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.