www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik RN Software UART und das Geheimnis der verlorenen Zeichen


Autor: stinke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe hier auf einem Atmega64 @ 16Mhz den Roboternetz
Software UART [1] zwar zum laufen bekommen, aber
wir haben das Problem, dass etwa 5-10% der Zeichen verloren
gehen und zwar unabhängig von der Baurdrate
(4800, 9600, 19200, 32k, 56k).
Das Kommunikationsprotokoll wurde zwar Fehlertollerant
gemacht (musste eh gemacht werden) was wieder so eigene
Probleme mit bringt => Herumdoktorn an Symthomen.

Das Problem tritt nicht auf wenn Zeichen rechnerseitig mit 1ms Delay
gesendet werden.

Ich habe alle tests mit einem AVR seitigen echo gemacht,
um ausschließen um andere Störquellen auszuschließen.

Hat jemand vieleicht eine Idee?

Zur Schaltung: Der Quarz ist auf der Rückseite der Platine
aufgebracht (Vias). Könnte dies, bei einer sonst Störungsfreien
Platine die Fehlerquelle sein? Ich kann es leider nur sehr sehr
schwer umbauen/testen.


MfG stinke

[1] http://www.roboternetz.de/wissen/index.php/Softwar...

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stinke wrote:
> Hallo!
>
> Ich habe hier auf einem Atmega64 @ 16Mhz den Roboternetz
> Software UART [1] zwar zum laufen bekommen, aber
> wir haben das Problem, dass etwa 5-10% der Zeichen verloren
> gehen und zwar unabhängig von der Baurdrate
> (4800, 9600, 19200, 32k, 56k).

Die angegebene Info ist - vorsichtig ausgedrückt - etwas spärlich.

-- Werden die Zeichen in einer FIFO gepuffert?
-- Ist sicgergestellt, daß die FIFO nicht überläuft (ohne FIFO) hat 
diese effektiv eine Länge von 1 Zeichen)
-- Gibe es andere IRQs, welche die IRQ-Latenz in die Höhe schrauben?

Johann

Autor: stinke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Johann

Nein es gibt keine weiteren Interrupts.
Die FIFO (von RN) haben wir mal ausprobiert, aber diese lief
definitiv nicht über. Der Fehler hat sich nur dahingehend verändert,
dass mehr Zeichen verschluckt werden.

Ich denke also der Interrupt wird einfach zu langsam abgearbeitet,
aber kann das sein?
  suart_init(SUART_BAUD_SELECT(19200, F_CPU));

  sei();

  suart_puts("Ready...\n");

  int i = 0;
  while(1) {
    unsigned int sc = suart_getc_nowait();
    if(sc != QUEUE_EMPTY) {
      //uart_putc(sc);
      ++i;
      suart_putc(sc);
      if(sc == 'b') {
        suart_putc(i);
        i=0;
      }
    }
  }

Das ist im Prinzip das Programm. Bis eben noch auf den
gelinkten code in einer Datei. Magic byte für "Kein Zeichen"
und die Funktionsnamen wurden geändert. Es funktioniert,
nur die Details der Implementation
verstehe ich nicht ganz, zumindest nicht so, dass ich den
"Fehler" (dort oder bei mir) finden könnte.

Der Atmega64 ist mit den fuses
lfuse = 0xBE
hfuse = 0xC9
efuse = 0xFF

konfiguriert. Also externer Resonator, CKOPT, brown-out, kein JTAG
..?

MfG stinke

Autor: stinke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso,

suart_getc_nowait() oder suart_getc_wait() macht hier
keinen Unterschied.

Hier Ein- und Ausgaben:

Gesendet:
012345678901234567890123456789012345678901234567890123456789b

Empfangen:
01234567890123456789023456789023456789013456789013456789b9

Letztes Zeichen ist der Zähler i = 0x39 = 57 statt 61 (zzgl. 'b')

Autor: stinke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Achso,
der Fehler tritt immer bei den selben Zeichen, an der gleichen
Stelle auf. Ich kann das 100 mal wiederholen und es kommt
immer das gleiche Ergebnis heraus o_0

Autor: stinke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, nicht ganz exact

01234567890123456789023456789023456789013456789013456789b9
01234567890123456789023456789023456789013456789013456789b9
01234567890123456789023456789023456789013456789013456789b9
01234567890123456789023456789023456789023456789013456789b9
01234567890123456789023456789023456789013456789013456789b9
01234567890123456789023456789023456789023456789013456789b9
01234567890123456789023456789023456789013456789013456789b9
01234567890123456789123456789023456789023456789013456789b9
01234567890123456789023456789023456789013456789013456789b9
01234567890123456789123456789023456789023456789023456789b9
01234567890123456789023456789023456789013456789013456789b9

MfG Stinke

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich würd mal testen, ob die Zeichen überhaupt ankommen, oder ob sie zu 
schnell gesendet werden. In dem Beispiel weiß man ja, was auf dem AVR zu 
erwarten ist.

Möglicherweise reicht die Bandbreite nicht für Full Duplex aus, schon 
mal Half Duplex versucht?

Ausserdem wird nicht atomar auf sc zugegriffen. Das ist ein Fehler - 
wenn auch in diesem Zusammenhang nicht ausschlaggebend, aber dennoch...

Johann

Autor: stinke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dein schuss ins blaue war richtig.

Senden und empfangen wirft wohl das timing übern' Haufen.
Ohne Echo hab jetzt fast einen 100k block gesendet und die
Zeichen wurden alle samt richtig gezählt.

In unserer Anwendung tritt jedoch der Fehler natürlich weiterhin
auf weil wir natürlich senden müssen.

Gibt es hier überhaupt eine pratikable Lösung?

MfG stinke

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist natürlich schwer, was zu sagen, ohne den Code zu sehen.

Bei SW-UART sollte man generell ne FIFO nehmen, da man sonst nicht mal 
den 3-Byte Puffer der HW-UART hat. Es können also sehr leicht Zeichen 
verloren gehen.

Ein Beispielcode ist hier:

Beitrag "Software UART mit FIFO"

Ich hab damit bisher keine Probleme gehabt.

Längere Zeichenfolgen sollte man nicht mit Echo zurücksenden. Ist die 
Baudrate des AVR ein bischen langsamer als die des PC, fehlt irgendwann 
die Zeit.
Dieser Effekt kann ohne FIFO schnell auftreten (<100 Byte), mit FIFO 
nach >1000 Byte.


Peter

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab mal in den RN-Code geschaut, da sind 2 Probleme:

1.
    // OutputCompare für gewünschte Timer1 Frequenz 
    OCR1A = (uint16_t) ((uint32_t) F_CPU/BAUDRATE);

Damit sendest Du immer einen Takt zu langsam.

2.
Das Senden ist ohne FIFO, damit hast Du zusätzlich zwischen 2 Bytes eine 
Bitzeit Pause.


Peter

Autor: stinke (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Peter,

Die Roboternetz SW-UART ist oben im link zu finden. Leider
sind die Kommentare nicht so aufschlussreich wie die
aus deiner alten SW-UART.
Ich habe schon festgestlelt  das TX anders gelöst wurde;
gerade lese ich mich in Timer ein. Neuland für mich.

Ich denke es würde helfen wenn TX _vect ist. Ich probiere das gleich mal
aus.
Habe auch gerade festgestellt das du das auch machst.
Danke für den Hinweis auf die neue Version/den neuen Thread.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die uart_putc ist blockiered: Sie wartet so lange, bis das Byte gesendet 
werden kann. Hier mal ne nicht-blockierende Lösung versuchen. Durch das 
Blockeren verliert men evtl. empfangene Zeichen.

Eigentlich sollte das bei niedrigen Baudraten im Full Duplex gangbar 
sein; daher sicherstellen, daß die Blockierung nicht der Bösewicht ist.

Auch mal die Timer-Werte nachrechnen, welche Fehler sich durch Rundung 
wegen den 16 MHz ergeben. diese Frequemz ist nicht so schmackig für den 
UART wie zB 14.7456 MHz oder 18.432 MHz.

Die Hardware ist wie ich verstanden habe schon fertig? Da das Zeug aber 
noch nie (richtig) funktioniert hat, nehme ich mal an, es handelt sich 
dabei um nen Prototypen oder ne Nullserie.

Bei anderer Handware würd ich ne (Hardware-)Flußsteuerung vorsehen, 
damit der recht langsame Software-UART sich net verschluckt.

Ansonstend dünkt mich, daß da ein etwas seltsames Konzept am Werke ist. 
Der µC hat doch UART, sogar mehrere, wenn ich mich recht entsinne...

Johann

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger wrote:
> Ich hab mal in den RN-Code geschaut, da sind 2 Probleme:
>
> 1.
>
>     // OutputCompare für gewünschte Timer1 Frequenz
>     OCR1A = (uint16_t) ((uint32_t) F_CPU/BAUDRATE);
> 
>
> Damit sendest Du immer einen Takt zu langsam.
>

Sollten doch Peanuts sein, ob man einen Tick (bzw. ca 10 Ticks beim 
letzten Bit) zu langsam oder zu schnell ist. Oder? Zudem wird ohenhin 
abgerundet.

Viel drastischer wirkt sich ein Jitter aus, der durch eine andere 
IRQ/ISR ausgelöst wird und sich im Bereich von mindestens 50 Ticks 
bewegen dürfte.

Johann

Autor: stinke (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab ein sende FIFO eingebaut und konnte das Problem so lösen.


Wir werden in der praxis natürlich nicht jeden Character echo'n,
aber wir haben seitens des AVR Befehle im Befehlssatz die auch "mal
zu Wort kommen wollen". Das hat die Probleme verursacht.

Danke für eure Hilfe. Auch an Peter für deine Implementation
(die ich erst später entdeckt habe).

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
stinke wrote:
> Ich hab ein sende FIFO eingebaut und konnte das Problem so lösen.

Ohne im Detail auf die FIFO-Implementierung geschaut zu haben würd ich 
was drauf wetten, daß dort noch mindestens ein Hund in einer 
Race-Condition begraben ist.

Johann

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Johann L. wrote:
> Ohne im Detail auf die FIFO-Implementierung geschaut zu haben würd ich
> was drauf wetten, daß dort noch mindestens ein Hund in einer
> Race-Condition begraben ist.

Da wirst Du wohl recht haben.

Der RN-Code liegt leider nicht als compilierbares Programm vor, daher 
kann man das auch nicht prüfen.
Deshalb fragte ich ja auch nach dem Code (nicht nach Schnipselchen).

Der Fehler wird wohl in den unbekannten FIFO-Macros liegen.
Macros sind ja schön und gut, aber manchmal ist eine angepaßte FIFO doch 
besser und sicherer.

Ich hab auch ne Weile überlegen müssen, damit mein Code interruptfest 
ist.
Die Hauptbedingung dafür war, daß der Index 8-Bittig ist, somit konnte 
auf Interruptsperre verzichtet werden.


@stinke

Dein Code sieht sehr seltsam, aus, da dürften noch einige Fallgruben 
drin sein.
Der Empfang ist ohne FIFO, da könnts schnell mal klemmen.
Und der Sende-FIFO macht keinen Sprung an den Anfang, sondern schmeißt 
alle Bytes nach dem 64-sten weg.


Peter

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.