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
Es gibt keine "Stelle". Programmierst du in C oder in Assembler? Allerdings muß das ja ein sehr kleiner Tiny sein, den du da verwendest. Oliver
Im Map-File in der data Sektion. Z.B.:
1 | .data 0x00800060 0x4 C:\WINDOWS\TEMP/ccik2v6G.o |
2 | 0x00800060 display_mem |
Besagt, daß an Adresse 0x60 4 Byte als display_mem belegt sind.
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.
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.
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...
>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.
M. S. schrieb: > Aus welchem Grund auch immer ein switch(uint8_t) so viel Arbeitsspeicher > benötigt... Aus welchem Grund auch immer du darauf kommst, das ist es nicht. Wie weiter oben schon steht, steht Code im Programmspeicher, nicht im Sram. Daher, wie immer: Code zeigen, und zwar komplett. Oliver
:
Bearbeitet durch User
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?
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
:
Bearbeitet durch User
wenn Du dir helfen lassen willst bitte nicht immer irgendwelche Bröckchen präsentieren, sondern einfach das komplette Programm
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.
M. S. schrieb: > Der verwendete Speicher ist dabei proportional zur länge des Strings, Richtig. Die Zeile lcd_string("123456789"); braucht 10 Bytes RAM um der String zu speichern. Jede solche String im Code landet von Haus aus im RAM.
@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?
M. S. schrieb: > demnach auch nur höchstens 16 Zeichen an die Funktion übergebe, 17 Bytes (Nullbyte am Stringende beachten!)
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.
Der GCC legt Strings per default im SRAM ab und nicht im Programmspeicher. Schau mal ob deine LCD Bibliothek Funktionen anbietet, die direkt aus dem Programmspeicher lesen. ( meist sb lcd_stringP( PSTR("Hallo"));) Gruß Roland
Danke, der Tip hört sich gut an. Die Funktion ist so noch nicht in der lib vorhanden, ich werde hoffentlich morgen dazu kommen, das auszuprobieren und gebe dann Rückmeldung!
Ganz generell ist C-Programmierung auf einem Tiny mit nur 128 Byte Sram sportlich. Da sollte man schon einen Überblich behalten, was da genau verbraucht wird. Insofern ist da die unreflektierte Nutzung von libs aus dem Netz nicht unbedingt der richtige Ansatz. Oliver
@ 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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.