PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Attiny2313: Arbeitsspeicher läuft über?



-schumi-
26.06.2011, 23:58
Hallo zusammen,

was passiert wenn einem Attiny der Ram überläuft? Bleibt er dann stehen oder macht er undefinierte Sachen?

In meinem Fall ist das konkret so, dass ich u.a. Strings über den UART an den PC sende. Allerdings kommt am PC, wenn die Strings zu lang sind, ab einer bestimmten Stelle nur noch Müll an. Das Phänomen gibts aber erst seit dem der Code gewachsen ist.

Außerdem macht der komische Sachen, die ich so noch nicht gesehen hab, z.B.




1 ....
2 while(true_false)
3 {
4 UART_STRING("Sending: "); ### 1
5 UART_SEND(text);
6 UART_STRING(" ");
7 _delay_ms(2);
8 RF12_TXDATA(data,6);
9 if(RF12_READY_TIMEOUT_RX(300000)) ### 2
10 {
11 UART_STRING("reaction: YES "); ### 3
12 //RF12_RXDATA(cksm,6);
13 if(cksm_false_OK(cksm[1]))
14 {
15 UART_STRING("checksum: OK ");
16 true_false=0;
17 }
18 else
19 UART_STRING("cksm: FALSE\n");
20
21 }
22 else
23 UART_STRING("reaction: NO\n"); ### 4
24 }
25 ....



Wenn ich bei ###2 "if(1) " reinschreibe, dann erhalte ich am UART wie erwartet "reaction: YES " (###3)
Wenn ich bei ##2 "if(0) " reinschreibe, dann erhalte ich am UART wie erwartet "reaction: NO\n" (###4)
Wenn ich aber bei ###2 wie jetzt im Qellcode "if(RF12_READY_TIMEOUT_RX(300000))" reinschreibe, dann erhalte ich immer nur "Sending: " (###1), wobei die IF-Anweisung doch nicht einfach so übersprungen werden darf?!? (RF12_READY_TIMEOUT_RX(300000) gibt char zurück)

Ist das ein eindeutiger Hinweis dafür, dass der Arbeitsspeicher ausgeht? Währ doof :|

(Flash geht aber schön langsam auch zuneige: avrdude: 1704 bytes of flash verified und 2048 hat er soweit ich weis)

Gruß
-schumi-

PicNick
27.06.2011, 09:45
Vorweg: Speicherüberlauf bewirkt undefinierte Sachen
Frage eine unwissenden: was macht diese Funktion ?
RF12_READY_TIMEOUT_RX(300000))

Slein
27.06.2011, 10:46
Was passiert wenn das RAM überläuft?

Der 2313 hat 128 byte sram. Das wird vom Programm von unten nach oben mit Variablen vollgeschrieben.
Von oben nach unten wird der Stack größer, also gesicherte Registerinhalte und Rücksprungadressen bei Funktionsaufrufen.

Wenn du jetzt den Stack mit Variablen überschreibst, veränderst du wahllos die gesicherten Register und damit Daten, oder Rücksprungadressen. Du baust also zufälligen Datenmüll und der Programmablauf ist nur noch als zufällig zu beschreiben.

Anders herum ändert sich nur mehr oder weniger zufällig der Inhalt deiner Variablen.

Von den 128 byte benutzt du alleine im oben aufgeführten Codefragment ca. 60 für strings.

Schau mal hier: http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc

-schumi-
27.06.2011, 12:36
Hi PicNick, hi Slein

danke für eure Antworten :-D


Frage eine unwissenden: was macht diese Funktion ?

Die Funktion wartet darauf, dass das RFM12-Funkmodul etwas empfangen hat. Dabei wird die Timeout-Zeit in us übergeben:

char RF12_READY_TIMEOUT_RX (unsigned long time)
{
RF12_TRANS(0x82C8); // RX on
RF12_TRANS(0xCA81); // set FIFO mode
RF12_TRANS(0xCA83); // enable FIFO
unsigned long timer=0;
cbi(RF_PORT, CS);
while (!(RF_PIN&(1<<SDO)))
{
_delay_us(1);
timer++;
if(timer>time)
return 0;
}
return 1;
}


Von den 128 byte benutzt du alleine im oben aufgeführten Codefragment ca. 60 für strings.
Wird der Platz nach dem der Text rausgeschrieben wurde nicht mehr freigegeben?

Der betreffende Teil aus der UART.c:

void UART_SEND (unsigned char data)
{
while(!(UCSRA & (1 << UDRE))); // warten bis UDR bereit ist
UDR = data; // sende Zeichen
}

void UART_STRING(char *string)
{
while(*string)
{
UART_SEND(*string++);
_delay_ms(2);
}
}


Schau mal hier: http://www.rn-wissen.de/index.php/Sp...en_mit_avr-gcc (http://www.rn-wissen.de/index.php/Speicherverbrauch_bestimmen_mit_avr-gcc)
Danke für den Link, werd ich mir mal zu Gemüte führen

Wer sich den ganzen Quellcode ansehen möchte, hier ist der Projektordner:
https://www.dropbox.com/s/7m7i9zfifezgfnv/Robo_zu_PC_mit_Ueberpruefung.zip
(Grob umschrieben: Ein Atmega88 sendet an den Attiny2313 eine Text ("Das ist ein Test"). Der Attiny sendet dann den Text via RFM12 an einen Atmega16 weiter (Mit Fehlerkorrektur) und gibt am UART Debugginginfos aus. Der Atmega16 gibts dann am UART aus)

Gruß
-schumi-
(https://www.dropbox.com/s/7m7i9zfifezgfnv/Robo_zu_PC_mit_Ueberpruefung.zip)

uwegw
27.06.2011, 12:46
Du solltest die konstanten Strings in das Flash verlagern.

Wenn du die Strings so wie bei dir definiert, landen sie zunächst einmal im Flash (damit sie dauerhaft erhalten bleiben) und werden dann beim Bootvorgang ins RAM kopiert. Aus Sicht des Compilers sind es nämlich ganz gewöhnliche Variablen, die auch zur Laufzeit geändert werden könnten. Somit wird dauerhaft eine Menge RAM belegt, und das ist auf nem Tiny oft tödlich.

Daher sollte man bei solchen langen konstanten Texten eine separate Funktion schreiben, die die Daten direkt aus dem Flash lädt (mit LPM bzw. den entsprechenden avr-libc-Funktionen).

-schumi-
27.06.2011, 22:53
Du solltest die konstanten Strings in das Flash verlagern.

Das hab ich getan:

vorher:

Device: attiny2313

Program: 1704 bytes (83.2% Full)
(.text + .data + .bootloader)


Data: 120 bytes (93.8% Full)
(.data + .bss + .noinit)




nachher (Programm wurde sogar noch etwas erweitert!!):

Device: attiny2313

Program: 1776 bytes (86.7% Full)
(.text + .data + .bootloader)


Data: 14 bytes (10.9% Full)
(.data + .bss + .noinit)




Das ist einfach der blanke Wahnsinn - FETTES DANKEE!! :-D

Jetz muss ich nur noch versuchen, auch noch die Funkbrücke in anderer Richtung zu implementieren ohne dass mir der Flashspeicher ausgeht..

Gruß
-schumi-

PS: Die Fehlerkorrekturfunktion arbeitet im übrigen schon so gut, dass ich mit den RFM12-Modulen ohne Antenne 140cm überbrücken kann. Einziger Fehler der noch auftritt ist, dass die Bestätigung des Empfängers manchmal verloren geht und dann der Sender aufgrund des Timeouts ein weiteres mal sendet -> Ich bekomme manchmal Zeichen doppelt
Aber das lässt sich sicher auch noch fixen :-D

uwegw
28.06.2011, 09:10
Wenns dann wieder eng wird, könntest du die Texte noch ins EEPROM verlagern, da hast du noch mal 128 Bytes zur Verfügung...