Forum: Mikrocontroller und Digitale Elektronik Eigenes Transportprotokoll entwickeln


von user (Gast)


Lesenswert?

Guten Morgen,

für ein Firmware-Update müssen mehrere KByte Daten auf einen 
Mikrocontroller transportiert werden. Als Kommunikationsschnittstelle 
wird UDP eingesetzt. Meine jetzige Implementierung funktioniert so, dass 
die Übertragung durch ein erstes Segment an Daten gestartet wird. Sobald 
der Mikrocontroller ein Acknowledge Frame an den PC sendet wird 
daraufhin gleich das nächste Segment versendet. Der Upload Vorgang läuft 
nicht immer zuverlässig. Wie könnte man den Update-Vorgang stabiler 
realisieren?

von Paul (Gast)


Lesenswert?

user schrieb:
> Wie könnte man den Update-Vorgang stabiler realisieren?

Indem man herausfindet, weswegen es nicht stabil (Hardware und/oder 
Software) läuft. UDP läuft eigentlich sehr zuverlässig, somit ist es 
fraglich, ob ein eigenes Protokoll besser läuft.

von blubb (Gast)


Lesenswert?


von user (Gast)


Lesenswert?

Ja da bin ich auch überfragt ob es an der Hardware oder Software liegt.

von Paul (Gast)


Lesenswert?

user schrieb:
> Ja da bin ich auch überfragt ob es an der Hardware oder Software liegt.

Damit gibt es jetzt für Dich 3 Möglichkeiten:

1) Dich in die Hard- und Software soweit einzuarbeiten, dass Du mit 
geeigneten Werkzeugen (Oszilloskop, In-Circuit Emulator, etc.) den/die 
Fehler findest.

2) Eine gute Glaskugel besorgen.

3) Das Projekt ohne Lösung beenden.

von Mario M. (thelonging)


Lesenswert?

Was passiert denn, wenn mal ein Daten-/ACK-Paket nicht durchkommt? Nutzt 
Du "retransmit timer"? (siehe TFTP)

von user (Gast)


Lesenswert?

Manchmal kommt auf der PC Seite das Ack Telegramm nicht an. Ein 
"retransmit timer" habe ich nicht.

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

reines UDP kann per Definition keine zuverlässige Kommunikation 
garantieren, dafür ist es nicht gemacht. Selbst wenn Du herausfindest, 
warum es in deiner Combo Hard/Software nicht zuverlässig tut und das 
fixt, wird die Kommunikation in anderen Netzwerken wieder haken.

Für zuverlässige Kommunikation ist TCP gemacht. Wenn Du zuverlässig 
kommunizieren willst, aber auf UDP nicht verzichten willst oder kannst, 
musst Du die Mechanismen von TCP zur verlässlichen Kommunikation 
emulieren (also Paketsequenzierungen und retransmissions). Oder gleich 
TCP benutzen.

von Andreas M. (amesser)


Lesenswert?

Bei UDP kann es immer vorkommen das Telegramme nicht beim Empfänger 
ankommen. Sei es durch Überlastung von zwischengeschalteten 
Netzwerkswitchen, dem Empfänger/Sender (Betriebs)-system oder EMV 
Störungen die die Übertragung stören. Das ist per Definition so. Braucht 
man sichere Datenübertragung per UDP muss mann sich ein 
Handshakeprotokoll ausdenken, bei dem jedes einzelne Telegram vom 
Empfänger bestätigt werden muss. Der Empfänger muss dann natürlich auch 
damit klar kommen Daten mehrfach zu empfangen, nämlich dann wenn seine 
Bestätigung nicht beim Sender der Daten ankommt und dieser deswegen die 
Übertragung wiederholt. Beispiele für solche Protokolle wäre das o.g 
TFTP oder auch das Connectionless DCERPC. Alternativ könnte man den 
gesamten Datenblob auch per Prüfsumme absichern und wenn diese falsch 
ist die Übertragung einfach nochmal komplett wiederholen. Wäre in diesem 
Fall eventuell einfacher.

von Pandur S. (jetztnicht)


Lesenswert?

UDP ist ein Hinausschreien in den Wald. Bedeutet irgendwas an Sicherheit 
muss selbst gemacht werden. Das Protokoll muss zustandsfrei sein. Also 
nicht ein Block kommt nach dem Anderen, mit autoincrement, sondern die 
Bloecke werden adressiert uebertragen. Die Quitierung, nach einem Block, 
inkl. CRC, enthaelt die Blocknummer. Dann ist auch klar welcher Block 
nochmals gesendet werden muss. Das Protokoll sieht also irgendwie so aus 
:

PC : SendFirmware, Ver# 1234, len=1234, #bloecke=25, CRC

uC : ok, SendFirmware, Ver# 1234, CRC

PC : SendBlock=1, len=40, CRC

uC : ok, SendBlock=1, CRC

PC : SendBlock=2, len=40, CRC

uC : ok, SendBlock=2, CRC

von user (Gast)


Lesenswert?

Ok vielen Dank für eure Beiträge.

Gibt es das TFTP Protokoll quasi als open source Software ?

von Alex G. (dragongamer)


Lesenswert?

Wie andere schon gesagt haben, ist UDP für sowas nicht gedacht. Vorallem 
da du auch noch das System mit dem ack nutzst und Pakete hintereinander 
abschickst, bringt dir das nicht mal einen Geschwindigkeitsvorteil 
gegenüber anderen Protokollen (bei z.B. Multiplayer games wird aufgrund 
der Gewchwindigkeit oft zum Teil auf UDP gesetzt).

Wenn du nach TFTP Lizenz googlest, findest du ein paar Open Source 
Implementationen, daher würde ich davon mal ausgehen.

Alternativ mal TCP anschauen.

von Mario M. (thelonging)


Lesenswert?

Ich würde einfach das Programm dahingehend ändern, dass Du auf der 
PC-Seite nicht stumpf auf ein ACK vom µC wartest, sondern auch erfasst, 
wie lange er auf das ACK wartet. Dann nach z.B. 100 ms abbrechen und den 
aktuellen Block wiederholen. Nach ein paar erfolglosen Versuchen noch 
das Senden mit Fehlermelsung beenden. Dazu ist es wichtig, die aktuelle 
Blocknummer mit zu übertragen. Auf der µC-Seite noch den zuletzt 
geschriebenen Block merken und bei Wiederholung einfach ignorieren. 
Wegen ein paar kb muss man keinen TCP-Stack oder ein komplettes TFTP 
implementieren.

von user (Gast)


Lesenswert?

Ich habe nun meine Applikation auf einem Microcontroller um eine TCP 
Verbindung erweitert. Nun kann ich per UDP und auch per TCP auf den 
Mikrocontroller zugreifen. Wie würde dies nun genauer aussehen, wenn nun 
größere Datenmenegen via TCP an den Mikrocontroller versendet werden?

von user (Gast)


Lesenswert?

Kann über TCP sichergestellt werden wenn zum Beispiel 500 Frames a 500 
Bytes übertragen werden das diese Daten auch alle ankommen?

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

user schrieb:
> Kann über TCP sichergestellt werden wenn zum Beispiel 500 Frames a 500
> Bytes übertragen werden das diese Daten auch alle ankommen?

Was TCP sicherstellt ist Folgendes:

Voraussetzung: Eine Verbindung ist etabliert (also asymmetrisches Open - 
listen/accept() auf Serverseite und connect() auf Clientseite - ist 
erfolgreich abgeschlossen).

Du schiebst von der einen Seite x (z.B. 500) bytes mit send() Aufrufen 
in die Verbindung. TCP garantiert, dass Du auf der Anderen Seite mit 
recv() Aufrufen genau diese x bytes in genau der Reihenfolge 
zurückliest, solange die Verbindung nicht in der Zwischenzeit 
geschlossen wird. Exoten wie Out-Of-Band Data seien hier mal 
vernachlässigt. TCP stellt sicher, dass keine Daten verloren gehen oder 
im Datenstrom ihre Positionen wechseln.

Im Nutzdatenstrom von TCP hat zunächst der Begriff des "frames" keine 
Bedeutung. In TCP gibt es einen "Stream," dessen innere Struktur TCP 
nicht interessiert.

TCP entbindet Dich nicht davon, ein Protokoll auf höherer Ebene zu 
spezifizieren und zu implementieren. TCP ist inherent Voll Duplex, d.h. 
beide Seiten können unabhängig voneinander und asynchron jederzeit Daten 
senden. OB die das tun, hängt davon ab, welches Applikationsprotokoll 
über TCP realisiert ist. In vielen Fällen ist das darüberliegende 
Protokoll Halbduplex, d.h. die beiden Partner erwarten eine gewisse 
Ordnung der Daten und wechseln sich in einem PingPong Spiel mit 
Datensenden und -bestätigen ab. Das muss aber nicht sein.

TCP garantiert keine Maximallatenz zwischen Senden und Empfangen 
derselben Daten.

Programmtechnisch ist das Arbeiten mit TCP relativ einfach. Du brauchst 
im Kern nur send() (~write) und recv() (~read) mit einem socket 
(~Verbindungskennung, die nach Verbindungsaufbau geliefert wird) als 
Parameter. Dafür gibt es unendlich viele Beispiele im Netz.

Es gibt aber zur Realisierung von stabilen Kommunikationen ein paar 
Fallstricke zu beachten. Z.B. machen nach wie vor erstaunlich viele 
Leute den Fehler, die Returnwerte von send() und recv() zu ignorieren 
und damit ihre Kommunikation zum Stolpern zu bringen. Ausserdem sollte 
jedes High Level Protokoll mit Timeouts abgesichert sein, um z.B. zu 
verhindern, dass ein Bug im Protokoll des peers die einene Seite der 
Kommunikation einfriert. Auch sollte das Protokoll über TCP einigen 
Anforderungen genügen (z.B. bei variabel langen Paketen die Paketlänge 
im header enthalten). Im Kapitel 7 meines Buches widme ich mich den 
Details relativ ausführlich.

: Bearbeitet durch User
von Edi M. (Gast)


Lesenswert?

TCP ist nicht so einfach, bei vollständig implementiertem IP Layer ist 
es aber schon recht sicher. UDP kann ja da so ziemlich nichts. Ich würde 
trotzdem UDP nehmen und Redunanz einbauen, damit möglichst wenig schief 
geht. Manche Router machen z.B. bei USP komische Sachen!

Wichtig ist in jedem Fall genaue Prüfungen der empfangenen SW bevor 
irgendwas geflascht wird. Auch golden image handling wird benltigt.

Und wie gesagt, einiges an Redunanz auf dem Zuführkanal, weil sonst zu 
oft was schief geht. Wir haben gerade so ein nettes Problem. Es ist kaum 
was rein oder rauszubekommen von und ins Gerät.

von Karl K. (leluno)


Lesenswert?

> Welche Hardware, welche Software?

Beim ENC28j60 ist im Netz viel über Hardware-Probleme gerätselt worden, 
die mit zusätzlichen Kondenstoren gelöst werden sollten. Ich hatte diese 
HW-Probleme auch. Mit Verwendung geänderter Software waren sie weg.

von Werner M. (Gast)


Lesenswert?

Paul schrieb:
> UDP läuft eigentlich sehr zuverlässig, ...

UDP garantiert für überhaupt nichts. Der Empfänger eines Blockes kann 
nur entscheiden, ob es den Block richtig empfangen hat, aber es ist bei 
UDP völlig unklar, ob alle Blöcke beim Empfänger ankommen. Wenn es auf 
sichere Übertragung ankommt, muss eine Protokollschicht oberhalb von UDP 
dafür sorgen.
Da kann man mit relativ wenig Aufwand sich selber etwas ausdenken, ohne 
gleich ein komplexes Protokoll komplett neu zu erfinden - aber UDP 
alleine reicht für die Aufgabe nicht.

von Bernd K. (prof7bit)


Lesenswert?

user schrieb:
> Ok vielen Dank für eure Beiträge.
>
> Gibt es das TFTP Protokoll quasi als open source Software ?

TFTP ist in RFC-1350 definiert (mit ein paar optionalen Erweiterungen 
RFC-2347, 2348, 2349), es gibt etliche freie Implementierungen für 
Server und Client.

TFTP ist so simpel gestrickt daß man in 2 Stunden mit nichts als der 
nackten socket API selber einen vollständigen Server zusammengeklöppelt 
hat, das hab ich am Donnerstag Nachmittag für mein Update-Tool gemacht, 
die paar Dutzend Zeilen Code schnell selber hinzuschreiben ging unter 
dem Strich schneller als lang herumzugoogeln um einen der vielen 
existierenden Server auszusuchen und dann so mit meinem eigenen Programm 
zu verheiraten daß es aussieht als wäre alles aus einem Guss.

Im Prinzip wird einfach ein Block an Daten als ein UDP Paket geschickt, 
im 4 Byte langen Header stehen 2 Byte Sequenznummer und 2 Byte 
Datenlänge, jedes Paket muss vom Empfänger mit einem ACK-Paket quittiert 
werden, der Sender wartet nach jedem Block auf das ACK bevor er den 
nächsten sendet. Es gibt einen Timeout, dann wird das letzte Paket mit 
der letzten Sequenznummer einfach nochmal gesendet, so oft bis endlich 
ein ACK kommt. Das Ende wird markiert indem ein Block gesendet wird der 
weniger Daten als die maximale Blocklänge enthält. Das ist schon alles.

von Wolfgang (Gast)


Lesenswert?

Bernd K. schrieb:
> ... der Sender wartet nach jedem Block auf das ACK bevor er den
> nächsten sendet.

Bei einer längeren Datenübertragungskette macht das die Sache unnötig 
langsam. Der Sender könnte den nächsten Block durchaus schon vor 
Eintreffen des ACK senden und muss nur buchführen, welche Blöcke schon 
bestätigt sind. Dann kann immer noch ein Timeout greifen, ohne bei jedem 
Block die Warterei einzubauen.

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
Noch kein Account? Hier anmelden.