mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Hilfe! AVR spinnt / macht was er will.


Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.

Ich habe eine Atmega32 mit einem S65 LCD und einer SD karte am laufen.
Die SD karte läuft mit dem Code von Ulrich R.
Leider habe ich seit ein paar Wochen sehr komische Probleme mit der 
Schaltung.
Mein Code ist mit der zeit am wachsen. logisch.
aber jetzt das komische verhalten vom avr.
Es ist so, das wenn ich eine neue Funktion "hinzufügen" in der lib fürs 
LCD, funktionier mein gesamtes Programm nicht mehr sauber. das LCD zeigt 
nur noch schrott an. Und das, obwohl die Funktion gar nicht aufgerufen 
wird?
Wenn ich in der Main Funktion hinter der LCD Ausgabe etwas auf der uart 
ausgeben möchte, habe ich ähnliche Fehler verhalten. nehme ich die uart 
Geschichte wieder raus, läuft es.
Achso, das Bild wird auf der SD karte gefunden, und auch geladen.
Kann es sein, das mein RAM im AVR defekt ist vom (vielen) programmieren?
Oder kann es am AVR Studio liegen? Habe die Version 4.14.
Achso, sobald ich den compiler aus eine andere optimierung einstelle, 
bekomme ich auch ein ähnliches verhalten, das das LCD nur noch mist 
anzeigt, bzw. er den Bild bereich ändert.
vieleicht hat jemand eine lösung für mich.
ich weiß nicht wirklich, wo ich anfangen soll zu suchen.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich vermute mal das dein RAM am Ende ist.
Stacküberlauf.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Klingt nach einer möglichen ursache.
Bedeutet das ein Programmier fehler?
Oder defekter RAM?
Wie kann ich es überprüfen, und falls es der fall sein sollte, beheben?

Autor: Moritz E. (devmo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
laut ockhams razor wirds an deinem code liegen ;).. hast du keine 
simulationsmöglichkeit? oder hardware debugger? in der software 
irgendwelche debug-ausgabe möglichkeit? ich habe für debug ziemlich viel 
code investiert, damit ich per uart alles mögliche an internen zuständen 
ausgeben kann, sowie umfangreiche exception try-catch konstrukte 
(allerdings in asm).. ohne alles das wäre ich nie weitergekommen, und 
auch mit diesen möglichkeiten hilft manchmal nur das simulieren. wenn 
fehler sich eingrenzen lassen, in dem du bestimmte programmteile 
rausnimmst, weißt du ja schon wo du anfangen musst. weiter eingrenzen 
lässt sich es in dem du zu debugzwecken den code weiter veränderst, und 
die auswirkung auf das fehlerbild analysierst. oft zeigt sich z.b. am 
zeitpunkt des auftretens was der auslöser sein könnte. wenn dein 
programm sofort beim einschalten abschmiert kommt man mit dem simulator 
schnell weiter, da man nicht viele taktzyklen warten muss.

wie immer gilt, ohne weitere infos, quellcode, kann man kaum mehr als 
das orakel befragen...

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Bedeutet das ein Programmier fehler?

In gewisser Weise schon ;)

>Oder defekter RAM?

Nein.

>Wie kann ich es überprüfen, und falls es der fall sein sollte, beheben?

Man kann durch exzessive Nutzung von z.B. printf()
ganz schön viel RAM verbrauchen. Da liegen die auszugebenden
Strings im RAM. Wenn man printf_P() nimmt liegen sie im Flash.
Ist aber nur ein Beispiel. Wo du RAM vernichtest kann uns
nur dein Code verraten.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
OK, hier meine "main"
int main(void){

  usart_init(38400);
  DDRD |= (1 << PD7); // PD0 als Ausgang festlegen

  display_init();
  init_sd();

//____________________________________
  // Drehgeber Anschluß 
  DDRC  &= ~(_BV(PC1) | _BV(PC0)); // Pin's als Eingang
  PORTC  =  (_BV(PC1) | _BV(PC0)); // PullUp's ein
  DDRB   = 0xFF;                   // Port  als Ausgang

  // Timer0 einstellen                
//  TCCR0 = 1<<CS01 | 1<<CS00;   // Teilung durch 256 *  64 Int. alle   2ms bei 8MHz CLK
  TCCR0 = 1<<CS02;             // Teilung durch 256 * 256 Int. alle 8,2ms bei 8MHz CLK
  TIMSK  = 1<<TOIE0;            // enable timer interrupt
  sei();
//______________________________________________


  unsigned int Clustervar;
  unsigned char Dir_Attrib = 0;
  unsigned long Size = 0;

  //Ausgabe des Root Directory
  usart_write("\n\nDirectory\n\n");
  for (char a = 1;a < 240;a++)
  {
    Clustervar = fat_read_dir_ent(0,a,&Size,&Dir_Attrib,Buffer);
      if (Clustervar == 0xffff)
      {
        break;
      }
    tmp = (Size & 0x0000FFFF);
    usart_write("Cluster = %4x DirA = %2x FileName = ",Clustervar,Dir_Attrib);
    usart_write(&Buffer);
    usart_write("\n");
  }
  usart_write("\nDirectory Ende\n\n");*/



////////////////////////////////
  char picname[20];
  char npicnamen3[20] = "conf.txt";


  strcpy(picname, "16.bmp");
  S65_PutBmpFromSD(0,0, &picname[0]);
  _delay_ms(1000);


  S65_Fillscreen(0000);
  s65_mainsplit();


  S65_SetTextColor(0x07E0);
  char e[20] = {'U','h','r',0};
  S65_PutStr(30,108, &e[0]);
  
  _delay_ms(2000);
  strcpy(picname, "door_o.bmp");
  S65_PutBmpFromSD(0,20, &picname[0]);
  _delay_ms(1000);


  while (1) {
  
    //__________________________________________
    //Ausgabe  = richtung;
    //cls(1);
    //S65_PutByte(80,40, richtung);
      Ausgabe  = ~richtung;         // Nur beim STK500
      //usart_write(richtung);
      usart_write("Drehrichtung: %i \n",richtung);
      usart_write("\n");
    //____________________________________________


    PORTD |= (1 << PD7); // PD0 aktivieren
        _delay_ms(500);
        PORTD &= ~(1 << PD7); // PD0 deaktivieren
        _delay_ms(500); 
    
  }
}

Und hier die andere funktion:
int S65_lese_konfig(char *picname3)
{
  uint8_t tmp3;
  unsigned int Clustervar3;
  unsigned char Dir_Attrib3 = 0;
  unsigned char Buffa3[512];
  unsigned long Size3 = 0;
  //char picname3[20];
  // --------------------------------------------------------------------------
  // Konfig datei lesen:
  usart_write("------------------------------------------\n\n");
  usart_write("\n\nlese konfig file\n\n");
  mmc_read_csd (Buffa3);
  usart_write_str (picname3);


  /*Clustervar3 = 0;
  if (fat_search_file(picname3,&Clustervar3,&Size3,&Dir_Attrib3,Buffa3) == 1)
    {
    usart_write("\n--------------------------------\n\n");
    usart_write("\nKonfig File Found!!\n\n");
    usart_write("Size = %i \n",&Size3);
    //char filefound[20] = {'F','i','l','e',' ','f','o',' ',0};
    //S65_PutStr(10,50, &filefound[0]);
    //Lese File und gibt es auf der seriellen Schnittstelle aus

    fat_read_file (Clustervar3,Buffa3,0);
    _delay_ms(400);

    for (tmp3 = 0;tmp3<160;tmp3++)
    {
      usart_write("Buffer: %x ",Buffa3[tmp3]);
  //  char e[20] = {'B','u','f',0};
  //  S65_PutStr(10,30, &e[0]);
    };

    usart_write("\n--------------------------------\n\n");
    }

    else
    {
      usart_write("File Not Found - conf.txt");
    }*/
  // ------------------------------------------------------------------------
  usart_write("\n\nende lese konfig file\n\n");
  usart_write("------------------------------------------\n\n");
  return(1);    // Alles klar, keine Fehler
}
Sobald ich das kommentar bei "if (fat_search_file" raus werfe spinnt 
mein programm rum.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schmeiss doch mal alle

  usart_write("------------------------------------------\n\n");

raus. Funktioniert es dann ?

Autor: Albrecht H. (alieninside)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gast wrote:
> Klingt nach einer möglichen ursache.
> Bedeutet das ein Programmier fehler?
> Oder defekter RAM?

Nein, das bedeutet, dass dein Programm mehr RAM-Speicher benötigt als 
der Baustein zur Verfügung stellt, der ATmega32 hat "nur" 2-Kbyte SRAM 
dein Programm bräuchte aber möglicherweise 3KB, 4KB oder noch mehr SRAM.

> Wie kann ich es überprüfen,

Du könntest dir evt. an bestimmten Stellen den Inhalt des Stackpointers 
ausgeben lassen, also wenn der Stack beim AVR von oben nach unten wächst 
und der Stackpointer plötzlich "ganz unten" ankommt, also z.B. bei 0000 
oder 0002, (läuft das so beim ATmega?), dann spricht vieles dafür, dass 
du zu wenig SRAM hast, dann kann alles durcheinander kommen: Variablen 
werden überschrieben, Unterprogramm und Interruptrücksprungadressen 
gehen verloren, usw. ...

> und falls es der fall sein sollte, beheben?

Einen Prozessor mit mehr SRAM besorgen z.B. den ATmega644 (mit 4KB 
SRAM), oder externes RAM verwenden, (eher unpraktisch). Oder mal dein 
Programm durchschauen: Rekursive oder sehr verschachtelte 
Unterprogrammaufrufe brauchen viel RAM, und, (da hab ich leider noch 
nicht allzu viel Ahnung von Win-AVR-C), möglicherweise kannst du was 
retten wenn du darauf schaust, dass alle Funktionsparameter "By 
Reference" d.h. als Pointer und nicht als Speicherkopie d.h. "By Value" 
übergibst. Umfangreiche Stringmanipulationen sind bei 2KB Ram wohl auch 
nicht drin.
Im Prinzip musst du dir bei jeder Funktion, bei jeder Schleife und bei 
jeder zur Laufzeit angelegten Variable überlegen wieviel RAM dafür wohl 
verbraucht wird.

Nachtrag:
Gerade mal kurz in deinen Code reingeschaut, (wie gesagt, hab da nicht 
viel Ahnung von), aber wenn ich nur 2KB SRAM hätte, würde ich nicht so 
verschwenderisch mit den "char filefound[20]" etc. um mich werfen...
Alle Stringkonstanten müssen ins Flash, (oder optimiert das der 
Compiler?).

Und der "unsigned char Buffa3[512];" da ist ja schon mal von vornerein 
ein Viertel des RAMs auf einen Schlag weg.

Autor: Jadeclaw Dinosaur (jadeclaw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Alle Stringkonstanten müssen ins Flash, (oder optimiert das der
> Compiler?).
Der Compiler optimiert das nicht.
Die Stringkonstanten sind zwar im Flash, werden sie aber nicht auf eine 
spezielle Weise deklariert und über eine Spezialfunktion gelesen, 
sondern einfach nach der Methode 
"usart_write("------------------------------------------\n\n");" 
eingetragen, dann werden diese Konstanten beim Programmstart ins RAM 
umgeladen. Da bleibt dann für den Stack nichts mehr übrig.
Besser man macht es so: 
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...


Gruß
Jadeclaw.

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schade, ich dachte der compiler meldet sich mal, wenn er merkt falls es 
eng wird.
Der hätte ja nun wirklich den überblick.

"Buffa3[512];" wird in einer Funktion deklariert.
Wenn ich diese Funktion jetzt dreimal aufrufe, belegt sie doch nur 
einmal den speicher, oder habe ich da grundsätzlich irgendwas noch nicht 
verstanden?

Autor: Daniel F. (df311)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
nein, der speicher wird jedesmal reserviert. er wird zwar (im 
normalfall) wieder freigegeben, aber wenn z.b. nur mehr 300 kB ram übrig 
sind, es werden aber 512 benötigt gibts schon probleme.
wie die speicherverwaltung auf dem avr in c funktioniert weiß ich leider 
nicht genau, programmiere in asm...

Autor: Zweiter Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hmm, hilft da "static unsigned char Buffa3[512];" ?

Autor: Albrecht H. (alieninside)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zweiter Gast wrote:
> Hmm, hilft da "static unsigned char Buffa3[512];" ?

Dann werden die 512 Bytes eben dauerhaft belegt, (könnte aber 
vielleicht, in anderen Situationen, unter gewissen Umständen, wenn man 
das gleich beim Programmstart mit allen dauerhaft benötigten Buffern 
macht, dabei helfen, die  Speicherfragmentierung zu verringern).

Aber das Grundproblem bleibt dasselbe: Nur 2024 Bytes RAM die sich 
Variablen und Stack teilen müssen.

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zweiter Gast wrote:
> Hmm, hilft da "static unsigned char Buffa3[512];" ?

Wurde doch schon gepostet:
http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

Autor: gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstaunlich.
Durch ein wenig optimierung und ausklammern von "usart_write" 
funktioniert es jetzt.
An einen Stacküberlauf habe ich überhaupt nicht gedacht.

Ein "Danke" an alle beteiligten.

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.