Fehler nach Einfügen einer Else-Anweisung

OP #3273512
Lesenswert?

Hallo,
nachdem ich in meinem Programm eine weitere Else-Anweisung eingefügt 
habe,
funktioniert es nicht mehr vernünftig.

Zum Programm:
Das uart_receive_complete bool wird auf true gesetzt, wenn ein String 
über eine UART-Interruptroutine empfangen wurde. Dann wird damit 
begonnen, den String zu verarbeiten. Das funktioniert auch, solange kein 
weiteres Else verwendet wird.
1
if(uart_receive_complete)
2
    {
3
      lcd_clear();
4
      char cmd = uart_string[0];
5
      if ( cmd == CMD_HEADER )
6
      {
7
        strcpy(g_Header, uart_string+1);
8
      }
9
      else if ( cmd == CMD_TAG )
10
      {
11
        timer1_disable();
12
        timer1_reset();
13
        char accepted = uart_string[1];
14
        
15
        if ( accepted == UART_TRUE )
16
        {
17
          lcd_stringCenter("Welcome", 1);
18
          char* name = ( uart_string + 2);
19
          lcd_stringCenter(name, 2);
20
          led_toggle(LED_ACCEPT);
21
          delay(3000);
22
        }
23
        else if ( accepted == UART_FALSE )
24
        {
25
          lcd_stringCenter("ID unknown.", 1);
26
          lcd_stringCenter("Access denied.", 2);
27
          led_toggle(LED_DENIED);
28
          delay(3000);
29
        }
30
      /*  else
31
        {
32
          lcd_stringCenter("ID transmitted.", 1);
33
          delay(2500);
34
        }
35
      */
36
        rfid_enable();
37
      }
38
      else
39
      {
40
        lcd_stringCenter("Unknown command:", 1);
41
        lcd_stringCenter(uart_string, 2);
42
        led_toggle(LED_ACCEPT);
43
        led_toggle(LED_DENIED);
44
      }
45

46
      free(uart_string);
47
      uart_receive_complete = false;
48
      LED_PORT &= ~(1<<LED_ACCEPT);
49
      LED_PORT &= ~(1<<LED_DENIED);
50
      renderHeader();
51
    }

Wenn ich aber nun die Else-Anweisung ausklammere um eine weitere 
Verarbeitungsmöglichkeit hinzuzufügen, wird g_header nicht mehr 
vollkommen erkannt. Es wird lediglich, der erste Buchstabe kopiert.
Ich flashe mit diesem Programm einen Attiny 4313. Der Flashspeicher ist 
dann zu etwa 95% voll. Woran könnte das Problem liegen.
So langsam bin ich am verzweifeln.
Wenn Jemandem etwas auffällt würde ich mich über Hinweise oder Lösungen 
freuen.
MfG Jonas
Gast #3273550
Lesenswert?

Jonas E. schrieb:
> free(uart_string);
Du verwendest dynamische Speicherverwaltung auf einem Controller mit 256 
Bytes RAM?! Du verwendest fröhlich ewig lange Delays während derer das 
Programm auf keine Eingaben reagiert? Eventuell klappt das, eventuell 
generiert das aber auch schwierig zu findende Probleme...
Gast #3273570
Lesenswert?

>Du verwendest dynamische Speicherverwaltung auf einem Controller mit 256
>Bytes RAM?! Du verwendest fröhlich ewig lange Delays

und Strings die vermutlich auch im RAM liegen.

z.B.         lcd_stringCenter("Unknown command:", 1);

Das else

          lcd_stringCenter("ID transmitted.", 1);


hat dem Stack vermutlich nur noch den Rest gegeben. Aus die Maus.
Gast #3273599
Lesenswert?

Jonas E. schrieb:
> Wie kann aus dem Ram die nicht mehr benötigten Strings entfernen, um
> wieder Speicherplatz zu erlangen?
Gar nicht. Allerdings sollte der GCC clever genug sein, die Strings in 
den Flash zu packen. Mach dich mal schlau wie man Pointer auf 
PROGMEM-Arrays (aka. String-Konstanten) mit dem AVR-GCC an Funktionen 
übergibt. Und nimm alle malloc&free aus dem Programm...
Gast #3273616
Lesenswert?

>Wie kann aus dem Ram die nicht mehr benötigten Strings entfernen, um
>wieder Speicherplatz zu erlangen?

Überflüssige Ausgaben gar nicht erst machen.

          lcd_stringCenter("ID unknown.", 1);
          lcd_stringCenter("Access denied.", 2);

Da reicht doch auch:

          lcd_stringCenter("ID unknown", 1);
          lcd_stringCenter("Access denied", 2);

Ich hab jetzt mal die beiden '.' weggelassen. Spart zwei Byte.

Oder

          lcd_stringCenter("ID?", 1);
          lcd_stringCenter("Access denied", 2);

Nochmal 7 Byte weniger.

Oder einfach nur

         lcd_stringCenter("Access denied", 1);

Es gibt immer einen Weg RAM zu sparen.
Gast #3273636
Lesenswert?

>> Es gibt immer einen Weg RAM zu sparen.
>Wieso RAM?! String-Literale gehören in den Flash!

Das weiss ich selber, ich bin ja nicht blöd. Im Flash
stehen die sowieso. Woher sollen die sonst ins RAM kommen?

Schreib ihm seine Routine um Daten aus dem Flash zu nehmen
doch einfach. Da hatte ich jetzt im Moment keinen Bock drauf.

Ich hab ihm nur einen Weg gezeigt wie er da ohne grosse
Verrenkungen evtl. noch mal so davonkommt.
OP #3273661
Lesenswert?

lcd_StringCenter():
1
void lcd_stringCenter(const char* data, int row)
2
{
3
  if ( sizeof(data) > 0 )
4
  {
5
    int length = strlen(data);
6
    int column = 0;
7
    
8
    if ( length <= LCD_COLOUMS )
9
    {
10
      column = LCD_COLOUMS / 2 - ( length + ( length % 2 ) ) / 2;
11
    }
12
    
13
    lcd_stringAt(data, column, row);
14
  }
15
}
lcd_stringAt(data, column, row):
1
void lcd_stringAt( const char *data, int coloumn, int row )
2
{
3
  lcd_setcursor(coloumn, row);
4
  
5
  while( *data != '\0' )
6
  {
7
    if ( coloumn >= LCD_COLOUMS )
8
    {
9
      coloumn = 0;
10
      row++;
11
      lcd_setcursor(coloumn, row);
12
    }
13
    lcd_data( *data++ );
14

15
    coloumn++;
16
  }
17
}
Gast #3273674
Lesenswert?

>lcd_StringCenter():

Das jetzt auf PROGMEM umzubauen sieht nicht so einfach aus.

Aber mal ein paar andere Tips vor dem schlafen gehen:

>void lcd_stringCenter(const char* data, int row)

int row? Wozu? Kann row negativ werden? Dein Display hat ja
auch nur zwei Zeilen. Wozu brauchst du da einen 16 Bit Wert?

void lcd_stringCenter(const char* data, uint8_t row)

ist doch besser oder nicht?

Der gleiche Müll:

    int length = strlen(data);
    int column = 0;

Besser

    uint8_t length = strlen(data);
    uint8_t column = 0;

Noch son Ding. Ausser int scheinst du ja nichts anderes zu kennen.

>void lcd_stringAt( const char *data, int coloumn, int row )

void lcd_stringAt( const char *data, uint8_t coloumn, uint8_t row )

Das gleiche vermutlich mit   lcd_setcursor(coloumn, row);

sizeof(data) ist immer grösser 0.

  if ( data != 0 )

usw.

Bring erstmal diesen Unsinn in Ordnung.
Das wird dein Programm schon mal ordentlich eindampfen.
Gast #3274956
Lesenswert?

>Hallo Holger,
>ist es möglich, dass du mir deine E-Mail Adresse per PN schreibst,

Nö;)

Ich hab mich mal an deiner Funktion vergangen. Nur rein
theoretisch, könnten also noch Fehler drin sein.

So müsste das mit Strings aus dem Flash klappen.
Ohne Gewehr!
1
void lcd_stringCenter_P(const char* data, uint8_t row)
2
{
3
  char c;
4

5
  if ( data > 0 )
6
  {
7
    uint8_t length = strlen_P(data);
8
    uint8_t column = 0;
9
    
10
    if ( length <= LCD_COLOUMS )
11
    {
12
      column = LCD_COLOUMS / 2 - ( length + ( length % 2 ) ) / 2;
13
    }
14
    
15
    lcd_setcursor(coloumn, row);
16
  
17
    while((c = pgm_read_byte(data++)))
18
    {
19
      if ( coloumn >= LCD_COLOUMS )
20
      {
21
        coloumn = 0;
22
        row++;
23
        lcd_setcursor(coloumn, row);
24
      }
25
      lcd_data(c);
26

27
      coloumn++;
28
    }
29
  }
30
}


Du ersetzt jetzt aber nicht deine void lcd_stringCenter() mit dieser
Funktion. Du nimmst dies als eine neue Funktion mit rein.

Da wo du z.B

          lcd_stringCenter("ID unknown.", 1);

schreibst musst du jetzt

          lcd_stringCenter_P((PSTR)"ID unknown.", 1);

draus machen.

Strings aus dem RAM kannst du damit nicht ausgeben! Also

          lcd_stringCenter(name, 2);

bleibt so wie es war.

Viel Spass damit;)

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