Die endgültige Hardwarekonfiguration für das KCNET TCPIP-Interface steht fest. Damit kann es in die Dokumentationsphase gehen. Wie aus der Idee das Interface entstanden ist und wie es im KC85-System funktioniert, kann man in diesem Beitrag nachlesen.
Seit August 2008 steht der Standard-WIZnet-Chip für das KCNET-Interface fest. Es ist der W5100, welcher auf den Netzwerk-Modulen WIZ810MJ bzw. WIZ811MJ/WIZ812MJ (siehe Ende des Artikels) verbaut ist.
Da der TCPIP-Core des bis dahin verwendeten Chips W3150A+ identisch zum W5100 ist, kann man nach wie vor auch das Netzwerkmodul NM7010B+ benutzen Wer die Wahl hat, sollte sich aber für die aktuelleren Module mit dem W5100 entscheiden!
WIZ810MJ
Ausschlaggebend für die Wahl des W5100 waren vor allem zwei Aspekte. Erstens natürlich ein erfolgreicher Test mit meiner vorhandenen Experimentierplatine, welcher keinerlei Probleme ergab - weder bei der Hardware noch bei der bis jetzt erstellten Software musste irgendeine Kleinigkeit geändert werden.
Zweitens war es die Aktualität des W5100, durch ein Telefonat mit einem deutschen Distributor habe ich erfahren, dass es den bisher benutzten W3150A+ zwar noch offiziell gibt aber nur aufgrund bestehender Abnehmer. Bei der nächsten Gelegenheit wird er ausgemustert werden, da er durch den identischen TCPIP-Kern des Nachfolgers W5100 auch 1:1 ersetzt werden kann.
Die niedrigeren Herstellungskosten eines Netzwerkmodules mit dem W5100 spielten natürlich auch eine Rolle, da sich der Preis entsprechend reduziert. Das identische Modul mit dem neueren Chip kostet ca. 8 EUR weniger, was doch schon einen erheblichen Unterschied ausmacht.
Die auffällige rote Farbe der neueren Netzwerkmodule hat dagegen keine ausschlaggebende Rolle gespielt :-).
Nachfolgend einige Bilder vom WIZ810MJ:
Ansicht von der Seite, von oben und von unten...
... von vorn und hinten.
Da das WIZ810MJ pinkompatibel zum NM7010B+ ist, musste an der eigentlichen KCNET-Platine auch nichts geändert werden, ich habe das alte durch das neue Modul einfach ersetzt. Um auch funktionskompatibel zu sein, muss Pin 9 von JP2 zwingend auf Masse liegen. Im KCNET-Schaltplan ist das bereits der Fall, auf der KCNET-Platine musste ich diese Verbindung erst noch durch eine zusätzliche Leitung herstellen. Danach konnte der erste Test gefahren werden und es funktionierte alles wie bisher mit dem NM7010B+, die endgültige Hardware des Prototyps kann man auf den beiden folgenden Bildern sehen:
Im Schaltplan des KCNET ist wahlweise das Modul NM7010B+ angegeben. Wenn man es verwendet, muss der entsprechende Jumper umgesteckt werden.
Da die Stiftleisten der Module NM7010B+/WIZ810MJ im 2 mm Raster ausgeführt sind, lassen sich diese beiden Module mit Amateurmitteln schlecht verarbeiten. Speziell für den Einsatz auf 2,54 mm Raster Lochrasterplatine gibt es seit September 2008 das Netzwerkmodul WIZ812MJ, welches unter Beachtung einiger Hinweise eingesetzt werden kann, siehe Ende dieses Artikels.
Idee und Funktionsweise des KCNET
Wie in den ersten Artikeln geschrieben, war das BASCOM Easy-TCPIP Projekt der Auslöser für das KCNET-Projekt aber wie funktioniert das Ganze nun eigentlich am KC85 nach den vielen Änderungen und welche Rolle spielen Firmware. Treiber und Software?
Das ist eigentlich gar nicht so schwer nur etwas unübersichtlich. Die Gründe dafür liegen beim WIZnet-Chip selbst, welcher natürlich nicht für ein 20 Jahre altes Heimcomputersystem entworfen und auf den Markt gebracht wurde. Zielplattform des Chips ist die Welt der Microcontroller. Dort bestehen ähnliche Probleme, wie bei einem 8 Bit Heimcomputer - Rechenleistung steht nur begrenzt zur Verfügung und der Programmspeicher ist bei den 8 Bit Typen ohne Tricks auch nur maximal 64 kB gross. Diese Ressourcen sollen der eigentlichen Controller-Anwendung zur Verfügung stehen, so dass ein TCPIP-Stack nicht mal so nebenbei per Software eingebaut werden kann. Also kommt auch dort ein einfach anschliessbarer und mit wenigen Bytes programmierbarer Hardware TCPIP-Stack gerade recht und man ist schnell in der Lage die Anwendung netzwerkfähig zu machen.
Dazu muss der W5100 an den Controller angeschlossen werden, was auf drei verschiedenen Wegen geht. Im direkten Bus-Modus arbeitet der W5100 wie ganz normaler externer RAM und belegt 32 kB im Adressbereich der MCU. Im indirekten Bus-Modus ist das ähnlich aber dort belegt der Chip nur noch 4 Adressen und die Adressierung der dann nur indirekt erreichbaren Register und Datenpuffer muss per Software im Controller programmiert werden. Schliesslich kann er auch noch im SPI-Modus betrieben werden, dieser Bus ist bei den Mikrocontrollern mittlerweile zum Standard geworden.
Am einfachsten und schnellsten ist von diesen 3 Möglichkeiten der direkte Bus-Mode, welcher auch im KCNET verwendet wird. Nun könnte man den W5100 ja auch direkt an den Z80 anschliessen und den Controller ganz weglassen - klar, theoretisch geht das sicher aber praktisch sind ein paar Probleme zu lösen und es gibt 2 Killerkriterien, welche eine universelle Nachnutzung mit beliebigen Z80 Systemen ausschliessen.
Leider hat der Chip natürlich keinen Z80 kompatiblen Bus, sondern ein Standard MCU-Interface mit den Signalen /RESET, ADDR14-0, DATA7-0, /CS, /INT, /WR und /RD. Also müsste man zusätzliche Hardware bemühen, um mit Hilfe dieser Signale etwas zusammenzubasteln.
Wenn man die einfachste und schnellste Möglichkeit, den direkten Bus-Modus benutzt, benötigt der Chip einen zusammenhängenden Adressbereich von 32 kB im System - das ist viel bzw. sehr viel oder drastisch ausgedrückt die Hälfte des direkt adressierbaren Speichers eines Z80. Jedes System ist aber anders was die Verteilung von RAM, ROM, Bildwiederholspeicher u.s.w. angeht, es gibt mindestens genau so viele Varianten für ein optimales Z80-System, wie Ideen und Meinungen der Entwickler solcher Systeme - was heisst, dass eine Universallösung schlicht unrealistisch bzw. unmöglich ist.
Selbst wenn man dieses Problem durch Segmentierung, also mit viel Aufwand per Hardware lösen könnte, spielt der nicht oder schlecht trennbare Speicherbedarf von 16 kB für die Sende- und Empfangspuffer der Netzwerkdaten des Chips immer noch eine grosse Rolle, denn das sind immer noch 25% des Hauptspeichers beim Z80 - der ist weg und steht für die Anwendung nicht zur Verfügung. Beim KC85 unter CAOS ist es noch prekärer, ohne zusätzliche Massnahmen stehen Anwendungen nur die ersten 32 kB des Speichers zur Verfügung, wenn man davon 16 kB abzieht, bleiben noch 16 kB übrig und das ist dann schon etwas knapp :-)
Blieben noch die anderen Modi für einen direkten Anschluss? SPI schied aus, da es das beim KC85 nicht gibt und der indirekte BUS-Mode macht die Sache wieder komplizierter. Ich wollte ein einfaches Interface, wo ich im Fehlerfall bzw. am Anfang der Entwicklung auch vernünftig entwickeln kann, da muss man sich auch schnell und unkompliziert mal die Inhalte von Chipregistern oder Speicherbereichen anschauen können und das geht nur im direkten Busmode, wo alles schön sichtbar in den 32 kB Speicher der MCU liegt und nur ausgelesen werden muss.
Erleichternd kam hinzu, dass ich durch die Easy-TCP Platine eine fertige Basis zum Experimentieren hatte, nachdem die BASCOM-Beispiele damit funktionierten, stellte sich für mich gar nicht mehr die Frage nach anderer Hardware.
Soweit so gut, der W5100 wird also wie externer RAM an den AVR-Controller angeschlossen und belegt dort 32 kB im Adressbereich des Controllers. Im Datenblatt des W5100 ist das folgendermassen dargestellt:
Jetzt hätte der ATmega aber ein Problem, denn von Adresse 0 bis 500H liegen dessen Register und der interne RAM im Adressbereich der MCU, was sich mit dem W5100 überschneiden würde. Also wurde der W5100 in der Schaltung des Easy-TCP Projektes so verdrahtet, dass er erst ab Adresse 8000H in den Adressbereich der MCU eingeblendet wird, so dass zu allen Angaben im Datenblatt des W5100 ein Offset von 8000H zu addieren ist, wenn man die physische Adresse berechnet, es ergeben sich dann die folgenden Anfangsadressen für die vier Hauptbereiche des W5100:
COMMON REGISTERS | 8000 H |
|
SOCKET REGISTERS |
8400 H |
|
TX MEMORY |
C000 H |
|
RX MEMORY |
E000 H |
Damit ist die Hardware klar, der TCPIP-Stack hat seinen Platz im Adressraum des Controllers gefunden und könnte durch ein Programm, welches im Controller abgearbeitet wird, in Betrieb genommen werden, so wie es der Treiber und die Beispielprogramme von WIZnet auch vorsehen.
Aber das war nicht mein Ziel - ich wollte ja den Stack selbst programmieren und zwar mit einem Programm im Z80-System. Da der Stack wie RAM im Controller behandelt wird, erfolgt eine Programmierung durch Lese- und Schreibbefehle des Controllers. Beim Beschreiben einer RAM-Adresse kann man Aktionen auslösen oder Daten übergeben und beim Lesen entsprechend Zustände abfragen oder Daten vom Stack zurücklesen.
Das kann der Z80 ja auch und der verwendete 8 Bit Controller ATmega 162 ist beim Lesen und Schreiben von der Struktur her softwarekompatibel mit dem Z80. Er verwendet 16 Bit für die Adresse, 8 Bit für ein Datenbyte und arbeitet mit Little Endianess bei der Organisation von Daten im Speicher - also die ideale verlängerte Werkbank für das Z80-System.
Wenn man nun die Organisation der Lese- und Schreibbefehle, sprich die Intelligenz des eigentlichen Programmes, in das Z80-System verlegt und nur ihre physische Ausführung dem Controller überlässt, hätte ich mein Ziel erreicht und könnte mit dem Z80 den Stack logisch vollkommen frei programmieren, ohne irgendwelche Einschränkungen physischer Ressourcen des Z80-Systems hinnehmen zu müssen.
Da die Adress- und Datenstrukturen 1:1 vom Z80 an den Controller weitergegeben werden können, muss man erstens nichts umrechnen, es bleibt also hinreichend schnell und man kann jede vorhandene Programmierumgebung bzw. Sprache des Z80-Systems für die Programmierung benutzen - man benötigt lediglich einen definierten Zugang zum Controller.
An dieser Stelle kommt die PIO ins Spiel. Um universell und absolut kompatibel zu jedem Z80-System zu sein, kam für einen definierten Zugang zum Controller nur ein Standard-Schaltkreis der Z80 Familie in Frage. Die Entscheidung war dann eigentlich keine mehr, da es an dieser Stelle auf die höchstmögliche Geschwindigkeit bei der Weiterleitung von Befehlen des Z80 zum Controller ankommt und da ist nun mal naturgemäss eine parallele Übertragung einer seriellen überlegen, wenn man beide mit dem gleichen Systemtakt betreibt, wie das bei der SIO und PIO im Z80-System normalerweise der Fall ist.
Am ATmega des Easy-TCP waren auch noch genug freie Portleitungen für die Ankopplung vorhanden, immerhin werden 12 Verbindungen benötigt. Für den KC85 gibt es ein fertiges DIGITAL IN/OUT Modul mit einer PIO, welches genau für solche Experimente gedacht ist. Wie die PIO nun an den ATmega angeschlossen werden muss, ist im Schaltplan des KCNET zu sehen.
Nachfolgend das Blockschaltbild aus dem Datenblatt des W5100, dort sieht man die Struktur und den internen Aufbau des Hardware TCPIP-Stacks:
Mit dem KCNET-Interface sieht das dann so aus, dass "Application", "Socket API" und "Driver Program" im Z80 ablaufen und auf der untersten Hardware Ebene, zwischen "Driver Program" und "MCU Bus I/F" die transparente Übergabe und Ausführung der Schreib- und Lesezugriffe durch die Hard- und Software des KCNET abgewickelt wird.
Dazu werden im Z80-System der Low-Level Interface-Treiber für die PIO benötigt und auf der anderen Seite muss im Controller eine Software laufen, welche die Befehle entgegennimmt, ausführt und Ergebnisse bei Notwendigkeit wieder zurückgibt.
Für ein reibungsloses Zusammenspiel der beiden Prozessorsysteme ist natürlich die Definition der erlaubten Kommunikationsbefehle und ihre Syntax festzulegen, welche in Form des KCNET-PROTOKOLL's vorliegt. Das entsprechende Dokument steht im Downloadbereich zur Verfügung.
Das Programm, welches im Controller läuft, wird als Firmware bezeichnet. Diese Software hat nun die Hauptaufgabe, Lese- und Schreibbefehle des Z80-Systems transparent zum/vom W5100 durchzureichen - logisch ist damit über diesen Trick ein virtuelles 8 Bit Prozessorsystem vorhanden, was mit allen Programmiersprachen, welche auf der Z80 Seite zur Verfügung stehen, programmiert werden kann.
Damit habe ich nun schliesslich auch mein Primärziel erreicht. Dem KC85-System steht ein vollkommen frei programmierbarer TCPIP-Stack zur Verfügung, welcher universell im Rahmen der Möglichkeiten des W5100 eingesetzt und benutzt werden kann und mein System überhaupt nicht belastet. Da nur eine PIO benötigt wird, beschränken sich die notwendigen Systemressourcen auf 4 freie zusammenhängende I/O-Adressen des Z80-Systems. Die sollten wohl immer und in jedem noch so exotischen Z80-System frei sein, so dass einer nahezu unbegrenzten Nachnutzung von der Hardwareanbindung nichts entgegenstehen sollte.
KCNET im KC85-System
Mit der Version 1.2 des Interface wurden nun noch einige Optimierungen und Änderungen der Hard- und Firmware vorgenommen, so dass für den Aufbau eines richtigen KC85-Modules eine solide Basis bereitsteht. Diese Version wird in die erste Serie des KC Modules übernommen werden. Im nachfolgenden Bild sind die Grundelemente des KCNET noch einmal zusammengestellt:
Der W5100 auf dem WIZ810MJ bildet den eigentlichen Hardware TCPIP-Stack. Weiterhin benötigt man einen ATmega 162 mit Reset-IC, einige Logik-IC's, ein 3,3V Netzteil und optional für die direkte Kontrolle der Funktion der Firmware per Terminalprogramm den Pegelumsetzer mit dem MAX232 für den Anschluss einer Standard RS232 Schnittstelle. Für den Anschluss an ein beliebiges Z80 System wird eine komplette PIO gebraucht. Die gesamte Schaltung muss natürlich an die 5V des Z80-Systems angeschlossen werden und benötigt ca. 200 mA Strom vom Netzteil.
Jedes Gerät im Ethernet muss eine einmalige und eindeutige MAC-Adresse besitzen, also auch das KCNET-Interface. Diese MAC-Adresse wird fest in der Firmware hinterlegt und ist vom Anwender für jedes einzelne Exemplar des Interface zu liefern. Dafür kann man eine alte ausrangierte (eine neue für 4 EUR geht natürlich auch) Netzwerkkarte benutzen, deren MAC-Adresse ermittelt und übernommen werden kann, das wird die einzige Voraussetzung für den Erhalt der kostenlosen Firmware sein. Die sonstige Software läuft im KC unter CAOS oder CP/M und steht hier im Downloadbereich zur Verfügung.
Was leistet nun die Ethernet-Schnittstelle im Zusammenspiel mit dem TCPIP-Stack - sie besitzt eigentlich alle üblichen Merkmale, welche dem heutigen Standard entsprechen, siehe folgendes Bild:
Die Ethernet Eigenschaften des Netzwerkanschlusses werden einschliesslich Crossover Kabel automatisch erkannt. Der Stack bietet durch die Socket-Schnittstelle einen sehr einfachen Zugang zum UDP- oder TCP-Layer eines TCPIP-Protokoll-Stacks für Programmierer. Auch das PPPoE für eine direkte Einwahl per DSL-Modem beim Provider kann der Chip - das wird von der bisherigen KC-Software aber nicht unterstützt und ich habe eine Umsetzung im KC auch nicht vor, prinzipiell könnte man es aber programmieren.
Die Beschränkungen, wie ausschliesslich IPv4 oder nur 4 simultane Verbindungen ins Netzwerk gleichzeitig oder fehlende Unterstützung der IP-Fragmentierung sind für den Betrieb am KC85 nicht von Bedeutung. Das spielt im privaten Heimnetzwerk keine Rolle und ich war schon sehr froh, als der KC im Januar schon mal 1 Verbindung zum PC über das Netzwerk herstellen konnte!
Die beiden folgenden Abbildungen zeigen im Blockschaltbild die Einbindung des KCNET-Interface in die Soft- und Hardware des KC85 Systems:
In der CAOS-Betriebsart ist das alles etwas übersichtlicher als unter CP/M, da es keinen Koppel-RAM gibt, welchen die Software überwinden muss. Die Abbildung links wäre auch das Modell für andere Z80-Systeme, wo die PIO im I/O-Adressbereich der CPU liegt und direkt programmiert werden kann.
Der Low-Level Interface-Treiber für CAOS, welcher die PIO bedient (nicht im Blockschaltbild), sollte sich nach Entfernung des speziellen Codes für die Zu- und Abschaltung des M001 bei der Initialisierung bzw. beim Beenden des Programmes auf dem KC85 ansonsten unverändert übernehmen lassen. Damit könnte man auch den TCP/IP-Treiber mit der Socket-API unverändert übernehmen. Der setzt auf den Low-Level Treiber auf, ist aber vollkommen unabhängig vom Betriebssystem, ich kann ihn auf dem KC85 sowohl unter CAOS als auch CP/M ohne Änderungen benutzen.
Dann wären nur die systemspezifischen Programmteile, wie Laden/Speichern von Daten, Bildschirmausgaben oder Tastatureingaben von CAOSNET anzupassen, was für einen Assemblerprogrammierer kein Problem darstellen sollte.
Die Netzwerkroutinen könnte man für sein System unverändert übernehmen. Mit CP/M 2.x entfallen selbst diese Anpassungen, da dort die Systemein- und -ausgaben per BDOS genormt sind. Diese Programme wären bei ausschliesslicher Benutzung von überall vorhandenen Terminalcodes sofort austauschbar, so wie das in CPMNET praktiziert wurde.
WIZ812MJ
Das Modul WIZ812MJ mit 2,54mm Stiftleisten kann anstatt des WIZ810MJ eingesetzt werden, das ebenfalls noch erhältliche Modul WIZ811MJ ist ungeeignet.
Wenn man ein WIZ812MJ benutzt, kann man die beiden Gatter an /RxLED bzw. /TxLED und den Jumper für die Modulumschaltung der beiden amderen Module weglassen und das /LINK-Signal des Modules direkt mit Pin 15 des ATmega 162 verbinden.
Alle anderen Pins werden entsprechend der folgenden Aufstellung verschaltet. Alle mit "n.c." gekennzeichneten Pins in der Spalte Bemerkung des WIZ812MJ bleiben frei.
Cross-Referenz Liste WIZnet 810MJ-WIZnet 812MJ |
|||||
WIZ810MJ |
WIZ812MJ |
||||
Bezeichnug |
Pin |
Bezeichnung | Pin | Bemerkung | |
MOSI |
J1:1 |
n.c. |
|||
MISO |
J1:2 | n.c. | |||
D1 |
J2:15 | D1 |
J1:3 | ||
D0 |
J2:16 | D0 |
J1:4 | ||
D3 |
J2:17 | D3 |
J1:5 | ||
D2 |
J2:18 | D2 |
J1:6 | ||
D5 |
J2:19 | D5 |
J1:7 | ||
D4 |
J2:20 | D4 |
J1:8 | ||
D7 |
J2:21 | D7 |
J1:9 | ||
D6 |
J2:22 | D6 |
J1:10 | ||
GND | J1:8,13,24 | GND |
J1:11 | ||
VCC (3,3V) | J1:1 | VCC (3,3V) |
J1:12 | ||
A8 |
J1:15 | A8 |
J1:13 | ||
A9 |
J1:14 | A9 |
J1:14 | ||
A10 |
J1:11 |
A10 |
J1:15 | ||
A11 |
J1:12 | A11 |
J1:16 | ||
A12 |
J1:9 | A12 |
J1:17 | ||
A13 |
J1:10 |
A13 |
J1:18 | ||
A14 |
J1:7 |
A14 |
J1:19 | ||
n.c. |
J1:20 | n.c. |
|||
VCC (3,3V) | J2:24 | VCC (3,3V) | J2:1 |
||
/RESET |
J2:2 |
/RESET | J2:2 | ||
SCLK | J2:3 | n.c. | |||
/SCS | J2:4 | n.c. | |||
/WR | J1:3 |
/WR | J2:5 | ||
/RD | J1:4 |
/RD | J2:6 | ||
/CS |
J1:5 |
/CS | J2:7 | ||
/INT | J1:2 |
/INT | J2:8 | ||
LED_RX | J2:9 | n.c. |
|||
LED_TX | J2:10 | n.c. |
|||
A0 |
J1:23 | A0 | J2:11 | ||
A1 |
J1:22 | A1 | J2:12 | ||
A2 |
J1:21 | A2 | J2:13 | ||
A3 |
J1:20 | A3 | J2:14 | ||
A4 |
J1:19 | A4 | J2:15 | ||
A5 |
J1:18 | A5 | J2:16 | ||
A6 |
J1:17 | A6 | J2:17 | ||
A7 |
J1:16 | A7 | J2:18 | ||
/LED_LINK | J2:19 | direkt an ATmega162 Pin 15 |
|||
GND |
J2:1,4,7,13,14,23 | GND | J2:20 |