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


von Matthias R. (matsch)


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

von nichtgast (Gast)


Lesenswert?

Data:       1302 bytes (127.1% Full)

– 1K Byte Internal SRAM


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

doch Gast

von oldmax (Gast)


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

von Matthias R. (matsch)


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

von Karl H. (kbuchegg)


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.

von Karl H. (kbuchegg)


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.

von H.Joachim S. (crazyhorse)


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.

von Matthias R. (matsch)


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

von Karl H. (kbuchegg)


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.

von Peter B. (pbuenger)


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

von Matthias R. (matsch)


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.
1
if(Flags & DebugFlag){  // Schleife für Debugging durch Flag aktivieren
2
  uart_puts("neuer String empfangen");
3
  ...                   // Variablenwert ausgeben
4
}

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

Dann habe ich jeweils nur den Teil Code im Programm, den ich per define 
aktiviere.
1
#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

von Karl H. (kbuchegg)


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-Tutorial#Programmspeicher_.28Flash.29


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.

von Karl H. (kbuchegg)


Lesenswert?

zb so

Neue Funktion
1
#include <avr/pgmspace.h>
2
3
.....
4
5
6
void uart_puts_p( const char* text )
7
{
8
  char c;
9
  while( ( c = pgm_read_byte( text++ ) ) != '\0' )
10
    uart_putc( c );
11
}

und schon kannst du schreiben
1
.....
2
3
if(Flags & DebugFlag){  // Schleife für Debugging durch Flag aktivieren
4
  uart_puts_p( PSTR("neuer String empfangen") );
5
  ...                   // Variablenwert ausgeben
6
}

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

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

denn dann brauchst du nur noch in
1
   uart_puts( "neuer String empfangen" );
den Funktionsaufruf ändern zu
1
  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!

von Matthias R. (matsch)


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

von Karl H. (kbuchegg)


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 :-)

von Matthias R. (matsch)


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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.