mikrocontroller.net

Forum: Compiler & IDEs [AVR] UART Interrupt und FIFO. Ich finde den Fehler nicht


Autor: Malte __ (malte) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
in meinem Programm empfange ich Daten von der Seriellen Schnittstelle 
per Interrupt und speichere sie in einem FIFO zwischen, bis sie vom 
Hauptprogramm ausgelesen werden. Das funktioniert auch meistens. Aber 
alle 1:100 bis 1:1000 Zeichen geht plötzlich mal irgendwie eins 
verloren. Jetzt habe ich bereits den ganzen Vormittag den Fehler gesucht 
und werde aber einfach nicht fündig.

Die Abfrage im Hauptprogramm sieht wie folgt aus:
void analyse_income_cmd(void) { //Dekodiert die per RS232 erhaltenen Befehle
  u08 uart_emp_local[4];
  u08 i;
  u08 in_number = 0;
  //Look if there are at least 4 bytes in the RX FIFO
  cli();
  if ((UART_RX_BUF_SIZE-uart_rx_free()) < 4) {
    sei();
    return;
  }
  for (i = 0; i < 4; i++) {
    if ((UART_RX_BUF_SIZE-uart_rx_free()) == 0) { //may not happen
      sei();
      print_p(DEV_UART, fifoe2); //but happens in 1:1000 cases
      return;
    }
    uart_emp_local[i] = uart_rx_get();
    processed_rx_bytes++; //for debugging
    if ((uart_emp_local[i] == 13) && (i < 3)) {
      sei();
      cmd_error(uart_emp_local, i+1);
      return;
    }
    if (uart_emp_local[i] == 255) { //may not happen
      sei();
      print_p(DEV_UART, fifoe1);
      return;
    }
  }
  sei();
Die Konstanten sind:
#define UART_RX_BUF_SIZE 32
#define UART_TX_BUF_SIZE 64

Mit den ganzen cli() und sei() in dem Abfragecode funktioniert es 
fehlerfrei. Nehme ich die aber raus, ist der FIFO manchmal unerwartet 
leer.
Ich hatte den FIFO so gebaut, dass er eigentlich ohne Interruptsperren 
funktionieren müsste. Ein Schreib und ein Lesezeiger laufen auf einem 
Array immer "im Kreis". Eine leere Speicherzelle wird dadurch markiert, 
dass 0xff drin steht, so dass die beiden Zeigen nicht miteinander 
verglichen werden müssen um Unter und Überläufe auszuschließen. Der Code 
für die RS232 Verbindung ist im Anhang.

Hat jemand eine Idee was falsch läuft?

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Malte __ wrote:

> Hat jemand eine Idee was falsch läuft?

Ja. Schau dir folgendes an:
u08 uart_rx_free(void) {
  u08 f = 0;
  u08 p = uart_rx_wp;
// hier kommt ein Receive-Interrupt
  while ((uart_rx_buf[p] == 0xff) && (f < UART_RX_BUF_SIZE)) {
    f++;
    p++;
    p %= UART_RX_BUF_SIZE;
  }
  return f;
}
-> uart_rx_buf[p] ist nicht 0xff
-> Funktion liefert 0 zurück, obwohl der Puffer vielleicht alles andere 
als voll ist

Dieser Test:
  if ((UART_RX_BUF_SIZE-uart_rx_free()) < 4) {
ist daher nicht zuverlässig.

Es kann also passieren, dass du in die Schleife läufst, obwohl weniger 
als 4 Zeichen im FIFO sind.

Autor: Malte __ (malte) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, den Fall hatte ich übersehen. Ich habe jetzt die Funktion in eine 
verwandelt, welche stattdessen den Lesepointer verwendet.
u08 uart_rx_available(void)
Damit geht es jetzt fehlerfrei.

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.