<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">% Content-encoding: UTF-8
\documentclass[ngerman]{article}
\usepackage[T1]{fontenc}
\usepackage[latin1]{inputenc}
\setcounter{secnumdepth}{0}
\setcounter{tocdepth}{0}

\newcommand{\qed}{\hfill \mbox{\raggedright \rule{.07in}{.07in}}}

\begin{document}

\title{T4 â€” ein Embeddedâ€“Forthâ€“Experiment}[T4 Embeddedâ€“Forthâ€“Experiment]
\author{JÃ¶rg VÃ¶lker}
\maketitle

Seit nunmehr fast 6 Jahren bringt die tematik GmbH unter dem Markennamen \emph{Servonaut} (\url{www.servonaut.de}) Module fÃ¼r den Truckmodellbau bzw. Funktionsmodellbau im MaÃŸstab 1:16 bis 1:8 auf den Markt. Die Fahrtregler, Lichtanlagen und Truck--Soundmodule sind bis auf wenige Ausnahmen in Forth programmiert.

\begin{multicols}{2}

Unser erstes Modellbau--Produkt, eine Kombination aus Fahrtregler, Lichtanlage und einem kleinen Bordcomputer, wurde 2001 noch auf Basis eines 68HC11 und unter Holon11 entwickelt. Nach dem Erfolg dieses ersten Moduls musste dann allerdings leider gleich ein Wechsel der Prozessorfamilie stattfinden, denn der 68HC11 wird von Freescale (ehemals Motorola) nicht weitergefÃ¼hrt und ist fÃ¼r einfache Anwendungen zu teuer. Schade â€” Holon11 hatte sich bestens bewÃ¤hrt.

Die Wahl fiel auf die kleinere 68HC08--Familie. Zwar ist dieser Prozessor etwas einfacher aufgebaut als ein 68HC11, dafÃ¼r sind zahllose auch sehr kleine Varianten mit Flash--Speicher und leistungsstarker Peripherie zu fairen Preisen verfÃ¼gbar. Alle Typen sind zudem in--circuit--programmierbar, und durch die hÃ¶heren Taktfrequenzen im Vergleich zum 68HC11 wird der weniger leistungsfÃ¤hige Befehlssatz mehr als kompensiert.

FÃ¼r den 68HC08 konnten wir allerdings weit und breit nur ein Forth--System finden, und zwar das nanoFORTH von Rafael Deliano. Da diese Forth--Variante auf dem Zielsystem selbst lÃ¤uft, benÃ¶tigt sie jedoch fÃ¼r unsere Zwecke zu viel Speicher und ist auf Chips mit weniger als 24kByte nicht sinnvoll einzusetzen.

In dieser Not und unter Zeitdruck wurde deshalb zunÃ¤chst ein Zwischenschritt unternommen und lediglich ein Forth--Kern und ein innerer Interpreter fÃ¼r Direct--Threaded--Code erstellt. Die Programmierung erfolgte dann jedoch weiterhin in Assembler, die Forth--Programmteile wurden in Form von Konstanten--Tabellen eingegeben â€” ein recht mÃ¼hsames und fehlertrÃ¤chtiges Unterfangen. Immerhin konnten so bewÃ¤hrte Programmteile von Holon11 Ã¼bernommen werden.

\setcounter{figure}{1}
\begin{figure*}[t]
\begin{center}
\includegraphics[width=0.8\textwidth]{2007-02/T4-ScreenShot1}\\
\caption{\label{T4-ScreenShot1}T4-OberflÃ¤che orientiert sich entfernt an Holon11.}
\end{center}
\end{figure*}


Auf die Dauer konnte dies kein befriedigender Zustand sein. Aber vor dem letzten Schritt hin zu einem eigenen kompletten Forth--System wurde lange gezÃ¶gert. Da ich noch nie ein vollstÃ¤ndiges Forth implementiert hatte, war der Aufwand schwer abzuschÃ¤tzen. Es geht dabei schlieÃŸlich um kommerzielle Produktentwicklung. Zeit ist hier nun einmal Geld. Ich hatte offen gesagt groÃŸe Sorge, mich zu verzetteln. Nach jahrelanger Software--Entwicklung fÃ¼r Industrie--Waagen in C stand ein Umstieg auf ein kommerzielles C fÃ¼r den 68HC08 als Alternative allerdings auch nie zur Debatte.
\end{multicols}

\vfill
\setcounter{figure}{0}
\begin{figure}
\begin{center}
\includegraphics[width=0.7\textwidth]{2007-02/T4-UniWellhausen2}\\
\caption{\label{T4-UniWellhausen2}Mit T4 programmierter Modellbau-Truck}
\end{center}
\end{figure}
\setcounter{figure}{2}
\vfill

\begin{multicols}{2}
Wie kann man nun aber bei der Implementierung von Forth das 
Kosten/Nutzen--VerhÃ¤ltnis optimieren, wie kommt man mit wenig Aufwand zu einem einigermaÃŸen komfortablen System?

Alle Vorgehensweisen haben ihre Vor-- und Nachteile. Wie man ein 
Stand--Alone--Forth auf einem Zielsystem erstellt ist relativ gut dokumentiert, und es gibt viele Vorlagen, an denen man sich orientieren kann. AuÃŸerdem entspricht das Ergebnis noch am ehesten einem klassischen Forth. Leider ist der Speicherbedarf hoch. Auch der Code, der nur zur Ãœbersetzungszeit benÃ¶tigt wird, (und das Dictionary) belegt Speicherplatz im Zielsystem. Der Komfort bei der Entwicklung hÃ¤lt sich in Grenzen, da ein Embedded System oft keinen Massenspeicher besitzt und nur Ã¼ber das NadelÃ¶hr einer seriellen Schnittstelle und einen PC auf Quellen zugegriffen werden kann.

Ein typischer Cross--Compiler dagegen, der vollstÃ¤ndig auf einem PC als Entwicklungsrechner lÃ¤uft, kÃ¶nnte einigen Luxus heute Ã¼blicher integrierter OberflÃ¤chen bieten. Nur eben zwei entscheidende Forth--Eigenarten nicht: Die Erweiterbarkeit der Sprache und das interaktive Entwickeln und Debuggen werden nicht unterstÃ¼tzt.


Bleiben noch die \emph{groÃŸen} LÃ¶sungen, darunter die kommerziellen Systeme wie SwiftX von Forth,Inc., VFX Forth von MPE, und in gewisser Weise auch Holon11. Hier wird ein Cross--Compiler mit einem Forth auf dem Entwicklungsrechner kombiniert, und ein Interface zum Zielsystem erlaubt zudem interaktives Arbeiten. Optimal â€” nur leider nicht gerade an einem Wochenende implementiert. Allein die Notwendigkeit, mehrere AdressrÃ¤ume im PC zu verwalten, erhÃ¶ht die KomplexitÃ¤t wesentlich, und fast alle Forth--Worte mÃ¼ssen zudem in zwei Versionen vorliegen, fÃ¼r den Host und fÃ¼r den jeweiligen Targetprozessor.     

Die ersten beiden AnsÃ¤tze kommen auf Grund ihrer EinschrÃ¤nkungen fÃ¼r mich nicht in Frage, die dritte Variante ist zu aufwÃ¤ndig â€” Was also tun? Not macht zum GlÃ¼ck erfinderisch â€” so auch in diesem Fall.

Schaut man sich einmal die Quellen fÃ¼r ein Stand--Alone--Forth, z.~B.\ ein altes FIG--Forth genauer an, dann fÃ¤llt auf, das die lÃ¤ngsten Worte, die gleichzeitig am meisten Speicher belegen und beim Ãœbersetzen den grÃ¶ÃŸten Teil der Rechenzeit benÃ¶tigen, natÃ¼rlich mit dem interaktiven Interpreter, der Compilierung und dem Dictionary zu tun haben: Accept, Parse, Find, Create usw. Dazu kommt noch die Zahlenkonvertierung mit Number, \verb|&lt;#|, \verb|#|, \verb|#&gt;|, usw. Diese Worte werden in einem Embedded--System (typischerweise) wenn Ã¼berhaupt nur in der Entwicklungsphase benÃ¶tigt. Die Grundidee besteht nun darin, nur diese Worte zusammen mit dem Dictionary auf einen Entwicklungsrecher auszulagern â€” den eigentlichen Interpreter-- und Compilerkern aber im Zielsystem zu belassen. Die Ãœbersetzung wird also durch das Zielsystem gesteuert, der Entwicklungsrechner ist nur ein Slave, eine Art intelligentes Terminal mit Forth--spezifischen  Zusatzfunktionen. Dieser Ansatz ist ein Kompromiss. Es werden zwar nicht alle nur fÃ¼r die Ãœbersetzung erforderlichen Worte aus dem Zielsystem entfernt, aber der weitaus Ã¼berwiegende Teil. Der Charakter eines traditionellen interaktiven Forth--Systems bleibt vollstÃ¤ndig erhalten. Die KomplexitÃ¤t ist dabei nicht nennenswert hÃ¶her wie bei einem Stand--Alone Forth. Da der PC sowohl das Dictionary als auch alle Quellen verwalten kann, sind komfortable Hilfe-- und Suchfunktionen einfach umzusetzen.   


\begin{figure*}[t]
\begin{center}
\includegraphics[width=0.8\textwidth]{2007-02/T4-ScreenShot2}\\
\caption{\label{T4-ScreenShot2}Ein einfaches Demo wird Ã¼bersetzt und ausgefÃ¼hrt.}
\end{center}
\end{figure*}

Das Projekt wurde nach einigem ZÃ¶gern dann im Sommer 2005 unter dem Namen \emph{T4} in Angriff genommen. FÃ¼r die PC--Software fiel die Wahl auf Delphi, einfach weil bei uns Erfahrung mit diesem System vorhanden ist. Die OberflÃ¤che orientiert sich entfernt an Holon11 und ist aufgeteilt in vier fest zugeordnete Bereiche. Je ein groÃŸes Fenster stehen fÃ¼r  den Editor und das Terminal, d.h. die direkte Verbindung zum Forth--Interpreter im Zielsystem zur VerfÃ¼gung. Zwei kleine Fenster dienen der Navigation in den Quelldateien und dem direkten Einblick in das Dictionary. Um schnell voranzukommen, wurden wo immer mÃ¶glich fertige Delphi--Komponenten eingesetzt, auf Kosten der Effizienz und Geschwindigkeit. Da Speicherplatz im PC im Ãœberfluss vorhanden ist, kÃ¶nnen im Dictionary beliebige Zusatzinformationen abgelegt werden. T4 merkt sich fÃ¼r jedes neu definierte Wort die Quelldatei und Zeilennummer, auÃŸerdem wird die vollstÃ¤ndige Zeile, in der die Definition erfolgt ist, mit abgespeichert. Ist die Quelle entsprechend aufgebaut, hat jeder Dictionary--Eintrag somit automatisch auch einen hilfreichen Kommentar, z.~B.\ in der Form \verb|rot (n1 n2 n3 -- n2 n3 n1)| Ein Doppelklick auf ein Wort im Editor holt den entsprechenden Eintrag in das Dictionary--Fenster â€” ein Doppelklick in das Dictionary lÃ¤dt wiederum den Quelltext eines Worts direkt in den Editor.

Auf dem Zielsystem wird ein Forth--Kernel benÃ¶tigt, der notwendigerweise in Assembler erstellt werden muss. Der Kernel umfasst zunÃ¤chst einmal alle grundlegenden Worte. Compiler und Interpreter sind weitgehend bereits in Forth erstellt, allerdings notgedrungen im Kernel noch von Hand codiert. Viele Worte des Compilers, wie if, else, then usw., kÃ¶nnen dagegen schon aus einer Forth--Quelle nachgeladen werden.

Die Kommunikation zwischen PC und dem Zielsystem erfolgt seriell, dabei hat die Schnittstelle eine Doppelfunktion. Neben der ganz normalen ASCII--Ein-- und 
--Ausgabe bei einem laufenden Anwender--Programm werden vom Interpreter und Compiler dagegen ASCII--Steuerzeichen Ã¼bertragen. Der eigentliche Ablauf ist verblÃ¼ffend einfach, ein Beispiel: Im Zielsystem ist Accept wie folgt definiert:

\begin{verbatim}
: accept ( -- u ) 12 emit key ;
\end{verbatim}


Das Steuerzeichen 12 startet im PC die eigentliche Accept--FunktionalitÃ¤t. Es wird eine Zeile gelesen und im TIB, ebenfalls im PC, abgelegt. Danach sendet der PC die Anzahl der gelesenen Zeichen gleichsam als Quittung an das Zielsystem zurÃ¼ck. Der Ablauf ist immer gleich: Das Zielsystem sendet ein Kommando, der PC antwortet mit bis zu drei Byte. Ein zusÃ¤tzliches Handshake ist so nicht erforderlich. An die Schnittstelle werden minimale Anforderungen gestellt, noch nicht einmal ein Buffer (im Target) ist erforderlich. Die Verarbeitung im Zielsystem ist nÃ¤mlich normalerweise schnell genug, um beim Empfang der Daten mit der Ãœbertragungszeit zweier Stopp--Bits auszukommen. Die Schnittstelle kann so notfalls auch vollstÃ¤ndig in Software erstellt werden, ohne Timer, Interrupts oder UART--Hardware zu benÃ¶tigen oder zu blockieren. Bei unseren Modulen werden in der Entwicklungsphase Port--Pins zur Kommunikation genutzt, die spÃ¤ter dann die Funktion von Konfigurations--Jumpern Ã¼bernehmen.

\begin{figure*}[t]
\hfil
\begin{minipage}[b]{0.45\textwidth}
\begin{center}
\includegraphics[width=0.8\textwidth]{2007-02/T4-K30}\\
\caption{\label{T4-K30}Truck-Fahrtregler mit Lichtanlage, noch in bedrahteter Technik mit dem 68HC11}
\end{center}
\end{minipage}\hfil
\begin{minipage}[b]{0.45\textwidth}
\begin{center}
\includegraphics[width=0.8\textwidth]{2007-02/T4-M20Plus}\\
\caption{\label{T4-M20plus}Aktueller 20A Fahrtregler fÃ¼r Funktionsmodelle mit Lichtanlage auf der Basis eines 68HC08}
\end{center}
\end{minipage}
\hfil
\end{figure*}


Das Konzept von T4 ist von der Art der Implementierung des Forth auf dem Target zunÃ¤chst einmal unabhÃ¤ngig. Welche Implementierung \emph{optimal} ist, hÃ¤ngt vÃ¶llig vom Prozessor und den Randbedingungen ab, pauschale Aussagen kann man da meiner Meinung nach nicht machen. FÃ¼r unsere Anwendungen soll mÃ¶glichst viel Funktion in mÃ¶glichst kleinen (preiswerten) Chips untergebracht werden. Die Rechenleistung ist dabei eher zweitrangig. Immerhin hat ein 68HC08 je nach Taktfrequenz schon den vier-- bis achtfachen Durchsatz eines Commodore C64, fÃ¼r viele Anwendungen ist das vÃ¶llig ausreichend. Und zeitkritische Funktionen sowie Interrupt--Services werden eh bevorzugt in Assembler erstellt. Die Wahl fiel nach einigen Voruntersuchungen auf eine Kombination von direkt--threaded und token--threaded Forth. Der innere Interpreter kann bis zu 128 7--Bit Token erkennen und einen Adressraum bis zu 32 kByte Ã¼ber 15--Bit Adresstoken abdecken. Ein Bit unterscheidet die beiden FÃ¤lle. Die in Assembler codierten Worte werden dabei grundsÃ¤tzlich mit Byte--Token angesprochen, die Ã¼ber Forth compilierten Worte dagegen mit 15--Bit--Adressen. Einige weitere Optimierungen fÃ¼hren dazu, dass z.~B.\ das Wort \verb|2DUP| in nur vier Byte codiert werden kann:

\begin{verbatim}
$FD	jsr  ,x
$44	dc.b	over
$44	dc.b	over
$4B	dc.b	next
\end{verbatim}
\medskip

Der Einsatz eines \emph{klassischen} inneren Interpreters hat zudem den Vorteil, das sich auch ein Single--Step Debugging schÃ¶n einfach implementieren lÃ¤ÃŸt. FÃ¼r ein Multitasking wird ebenfalls das typische kooperative Konzept mit \verb|pause| angewendet, bei unseren Modellbau--Projekten werden meistens zwei bis vier Tasks eingesetzt. \verb|Create|~--~\verb|Does&gt;| darf natÃ¼rlich auch nicht fehlen. Da T4 aber direkt in einen Flash--Speicher kompiliert, wurde aus \emph{technischen} GrÃ¼nden auf das Ã¤ltere \verb|&lt;Builds Does&gt;| Konstrukt zurÃ¼ckgegriffen. Die Ãœbersetzung in den Flash--Speicher hat zusammen mit einem Marker--Mechanismus (Ã¤hnlich Forget) den unschÃ¤tzbaren Vorteil, dass nach einem Absturz des Zielsystems in der Entwicklungsphase oft nur einige Sekunden vergehen, bis nach dem Reset die Arbeit (und das heiÃŸt in diesem Fall die Fehlersuche) fortgesetzt werden kann.
\vspace*{2em}
~
\end{multicols}

\vfill
\begin{figure}
\begin{center}
\begin{quotation}
\listinginput[1]{1}{2007-02/T4-codefragment1.fs}
\end{quotation}
\caption{\label{T4-codefragment1}\texttt{swap} ist in Assembler codiert. \texttt{rot} belegt in handcodiertem Forth bereits nur noch 6 Byte.}
\end{center}
\end{figure}

\begin{multicols}{2}  
Verzichtet man auf Zahlenkonvertierung (im Target) und doppelt--genaue Arithmetik so benÃ¶tigt ein Minimal--System mit Multitasking nur etwas Ã¼ber 2kByte Speicher. Der Ã¤uÃŸere Interpreter belegt davon ca.\ 230 Byte, der Compiler rund 260 Byte und die nÃ¶tigen Flash--Routinen etwa 220 Byte. Single--Step und ein einfaches Dump belegen nochmals ca.\ 170 Byte. Zusammen sind das weniger als 1kByte, die nur in der Enwicklungsphase benÃ¶tigt werden und spÃ¤ter \emph{nutzlos} in der Seriensoftware verbleiben.
  
Bereits ab 4k Flash ist so ein sinnvoller Einsatz mÃ¶glich, mit Platz fÃ¼r bis zu 1000 Forth--Token fÃ¼r die Applikation. Die Schnittstelle kann noch auf Halb--Duplex minimiert werden, dann ist der kleinste sinnvoll einsetzbare Microcontroller ein 4k--Chip z.~B.\ ein 68HC908QT4 im DIL8-- oder SO8--GehÃ¤use mit noch 5 freien Ein--/AusgÃ¤ngen (Zwei werden fÃ¼r die Versorgungsleitung benÃ¶tigt, ein weiterer Pin fÃ¼r die Kommunikation mit T4 in der Entwicklungsphase.)
      
T4 wurde, kaum dass es einigermaÃŸen einsetzbar war, sofort fÃ¼r einem Software--Redesign eines Fahrtreglers mit Lichtanlage verwendet. Der Funktionsumfang der Baugruppe konnte ein gutes StÃ¼ck erweitert werden, denn durch den nun sehr kompakten Code wurde wieder Speicherplatz im Controller frei. Bis heute wurden fÃ¼nf Projekte unterschiedlicher KomplexitÃ¤t mit T4 realisiert, und das System soll auch fÃ¼r zukÃ¼nftige Entwicklungen, soweit irgendwie mÃ¶glich, zum Einsatz kommen. Leider gab es bisher keine Zeit, den PC--Teil von T4 weiter zu optimieren. Es gibt noch einige MÃ¤ngel, allem voran in der Fehlerbehandlung, die nur rudimentÃ¤r existiert. Die Arbeit an einer AVR--Variante wurde bereits aufgenommen, ist aber noch nicht abgeschlossen.

Fazit: Mit dem beschriebenen Ansatz kann ein Forth fÃ¼r die Cross--Softwareentwicklung vergleichsweise einfach und in kurzer Zeit implementiert werden. Alle wesentlichen Merkmale von Forth, wie interaktives Arbeiten und Debuggen, inkrementelles Compilieren und die Erweiterbarkeit der Sprache, bleiben erhalten. ZusÃ¤tzlich kann einiges an Komfort in der Entwicklungsumgebung realisiert werden. Die Software im PC ist weitgehend unabhÃ¤ngig vom Zielprozessor. In der Praxis hat sich T4 gut bewÃ¤hrt und die Entwicklungszeiten deutlich reduziert. Das Konzept eignet sich allerdings nicht fÃ¼r alle Prozessor--Typen und Anwendungen gleich gut. Ein Flash--Speicher mit geringer BlockgrÃ¶ÃŸe und die FÃ¤higkeit des Prozessors, auf den eigenen Code--Speicher zuzugreifen, sind Voraussetzung. Im Forth--Sinn nicht optimal gelÃ¶st ist die Entwicklung auf Assembler--Ebene und die geringe FlexibilitÃ¤t des Dictionaries, dessen Struktur nur im PC selbst geÃ¤ndert oder erweitert werden kann. Die Interaktion zwischen PC und Zielsystem setzt auÃŸerdem der Ãœbersetzungsgeschwindigkeit Grenzen. Der fertige Code fÃ¼r die Serie muss zudem mit einem zusÃ¤tzlichen Tool aus dem Target kopiert werden. \qed

\end{multicols}

\vfill
\begin{figure}
\begin{center}
\includegraphics[width=0.7\textwidth]{2007-02/T4-MBS.eps}\\
\caption{\label{T4-MBS}Die Servonaut--Werbe--Trucks --- Forth driven}
\end{center}
\end{figure}

\end{document}</pre></body></html>