mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Wiefiel Platz ist in einem AVR Mega16?


Autor: Matthias R. (matsch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin,
ich habe ein Programm für einen ATmega16 geschrieben (AVR-GCC & AVR 
Studio4 4.18). Nach einem Build erhalte ich unten stehende Meldung.
Mein Programm läuft scheinbar einwandfrei.
Aber wie kann es sein, das der Datenspeicher zu 127.1% voll ist? Oder 
wie muss diese Info verstehen?
Gruß
Matthias

----------------
Device: atmega16

Program:   14124 bytes (86.2% Full)
(.text + .data + .bootloader)

Data:       1302 bytes (127.1% Full)
(.data + .bss + .noinit)

Build succeeded with 0 Warnings...

---------------
Im Datenblatt steht:
Nonvolatile Program and Data Memories
– 16K Bytes of In-System Self-Programmable Flash
  Endurance: 10,000 Write/Erase Cycles
– Optional Boot Code Section with Independent Lock Bits
  In-System Programming by On-chip Boot Program
  True Read-While-Write Operation
– 512 Bytes EEPROM
  Endurance: 100,000 Write/Erase Cycles
– 1K Byte Internal SRAM
– Programming Lock for Software Security

Autor: nichtgast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Data:       1302 bytes (127.1% Full)

– 1K Byte Internal SRAM


1K ist wohl 1024 Bytes  also sind 1302 127% davon.

doch Gast

Autor: oldmax (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi
>Mein Programm läuft scheinbar einwandfrei.
Wie du schon schreibst, scheinbar. Bei dieser Auslastung ist z.B. kein 
Platz mehr für den Stack, d. H. die Variablen, die in diesem Bereich 
sind, enthalten entweder Rücksprungadressen oder irgendwann springt dein 
Programm nicht nehr an die vorgesehene Adresse zurück, weil das 
Beschreiben der Variablen den Stack verändert. Du solltest dich von 
einigen Daten trennen oder einen anderen Speicher ansprechen.
Gruß oldmax

Autor: Matthias R. (matsch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>1K ist wohl 1024 Bytes  also sind 1302 127% davon.
dessen bin ich mir durchaus bewusst. Ich frage mich nur, wie ich 127% 
Daten in 100% Speicher bekommen???
Hätte erwartet, dass der Compiler zumindest eine Warnung ausgibt.

oldmax schrieb:
> Hi
>>Mein Programm läuft scheinbar einwandfrei.
> Wie du schon schreibst, scheinbar. Bei dieser Auslastung ist z.B. kein
> Platz mehr für den Stack, d. H. die Variablen, die in diesem Bereich
> sind, enthalten entweder Rücksprungadressen oder irgendwann springt dein
> Programm nicht mehr an die vorgesehene Adresse zurück, weil das
> Beschreiben der Variablen den Stack verändert. Du solltest dich von
> einigen Daten trennen oder einen anderen Speicher ansprechen.
> Gruß oldmax
So etwas in der Art habe ich vermutet. Mit Anderen Worten: Das Programm 
läuft 100 mal und beim 101 mal wundere ich mich, finde den Fehler nicht, 
weil der C-Code richtig ist, aber im Speicher etwas undefiniertes 
passiert ist.
Gruß
Matthias

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

Bewertung
0 lesenswert
nicht lesenswert
Matthias R. schrieb:

> So etwas in der Art habe ich vermutet. Mit Anderen Worten: Das Programm
> läuft 100 mal und beim 101 mal wundere ich mich,

Wenns nur so einfach wäre.
Es ist eher so, dass dein Programm in manchen Funktionalitäten ganz gut 
funktioniert, während andere Funktionalitäten manchmal überhaupt nicht 
funktionieren. Dazu kommen unerklärliche Abstürze etc.

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

Bewertung
0 lesenswert
nicht lesenswert
Matthias R. schrieb:
>>1K ist wohl 1024 Bytes  also sind 1302 127% davon.
> dessen bin ich mir durchaus bewusst. Ich frage mich nur, wie ich 127%
> Daten in 100% Speicher bekommen???
> Hätte erwartet, dass der Compiler zumindest eine Warnung ausgibt.

Woher soll der Compiler denn das wissen?
Der sieht doch das komplette Programm überhaupt nicht.
Wenn schon, dann könnte das der Linker machen, denn der baut das 
Programm zusammen.

Aber zum Schluss kommt doch die Speicherstatistik raus, in der sieht man 
es ohnehin. Als Programmierer hat man eben auch ein wenig Verantwortung 
sich selber um Dinge zu kümmern.

Autor: H.Joachim Seifert (crazyhorse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hm, gibt zwar immer besondere Fälle, die mehr RAM brauch als üblich, 
aber normalerweise komme ich mit dem Verhältnis ROM/RAM gut zurecht.
Typischer Anfängerfehler: Variable alle global anlegen. Die verbrauchen 
dann den entsprechenden Speicherplatz dauerhaft. Lokale Variable 
(solange sie nicht static sind) sparen RAM, da deren Speicherplatz nach 
Verlassen der Funktion wieder freigegeben wird und für andere benutzt 
werden kann, also Mehrfachnutzung.
Kommt auch auf den Compiler an: lokale Variable werden oft in einem Teil 
der Register untergebracht, braucht dann gar keinen RAM und schneller 
ist es auch noch.

Autor: Matthias R. (matsch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Wenn schon, dann könnte das der Linker machen, denn der baut das
> Programm zusammen.
1:0 für dich ;-) der Compiler kann es wirklich nicht wissen.

> Als Programmierer hat man eben auch ein wenig Verantwortung
> sich selber um Dinge zu kümmern.
Seit wann denn das? Ich bin immer davon ausgegangen, dass mein Computer 
erahnt, was ich mir denke, und mein Programm dahin optimiert. 
**KneifAugeZuUndGrinseEinWenigIronisch**

H.joachim Seifert schrieb:
> Kommt auch auf den Compiler an: lokale Variable werden oft in einem Teil
> der Register untergebracht, braucht dann gar keinen RAM und schneller
> ist es auch noch.
Wie der Compiler was im einzelnen macht, muss ich (da 
Gelegenheitsprogrammierer) jetzt gar nicht bis ins einzelne wissen.

Es ist aber so, dass ich mit dem jetzigen Programm ein nicht zu 
unterschätzendes Problem erzeugt habe. Ich werde also die 
Speicherauslastung unter die 100% "drücken".
Danke allen für die Infos
Gruß
Matthias

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

Bewertung
0 lesenswert
nicht lesenswert
Matthias R. schrieb:

>> Als Programmierer hat man eben auch ein wenig Verantwortung
>> sich selber um Dinge zu kümmern.
> Seit wann denn das? Ich bin immer davon ausgegangen, dass mein Computer
> erahnt, was ich mir denke, und mein Programm dahin optimiert.
> **KneifAugeZuUndGrinseEinWenigIronisch**

Den 'Do what I mean'-Modus gibts erst in der übernächsten 
Windows-Version :-)

Bis dahin werden die 'Profis' auch weiterhin den Inhalt dieser kleinen 
bunten Fensterchen lesen, bei denen Normalsterbliche einfach auf OK 
drücken, weil sie Computer ja sowieso nicht verstehen ("Ja, da war so 
eine Fehlermeldung, ich hab die einfach weggedrückt - Nein, was da 
gestanden hat weiß ich nicht mehr, hab ich auch gar nicht gelesen" - 
Grrrrr)

:-)

> Es ist aber so, dass ich mit dem jetzigen Programm ein nicht zu
> unterschätzendes Problem erzeugt habe. Ich werde also die
> Speicherauslastung unter die 100% "drücken".

Hast du viele konstante Texte?

Da ist meistens hohes Potential vorhanden, mit dem man ziemlich schnell 
und einfach massig SRAM-Speicher sparen kann.

Autor: Peter Bünger (pbuenger)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Speicherauslastung unter die 100% "drücken".

Die solltest Du deutlich(!) unter 100% drücken. Denn in der vom Linker 
angegebenen Größe ist der Stack nicht drinnen. Und dort liegen alle 
dynamischen Variablen. Da können auch mal 80% schon zuviel sein.

Peter

Autor: Matthias R. (matsch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Hast du viele konstante Texte?

Ja, meine ganzen Debug-Infos laufen über konstante Texte in Klartext z.B 
"neuer String empfangen".
Ich kann die Debug-Infos über ein Debug-Flag ein/ausschalten.
if(Flags & DebugFlag){  // Schleife für Debugging durch Flag aktivieren
  uart_puts("neuer String empfangen");
  ...                   // Variablenwert ausgeben
}

Ich bau das gerade so um, das ich die Debug-Info über
#if (DEBUGFLAG == 1)  
    {
     ....
    }
#endif
ein/ausschalten kann.

Dann habe ich jeweils nur den Teil Code im Programm, den ich per define 
aktiviere.
#define  DEBUGFLAG 0 // 0: keine Debug-Info, 1: Debug-Info

In der Release Software ist dann alle Debug-Info aus.
Ist doch richtig, oder? (Habe #if / #endif noch nie verwendet.)
Gruß
Matthias

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

Bewertung
0 lesenswert
nicht lesenswert
Matthias R. schrieb:

> In der Release Software ist dann alle Debug-Info aus.
> Ist doch richtig, oder? (Habe #if / #endif noch nie verwendet.)

Schon.
Aber du zäumst das Pferd von der falschen Seite auf.

Lass die Texte alle im Flash, dort sind sie sowieso schon, und bau dir 
eine Ausgabefunktion, die die Texte aus dem Flash laden kann, anstelle 
von aus dem SRAM.

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...


Und schon brauchst du da nicht mehr mit #ifdefs rumspielen.
Kannst du natürlich machen, weil man in der Regel ja nicht alle 
Debug-Infos braucht. Aber zum Speichersparen ist das unnötig.

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

Bewertung
0 lesenswert
nicht lesenswert
zb so

Neue Funktion
#include <avr/pgmspace.h>

.....


void uart_puts_p( const char* text )
{
  char c;
  while( ( c = pgm_read_byte( text++ ) ) != '\0' )
    uart_putc( c );
}

und schon kannst du schreiben
.....

if(Flags & DebugFlag){  // Schleife für Debugging durch Flag aktivieren
  uart_puts_p( PSTR("neuer String empfangen") );
  ...                   // Variablenwert ausgeben
}


und der Text "neuer String empfangen" belegt dir keinen Speicher im SRAM 
mehr.

richtig schön wird das dann noch mit einem Makro
#define uart_puts_P(s) uart_puts_p(PSTR(s))

denn dann brauchst du nur noch in
   uart_puts( "neuer String empfangen" );
den Funktionsaufruf ändern zu
  uart_puts_P( "neuer String empfangen" );
und der String bleibt im Flash und wird auch von dort ausgegeben.
Und wieder 23 Bytes SRAM gespart. Bei 10 Strings in dieser Größenordnung 
sind das immerhin rund 230 Bytes oder ca. 20% vom SRAM. Und das alles 
ohne Einbussen. Das lohnt also!

Autor: Matthias R. (matsch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> und bau dir eine Ausgabefunktion, die die Texte aus dem Flash
> laden kann, anstelle von aus dem SRAM.
> void uart_puts_p( const char* text )
Ich benutze ja die lib von Peter Fleury - da ist doch eine uart_puts_p 
Funktion enthalten.
Ich benutze also für Konstante Texte uart_puts_p und wenn ich zB. den 
Inhalt einer Variablen  ausgebe uart_puts (nach Konvertierung in einen 
String) bzw. uart_putc (für 8Bit Variablen).
Und mit der #if Variante habe ich nur die Texte von dem Programmteil im 
Flash, an dem ich gerade "rumspiele".
Danke für die Hilfe.
Gruß
Matthias

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

Bewertung
0 lesenswert
nicht lesenswert
Matthias R. schrieb:
> Karl heinz Buchegger schrieb:
>> und bau dir eine Ausgabefunktion, die die Texte aus dem Flash
>> laden kann, anstelle von aus dem SRAM.
>> void uart_puts_p( const char* text )
> Ich benutze ja die lib von Peter Fleury - da ist doch eine uart_puts_p
> Funktion enthalten.

Na was willst du mehr?
Die Fleury Lib hat m.W. auch das Makro zur einfachen Verwendung bereits 
fertig mit.

Es lag also nur daran, dass man sich eine ins Projekt geholte Lib auch 
mal genauer ansehen sollte und zumindest die Header File durchstöbern 
:-)

> Ich benutze also für Konstante Texte uart_puts_p und wenn ich zB. den
> Inhalt einer Variablen  ausgebe uart_puts (nach Konvertierung in einen
> String) bzw. uart_putc (für 8Bit Variablen).

Yep.

> Und mit der #if Variante habe ich nur die Texte von dem Programmteil im
> Flash, an dem ich gerade "rumspiele".

Yep.
Allrdings: Flash hast du normalerweise genug. SRAM wird meistens eher 
knapp als Flash. Aber in Zukunft wird sich das drehen :-)

Autor: Matthias R. (matsch)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl heinz Buchegger schrieb:
> Allerdings: Flash hast du normalerweise genug. SRAM wird meistens eher
> knapp als Flash. Aber in Zukunft wird sich das drehen :-)
Wie cool ist das denn. Nur durch ein paar "_P" an die uart_puts und 
lcd_puts angehängt, bin ich von 127.1% auf 81.1%.
Da habe ich ja jetzt wieder massig Platz für globale Variablen ;-)

Danke noch mal allen für die Hilfe. Besonders Dir KhB. Ein gesegnetes 
Weihnachtsfest und rutscht gut nach 2011.

Gruß
Matthias

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.