Forum: Compiler & IDEs Ram wird follgeschrieben


von Florian Pfanner (Gast)


Lesenswert?

Hallo,

ich habe einen Controller Programmiert, welcher über den UART Texte 
ausgibt. Sobald ich aber mehr text ausgeben will, so hängt er sich auf. 
Ich hab das Programm mal im AVR-Studio schritt für schritt angeschaut 
und da viel mir auf, dass das ganze Ram mit dem Text für den UART 
follgeschrieben wird und damit die anderen Variablen löscht. Auch den 
Text in mehrere kleine stücke unterteilen bringt nichts, die alten 
stücke im Ram.

Danke, Florian

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Ja und wie sieht dieses Programm aus?

von Florian Pfanner (Gast)


Lesenswert?

Hier sind die Code-Fragmente:

static volatile unsigned char *uart_data_ptr;
static volatile unsigned char uart_counter;

SIGNAL(SIG_UART_TRANS)
{
    uart_data_ptr++;
    if (--uart_counter)
      outp(*uart_data_ptr, UDR);
}


void uart_send(unsigned char *buf, unsigned char size)
{
  if (!uart_counter)
  {
    uart_data_ptr  = buf;
    uart_counter   = size;
    outp(*buf, UDR);
  }
}


Text ausgeben mit:
uart_send("Text",länge);

von Jonas Diemer (Gast)


Lesenswert?

hmm, hat das evtl. damit zu tun, dass er (aus welchem grund auch immer, 
so firm bin ich da nicht) den stack mit deinem text vollklatscht? Kann 
eigentlich nur so sein. die frage ist: wieso? wie gesagt, bin da nicht 
so firm.

von Peter (Gast)


Lesenswert?

Sehe ich das richtig, es wird einfach ein Zeiger ohne allokierten 
Speicherbereich angelegt und dann munter hineingeschrieben? Das ist aber 
schon ein grober Schnitzer! Irgendwann treffen sich Heap und Stack und 
dann ist Ende im Gelände ;-)

Gruss,

Peter

von Jonas Diemer (Gast)


Lesenswert?

yo, uart_data_ptr zeigte einst auf buf, welches ja aber nur in uart_send 
gültig ist. Das war mir auch aufgefallen... allerdings wird da ja nix 
hingeschrieben, sondern von dort an den UART gesendet...

und uart_counter ist ja global, müsste also tatsächlich irgendwann auf 0 
stehen...

oder seh ich das falsch?

von Florian Pfanner (Gast)


Lesenswert?

Die Problematik habe ich nun erkannt: Der zeiger uart_data_ptr wird 
immer um eins erhöht und zeigt so auf immer einen anderen wert. Also 
auch beim laden von neuen Texten. Kann ich den Zeiger irgendwie 
zurückstellen, also auf einen festen Speicherbereich zeigen lassen?

von Peter D. (peda)


Lesenswert?

Hallo Florian,

Du must überhaupt erstmal Speicher für den UART-Puffer zuweisen.
Ansonsten schreibst Du mit Deinem Pointer irgendwo ins RAM.

char buffer[40];

char * ptr = buffer;

und dann im Interrupt:

ptr++;
if( ptr == (buffer + sizeof(buffer)) ) // am Ende angelangt ?
  ptr = buffer; // dann wieder von vorne


Peter

von Florian Pfanner (Gast)


Lesenswert?

Ich habe nun die Routienen umgeschrieben. Sie sehen so aus:

char buffer[41];
char *ptr = buffer;
int laenge;

SIGNAL(SIG_UART_TRANS)
{
  ptr++;
  laenge--;
  if (laenge)
    outp(*ptr,UDR);
}

void uart_send(unsigned char *buf, unsigned char size)
{
  for(;;)
  {
    if (laenge==0)
    {
      laenge=size;
      int t;
      for (t=0;t<=size;t++)
      {
        if (t<=40);
        {
          buffer[t]=PRG_RDB(buf+t);
        }
      }
      ptr=&buffer[0];
      outp(*ptr,UDR);
      break;
    }
  }
}

wenn ich nur den Aufruf:
  char *line1 = PSTR("1.Test von Florian");
  uart_send(line1,18);
schreibe, so funktionierts.

wenn ich aber
  char *line1 = PSTR("1.Test von Florian");
  uart_send(line1,18);
  char *line2 = PSTR("2.Test von Florian");
  uart_send(line2,18);
schreibe, so wird zwar der 1.Text ausgegeben, jedoch der 2.Text nicht 
mehr und der Controller reagiert nicht mehr.

Ich weiß nicht ob ich einen Fehhler in meiner Denkweise oder in meinem 
Algoritmus suchen muss.

von Jonas Diemer (Gast)


Lesenswert?

das liegt daran, dass er nach dem ersten interrupt weitermacht. d.h. er 
gibt das erste zeichen aus ('1'), springt, macht dann weiter (Line 2 
laden). dann mach er die zeile

 uart_send(line2,18);

Irgendwann (wenn er fertig ist, mit dem ersten zeichen, keine ahnung, 
wielange das dauert), springt er in den interrupt... verstehst?

von Florian Pfanner (Gast)


Lesenswert?

Danke - Jetzt gehts (ich hab zwischen den Send-Befehle eine 
Pauseroutiene geschrieben). An das Problem habe ich nicht gedacht.

Danke, Florian

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.