Für das Projekt "Network Controller/PC" werden hier die ganz konkreten Spezifikationen angelegt.
Inhaltsverzeichnis
Layer-0
Für die unterste Schicht, Layer-0, gibt es drei Versionen:
IP (TCP/IP)
Die Länge ist "host-order" d.h. low-Byte zuerst, immer exklusive Länge, d.h. für 4 Bytes Layer-1 Daten werden insgesamt 6 Byte übertragen.
UART
I2C
- Fwd die Empfänger-I2C-Adresse. In der vorliegenden Version werden nur 7-Bit Adressen zugelassen. Für Broadcasts (HBT, ASK) wird GCA (= NuLL) verwendet.
- Bck ist immer die Absender-I2C-Adresse. Aus formalen Gründen wird immer das Bit 0 gesetzt.
Programmiertechnisch ist dazu wohl nicht viel zu sagen.
Layer-1 Version 0.1
Hier sind es zwei Ausprägungen: Für die PC-Seite und für die Microcontroller
PC
In dieser Version gibt es keine Pfadangaben, sondern immer 16-Bit IDs. Da sich eine IP-Verbindung ja als point-to-point darstellt, ist der Bedarf an Routing-Pfaden nicht sosehr gegeben.
ID (Identifier)
Die ID sollte eine systemweit eindeutige Adresse für ein Gerät sein. Also zum Beispiel ein ganz bestimmter AD-Converter auf einem Kontroller im Netzwerk. Oder die Steuerung für einen bestimmten Schrittmotor o.Ä.
µC
T-1, T-2, S-1, S-2 sind in dieser Version immer 8-Bit Pfadangaben. In dieser Version sind nur zwei Pfadangaben je Richtung erlaubt, die sind aber auch immer da, selbst wenn der Inhalt NULL ist (void).
Pfade
Die Referenzen 0-63 brauchen nur innerhalb eines Rechners eindeutig zu sein. Die ersten 8 Werte sind allerdings vordefiniert und für alle Rechner gleich
HBT Heartbeat
0 (&H01) (Broadcast) Jeder Rechner, der RnCom-Messages verarbeiten kann, sendet periodisch (1-4 sek) einen Message an dieses Ziel. Wenn das Heartbeat Signal länger als 5 sekunden ausfällt, wird das Geräte und alles, was darunterhängt, aus den Routing Tabellen entfernt und gilt als nicht erreichbar. Wenn in der Zeit allerdings eine andere Message gesendet wurde, kann für diese Periode der Hearbeat auch unterbleiben.
NXT Next
1 (&H05) Frage nach Geräteliste Daten: 8-Bit Geräteindex Der Empfänger sendet von dem nächsten Gerät, das dem Geräteindex folgt, eine "IAM" Message.
IAM "I am"
2 (&H09) Information über ein Gerät Daten: 8-Bit Device-Index, 16-Bit ID Eine Meldung über ein Gerät, mit Index und ID. NACH dem letzen Gerät wird der Index "FF" gesendet und kEINE ID
ASK Suchen ID
3 (&H0D) (Broadcast) Daten: 8-Bit NULL, 16-Bit ID Eine Frage an alle Rechner, ob ihnen die ID bekannt ist. wenn ja, wird eine "IAM" Message von dort zurückgesendet
UART
4 (&H11) Die UART (In Vers-0.1 wird von maximal 1 UART je Rechner ausgegangen) Das aktuelle Ziel ist die UART, d.h. die Message wird dort weitergeleitet, ohne den restlichen Inhalt zu interpretieren. Es ist somit das Äquivalent zu einer I2C-Adresse.
VAL Meßwert
5 (&H15) (Broadcast) Daten: Source-Abhängig Geräte können mit dieser Message "an alle" einen aktuellen Meßwert bekanntgeben. Es ist Sache der Empfänger, diese Message zu interpretieren.
reserviert
- 6 (&H19)
- 7 (&H1D)
Level-0
Erzielt werden soll eine sichere, transparente Daten-Übertragung zwischen µCs und PCs sowie uCs bzw PCs untereinander. Die geplanten Übertragungsmedien sind im Moment:
- UART (RS232), vor allem zur Anbindung von uCs an PCs
- LAN (IP), vor allem zur Anbindung von PCs untereinander (z.B. Steuerrechner - GUI)
Dabei betrachtet dieses Projekt die IP-Funktionalitäten als "black-box" und alles unterhalb der üblichen Schnittstelle (sockets) wird elegant als Level-0 betrachtet.
- i2c (spätere Ausbaustufe), vor allem zur Anbindung von uCs untereinander
Ziel der Schicht 0 muß es sein für die oberen Schichten Datenpakete mit einer bestimmten Länge zu übertragen. Dabei sollen die oberen Schichten nichts über das Medium (UART, LAN, i2c) wissen müssen. Da die Datenbytes alle Werte von 0-255 einnehmen können, muß die jeweilige Schicht geeignete Kontrollmechanismen definieren.
Level-0 UART (point-to-point)
Die Implementierung der Schicht 0 hängt stark von den verwendeten Medien ab. Die Arbeitsgruppe ist übereins gekommen, Daten über den UART wie folgt zu übertragen: Die Nachrichten wird mit einem STX-Zeichen begonnen, dann die Daten, eine Kontrollsumme und als Abschluß ein ETX-Zeichen.
START....daten....CHECK.ENDE
Jetzt kann natürlich zwischen den Daten jederzeit ein Zeichen drin sein, das denselben Wert hat wie eine Start- oder Endekennung. Daher wird "Bytestuffing" verwendet
Byte-Stuffing
Es gibt drei besondere Zeichen
- STX als Start-Kennung
- ETX als Ende-Kennung UND
- PFX als Daten-Kennung (durch dieses Zeichen wird das nachfolgende zu einem normalen Datenbyte)
Am besten ein Beispiel:
Oben ist eine Nachricht, die ein Zeichen enthält, das denselben Wert hat wie die Endekennung (ETX) Bis zu dem Zeichen werden die Daten normal übertragen. Dann wird aber das PFX eingefügt und danach der Rest.
Der Empfänger findet das Startzeichen STX und beginnt, die Zeichen nach der Reihe zu übernehmen. Dann entdeckt er PFX. Das speichert er zwar nicht, aber dadurch enterpretiert er das Folgezeichen, das ja eigentlich eine Endekennung wäre, nicht als solches und gibt es zu den normalen Daten dazu. So gehts weiter bis zum Ende ETX, das ja "blank" dasteht, also sozusagen "echt" ist.
Es ist immerhin möglich, daß ein Teilnehmer beim Empfangen irgendwie nicht gut drauf ist, und er erst genau zwischen PFX und Folgezeichen die Bytes wieder richtig mitkriegt. Er würde also denken, daß dieses Folgezeichen ein Kontrollzeichen ist und letzlich Müll empfangen. Für diesen Fall wurde vorgeschlagen, dieses Folgezeichen gleich überhaupt durch eine Addition unkenntlich zu machen. Derjenige, der das PFX mitgekriegt hat, weiß das ja und kann wieder subtrahieren, unser Schläfer weiß das aber eben nicht, kann aber auch kein (falsches) Steuerzeichen erkennen. Beim Wiedereinstieg an einer beliebigen anderen Stelle kann sowieso nicht Schlimmes passieren, denn bis zum nächsten un-prefixten STX wird ja alles ignoriert.
Kontrollsumme BCC
- Beginnend mit NULL, werden alle Datenzeichen (ohne PFX, STX, ETX und andere Kontrollzeichen) mit Exklusiv-Oder "übereinandergelegt". Das Ergebnis hängt der Sender an die Daten an. Es wird zusammen mit den Daten geprefixed.
- Der Empfänger tut das Gleiche, dann aber vergleicht er sein Ergebnis mit dem Prüf-Byte, das der Sender weggeschickt hat.
Stimmt das Prüfbyte nicht, wird die Nachricht verworfen. Das ist zwar auch nicht todsicher, aber immerhin beruhigend. Wenn sich das nicht bewährt, kann immer noch ein CRC-Verfahren festgelegt werden.
Praxis
- Maximale Frame-Size
#define FRAME_C_MAX 127
Das ist die maximale Netto-Länge zwischen STX und ETX, exklusive. Auch das scheint für µC etwas groß, aber es wird davon ausgegangen, daß die real benötigten Messages weit kürzer sein werden, d.h. das regelt sich vermutlich von selbst durch die Vereinbarungen und Restriktionen in den oberen Layern
- Kontrollzeichen
#define CTL_M_MASK 0xF8 #define CTL_M_ADON 0x08 #define CTL_C_BASE 0xA8 #define CTL_C_STX CTL_C_BASE + 1 #define CTL_C_ETX CTL_C_BASE + 2 #define CTL_C_PFX CTL_C_BASE + 3
- Code-Beispiel/Muster für Paket-senden
( transmit() stellt die Funktion für den tatsächlichen physischen Output dar).
static unsigned char bTxBcc; // Checksum für BCC // -------------------------------------------------------------- void TxStartFrame ( void ) { bTxBcc = 0 transmit ( CTL_C_STX ) } // -------------------------------------------------------------- void TxCloseFrame ( void ) { TxSendStuffByte ( bTxBcc ) // auch das BCC mit ev. prefixed werden transmit ( CTL_C_ETX ) } // -------------------------------------------------------------- void TxSendFrameByte ( unsigned char bTxChar) { bTxBcc ^= bTxChar TxSendStuffByte ( bTxChar ) } // -------------------------------------------------------------- void TxSendStuffByte ( unsigned char bTxChar) { if (bTxChar & CTL_M_MASK) == CTL_C_BASE) { transmit ( CTL_C_PFX ) transmit ( bTxChar + CTL_M_ADON ) } else { transmit ( bTxChar ) } }
- Die entsprechende Empfangsroutine ist etwas komplexer und wird wesentlich mehr vom Geschick und den Gewohnheiten des Programmieres bestimmt.