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/Software-UART_mit_avr-gcc
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
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?
1 | suart_init(SUART_BAUD_SELECT(19200, F_CPU)); |
2 | |
3 | sei(); |
4 | |
5 | suart_puts("Ready...\n"); |
6 | |
7 | int i = 0; |
8 | while(1) { |
9 | unsigned int sc = suart_getc_nowait(); |
10 | if(sc != QUEUE_EMPTY) { |
11 | //uart_putc(sc);
|
12 | ++i; |
13 | suart_putc(sc); |
14 | if(sc == 'b') { |
15 | suart_putc(i); |
16 | i=0; |
17 | }
|
18 | }
|
19 | }
|
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
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')
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
Sorry, nicht ganz exact 01234567890123456789023456789023456789013456789013456789b9 01234567890123456789023456789023456789013456789013456789b9 01234567890123456789023456789023456789013456789013456789b9 01234567890123456789023456789023456789023456789013456789b9 01234567890123456789023456789023456789013456789013456789b9 01234567890123456789023456789023456789023456789013456789b9 01234567890123456789023456789023456789013456789013456789b9 01234567890123456789123456789023456789023456789013456789b9 01234567890123456789023456789023456789013456789013456789b9 01234567890123456789123456789023456789023456789023456789b9 01234567890123456789023456789023456789013456789013456789b9 MfG Stinke
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
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
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
Ich hab mal in den RN-Code geschaut, da sind 2 Probleme: 1.
1 | // OutputCompare für gewünschte Timer1 Frequenz
|
2 | 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
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.
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
Peter Dannegger wrote: > Ich hab mal in den RN-Code geschaut, da sind 2 Probleme: > > 1. >
1 | > // OutputCompare für gewünschte Timer1 Frequenz |
2 | > OCR1A = (uint16_t) ((uint32_t) F_CPU/BAUDRATE); |
3 | >
|
> > 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
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).
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.