Die Software beinhaltet verschiedene IP-Peripherie-Cores, die in einer Embedded-Applikation eingesetzt werden können. Für eine möglichst bedienfreundliche Konfiguration und Bedienung dieser Peripherie steht ein Software-Framework namens Software-Platform-Builder zur Verfügung.
Der Nutzen für den Anwender besteht darin, dass er die Low-Level-Treiber für die Periphere nicht mehr selber schreiben muss, sondern auf fertige Bibliotheksfunktionen zugreifen kann, die im C-Quellcode vorliegen. Das erspart ihm, sich zeitaufwendig mit der internen Arbeitsweise der Peripherie, deren SFR-Registern, einem Kommunikationsprotokoll sowie der Interrupt-Nutzung zu befassen. Die Peripherie selbst wird über entsprechende Parameter-Einträge in dem Software-Platform-Builder-Dokument bzw. über den Aufruf der dazu vorhanden C-Bibliotheksfunktionen konfiguriert.
Da die Peripheriecontroller über „memory mapped I/O“ angesprochen werden, ist ein automatischer Import der Konfiguration aus dem FPGA-Projekt heraus möglich; und zwar mit der Absicht, die Software-Platform-Builder-Konfiguration jederzeit per Knopfdruck aktualisieren zu können. Das ist erforderlich, wenn sich z.B. das Speicher-Mapping geändert hat oder die Anzahl der Steuerleitungen angepasst werden muss. Letzteres ist dann vonnöten, wenn anstatt eines I/O-Ports nun vier I/O-Ports adressiert werden müssen und somit zwei zusätzliche Adressleitungen erforderlich sind.
Der Software-Platform-Builder besteht aus drei Ebenen: Die unterste Ebene, die so genannte Hardware-Wrapper-Ebene, bietet Zugriff auf Basisfunktionen wie die Startadresse der Peripherie im „memory mapped“-Speicher oder die Interrupt-Zuweisung. Diese Ebene wird normalerweise nur von den übergeordneten Treibern angesprochen, nicht jedoch direkt aus der Applikation. Bei einem einfachen Zugriff auf einen I/O-Port kann jedoch auch diese Funktion genutzt werden. Hier stellt der Hardware-Wrapper dann automatisch erzeugte C-Makros zur Verfügung (Listing 1).
Die nächste Ebene ist die Treiber-Ebene: Ein Treiber benutzt die Hardware-Wrapper oder andere Treiber beim Zugriff auf die Peripherie. Der Unterschied zwischen dem Hardware-Wrapper und dem Treiber ist, dass der Hardware-Wrapper lediglich Basisinformationen zu der Peripherie liefert, aber keine weiteren Funktionen. Diese Informationen können dann vom übergeordneten Treiber benutzt werden.
Jeder Treiber hat seinen zugehörigen Hardware-Wrapper. Wird von einer Applikation heraus direkt über das API auf die Treiber zugegriffen, bleibt diese allerdings hardware-abhängig, da beim Wechsel der Peripherie auch die Treiber gewechselt werden müssen.
Die nächste Ebene ist die Treiber-Ebene: Ein Treiber benutzt die Hardware-Wrapper oder andere Treiber beim Zugriff auf die Peripherie. Der Unterschied zwischen dem Hardware-Wrapper und dem Treiber ist, dass der Hardware-Wrapper lediglich Basisinformationen zu der Peripherie liefert, aber keine weiteren Funktionen. Diese Informationen können dann vom übergeordneten Treiber benutzt werden.
Jeder Treiber hat seinen zugehörigen Hardware-Wrapper. Wird von einer Applikation heraus direkt über das API auf die Treiber zugegriffen, bleibt diese allerdings hardware-abhängig, da beim Wechsel der Peripherie auch die Treiber gewechselt werden müssen.
Die oberste Ebene ist die Context-Ebene: Diese Ebene bietet einen standardisierten, hardware-unabhängigen Zugriff auf die Peripherie. Werden Funktionen der Context-Ebene benutzt, so bleibt die Applikation portabel. Wird beispielsweise ein generischer Maustreiber benutzt, so ändert sich der Applikations-Code nicht, wenn z.B. von einer PS/2- auf eine USB-Maus gewechselt wird. Hier werden dann einfach die untergeordneten Treiber durch die Software-Plattform ausgetauscht (Bild 3).
Zu den in der Entwurfsumgebung „Altium Designer“ unterstützten Treiber-Diensten gehören unter anderem:
Zusätzlich zu den drei Ebenen gibt es noch die Software-Services, die z.B. Funktionen, C-Präprozessor-Makros und C-Strukturen liefern, die nicht unmittelbar mit der Peripherie zu tun haben. Es stehen POSIX-Device-I/O-Dienste zur Verfügung, die einen Zugriff auf die nicht standardisierte I/O-Peripherie über standardisierte POSIX-I/O-Befehle ermöglichen.
Funktion der PS/2-Keyboard-Treiber
Was bei der vorhin gezeigten I/O-Port-Ansteuerung noch trivial ist, ändert sich schlagartig, wenn z.B. die Tastatureingaben eines PS/2-Keyboards eingelesen werden sollen. Hier werden auf der Hardware-Wrapper-Ebene wiederum die Basisadresse der Peripherie sowie die Adressen zum Zugriff auf die Takt- und Datenleitung definiert. Auf der ersten Treiber-Ebene wird der Keyboard-Interrupt bedient, welcher anzeigt, wann neue Daten anliegen, und diese Daten werden dann über die Datenleitung eingelesen. Zu den C-Bibliotheksfunktionen des Software-Platform-Builders, die auf dieser Ebene verfügbar sind, gehören z.B.
Das Keyboard sendet die Daten über einen Scancode, der aus 11 bit breiten Daten-Frames besteht, womit jeweils ein Byte übermittelt wird. Diese Daten werden auf der zweiten Treiber-Ebene ausgewertet. Wird z.B. ein 0xC1 empfangen, so bedeutet dies, dass die „A“-Taste gedrückt wurde. Zu den Funktionen der zweiten Treiber-Ebene gehören unter anderem „ps2kb_get_scancode“ oder „ps2kb_setleds“, um den kompletten Scancode statt der einzelnen Bytes einzulesen oder den Status der Keyboard-LEDs zu ändern.
Die Context-Ebene interpretiert und puffert diese Daten und zeigt dann direkt den empfangenen Buchstaben „A“ an. Hier sind dann die standardisierten POSIX-I/O-Befehle nutzbar (Bild 4).