Kritischen Pfad für den Datenspeicher herausfinden?

#3993535
Lesenswert?

Hallo zusammen,

ich bekomme momentan folgende Fehlermeldung:

Data Memory Usage :  162 bytes   126,6 % Full  (Memory Overflow)

Nun hätte ich gerne herausgefunden, an welcher Stelle denn mein 
Datenspeicher nicht ausreicht. Ich benutze Atme-Studio 6.2. Weiß jemand, 
ob es dort eine Möglichkeit gibt, anzeigen zu lassen an welcher Stelle 
dieser Fehler auftritt?

Folgendes habe ich schon versucht, ohne, dass sich die Zahlen geändert 
hätten:

- Funktionen zusammengeführt um Variabeln zu sparen und den Stack zu 
verkleinern
- Funktionen und Variabeln testweise ganz auskommentiert
#3993613
Lesenswert?

Peter Dannegger schrieb:
> Im Map-File in der data Sektion.
> Z.B.:
>
1
>  .data          0x00800060        0x4 C:\WINDOWS\TEMP/ccik2v6G.o
2
>                 0x00800060                display_mem
3
>
>
> Besagt, daß an Adresse 0x60 4 Byte als display_mem belegt sind.
1
.data           0x00800060       0x9a load address 0x000003f6
2
                0x00800060                PROVIDE (__data_start, .)

Das wären ja schon mal 154 byte. Aber woher die jetzt kommen wird mir 
daraus leider nicht ersichtlich. Meine im Programm verwendeten Variabeln 
finde ich nirgends wieder.

@Oliver: Es ist ein AtTiny2313A, ich möchte daran ein Display betreiben 
und per Inkrementalgeber eine Zahl zwischen 1 und 16.000.000 einstellen, 
welche auf dem Display angezeigt wird. Ursprünglich dachte ich, dass die 
dafür verwendete uint32_t daran schuld wäre, das erwähnte 
auskommentieren dieser Zahl und auch der Umweg über drei uint8_t haben 
leider nichts bewirkt.
#3993692
Lesenswert?

M. S. schrieb:
> Hallo zusammen,
>
> ich bekomme momentan folgende Fehlermeldung:
>
> Data Memory Usage :  162 bytes   126,6 % Full  (Memory Overflow)
>
> Nun hätte ich gerne herausgefunden, an welcher Stelle denn mein
> Datenspeicher nicht ausreicht.

Was meinst du mit "an welcher Stelle"? An welcher Stelle genau ist ein 
Eimer zu klein für das Wasser, das du reinschüttest?

> Folgendes habe ich schon versucht, ohne, dass sich die Zahlen geändert
> hätten:
>
> - Funktionen zusammengeführt um Variabeln zu sparen und den Stack zu
> verkleinern

Der Stack ist in der oben angegebenen Anzeige gar nicht enthalten. Der 
kommt also noch oben drauf. Dessen Größe ist dem Linker nicht bekannt, 
da sie sich erst zur Laufzeit ergibt, deshalb kann sie dort nicht 
angezeigt werden.

> - Funktionen und Variabeln testweise ganz auskommentiert

Funktionen brauchen Codespeicher, nicht Datenspeicher.

M. S. schrieb:
> Das wären ja schon mal 154 byte. Aber woher die jetzt kommen wird mir
> daraus leider nicht ersichtlich. Meine im Programm verwendeten Variabeln
> finde ich nirgends wieder.

avr-objdump -t <ELF-Datei> sollte dir eine Liste aller Symbole mit Name 
und Größe angeben.

M. S. schrieb:
> Ursprünglich dachte ich, dass die
> dafür verwendete uint32_t daran schuld wäre, das erwähnte
> auskommentieren dieser Zahl und auch der Umweg über drei uint8_t haben
> leider nichts bewirkt.

Ein uint32_t braucht vier Bytes. Drei uint8_t brauchen stattdessen drei 
Bytes. Ist also nicht sehr verwunderlich, wenn sich dadurch nicht viel 
ändert.
#3993762
Lesenswert?

Danke für die Antworten - ich habe zwischenzeitlich herausgefunden, 
welcher Teil des Codes das Problem verursacht hat.
1
    
2
switch(debounceIncrements())
3
{
4
  case 0:
5
    break;
6
  case 1:
7
    IncPlus();
8
    break;
9
  case 2:
10
    IncMinus();
11
    break;
12
  default:
13
    break;
14
}

Aus welchem Grund auch immer ein switch(uint8_t) so viel Arbeitsspeicher 
benötigt...
Gast #3993772
Lesenswert?

>Aus welchem Grund auch immer ein switch(uint8_t) so viel Arbeitsspeicher
>benötigt...

Sach mal gehts noch? Da sind drei unbekannte Funktionen drin.
Man könnte ja glatt von selber auf die Idee kommen das die das
Problem sind.
#3993802
Lesenswert?

Ja, dass die Funktionen nicht hier drin sind ist mir auch klar, ich 
dachte dass es an dem "switch" liegt und wollte das mitteilen. Bin nun 
aber durch weiteres ausprobieren darauf gekommen, dass es auf 
"lcd_string()" zurückzuführen ist, das aus der hier auf µC.net zu 
findenden lib verwendet wird:
1
void lcd_string( const char *data )
2
{
3
  while( *data != '\0' )
4
  lcd_data( *data++ );
5
}

mit
1
void lcd_data( uint8_t data )
2
{
3
  LCD_PORT |= (1<<LCD_RS);    // RS auf 1 setzen
4
  
5
  lcd_out( data );            // zuerst die oberen,
6
  lcd_out( data<<4 );         // dann die unteren 4 Bit senden
7
  
8
  _delay_us( LCD_WRITEDATA_US );
9
}

und
1
static void lcd_out( uint8_t data )
2
{
3
  data &= 0xF0;                       // obere 4 Bit maskieren
4
  
5
  LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
6
  LCD_PORT |= (data>>(4-LCD_DB));     // Bits setzen
7
  lcd_enable();
8
}

Der verwendete Speicher ist dabei proportional zur länge des Strings, 
konnte es dadurch umgehen, dass jedes Zeichen einzeln gesendet wird via 
lcd_data. Hat der Tiny2313A einfach extrem wenig Arbeitsspeicher?
#3993822
Lesenswert?

Auch die gezeigten Funktionen sind es nicht.

Der von AVR-size ausgegebene Wert umfasst nur globale und statische 
Variablen. Die gibt es in den von dir gezeigten Codeabschnitten aber gar 
nicht.

Und die Frage, ob ein Attiny2313a extrem wenig Arbeitspeixher hat, ist 
ja wohl nicht ernst gemeint, oder?

Oliver
#3993839
Lesenswert?

Es hängt auch vom Inhalt des Strings, d.h. ob Sonderzeichen enthalten 
sind ab. Aber wie gesagt führt das heraus nehmen dieser Funktion dazu, 
dass das Problem verschwindet. Anders herum führt das Einfügen eines 
Aufrufs von lcd_string() an einer beliebigen Stelle dazu, dass die 
Auslastung wieder extrem ansteigt. Ich habe exakt die Funktionen aus 
https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung 
verwendet. Dabei hängt die Auslastung auch vom Inhalt des Strings ab, 
bspw. ein Sonderzeichen, hier "^" benötigt mehr Speicher.
#3993843
Lesenswert?

@Walter: Es geht mir darum, zu erfahren, wie ich allgemein die 
Auslastung des Arbeitsspeichers verringern kann, da mir dadurch, dass 
hier im konkreten Einzelfall etwas optimiert wird nicht für die Zukunft 
geholfen ist.

@A.K.: Demnach dürften aber, da ich ein 16-Zeichen-Display verwende und 
demnach auch nur höchstens 16 Zeichen an die Funktion übergebe, 
höchstens 16 Bytes RAM verwendet werden, oder?
#3993849
Lesenswert?

M. S. schrieb:
> @A.K.: Demnach dürften aber, da ich ein 16-Zeichen-Display verwende und
> demnach auch nur höchstens 16 Zeichen an die Funktion übergebe,
> höchstens 16 Bytes RAM verwendet werden, oder?

Nein. Nicht die Funktion ist verantwortlich, sondern das "123456789". 
Das muss irgendwo stehen, und da AVRs architekturbedingt das Flash nicht 
mit einem const char * ansprechen können ist das eben RAM. Steht zwar 
zusätzlich auch im ROM, wird aber beim Start ins RAM kopiert.

Schreib die Funktion als lcd_string(const __flash char *) und ruf sie 
mit lcd_string(PSTR("123456789")) auf. Nun bleibt der String im Flash 
und braucht kein RAM.
#3994482
Lesenswert?

@ Oliver S. (oliverso)

>Ganz generell ist C-Programmierung auf einem Tiny mit nur 128 Byte Sram
>sportlich.

Naja. Für eine einfache Anzeige einer 24 Bit Zahl und bisser 
Drehgeberauswertung reicht es allemal.

Am Ende sind es nur die typischen Anfängerfehler, welche unnötig 
Resourcen verballern.

@ M. S. (elpaco)

Poste deine VOLLSTÄNDIGEN Quelltext oder gar das ganze Projekt als 
Anhang. Dann kann man dir in 5 Minuten sagen, wo das Problem liegt. 
Siehe Netiquette.
#3995275
Lesenswert?

Hallo zusammen, danke nochmals für den Tip mit dem Flash. Ich habe die 
Funktion ersetzt und kann nun auch lcd_stringP verwenden, ohne dass der 
RAM dabei voll wird.

Ich verstehe die Einwände hier, dass in der Regel der komplette Code für 
die Lösung eines Problems nötig ist. Jedoch konnte ich hier bereits die 
verantwortliche Funktion selbst heraus finden, so dass die Funktionen 
zum auswerten des Inkrementalgebers hier weg gelassen worden sind.

Problem gelöst, darf geschlossen werden.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren