Eines der wichtigsten Merkmale, die ein Mikrocontroller zum Zwecke einer guten C-Compiler-Unterstützung anbieten kann, ist das Vorhandensein eines flexiblen, Software-gesteuerten Stapelzeigers (Stack), weil unter Verwendung des Stapelzeigers Parameter zwischen Funktionsaufrufen ausgetauscht werden. Manche Low-end-8-bit-Mikrocontroller bieten lediglich einen Hardware-Stack mit einer festgelegten Zahl von Einträgen. Jedoch muss der Compiler mit einem einfachen Hardware-Stapelzeiger weniger optimale Methoden zur Implementierung von Funktionsaufrufen einsetzen, um in der Lage zu sein, überhaupt irgendein Programm zu compilieren. Zudem wird die Anzahl verschachtelter Funktionsaufrufe in hohem Maße eingeschränkt.
Die Architektur des Z8 Encore! bildet den Stapelzeiger in der Registerdatei ab, die bis zu 4 Kbyte groß sein kann. Auf diese Weise gewährleistet der Z8 Encore!, dass dem Entwickler die am besten geeignete Art von Stapelzeigern für das C-Programm der Anwendung zur Verfügung steht und er nicht gezwungen ist, mit einem Stack fester Größe zu arbeiten. Außerdem bietet er den Vorteil eines sehr schnellen Zugriffs auf die Stapeldaten.
Eine weitere Hilfe bei C-Compilern ist die Unterstützung von automatischer Sicherung und Wiederherstellung eines „Stack-Frame“ durch den Z8 Encore!, wenn der Mikrocontroller einen Interrupt durchführt. Dies stellt sicher, dass der Programmstatus automatisch gesichert wird, ehe der Code der Interrupt-Service-Routine beginnt. Der Programmierer wird von diesem Job entlastet, und der Vorgang trägt zur Reduzierung des Gesamt-Code-Bereichs bei. Darüber hinaus hilft dieses Verhalten bei der Funktion der gesteuerten Programmunterbrechung, mit deren Hilfe Programme Dienste über Interrupt-Service-Routinen – statt über Funktionsaufrufe – aufrufen können. Die Unterstützung solcher Software-Traps kann besonders in Mikrocontroller-Anwendungen wichtig sein, bei denen man einen kleinen Software-Kern haben möchte, der einen Satz individueller Programme unterstützt, wobei diese die I/O-Dienste gemeinsam nutzen. Der gemeinsame I/O-Code lässt sich in die Interrupt-Service-Routine einbauen und als standardisierte Programmunterbrechung anstelle von gemeinsamen Funktionsaufrufen initiieren. Das kann zu einer besseren Wartbarkeit der Anwendung beitragen, da gerätespezifischer Code hinter der Trap-Schnittstelle „abgeschirmt“ ist.
Reichhaltige Adressierungsarten
Der umfangreiche Satz von Adressierungsarten ist zur Verbesserung von Geschwindigkeit und Dichte des durch einen C-Compiler erzeugten Code ausgelegt. Zwar lässt sich auch mit einem eingeschränkten Satz von Adressierungsarten einiges erreichen, doch ist der Compiler oft gezwungen, zusätzliche Befehle zu erzeugen, um eine flexible Manipulation von Zeigern und Daten innerhalb von Strukturen zu ermöglichen. Zusätzlich zu den Befehlen, die zur Unterstützung des Zeiger-Einsatzes entwickelt wurden, gewährleisten diese Adressierungsarten, dass der Code sowohl kompakt ist als auch schnell abgearbeitet wird. Der Z8 Encore! bietet insgesamt sechs grundsätzliche Adressierungsarten (Tabelle 1): Register direkt, Register indirekt, Register indiziert, PC direkt, PC relativ und sofortige Daten (Immediate).
Wie oben erwähnt, gewähren die Registerbetriebsarten dem Compiler, falls erforderlich, Zugriff auf die gesamte Registerdatei, jedoch mit kompakten Befehlen für die Fälle, bei denen ein Zugriff auf einen kleineren Arbeitssatz erforderlich ist. Die „Register indirekt“-Betriebsart ermöglicht es, Registerinhalte als Zeiger auf andere Register oder den Programmspeicher abzulegen; dabei werden 4-bit-, 8-bit-, 12-bit- und 16-bit-Adressen unterstützt, um den Adressbereich jeder einzelnen Speicherbereichs-Variante vollständig abzudecken.
Die indizierte Adressierungsart, die nicht in allen Mikrocontroller-Architekturen vorhanden ist, jedoch durch viele C-Compiler unterstützt wird, bietet einen leistungsfähigen Zugriff auf Daten, die als im Registerbereich gehaltene Strukturen gespeichert sind. Ein vorzeichenbehafteter 8-bit-Index-wert kann einer in einem Arbeitsregister enthaltenen 8-bit-Basisadresse hinzugefügt werden. Die Basisadresse könnte der Beginn einer C-Struktur oder einer C-Matrix sein, wobei die Indexwerte für den einfachen Zugriff auf eine Variable in dieser Struktur Verwendung finden könnten.
Die PC-direkte Adressierungsart wird bei den Sprung- und Aufrufbefehlen eingesetzt. Der Sprung (Jump) oder Aufruf (Call) kann jede Position im linearen 64-Kbyte-Programmbereich erreichen. Das ermöglicht die einfache Compilierung von großen Mikrocontrollerprogrammen, ohne dass man den Compiler zwingen muss, komplexe Manipulationen von Seiten- oder Segmentregistern zu verwenden, die zusätzlichen Zeitaufwand und zusätzlichen Code-Raum erfordern.
Um kleinere Sprung- und Verzweigungsbefehle zu erlauben, unterstützt der Z8 Encore! außerdem die relative Adressierung, die das Programm auf jeden beliebigen Befehl innerhalb 128 byte der derzeitigen Programmzähleradresse verschiebt. Schließlich bietet die sofortige Betriebsart (Immediate) eine einfache Methode, konstante 8-bit-Werte in die Register zu laden.
Zur Unterstützung effizienter C-Zeiger-Arithmetik und Manipulation verfügt der Z8 Encore! über spezielle Befehle. Zum Beispiel gibt es für die einfache Manipulation von 16-bit-Zeigern spezielle Inkrement- und Dekrement-Wortbefehle zur Ergänzung der byteweisen arithmetischen Befehle.
Für längere arithmetische Berechnungen stehen Befehle zur Verfügung, die eine effiziente Verarbeitung von Werten mit Wortlänge erlauben, so wie sie für C-Ganzzahlen und lange Variablen benötigt werden. Zu ihnen zählen „Compare with Carry“-Befehle, die eine Übertragung des Ergebnisses einer Reihe von byteweisen Vergleichen von einer Operation zur nächsten erlauben.
Durch eine Kopplung des Compare-with-Carry mit Verzweigungsbefehlen erhält der C-Compiler eine wirkungsvolle Methode zum Testen von Zeigerwerten und zur Steuerung des Programmflusses auf Grundlage der Testergebnisse. Eine weitere Optimierung liegt im Hardware-Support von 8-bit-Multiplikationen, um lange Shift-and-Add-Routinen zum Multiplizieren von zwei Zahlen zu vermeiden.
Eine Optimierung auf Befehlsebene, die für die Umsetzung von C-Code außerordentlich nützlich ist, stellt der DJNZ-Befehl dar. Dieser vereint eine Countdown-Funktion und eine Zweig-Entscheidung in einem Befehl und trägt damit zur Reduzierung von Schleifenzykluszeiten bei. Im Gegensatz zu Hardwareschleifen-Steuerbefehlen, die in manchen anderen Architekturen anzutreffen sind, ermöglicht es der DJNZ-Befehl jedem Register, den Schleifenzähler aufzunehmen. Deshalb ist es leicht für den C-Compiler oder den Programmierer, unter Einsatz dieses Befehls verschachtelte Schleifen zu implementieren. Hardwareschleifen-Zäh-ler in anderen Architekturen erlauben häufig lediglich eine Schleifenvariable zu einem Zeitpunkt, was ihre Verwendung einschränkt. Insgesamt umfasst der ergänzte Z8-Basisbefehlssatz nunmehr 76 Instruktionen (Tabelle 2).
Bild 3 zeigt die Implementierung Z8F640x mit einem mit 20 MHz getakteten eZ8-CPU-Kern und 64 Kbyte Flash-Speicher sowie 12-kanaligem 10-bit-A/D-Umsetzer.
![]() | Dipl.-Ing. Mathias Löhr studierte Elektrotechnik an der Technischen Universität Braunschweig mit Schwerpunkt Elektronik/Elektrophysik. 1987 begann er als Systems-Engineer bei SGS-Thomson, wo er im Design-Center Grafing an Entwicklungswerkzeugen für 8-bit-Mikrocontroller arbeitete. 1993 wechselte er als Field Appli-cation Engineer zu Zilog in München und übernahm 2000 die Funktion des European Technical Manager. E-Mail: mloehr@zilog.com |