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
inti=0;
8
while(1){
9
unsignedintsc=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
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
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