Diplomarbeit Onepage Urls
Diplomarbeit Onepage Urls
Diplomarbeit Onepage Urls
Diplom-Informatiker (FH)
heute moderne Rechnersysteme gepaart mit Spezialhardware verwendet, durch die bisher
Im Rahmen dieser Diplomarbeit werden sowohl eine Firmware als auch ein Treiber für
eine solche Spezialhardware auf USBBasis entwickelt. Zudem wird eine Verteilungsschicht
entwickelt, mit der die gewonnenen Daten in Echtzeit parallel an verschiedene Programme
zur Weiterverarbeitung geleitet werden können. Dabei wird vor allem darauf geachtet,
gewährleisten.
In dieser Arbeit nden Techniken wie Semaphoren, Signalisierung, Mutex und Shared
Memory Anwendung. Auÿerdem befassen sich Teile der Arbeit mit der Programmierung
eines Mikrocontrollers und der Übertragung von Daten über den USBBus.
i
Danksagung
Zunächst möchte mich bei Herrn Berthold Graÿ dafür bedanken, dass ich meine Arbeit
Ich möchte mich ebenfalls bei meinem Betreuer Herrn Prof. Dr. Andreas Hagerer und
dem Zweitkorrektor Herrn Prof. Dr. WolfDieter Tiedemann für das Lesen und Bewerten
Mein Dank gilt weiterhin Herrn Joachim Rosskopf, welcher mich mit Herrn Graÿ in Kon-
takt gebracht hat und mir damit diese Arbeit erst ermöglicht hat.
ii
Inhaltsverzeichnis
Abstract i
Danksagung ii
1 Einleitung 1
1.1 Beschreibung der Aufgabenstellung . . . . . . . . . . . . . . . . . . . . . . 3
1.2 Anforderungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.2.1 Anwendungsszenarien . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2 Grundlagen 11
2.1 Aufbau der Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.1 HF-Teil . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
2.1.2 Digitalisierungsteil . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.1.4 Datentransfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.1.5 Steuerung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3 Firmware 20
iii
3.1 Was sie leistet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.1.1 Initialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.1.2 InterruptHandling . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
3.1.3 Kommandos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
3.1.4 Nutzdatentransfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
3.2 Aufbau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
4 Treiber 37
4.1 Aufgaben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
4.1.2 Initialisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
4.1.3 Gerätefunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
4.1.4 Datentransfer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
4.2 Aufbau . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
4.3 Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
4.3.1 Testsystem . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5 Verteilungsschicht 53
5.1 Konzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
5.2 Realisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
5.2.2 Synchronisation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
iv
5.2.3 API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
5.3 Performanceanalyse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Literaturverzeichnis vi
Eidesstattliche Erklärung ix
v
Kapitel 1
Einleitung
In der heutigen Zeit ist die drahtlose Kommunikation über elektromagnetische Wellen
nicht mehr aus dem Alltag wegzudenken. Menschen kommunizieren über Mobiltelefone,
verwenden schnurlose Babyphone, um das Schreien des Nachwuchs nicht zu überhören und
synchronisieren über Bluetooth die Kontakteinträge von PDA und Handy. Aber nicht nur
im zivilen Bereich ist man auf die dadurch nahezu uneingeschränkte Mobilität angewiesen,
Die Verwendung elektromagnetischer Wellen hat jedoch auch zur Folge, dass jeder im
Empfangsbereich dieser Wellen und dem notwendigen Wissen über die Kodierung der
Nutzdaten in der Lage ist, diese unbemerkt zu dekodieren. Die Voraussetzung ist jedoch,
dass eine Einrichtung vorhanden ist, welche diese Wellen empfängt, sie entsprechend der
Gerade in den politischen Krisengebieten dieser Welt ist es wichtig, den dortigen Funk-
verkehr mitzuverfolgen. Nicht nur der Inhalt der Nachrichten ist in diesem Fall von Be-
deutung, sondern auch die Häugkeit und die Regelmäÿigkeit von Funksendungen spielen
eine Rolle. Dies sind Merkmale für die Aktivität militärischer Gruppen und Bewegungen
1.1 zeigt eine solche Anwendung im Betrieb. Beim Auftreten einer Aktivität in einem
dieser Frequenzbereiche dekodieren, speichern und archivieren sie diese Daten in eigens
dafür programmierten Datenbanken. Diese Daten werden daraufhin je nach Inhalt sofort
1
Abbildung 1.1: Spektrogrammdarstellung durch die Bedienanwendung HyperFFT. Dieser
Ausschnitt zeigt den Frequenzbereich zwischen 9.350 MHz und 9.700 MHz, in dem sich
zwischen zwei AMRadiosendern ein DRMSender bendet (Digital Radio Mondiale [26]).
oder gesammelt an höhere Instanzen innerhalb der Bundeswehr weitergegeben. Mit Hilfe
dieser Informationen kann daraufhin eine Art Barometer für die militärische Stimmung
in diesem Gebiet erstellt werden; somit ist es möglich, rechtzeitig entsprechende Sicher-
heitswarnungen auszugeben.
me bietet es sich an, den kostenintensiven HardwareAnteil auf ein Minimum zu beschrän-
ken und die notwendigen Schritte zur Rückgewinnung der Nutzdaten aus dem Funksignal
durch spezielle Software erledigen zu lassen. Dadurch ergibt sich auch die Möglichkeit,
2
1.1 Beschreibung der Aufgabenstellung
Das Ziel dieser Diplomarbeit ist es, für eine Neuentwicklung eines USBFunkempfängers
mit dem Namen USBRX für den eingangs erwähnten Einsatzbereich zwei Bibliotheken
zu entwickeln.
Die erste Bibliothek muss eine API zur Verfügung stellen, mit der ein Zugri auf den
se Bibliothek nur noch als Treiber bezeichnet. Dieser Treiber muss binärkompatibel zu
einem ähnlichen Treiber eines Drittanbieters sein, aber speziell für die verwendete Hard-
ware ausgelegt werden. Das bedeutet, dass die API fest vorgegeben ist und es gilt, das
ist es erforderlich, auch eine passende Firmware für das vorliegende Gerät zu entwickeln,
die während der Initialisierung auf einen InterfaceBaustein im Gerät geladen wird. Diese
Die zweite Bibliothek muss eine Schnittstelle zum Austausch von digitalisierten Funk-
daten zwischen Anwendungen zur Verfügung stellen. Der Austausch der Daten soll über
Shared Memory stattnden und so exibel sein, dass auch während des Betriebs umkon-
guriert werden kann, welche Anwendung ihre Daten an welche weitergibt. Das Starten
und Beenden von Anwendungen während Daten übertragen werden, darf zu keiner Be-
einträchtigung führen. Sinn der Verteilung ist es, während des Betriebs die empfangenen
beiten zu lassen. Diese Zusatzprogramme werden unabhängig von dieser Arbeit und mit
Abbildung 1.2 zeigt in einem Blockschaltbild, wie die verschiedenen Komponenten zu-
sammenarbeiten. Die grau schraerten Blöcke entsprechen denen, die in dieser Arbeit
behandelt werden.
1.2 Anforderungen
zu wurde zunächst geklärt, welche Anforderungen die Firmware, der Treiber und die
3
1.2 Anforderungen
den. Diese wurden festgehalten und sowohl während der Arbeit als auch nach Abschluss
1.2.1 Anwendungsszenarien
Spektrumanalyser
1
In diesem Szenario wird der Empfänger USBRX dazu verwendet, ein breitbandiges
Ansicht werden die Frequenzbänder durch den Anwender über längere Zeiträume hinweg
Um aus dem digitalisierten Funksignal eine spektrale Ansicht zu berechnen, wendet die Be-
2
dienanwendung auf einen Datenblock kongurierbarer Gröÿe eine KurzzeitSpektralanalyse
an. Das Resultat dieser Transformation wird dann im Spektrogramm dargestellt. In diesem
Szenario liefert ein im Gerät verbauter Digital Down Converter Daten je nach ausgewähl-
3
ter Filterbreite mit bis zu 18 MSamples/s an einen FIFOBaustein mit 32 KiSamples
4
1.2 Anforderungen
Kapazität. Ausgewertet werden durch die Bedienanwendung des Gerätes aber je nach
FFTBlockgröÿe lediglich Blöcke im Bereich von 512 Samples bis 16 KiSamples in Inter-
Bei einem Betrieb in diesem Szenario muss sichergestellt sein, dass der neu eingelesene
Block möglichst aktuelle Daten enthält und somit die Verzögerung zwischen der Digitali-
sierung durch das Gerät und der Darstellung durch die Anwendung sehr gering gehalten
wird. Zahlenmäÿige Anforderungen werden keine gestellt, jedoch soll der Code durch ent-
Datenaufzeichung
Wird, wie soeben beschrieben wurde, ein Sender auf einer überwachten Frequenz gefunden,
so wird der Datenverkehr mit einer geringeren Bandbreite als bei der Spektrumanalyse
aufgenommen. Die Bandbreite wird in dem Fall der Breite des Sendesignals angepasst und
bewegt sich meist im Bereich von 10 kHz bis 600 kHz. Die Datenrate ist demnach mit bis zu
2400 KiByte/s relativ gering und es werden keine Ansprüche hinsichtlich der Verzögerung
vom Sampling bis zur Verfügbarkeit der Daten gestellt. Jedoch muss sichergestellt sein,
dass keine Daten verloren gehen, da dies einen Synchronisationsverlust und demzufolge
Um bei Bedarf auch mit hohen Datenraten aufzeichnen zu können, sollten die Teilprojekte
entsprechend ausgelegt werden. Als Referenz dient hierfür der bisher verwendete Treiber,
Die Bedienanwendung wechselt ohne weitere Signalisierung zwischen den beiden Anwen-
dungsszenarien. Es liegt an der Treiberschicht und der Firmware, anhand des Verhaltens
Durchsatz gearbeitet werden muss. Eine Modikation der Bedienanwendung wäre zwar
gestellt, die hauptsächlich diesen Teil betreen oder dessen Verhalten genauer spezizie-
ren.
5
1.2 Anforderungen
Firmware
Die Firmware muss Befehle über einen Kontrollkanal entgegennehmen und ausführen.
Dazu muss sie einen Kommandoparser implementieren, mit dem die in Tabelle 1.1 be-
Wird das Kommando zum Start der Datenübertragung aus dem FIFOBaustein gege-
ben, müssen diese über einen Datenkanal an den HostRechner geschickt werden. Dazu
soll ein im USBController vorhandener GPIFBlock verwendet werden, der speziell für
solche Aufgaben ausgelegt wurde. Dabei wird zwischen einem Transfermodus und einem
Blocktransfermodus unterschieden.
• Beim Blocktransfermodus wird eine angegebene Anzahl an Samples aus dem FIFO
Baustein gelesen und über den Bus zum Host geschickt. Dies ist vor allem für den
Betrieb als Spektrumanalyser wichtig, da bei dieser Betriebsart nur sporadisch Da-
tenblöcke für die Spektralanzeige benötigt werden. Nach dem Transfer dieses Blockes
• Der normale Transfermodus hingegen ist für den Betrieb zur Datenaufzeichnung
Host schicken, bis dieser den Vorgang durch Anforderung des IdleModus unter-
bricht.
Abbildung 1.3 zeigt ein Zustandsdiagramm, in dem diese Zustände graphisch dargestellt
werden. Unabhängig vom aktuellen Modus müssen alle eingehenden Kommandos bear-
Treiber
Der Zugri der Bedienanwendung auf die Hardware soll über eine Dynamische Bibliothek
(.DLL) stattnden, welche sich hinsichtlich der API nicht von der Bibliothek [3] des Her-
stellers eines Entwicklungsboards unterscheiden soll. Die DLL dieses Herstellers wird im
Die USB2.DLL stellt verschiedene Funktionen zur Verfügung, mit denen ein am USBBus
angestecktes Board mit einem Cypress FX2LP initialisiert und angesteuert werden kann.
Die in der Bedienanwendung verwendeten Funktionen beschränken sich auf einige wenige,
6
1.2 Anforderungen
Funktion Beschreibung
UsbOpen Önet ein am USBBus vorhandenes Gerät
die in Tabelle 1.1 beschrieben werden. Diese Funktionen müssen so nachgebildet werden,
dass ein Wechsel zwischen der in dieser Arbeit erstellten Bibliothek und der USB2.DLL
Wird durch den Aufruf der Bibliotheksfunktion UsbParIn() der Transfer von Daten vom
USBRX initialisiert, so muss der Treiber die gelesenen Daten dem Aufrufer über einen
übergebenen Puer zurückliefern und zugleich über eine Verteilungsschicht weiteren An-
wendungen zur Verfügung stellen. Es ist dem Treiber überlassen, anhand des Verhaltens
der Bedienanwendung zu entscheiden, ob weitere Daten gelesen und bis zum nächsten
Aufruf der Funktion gepuert werden oder ob es bei einem BlockTransfer bleibt.
7
1.2 Anforderungen
Verteilung
Eine Verteilungsschicht muss durch eine weitere Bibliothek in Form einer DLL zur Verfü-
gung gestellt werden. Ihre Aufgabe ist es, die durch den Treiber gelesenen Daten möglichst
zu machen. Zudem soll es diese Bibliothek ermöglichen, diese verarbeiteten Daten unkom-
Durch die Verwendung von Shared Memory für die Konguration soll eine MultiMaster
4
Architektur realisiert werden. Jede Instanz dieser Bibliothek muss demnach allein lauf-
Das erforderliche Locking muss die Bibliothek selbst verwalten. Aus der Sicht des Anwen-
ders soll lediglich eine API mit sprechenden Namen sichtbar sein. Eine Übertragung von
Daten zwischen Anwendungen muss mit nur einem Funktionsaufruf auf jeder Seite ein-
gerichtet werden und mit ebenfalls nur einem Funktionsaufruf ausgelöst werden. Um den
Anwendungen ein asynchrones Senden und Empfangen der Daten zu ermöglichen, ist ein
Übertragung angegeben werden, dürfen aber nicht durch die Bibliothek limitiert werden.
Sowohl die Gröÿe der übertragenen Datenblöcke als auch die Puergröÿe werden jedoch
nur ein Vielfaches von 4 Byte betragen, was der Gröÿe eines I/QSamples entspricht. Das
Übertragen von anderen Block und Puergröÿen kann geduldet werden, ist aber nicht
zwingend erforderlich.
Abbildung 1.4 zeigt, wie in einem BeispielAufbau die vom Gerät USBRX gelieferten
Die Verteilungsbibliothek muss es erlauben, dass sich Knoten während des Betriebs an
ist. Optimalerweise kann dieses Umkongurieren einzelner Knoten aus jeder Anwendung
heraus stattnden.
4 Lädt eine Anwendung eine DLL nach, so wird diese in den Speicher der Anwendung eingeblendet
und dort initialisiert. Jede gestartete Anwendung erzeugt somit eine weitere Instanz dieser DLL.
8
1.2 Anforderungen
durch den Treiber des USBRX gelesenen Daten werden an den Knoten Analyse und
Demodulation geleitet. Diese verarbeiten die Daten weiter. Der Knoten Demodulation
Abbildung 1.5: Die Beispielkonstellation in Abb. 1.4 wurde umkonguriert, so dass der
Knoten Archivierung nun die Rohdaten direkt vom Treiber des USBRX bezieht.
9
1.3 Gliederung dieser Arbeit
Im ersten Teil (Kapitel 2) werden die Grundlagen, insbesondere der Aufbau des Funkemp-
fängers, behandelt. Die Erklärung des I/QFormats ist hauptsächlich als Hintergrundin-
formation zu verstehen, da dieses bei der Implementierung selbst keine Rolle spielt.
Kapitel 3 beschreibt die Realisierung der erforderlichen Firmware für das USBGerät. Da-
bei wird genauer auf die Arbeitsweise und den Aufbau eingegangen. Der mit der Firmware
eng verbundene Treiber wird in Kapitel 4 behandelt und wird zunächst in Funktionsweise
und Aufbau beschrieben. Abschlieÿend werden verschiedene Tests zur Verizierung der
Anforderungen behandelt.
Der letzte Teil dieser Arbeit (Kapitel 5) befasst sich mit der implementierten Verteilungs-
schicht, die zum Austausch der Daten zwischen Anwendungen entwickelt wurde. Darin
wird neben dem Aufbau auch die Performance der Implementierung beleuchtet und auf
10
Kapitel 2
Grundlagen
Dieser Abschnitt behandelt die Grundlagen, die im Zusammenhang mit der verwendeten
Hardware und dem Format der durch diese Hardware gewonnenen Daten stehen. Diese
Informationen sind zum Verständnis dieser Arbeit zwar nicht zwingend notwendig, jedoch
sehr hilfreich.
Das Gerät USBRX, für das die Bibliotheken erstellt werden sollen, ist als EinPlatinen
Lösung in SMDTechnologie gefertigt, welche alles beinhaltet, was für eine direkte Di-
gitalisierung von Funksignalen an einer Antenne notwendig ist. Abbildung 2.1 zeigt die
fertig bestückte Platine in der Draufsicht. Dem Blockschaltbild in Abbildung 2.2 sind
beschrieben werden. Das Gerät ist eine Neuentwicklung und vergleichbar mit dem als
Peripheral [9]).
2.1.1 HF-Teil
Der HFTeil besteht gröÿtenteils aus passiven Bauteilen. Hier wird das Eingangssignal
tern. Dieser AAF ist notwendig, da durch die im nächsten Teil folgende AnalogDigital
11
2.1 Aufbau der Hardware
12
2.1 Aufbau der Hardware
signal überlappen würden und dadurch ein unbrauchbares oder sehr störbelastetes Signal
Weiterhin benden sich in diesem Bereich HalbleiterAnalogschalter, mit denen durch die
Bedienanwendung das Quellsignal aus mehreren Eingängen gewählt werden kann. So ist
2.1.2 Digitalisierungsteil
Das vorgelterte HFSignal wird durch einen AnalogDigitalConverter (ADC), der mit
bis zu 100 Mio. Abtastungen pro Sekunde arbeitet, in ein Digitalsignal konvertiert. Dazu
wird zu jedem Abtastzeitpunkt der Pegel des Eingangssignals erfasst und als vorzeichen-
behafteter, binär kodierter Wert auf den Ausgängen des ICs zur Verfügung gestellt.
Der auf dieser Platine verbaute ADC arbeitet je nach Bestückung fest auf den Frequenzen
48, 96 oder 100 MHz. Somit können im ankommenden TiefpassSignal je nach Taktfre-
quenz des ADC die Frequenzen von 0 Hz bis 24, 48 oder 50 MHz digitalisiert werden. Eine
Erklärung dazu bietet das Abtasttheorem von Shannon, welches in [1, S. 926] ausführlich
beschrieben wird.
Das Ausgangssignal des ADC ist ein 14 Bit breites Datum im Zweierkomplement und wird
beinhaltet alle Informationen über das Funksignal, die für eine Darstellung und Deko-
dierung am Rechner notwendig wären; jedoch ist es mit einer Datenrate von bis zu 1,4
GBit/s zu hochratig, um es in dieser Form über die USB 2.0 Schnittstelle zu übertragen.
Aus diesem Grund wurde ein Digital Down Converter (DDC) verbaut, der das digitalisier-
5
te Eingangssignal zunächst in das Basisband herabsetzt und danach in seiner Bandbreite
begrenzt. Zur Begrenzung der Bandbreite werden in diesem Baustein digitale FIRFilter
5 Ein Quellsignal, welches nicht durch Modulation in einen höheren Frequenzbereich verschoben vor-
liegt, bendet sich im Basisband.
13
2.1 Aufbau der Hardware
eingesetzt, die über ein SPIInterface frei kongurierbar sind. Somit kann auf der Bedie-
nerseite eingestellt werden, in welchem Frequenzbereich ein Signal mit welcher Bandbreite
herausgeltert werden soll. Die Ausgabe dieses Signals erfolgt im I/QFormat, welches ne-
Das Funksignal im I/QFormat (siehe Abschnitt 2.2) benötigt 32 Bit je Sample, wovon
sowohl der IAnteil als auch der QAnteil jeweils 16 Bit belegen. Die Datenrate dieses
Signals ist von der Breite des Filters im Digital Down Converter abhängig. Eine nähere
Erläuterung den Aufbau dieses Formats betreend, ist in ebenfalls in Abschnitt 2.2 zu
nden.
2.1.4 Datentransfer
Das vom Digital Down Converter erzeugte, digitalisierte I/QSignal wird über den USB
Bus zur verarbeitenden Anwendung geleitet. Dazu schreibt dieser die Daten mit seiner
ArbeitsDatenrate in einen FIFO, der 64 KiWörter mit bis zu 18 Bit Breite fasst. Um
dennoch die 32 Bit des I/QSignals übertragen zu können, werden I und QAnteil ge-
trennt voneinander alternierend mit 16 Bit Breite in den FIFO geschrieben. Somit kann
Durch einen speziellen USB Interface Chip werden die Daten wieder aus dem FIFO gele-
sen. Bei diesem Interface Chip handelt es sich um einen Cypress EZUSB FX2LP, einem
USB 2.0 HighSpeed Interface Controller. Er unterstützt alle in der USBSpezikation [25,
2
Abschnitt 4.7, S. 20] denierten Transfermodi und bietet neben I C, SPI und frei program-
mierbaren Ein und Ausgängen ein GPIF ( General Purpose Interface ), welches Daten
selbständig und ohne Software-Interaktion aus dem FIFOBaustein lesen und direkt über
USBPakete an den Host weiterleiten kann. Die Konguration des FX2LP wird durch die
Die USBseitige Datenübertragung mit dem FX2LP wird durch das USB Interface über
sogenannte Endpoints (EP) abgewickelt. Während der Initialisierung durch die Firmware
können bis zu 5 benutzerdenierte Endpoints festgelegt werden, die Daten im Bulk, Inter-
rupt oder Isochronous Modus entweder senden oder empfangen können. So können neben
dem Endpoint, über den automatisiert die I/QDaten übertragen werden, auch weitere
eingerichtet werden, über die eine Anwendung Befehle an den FX2LP sendet und Antwor-
ten dazu empfängt. Der Eingang eines Datenpaketes über Endpoints wird der Firmware
14
2.2 Das I/QFormat
2.1.5 Steuerung
Aufgrund der begrenzten Zahl an Ein/Ausgängen des FX2LP wurde zusätzlich ein Atmel
2
ATMega32 verbaut, der über I C angesprochen wird. Seine Aufgaben sind:
Diese Aufgaben werden durch eine Firmware erledigt, die im FlashSpeicher des ATMega32
gespeichert ist. Diese Firmware wurde durch Herrn Graÿ erstellt und ist nicht Teil dieser
2
Arbeit. Die Ansteuerung des I CBusses soll durch den FX2LP vorgenommen werden, die
Kommandos dazu werden jedoch unverändert von dessen Firmware durchgereicht. Somit
2
ist im FX2LP neben der notwendigen Logik, um als I C Bus Master zu arbeiten, nichts
weiter erforderlich.
Dieser Abschnitt geht genauer auf das Datenformat ein, welches ab der Digital Down
Mathematische Bedeutung
Die Modulation von Nutzdaten mit einer Trägerfrequenz kann allgemein mit folgender
Das dabei entstehende Trägersignal s(t) besitzt die Amplitude a(t) und die Frequenz ω(t)
mit dem Phasenwinkel ϕ(t). Sowohl Frequenz und Phasenwinkel als auch die Amplitude
eine sich ändernde Frequenz ω(t) auch durch einen sich kontinuierlich ändernden Phasen-
winkel ϕ(t) dargestellt werden kann, wird der Übersicht wegen ω(t) weiter nur noch als ω
bezeichnet. Die sich verändernde Frequenz wird daher durch ϕ(t) repräsentiert.
15
2.2 Das I/QFormat
Betrachtet man die Erläuterung zur physikalischen Bedeutung in [4, S. 183], lässt sich
i(t)
p
mit der Amplitude a(t) = i(t)2 + q(t)2 und dem Phasenwinkel tan(ϕ(t)) = − q(t) . Die
Variable i(t) wird weiterhin als In Phase oder kurz IAnteil und q(t) als Quadrature
Phase bzw. QAnteil bezeichnet. Beide Variablen sind unabhängig voneinander. Diese
Form der Darstellung ndet vor allem in der digitalen Signalverarbeitung ihre Anwendung.
Abbildung 2.3 veranschaulicht den Vorgang der Modulation. Die Multiplikation wird in
diesem Schaltbild durch einen Mischer repräsentiert, die Addition durch den Addierer.
Die Signale cos(ωt) und sin(ωt) dienen bei der Modulation als Träger.
Das durch die Modulation entstandene Trägersignal s(t) kann nun über ein geeignetes
Medium wie z. B. in Form elektromagnetischer Wellen durch die Luft übertragen und da-
nach einem Demodulator zur Rückgewinnung zugeführt werden. Bei der Rückgewinnung
der I und QAnteile wird das Trägersignal wie in Abbildung 2.4 skizziert mit den glei-
16
2.2 Das I/QFormat
1
cos(a) · cos(b) = 2
cos(a − b) + cos(a + b)
1
cos(a) · sin(b) = 2
sin(a − b) + sin(a + b) (2.4)
1
sin(a) · sin(b) = 2
cos(a − b) − cos(a + b)
entstehen nach dem Einsetzen der Gleichung 2.2 in die Gleichungen 2.3 und Umformen
die Gleichungen:
0
i (t) = 2 · i(t) · 12 · cos(0) + cos(2 · ωt)
+q(t) · 12 · sin(0) + sin(2 · ωt)
(2.5)
q 0 (t) = 2 · i(t) · 12 · sin(0) + sin(2 · ωt)
1
−q(t) · 2 · cos(0) − cos(2 · ωt)
Ersetzt man in diesen Gleichungen sin(0) durch den Wert 0 und cos(0) durch den Wert
In Gleichung 2.6 ist zu erkennen, dass noch immer ein unerwünschter Anteil mit dem
Doppelten der Trägerfrequenz (cos(2 · ωt), sin(2 · ωt)) vorhanden ist. Dieser kann lediglich
mit Hilfe eines idealen Tiefpasses mit der Grenzfrequenz fGrenz < 2 · ω herausgeltert
werden. Nach der Tiefpasslterung fällt dieser Anteil weg und es gilt:
i0 (t) = i(t)
(2.7)
q 0 (t) = q(t)
Die Abbildung 2.4 stellt die Demodulation und die Tiefpasslterung noch einmal schema-
tisch dar.
Das bedeutet, obwohl sowohl i(t) als auch q(t) in dem Trägersignal s(t) übertragen wur-
den, können diese bei der Demodulation korrekt zurückgewonnen werden. Somit sind die
beiden zurückgewonnenen Anteile i0 (t) und q 0 (t) ebenso orthogonal zueinander. Da die I
und QAnteile orthogonal zueinander sind, können sie auch in einem sog. Konstellations-
Die Repräsentation eines Trägersignals durch die Komponenten I und Q ist die Basis für
viele digitale Modulationsverfahren. Aber auch analoge Modulationen wie die Amplitu-
17
2.2 Das I/QFormat
S. 573]
18
2.2 Das I/QFormat
denmodulation oder die Frequenz bzw. Phasenmodulation können durch dieses Format
Digitale Repräsentation
Wie bereits eingangs erwähnt wurde, liefert der DDC die I und QAnteile mit einer
Auösung von je 16 Bit, also mit einer Breite von 32 Bit je Sample. Im weiteren Ver-
arbeitungspfad (FIFO, FX2LP) ist es nicht möglich, die Samples mit der vollen Breite
von 32 Bit zu übertragen. Aus diesem Grund wurde eine Schaltung verbaut, welche die
dung 2.6 illustriert, in welcher Reihenfolge die Samples bzw. deren Anteile in den FIFO
geschrieben werden. Eine weitere Hardwareschaltung stellt sicher, dass auch nach einem
Reset des FIFO die Reihenfolge I, Q, I, Q, . . . eingehalten wird. Ein Vertauschen von I und
Die Werte der beiden Komponenten werden im Zweierkomplement dargestellt und decken
demnach einen Wertebereich von -32768 bis +32767 ab. Diese Werte beziehen sich auf eine
Referenzspannung im Digitalisierungsteil des Gerätes, auf die hier nicht näher eingegangen
wird.
19
Kapitel 3
Firmware
Dieses Kapitel befasst sich mit den Aufgaben und dem Aufbau der Firmware für den
Cypress. Dieser Controller ist für die Kommunikation zwischen der Rechnerseite und der
Hardware zuständig und ist so kongurierbar, dass er die meisten Transfers autonom
durchführen kann. Dazu bietet der FX2LP mehrere Funktionsblöcke, die aufeinander ab-
gestimmt sind. Abbildung 3.1 zeigt den Aufbau des Controllers in einem Blockschaltbild.
Die im Controller integrierte SIE ( Serial Interface Engine ) und das USBInterface sind
senden. Sie müssen dazu jedoch zuerst konguriert werden - ohne vorherige Konguration
stellen sie nur den von der USBSpezikation geforderten Control Endpoint 0 (EP0) zur
Verfügung, über den automatisch nach dem Anstecken des Gerätes die USBKonguration
vorgenommen wird. Der Endpoint 0 bietet jedoch dem Treiber die Möglichkeit durch spe-
20
3.1 Was sie leistet
6
zielle Vendor Commands die Firmware in den Speicher des FX2LP zu laden und zur
2
• Zugri auf I C, SPI und I/Os über spezielle Befehle
3.1.1 Initialisierung
Während der Initialisierung müssen der Prozessor und die verwendeten Variablen und
Speicherbereiche in einen denierten Zustand gebracht werden. Dies muss von der Firm-
ware im ersten Schritt erledigt werden, um eine lauähige Umgebung für den weiteren
Code vorzubereiten. Weiter ist es die Aufgabe der Firmware, den FX2LP zunächst so
zu kongurieren, dass sich dieser in einem Leerlaufzustand bendet und auf weitere Be-
Reset Vector
Der im FX2LP integrierte 8051kompatible Prozessorkern wird nach dem Anstecken der
Hardware an den USBBus und dem Download der Firmware in einen denierten Zu-
0x0000(hex). Da sich an dieser Stelle nur Platz für einen 3 Byte groÿen Sprungbefehl
ndet [5, S. 4-1], muss dort ein Sprungbefehl zum eigentlichen Initialisierungscode stehen.
Der folgende Auszug aus der Datei 'interrupts.asm' zeigt den Code am Reset Vector:
6 Diese werden in [25, Abschnitt 9.3.1, S. 248] explizit erlaubt. Abbildung 3.4 listet die im Controller
vergebenen Vendor Commands auf.
21
3.1 Was sie leistet
Wie dem CodeBeispiel zu entnehmen ist, springt der 8051Kern durch die Ausführung
des LJMPBefehls zur Adresse 0x0380(hex), an welcher sich der Programmcode zur
Speicherinitialisierung
füllt den Speicherbereich statischer und globalen Variablen mit ihren Startwerten, initia-
lisiert den StackPointer und bereitet weitere Register der CPU auf die Ausführung der
dung initialisiert wurden, springt die Initialisierungsroutine zur mainRoutine, in der die
Der Code zur Speicherinitialisierung wird von der verwendeten Compilersuite automa-
tisch erzeugt und erfordert keine manuellen Änderungen. Die Speicherbereiche und deren
Inhalt werden während des LinkVorganges auf der Grundlage der durch den CCompiler
Peripherie
Zu Beginn der Hauptroutine main() muss zunächst die ausstehende Initialisierung der
beim FX2LP sämtliche USBrelevanten Tätigkeiten ausgelagert wurden. So ist die 8051
CPU von sämtlichen Aktivitäten auf dem USBBus entkoppelt und übernimmt lediglich
steuernde Aufgaben. Über einen gemeinsam Speicherbereich, spezielle Register und In-
terrupts kann die Firmware jedoch auch auf eingehende Pakete reagieren und selbst das
kation. Es hat bei der Anmeldung des Geräts am Bus dem HostRechner lediglich den
22
3.1 Was sie leistet
Endpoint 0 bekannt gemacht. Eine einfache Nachmeldung von weiteren Endpoints ist
zum Ausführungszeitpunkt der Firmware nicht mehr möglich. Jedoch bietet der Cypress
FX2LP eine Möglichkeit, das Gerät logisch vom Bus zu trennen und neu zu verbinden.
7
Cypress bezeichnet diesen Vorgang als ReNumeration . So ndet eine Neuanmeldung des
Um mit Hilfe dieser Möglichkeit weitere Endpoints zu registrieren, müssen die bei einer
Cypress FX2LP bietet jedoch Hilfsmittel, die den FirmwareEntwicklern diesen Vorgang
erleichtern.
einen SUDAVInterrupt aus. Abbildung 3.2 veranschaulicht dies. Das Format des Setup
Pakets ist in der USB 2.0 Spezikation festgelegt und der Abbildung 3.3 zu entnehmen.
Je nach RequestCode muss die Firmware nun die entsprechenden Aktionen durchführen
bzw. die erwarteten Deskriptoren zur Verfügung stellen. Abbildung 3.4 zeigt eine ausführ-
liche Liste der denierten Requests und den erwarteten Aktionen der Firmware.
das USBInterface mit den Registern SUDPTRH und SUDPTRL (Setup Data Pointer
High/Low) eine Schnittstelle, in die lediglich die Speicheradresse des zu sendenden De-
skriptors geschrieben werden müssen. Nachdem diese Register beschrieben wurden, schickt
das USBInterface die Deskriptoren automatisch im korrekten Format an den Host. Die
8
Anzahl der zu sendenden Bytes wird den Deskriptoren selbst entnommen .
Auf diese Art und Weise kann der komplette Enumerationsvorgang (SETUPPhase)
mit Hilfe eines einfachen switch/case Blockes innerhalb des Handlers für den SUDAV
Deskriptoren: Die USBSpezikation ermöglicht es, dass einem USBGerät eine Viel-
zahl von logischen Kongurationen zugewiesen werden. Diese Informationen werden dem
Host bei der Anmeldung des Gerätes am Bus durch Deskriptoren mitgeteilt. Der Host kann
das Gerät dann während des Betriebs anweisen, zwischen den verschiedenen angebotenen
Kongurationen umzuschalten. Auf diese Weise ist es möglich, dass ein Treiber ein Gerät
23
3.1 Was sie leistet
24
3.1 Was sie leistet
Gerätes [5]
AlternativSetups. Für dieses Projekt ist es jedoch ausreichend, eine einzige Konguration
Weiter werden dem Host in den Deskriptoren durch spezielle Vendor und Product
IDs zudem mitgeteilt, von welchem Hersteller und welchem Typ das Gerät ist. Anhand
dieser Informationen kann ein Treiber feststellen, ob er für dieses Gerät zuständig ist.
Zum Zeitpunkt der Erstellung dieser Firmware wurden noch keine eigenen IDs für dieses
Gerät erworben. Deswegen wurden zunächst die Vendor ID des Hersteller Cypress und
eine unbelegte Product ID verwendet. Diese können und müssen im Nachhinein durch das
25
3.1 Was sie leistet
Bezeichner Richtung
IN Transfer vom Gerät zum Host
Bei der Transferrichtung zwischen einem USBHost und einem Endgerät spricht die USB
Spezikation von IN und OUT Transfers (siehe Tabelle 3.1.1). Die Transferrichtung ist
immer aus der Sicht des HostRechners zu sehen und wurde daher unmissverständlich
Um eine logische Trennung zwischen den Kommandos an die Firmware bzw. Antworten
auf diese und den Signaldaten aus dem Digitalisierungsteil zu realisieren, werden zwei
auf abgewickelt. Sowohl die Rate als auch die Gröÿe der Pakete sind sehr gering,
OUT).
Host (Transferrichtung IN). Dieser Kanal ist unidirektional, da nur Daten vom Gerät
an den Host übertragen werden, muss aber mit sehr hohen Datenraten zurechtkom-
men.
Als geeigneter Kontrollkanal bietet sich der lowbandwidth Endpoint 1 an. Dieser un-
terstützt zwar lediglich Transfers mit einer Gröÿe von maximal 64 Byte, was aber für die
Kommandos in Tabelle 1.1 auf Seite 7 vollkommen ausreicht. Von diesen zu implemen-
2
tierenden Kommandos besitzen lediglich die I C und SPIKommandos eine Payload mit
variabler Gröÿe. Die Bedienanwendung schickt diese Kommandos aber nur mit maximal
9
8 Byte Nutzdaten (zzgl. Overhead) und ist somit deutlich unter der 64ByteGrenze.
Dieser Endpoint ist speziell für Kontrollkanäle ausgelegt und teilt sich keine Ressourcen
Beim Datenkanal ist die Wahl des korrekten Endpoints im Gerät ebenfalls sehr einfach.
Durch die externe Beschaltung des FX2LP ist vorgegeben, dass die aus dem externen FIFO
9 Dies wurde durch einen Blick auf den Quellcode der Anwendung ermittelt
26
3.1 Was sie leistet
gelesenen Daten in den Puer des Endpoint 6 geschrieben werden. Dies wird durch die
auch bei neueren Layouts beibehalten. Deshalb ist der Endpoint 6 als Datenkanal zu
verwenden.
Für die Wahl der passenden PuerKonguration muss auf Abbildung 3.6 aus dem Tech-
nical Reference Manual [5] verwiesen werden. In dieser Abbildung sind die im FX2LP
bandwidth Endpoints sind zunächst die Endpoints 2, 4, 6 und 8 mit zwei Puern zu je
512 Byte (double buered). Werden die Endpoints 2 oder 6 so konguriert, dass sie vier
Puer (quad buered) zu je 512 Byte oder zwei zu je 1024 Byte besitzen, so sind EP4
bzw. EP8 nicht mehr verfügbar. Weiterhin ist es auch möglich, einem einzigen Endpoint
(EP2) vier Puer mit je 1024 Byte zuzuweisen, oder gemischte Kongurationen, bei de-
nen drei Puer (triple buered) zum Einsatz kommen. Die Endpoints 0 und 1 sind nicht
Bei diesem Projekt wurde sich für die QuadbuerVariante mit vier 512 Byte Puern
entschieden. Aus Performancegründen schied eine Variante mit zwei Puern aus, da erst
ab drei Puern eine Übertragung ohne Wartezyklen gewährleistet ist. Bei zwei Puern
muss gewartet werden, bis ein Puer voll und der andere Puer leer ist, bevor diese beiden
Puer getauscht werden können (Wechselpuertechnik). Dies könnte beim Transfer mit
höheren Datenraten zu unnötigen Verzögerungen führen. Demnach stehen für den EP6
nur die Kongurationen 4x512 und 3x512 zur Wahl. Da jedoch die letzte Variante das
Setup aller anderen Endpoints vorschreiben würde und lediglich die Variante 4x512 noch
genug Freiraum für zukünftige Erweiterungen bietet, wurde sich für diese entschieden.
Für beide Endpoints wird der BulkTransfermodus verwendet. Dieser Transfermodus ist
für groÿe Datenmengen ausgelegt und stellt sicher, dass keine Daten verloren gehen. Bei
einem Übertragungsfehler wird das fehlerhafte Paket bis zu drei mal wiederholt. Der
ebenfalls für groÿe Datenmengen ausgelegte Isochrone Modus dagegen stellt zwar eine
feste Bandbreite zur Verfügung die auch bei hoher Buslast garantiert wird, verwirft aber
fehlerhafte Pakete. Beide Modi erlauben es, mit Datenraten von 53.248.000 Byte/s (Bulk
Modus [25, S. 55]) beziehungsweise 49.152.000 Byte/s (Isochroner Modus [25, S. 46]) zu
Da jedoch bei beiden Endpoints die Datensicherheit im Vordergrund steht, ist der Bulk
dieser nur für sporadisch anfallende Daten wie z. B. bei Computermäusen oder Tastaturen
ausgelegt ist.
27
3.1 Was sie leistet
Überlegt wurde, den Kontrollkanal über den Control Endpoint 0 abzuwickeln. Laut Ab-
bildung 3.4 stehen dafür frei belegbare Vendor Request Codes zur Verfügung. Jedoch
erschien es sinnvoll, diesen Kontrollkanal logisch von dem für das USBSetup wichtigen
Commands birgt zum einen ein zu groÿes Risiko hinsichtlich Konikte durch Änderungen
bzw. Erweiterung der Anforderungen und nutzt zum anderen nicht die durch den FX2LP
In Tabelle 3.1.1 ist die gewählte Konguration noch einmal übersichtlich dargestellt. Ent-
sprechend dieser Tabelle werden die Kongurationsregister des USBInterface und die
USBDeskriptoren gewählt.
28
3.1 Was sie leistet
3.1.2 InterruptHandling
Wie nahezu jedes MikrocontrollerSystem besitzt auch der Cypress FX2LP eine Vielzahl
an InterruptQuellen. Bei der Realisierung dieses Projektes werden nur die notwendig-
sten Arbeiten über Interrupts erledigt. Die folgenden Interrupts sind in dieser Arbeit zu
behandeln:
• USB SetupInterrupt
• KontrollkanalInterrupt
USB SetupInterrupt: Wie in Abschnitt 3.1.1 angesprochen, treten bei der ReNume-
ration also der Neuanmeldung des Geräts am USBBus Interrupts auf. Der zugehörige
den Daten mitzuteilen. Bei der weiteren Verwendung des Gerätes treten keine Interrupts
löst das USBInterface einen EP1OUTInterrupt aus. Dieser muss durch eine geeignete In-
terrupt Service Routine bedient werden. Beim Auftreten eines solchen Interrupts durch ein
eingehendes Kommando, trägt der Handler dieses Kommando ungeprüft in einen Puer
zur asynchronen Weiterverarbeitung durch die Hauptschleife ein. Eine sofortige Verarbei-
tung des Kommandos im Handler würde die Ausführung der Hauptschleife u.U. zu einem
ungünstigen Zeitpunkt unterbrechen oder andere Interrupts verzögern, daher ist dieser
möglichst kurz zu halten. Eine Überprüfung der Gültigkeit der Kommandos wäre an die-
ser Stelle zwar möglich, würde aber bedeuten, dass neue Kommandos an mehreren Stellen
Aus diesem Grund wird die Überprüfung und die Abarbeitung der eingegangenen Kom-
mandos asynchron durch die Hauptschleife erledigt. Dies birgt keine besonderen Risiken,
29
3.1 Was sie leistet
GPIF Transfer Interrupt: Wird der GPIFBlock angewiesen, eine bestimmte An-
zahl von Transfers durchzuführen, erledigt er diese Arbeit unabhängig von der Firmware.
Nachdem dieser alle Transfers abgeschlossen hat, löst er einen GPIFDONEInterrupt aus,
um dies der Firmware mitzuteilen. An dieser Stelle muss der InterruptHandler die im
der aktuellen Version dieser Arbeit wird dies jedoch noch durch Polling innerhalb der
an, den Timer als sog. Watchdog zur Überwachung der Vorgänge zu verwenden. Tritt
ein erwartetes Ereignis nicht innerhalb einer dafür vorgesehenen Zeitspanne ein, kann
eine ReNumeration auslösen, um das Gerät neu am Bus zu registrieren. Zu beachten wäre
allerdings, dass ein Problem dieser Art in der Regel auf Fehler in der Programmierung zu-
rückzuführen ist. Daher wurde sich bei dieser Arbeit mehr darauf konzentriert, Fehlerfälle
3.1.3 Kommandos
Eine Aufgabe der Firmware ist es, Kommandos, die von der Bedienanwendung über den
Wie im Abschnitt 3.1.2 erläutert, werden die Befehle durch den InterruptHandler in einen
Kommandopuer geschrieben. Die vom Treiber über ein USBPaket empfangenen Kom-
mandopakete bestehen aus einem Byte KommandoID gefolgt von einer variablen Anzahl
Datenbytes (siehe Abbildung 3.7). Um auch bei einem unbekannten oder fehlerhaften
Sollte bei der Weiterverarbeitung durch die Hauptschleife ein ungültiges Kommando er-
kannt werden, kann dieses so ignoriert und anhand dessen Längeneintrag weiter zum
Auf aufwändige Sperrmechanismen oder einen umständlichen Ringpuer kann bei ge-
eigneter Wahl des Puerzugris verzichtet werden. Da nur die Hauptschleife durch den
Interrupthandler unterbrochen werden kann, muss nur sichergestellt werden, dass keine
nichtatomaren Vorgänge durch den InterruptHandler beeinusst werden. Dazu wird die
30
3.1 Was sie leistet
Abbildung 3.7: a) Kommandopaket, wie es über den USBBus empfangen wird b) Kom-
Position des Kommandos im Puer ähnlich wie bei einem Ringpuer mittels Start und
EndeZeiger angezeigt. Da jedoch beide Zeiger nach vollendeter Abarbeitung aller und vor
dem Eintragen eines neuen Kommandos auf den Anfang des Puers zurückgesetzt wer-
den, stehen die Daten immer am Anfang des Puers. Sollte der EndeZeiger beim Eingang
eines neuen Kommandos über das Ende des Puers hinausgehen, wird das Kommando
verworfen.
Der entscheidende Vorteil dieser Puerart gegenüber einem Ringpuer ist die Einsparung
eines zusätzlichen Puers für den Fall, dass das Kommando im Puer umgebrochen wurde.
Mit dieser Puerart kann der behandelnden Kommandoroutine direkt die Adresse der Da-
ten im Puer übergeben werden. Der Nachteil ist allerdings, dass bei einer groÿen Anzahl
an eingehenden Kommandos der Hauptschleife diese nicht mehr schnell genug abarbeiten
kann. Dieses Risiko ist leicht zu umgehen, indem der Treiber lediglich wenige Kommandos
schickt und dann auf eine Antwort wartet, dass diese Kommandos abgearbeitet wurden.
• InterruptHandler
1. setzt Anfangs und EndeZeiger auf Null, sollten sie gleich sein. So wird bei
einem leeren Puer das nächste Kommandopaket immer an den Anfang des
Puers geschrieben.
den Puer.
31
3.1 Was sie leistet
• Hauptschleife
1. wartet bis Anfangs und EndeZeiger ungleich sind, als Indikator für ein vor-
handenes Kommando.
Da der InterruptHandler beim Zufügen eines Kommandos nur den EndeZeiger des Puf-
fers verändert, nicht aber die bereits im Puer stehenden Kommandos und damit das
Längenbyte des momentan abgearbeiteten Kommandos, sind alle Operationen der Haupt-
schleife sicher. Der Sonderfall im InterruptHandler wenn Start und Ende gleich sind,
beide Zeiger auf Null gesetzt werden, setzt voraus, dass die Hauptschleife zu diesem Zeit-
punkt nichts abarbeitet. Diese wartet darauf, dass beide Zeiger ungleich sind bevor sie
mit dem Abarbeiten des Kommandos beginnt. Da die Ausführung des InterruptHandlers
nicht durch die Hauptschleife unterbrochen wird, sind dessen Operationen grundsätzlich
Die Befüllung und Abarbeitung von Kommandos im Puer wird in Abbildung 3.8 noch
Nachdem ein Kommando abgearbeitet wurde, schickt die Firmware ein Paket mit der
KommandoID zurück. So kann auf der Treiberseite sichergestellt werden, dass dieses
32
3.1 Was sie leistet
Kommando Beschreibung
CMD_GET_MODE Lese aktuellen Betriebsmodus
Kommando auch abgearbeitet wurde. Handelt es sich um ein Kommando, das Antwort-
Auf diese Art und Weise kann der Treiber eine Kombination mehrerer Kommandos ge-
bündelt an die Firmware schicken und auf die Abarbeitung dieser warten.
Tabelle 3.3 listet die entsprechend Tabelle 1.1 implementierten Kommandos auf. Diese
3.1.4 Nutzdatentransfer
Der Transfer der Daten aus dem FIFOBaustein der Platine über den USBBus zum
Treiber ist die Hauptaufgabe dieses Gerätes. Diese Aufgabe wird im Wesentlichen autonom
durch die in Abbildung 3.1 dargestellten Blöcke GPIF ( General Purpose Interface ) und
dem USB Interface erledigt. An dieser Stelle muss jedoch der Begri FIFO noch einmal
FIFO bezeichnet. Dessen Aufgabe ist es, die vom DDC eintreenden Daten zu puern
33
3.1 Was sie leistet
Innerhalb des Cypress FX2LP gibt es aber noch eine weitere Art von FIFO. Das USB
Interface im FX2LP stellt dem GPIFBlock Puer zur Verfügung, in die dieser Daten
schreiben kann. Wie in Abschnitt 3.1.1 erklärt, werden mehrere dieser Puer in dieser
Konguration 4 Puer zu je 512 Byte zusammengeschalten und als Puer für einen
Endpoint verwendet. Der GPIFBaustein kann zu einem Zeitpunkt nur immer auf den
Puer zugreifen, den das USBInterface zum Füllen markiert hat. Zu diesem Zweck imple-
mentiert das USBInterface eine Art FIFOBaustein, in den der GPIFBlock die Daten
schreibt. Dieser interne FIFO wird im Weiteren als Endpoint FIFO (in [5] u. A. auch
Dieser Endpoint FIFO ist vom Prinzip her vergleichbar mit dem externen FIFOBaustein.
Jedoch werden die hineingeschriebenen Daten nicht von einer anderen Schaltung ausge-
lesen, sondern durch das USBInterface automatisch über den USBBus an den Host
geschickt, sobald dieser Daten anfordert. Die Firmware muss lediglich den GPIF so kon-
gurieren, dass dieser selbständig eine bestimmte Anzahl an Transfers aus dem externen
FIFO an die Endpoint FIFOs schreibt. Dabei beachtet er selbst die entsprechenden Signale
Die Konguration des GPIF wird über eine Vielzahl von Registern vorgenommen, über
die Taktrate, I/OLeitungen und die Waveform die Vorgehensweise beim Auslesen des
externen FIFO festgelegt werden. Dies ist sehr komplex, wird aber durch das Tool
Cypress GPIF Designer erleichtert, welches dem Entwickler ein graphisches Interface
zur Konguration anbietet und auf Knopfdruck fertigen CCode zur Einbettung in das
eigene Projekt erstellt. Abbildung 3.9 zeigt einen Screenshot dieser Anwendung. Die in
dieser Arbeit verwendete Konguration wurde im Vorfeld von Herrn Graÿ erstellt und für
Die durch das Tool erzeugte Konguration wird bei jedem Wechsel in einen GPIFModus,
also sowohl beim kontinuierlichen Transfermodus als auch beim Blocktransfermodus, ak-
tiviert. Die Anzahl der durchzuführenden Transaktionen wird über ein weiteres Register
angegeben. Im Blocktransfermodus ist demnach die von der Firmware angeforderte An-
muss die Firmware entsprechend der Anforderungen wieder in den IdleModus wechseln.
Beim kontinuierlichen Transfermodus kann in dieses Register ein beliebiger Wert geschrie-
ben werden es ist nur sicherzustellen, dass nach Durchführung aller Transaktionen dieses
Register erneut beschrieben wird. So wird den Anforderungen entsprechend eine durch-
34
3.1 Was sie leistet
35
3.2 Aufbau
3.2 Aufbau
Die Firmware ist zum gröÿten Teil in C programmiert. Lediglich die InterruptVektoren
programmiert. Abbildung 3.10 zeigt die Quelldateien gruppiert nach Aufgaben und Typ.
• interrupts.c handelt die eingegangen Interrupts ab, erledigt die in Abschnitt 3.1.1
beschriebene USBSetupBehandlung und das Einreihen der Kommandos in den
Kommandopuer
nen
Diese Dateien werden mittels eines Makele und dem Small Devices C Compiler [21]
zu einer .hexDatei kompiliert. Aus dieser .hexDatei werden durch ein spezielles Tool
CStrukturen generiert, die später in einen Treiber eincompiliert werden können. Ins-
besondere für die InterruptAbwicklung dient ein Demoprojekt von Nathan Friess und
36
Kapitel 4
Treiber
Dieses Kapitel behandelt den Treiber für das Gerät USBRX, durch den ein Zugri auf
die Funktionen des Gerätes vereinfacht werden. Bei diesem Treiber handelt es sich um eine
Treiber-Bibliothek für den UserSpace, die nur geladen wird, wenn die Bedienanwendung
dies anfordert. Das kann schon beim Laden der Bedienanwendung in den Speicher durch
10
das Betriebssystem erfolgen , oder aber während der Laufzeit durch spezielle Betriebs-
11
systemfunktionen .
Programmcode, der im UserSpace läuft hat keine Berechtigung, um direkt auf Hardware
arbeiten und automatisch durch das Betriebssystem geladen werden. Ihre Aufgabe ist
es, die aus dem UserSpace angeforderten Zugrie auf die Hardware durchzuführen. Die
Existenz eines passenden KernelModeTreiber für das Gerät USBRX ist aus den ange-
Um aus dem UserSpaceKontext, in dem der Treiber dieser Arbeit ausgeführt wird, auf
die USBHardware zugreifen zu können, wird sich der CyAPIBibliothek bedient. Die-
12
se stellt der Hersteller des Cypress FX2LP kostenlos zur Verfügung und besteht aus
10 Durch dynamisches Linken der Anwendung gegen die Treiber-Bibliothek wird später schon beim
Starten der Anwendung die Treiber-Bibliothek in den Speicher geladen.
11 Nachträgliches Laden von Bibliotheken mittels LoadLibrary, siehe [13]
12 Verfügbar als Teil der SuiteUSB [7]
37
4.1 Aufgaben
die CyAPIBibliothek können die Zugrie auf den Cypress FX2LP einfach realisiert wer-
den.
4.1 Aufgaben
2
• Zugri auf Gerätefunktionen wie I C, I/O und SPI
Da dieser Treiber nicht von der USB2.DLL, einer Treiber-Bibliothek eines Drittherstellers,
zu unterscheiden sein soll, muss er auch deren API nachbilden. Beim Design des Treibers
wurde sich aber nicht auf den Aufbau der USB2.DLLAPI gestützt, sondern eine eigene,
interne API deniert, die jedoch alle Möglichkeiten bietet, die das Original auch erlaubt.
Durch speziellen WrapperCode wird die erwartete API nach auÿen hin nachgebildet.
Besonders bei Neuentwicklungen geht man Risiken ein, wenn man das komplette Design
nach der erwarteten API ausrichtet. Spätere Erweiterungen erfordern zudem umständ-
13
liche Hilfsmaÿnahmen , um diese zu realisieren und kompatibel zu bleiben. Deswegen
wurde zunächst ein TreiberKern mit einer eigenen, internen API deniert, mit dem un-
ter anderem die erwartete Funktionalität der USB2.DLL realisiert werden kann. Diese
API ist zunächst nicht nach auÿen sichtbar, sondern nur für speziellen WrapperCode zu-
gänglich. Die Funktionen der USB2.DLL, die nachgebildet werden müssen, werden durch
einen Wrapper realisiert, der die entsprechenden Aufrufe an die interne API weiterreicht.
nen in diesem Wrapper untergebracht werden, ohne dass der TreiberKern durch solche
38
4.1 Aufgaben
Abbildung 4.1: Konzept des TreiberKerns und Wrapper für unterschiedliche Anwen-
dungsszenarien
Abbildung 4.1 veranschaulicht dieses Konzept in einer Grak. Die Bedienanwendung greift
über den USB2.DLL Wrapper auf den TreiberKern zu. Dieser Wrapper kann gegen einen
anderen ausgetauscht werden, um eine neuere API oder eine API für andere Einsatzzwecke
zur Verfügung zu stellen. Der in der Abbildung aufgeführte Java JNIWrapper ermöglicht
Dieser ist nicht Teil der Anforderungen, sondern wurde aus Demonstrationsgründen zu-
sätzlich entwickelt.
Wird im Weiteren von einem Aufruf von Treiberfunktionen oder APIAufrufen geschrie-
ben, handelt es sich - sofern nicht anders angegeben - dabei um einen Aufruf der API
4.1.2 Initialisierung
Beim Start der Bedienanwendung fordert diese den Treiber durch den Aufruf der Treiber-
funktionen UsbOpen() und UsbInit() auf, ein vorhandenes Gerät zu initialisieren. Bei
diesem Vorgang bezieht der Treiber über die CyAPI eine Liste der angeschlossenen USB
Geräte, iteriert durch diese und überprüft jedes Gerät auf dessen Vendor und Product ID
(siehe Abschnitt 3.1.1). Da zu diesem Zeitpunkt in das neu angesteckte Gerät noch keine
Firmware geladen wurde, sind die durch den Hersteller des FX2LP vorkongurierten IDs
39
4.1 Aufgaben
2
In späteren Revisionen des USBRX wurde ein serielles I CEEPROM verbaut, aus dem
der Cypress FX2LP beim Anmelden an den USBBus die zu verwendenden IDs liest.
So kann sich das Gerät auch ohne Firmware als USBRX zu erkennen geben. Auf diese
Wird ein Gerät gefunden, das die in der Tabelle 4.1.2 angegebenen Vendor und Product
IDs besitzt, wird versucht, dieses zu reservieren. Dieser Reservierungsvorgang ist so ge-
staltet, dass zunächst ein Named Mutex [15], also ein im Betriebssystem durch einen
Namen eindeutig identizierter Mutex, erstellt wird. Der Name dieses Mutex wird von
der im Betriebssystem eindeutigen ID des Ports abgeleitet, an dem das USBGerät an-
geschlossen ist. Die Existenz dieses Mutex bedeutet, dass das Gerät an diesem USBPort
bereits durch eine Instanz des Treibers belegt ist. Teilt das Betriebssystem mit, dass dieser
Mutex bereits vorher existierte, wird der Reservierungsvorgang abgebrochen und weiter
nach einem freien Gerät gesucht. Dieser Mutex bleibt so lange bestehen, bis der Treiber
das Gerät wieder freigibt. Auf diese Art und Weise ist sichergestellt, dass auch mehrere In-
stanzen dieses Treibers parallel laufen können, ohne dass es zu Zugriskonikten kommt.
Das erforderliche Locking wird durch Verwendung des Mutex schon vom Betriebssystem
übernommen.
Ist das gefundene Gerät noch nicht durch eine andere Instanz belegt, wird eine interne
GeräteinfoStruktur für dieses Gerät angelegt, in der sich alle für die weitere Verwen-
dung notwendigen Informationen darüber benden. Dies umfasst neben dem Handle des
14 Durch Verwendung der originalen Vendor und Product IDs des Chipherstellers für ein Endgerät kam
es bereits zu Problemen. Microsoft Windows XP lieferte einen Treiber für einen USB DVBTEmpfänger
mit, der die Standard IDs verwendet. Anwender von Development Boards konnten deswegen nicht mehr
auf dieses zugreifen, da automatisch der falsche Treiber geladen wurde. Siehe dazu auch [2], [24].
40
4.1 Aufgaben
Wird anhand der Product ID erkannt, dass das Gerät noch keine Firmware besitzt, wird
diese über die Vendor Commands des Cypress FX2LP (siehe Abbildung 3.4) in den Spei-
cher des FX2LP geladen und zur Ausführung gebracht. Das Binärabbild der Firmwa-
compiliert. Somit besitzt jede Version des Treibers die Firmware, für die er entwickelt
Wie bereits im Kapitel 3 beschrieben, trennt sich das Gerät bei der FirmwareInitialisierung
vom USBBus und registriert sich neu. Es ist davon auszugehen, dass sich das Gerät dar-
aufhin am selben USBPort wieder anmeldet. Daher wird gewartet, bis das Gerät mit
der entsprechenden Product ID an diesem USBPort wieder verfügbar ist, oder bis ein
Timeout auftritt. Die Dauer bis zu diesem Timeout wurde auf eine Minute festgelegt, da
beim erstmaligen Anmelden des Geräts mit der neuen Product ID das Betriebssystem
nach Treibern sucht, was mehrere Sekunden dauern kann. Tritt ein Timeout auf, werden
alle Strukturen und Handles wieder freigegeben und dies der aufrufenden Routine der
Nachdem das Gerät sich neu angemeldet hat und die in Tabelle 3.1.1 angegebenen End-
points zur Verfügung stellt, werden diese mit Hilfe der CyAPI geönet und die entspre-
chenden Handles dazu in der GeräteinfoStruktur des Treibers eingetragen. Über einen
ben, mit dem diese GeräteinfoStruktur später eindeutig referenziert werden kann. Dies
erlaubt es, mit einer Instanz des Treibers mehrere Geräte zu bedienen, sofern die Bedi-
4.1.3 Gerätefunktionen
Mittels der API des Treibers kann eine Anwendung auf verschiedene Gerätefunktionen
2
zugreifen. Als Gerätefunktionen werden die Zugrie auf den SPI und I CBus bezeichnet,
die Angabe des GeräteHandles, welcher bei der Registrierung zurückgegeben wurde.
Durch diesen Handle kann aus der entsprechenden GeräteinfoStruktur der Kommando
3.3 aufgeführten Kommandos abgesetzt. Der Treiber wartet nach jedem abgesetzten Kom-
mando auf die Mitteilung der Firmware über eine erfolgreiche Ausführung. Handelt es sich
41
4.1 Aufgaben
2
um Kommandos mit Rückgabedaten, wie z. B. dem Lesen vom I CBus, werden diese der
Weitere Tätigkeiten sind bei der Implementierung dieser Gerätefunktionen nicht erforder-
lich.
4.1.4 Datentransfer
Die Hauptaufgabe des Treibers ist es, das vom USBRX digitalisierte Funksignal aus
tragen. Die Bedienanwendung startet die Datenübertragung durch den Aufruf der API
Funktion UsbParIn() und erwartet nach dessen Rücksprung die gelesenen Daten in einen
beim Aufruf angegebenen Puer.
Um Daten vom DatenkanalEndpoint des USBRX zu lesen, müssen mit Hilfe der CyAPI
zunächst Transfers gestartet werden. Die Gröÿe dieser Transfers ist laut USBSpezikation
begrenzt (siehe dazu [25, S. 54]). Ein einzelnes BulkPaket auf dem USBBus kann ma-
ximal 512 Byte Nutzdaten fassen und wird mit anderen Paketen in Transfers gebündelt.
Maximal 13 BulkPakete können bei einer Nutzdatengröÿe von je 512 Byte zu einem
USBTransfer zusammengefasst werden. Demnach ist die maximale Datenmenge, die bei
einem USBTransfer auf einmal übertragen werden kann, auf 6656 Byte begrenzt. Die
teten Übertragungen bei Bedarf mehrere Transfers entsprechend der angeforderten Daten-
immer in Blöcken anzufordern, die einem Vielfachen von 6656 Byte entsprechen. Nur so
kann der Verwaltungsoverhead durch CyAPI, Kernel und USBController gering gehalten
werden.
Der Start von Transfers wird durch den Aufruf der Funktion BeginDataXfer() des ent-
werden. Nachdem ein Transfer gestartet wurde, muss mittels WaitForXfer() auf dessen
Ein solch gezielter Start von Transfers und dem Warten auf die Fertigstellung stellt kein
Problem dar, wenn nur einzelne Blöcke übertragen werden müssen. Für das geforderte
42
4.1 Aufgaben
absolut ausreichend.
Wird allerdings versucht, das digitalisierte Funksignal aufzuzeichnen, werden die Transfers
immer nur durchgeführt, wenn die Bedienanwendung dies explizit durch den Aufruf von
UsbParIn() einleitet. Während die Anwendung die beim letzten Aufruf übertragenen
Daten auswertet oder in eine Datei schreibt, ndet keine Aktivität auf dem USBBus statt.
Für Aufzeichnungen mit niedrigen Datenraten gibt es trotz der suboptimalen Ausnutzung
der Ressourcen keine Probleme. Jedoch bei Aufzeichnungen mit einer hohen Datenrate
wird der FIFOBaustein im USBRX nicht häug genug ausgelesen. Die Folge ist ein
Überlaufen des Puers im FIFOBausteins und damit der Verlust von Daten.
Um einen solchen Datenverlust zu verhindern, werden die Transfers über Threads abge-
wickelt. So können die Threads eine Übertragung mit maximaler Datenrate durchführen,
während die Bedienanwendung die beim letzten Aufruf der Funktion UsbParIn() gelese-
Threading
Die Aufgabe des Datentransfers wird durch zwei Threads erledigt, die beim Initialisieren
des Gerätes gestartet werden. Ein InitializeThread leitet die Transfers ein, auf deren
bis sie durch den anderen Thread oder durch den Aufruf von UsbParIn() aufgeweckt
werden. Dazu wurden bei der Initialisierung EventObjects [12] für beide Threads zur
Synchronisation angelegt und deren Handles in der GeräteStruktur des Treibers abgelegt.
Wird von der Bedienanwendung durch Aufruf der APIRoutine UsbParIn() ein Daten-
block mit einer bestimmten Gröÿe angefordert, muss zunächst zwischen den in den An-
dert sie Daten nur in Intervallen von ca. 100ms an. Das Volllaufen des FIFOBausteins
auf dem USBRX würde bei kleinen Blockgröÿen eine für den Benutzer unerwünschte
Verzögerung zwischen der Digitalisierung des Signals und dessen Darstellung am Monitor
15
verursachen . Zudem werden beim Schreiben von Daten durch den DDC in den bereits
15 Bei einer FFT mit der Blockgröÿe 512 Samples und einer Aktualisierungsrate von 10 FFT pro Sekunde
verursacht ein voller FIFO mit 32Ki Samples eine Verzögerung der Anzeige um 6.4 Sekunden.
43
4.1 Aufgaben
vollen FIFOBaustein einzelne I oder QWörter eines Samples verworfen. Die Folgen
sind fehlende oder vertauschte I/QAnteile in den Samples und damit verbunden eine
fehlerhafte Darstellung des Spektrums am Monitor. Um ein Volllaufen des Puers und
einem damit verbunden Datenverlust entgegen zu wirken, löst die Bedienanwendung vor
jedem Transfer eines Blocks einen Reset des FIFOBaustein aus, indem sie einen be-
16 2
stimmten ResetBefehl auf den I CBus legt. Dann erst liest diese den nächsten Block
ein und stellt diesen in der SpektrogrammAnsicht dar. Dieses Verhalten ist fest kodiert
und nicht kongurierbar. Startet die Bedienanwendung die Transfers im Wechsel mit dem
2
I CBefehl zum FIFOReset, ist davon auszugehen, dass sie sich in einem Modus zur
Spektrumanalyse bendet. In diesem Fall setzt UsbParIn() die Firmware in den Zustand
zum Blocktransfer und gibt dieser die Menge der zu übertragenden Daten mit.
chen, ist davon auszugehen, dass sie die Daten aufzeichnet. UsbParIn() schaltet die Firm-
ware auf den kontinuierlichen Transfermodus, so dass diese permanent Daten aus dem
externen FIFOBaustein zum Rechner hin überträgt. Zusätzlich setzt sie eine bestimm-
Unabhängig vom aktuellen Szenario weckt die APIFunktion UsbParIn() den Initialize
Thread über das entsprechende EventObject auf. Dieser leitet mit BeginDataXfer() die
ein und weckt den ProcessThread. Sollte dieser TransferRingpuer bereits voll sein,
schläft der InitializeThread so lange, bis er wieder geweckt wird. Der ProcessThread
wiederum wartet so lange, bis ihm mitgeteilt wird, dass neue Transfers im Ringpuer
vorhanden sind. Diese Transfers arbeitet er ab und weckt den InitializeThread, sobald ein
Platz im TransferRingpuer frei wurde. Durch die Synchronisation der beiden Threads
wird sichergestellt, dass die Transfers mit minimalsten Verzögerungen eingeleitet und
abgearbeitet werden.
Puerung
44
4.2 Aufbau
nauer eingegangen wird. Innerhalb der Funktion UsbParIn() werden diese geschriebenen
Daten über die Verteilungsschicht ausgelesen und wieder zurück an die Bedienanwendung
geliefert.
Das Verwenden der Verteilungsschicht bietet gegenüber einem einfachen Ringpuer den
Vorteil, dass sie bereits alle notwendigen Maÿnahmen zur Synchronisation und dem
dass der Treiber die gelesenen Daten auch an die Verteilungsschicht weitergibt, bietet es
sich nur an, das interne Puern ebenfalls über diese abzuwickeln. Als positiver Neben-
eekt können so die Daten, die die Bedienanwendung vom Treiber bekommt, über die
stet, dass sowohl kurze Verzögerungen bei kleinen Datenraten als auch Datensicherheit
In Abbildung 4.3 sind die Zusammenhänge zwischen den einzelnen Threads, der Bedienan-
stellt. Die notwendige Synchronisation und das Locking zwischen den Threads, die auf
45
4.2 Aufbau
4.2 Aufbau
Wie aus Abbildung 4.4 zu erkennen ist, ist die Quellcodestruktur des Treibers sehr ein-
fach gestaltet. Unter den Externen Abhängigkeiten benden sich die CyAPIBibliothek
und das FirmwareAbbild für den Cypress FX2LP. Das FirmwareAbbild liegt in Form
einer CStruktur in einer Headerdatei vor und wird beim Compilieren des Treibers fest in
dessen Binärstruktur eingebunden. Die CyAPIBibliothek hingegen wird erst beim Link-
vorgang statisch in die TreiberDLL eingebunden. Dadurch besteht neben den üblichen
Laufzeitbibliotheken des Compilers keine weitere Abhängigkeit, die zur Laufzeit aufgelöst
werden muss.
Der Zugri auf die CyAPI erfolgt durch Transferroutinen in der Worker.cpp, welche in
C++ geschrieben wurden. Da die CyAPI objektorientiert arbeitet, ist der Zugri nur über
selung des Treibers in Klassen wäre möglich gewesen, hätte aber durch die enge Bindung
an prozedurale Routinen keinen entscheidenden Vorteil geboten. Daher wurde sich auf den
beschränkt.
Der zur Bereitstellung der USB2.DLLAPI benötigte Wrapper wird ebenfalls beim Build-
vorgang mit in den Treiber gebunden. Sofern sich die API der verfügbaren Wrapper nicht
überschneidet, ist das Einbinden mehrerer Wrapper in eine DLL denkbar. Davon wurde
hat.
46
4.3 Tests
4.3 Tests
Während der Entwicklung des Treibers wurde in der Firmware des USBRX neben Id-
le , GPIF Transfer und GPIF Blocktransfer ein zusätzlicher Betriebsmodus Test
eingeführt. Die Aufgabe dieses Modus ist es, Datenblöcke mit 512 Byte Gröÿe und einem
bekanntem Inhalt mit minimaler Verzögerung (und demnach maximal möglicher Über-
tragungsrate) an den Treiber zu senden. Zusätzlich wird in diesen 512 Byte ein Zähler
Mit diesen durch die Firmware generierte Datenblöcken kann zwar auf korrekte Übertra-
gung aus den internen Puern, nicht aber auf korrekte Konguration des GPIF für die
Übertragung aus dem externen FIFO überprüft werden. Deswegen wurde zusätzlich eine
spezielle Version des USBRX entworfen, die inkrementierende SampleWerte mit Hilfe
eines Zählerbausteins erzeugt und in den externen FIFO schreibt. Da jedoch ein Test der
Auf der Treiberseite wurde zusätzlicher Testcode eingeführt, mit dem Benutzereingaben
So können während des Normalbetriebs Treiber und Firmware in den Testmodus versetzt
4.3.1 Testsystem
einusst, wurden alle Tests auf dem selben System durchgeführt. Informationen zum
Die Fehler dieser Kategorie sind unbedingt zu beheben, auch wenn es sich um Vorabver-
47
4.3 Tests
Komponente Bezeichnung
R
TM
Hauptprozessor Intel Core 2 Duo E8500, 3.16 GHz
Datenfehler
dieser den erwarteten Inhalt hat. Weicht ein Byte vom erwarteten Inhalt ab, wird eine
Paketverlust
Dieser Test fordert es vom Treiber, verloren gegangene Datenblöcke ausndig zu machen.
Dazu wird der in der Firmware geschriebene Zählerwert bei jedem Datenblock durch den
Testcode im Treiber überprüft. Weist der Zählerwert zwischen zwei Datenblöcken eine
gröÿere Dierenz als einen Zählerpunkt auf, ist davon auszugehen dass Pakete verloren
gingen oder umsortiert wurden. Beide Ursachen sind als Fehlerfall zu werten.
Gerätefunktionen fehlerhaft
Der Testcode des Treibers bietet auch die Möglichkeit, die I/OPins anzusteuern und
2
abzufragen und den I CBus nach Geräten zu scannen. Die I/OFunktionen wurden mit
Hilfe eines Testboards mit Leuchtdioden und Schaltern ausgiebig getestet. Auf den ak-
2
tuellen USBRXPlatinen ist ein serielles I CEEPROM verbaut, das für verschiedene
2
I CTests verwendet wurde.
2.1.5) an den SPIPins des Cypress FX2LP angeschlossen. Über dieses Interface kann eine
neue Firmware in den Atmel eingespielt werden. Mit Hilfe eines externen Testprogramms,
das in Java geschrieben wurde, konnte so die SPIFunktionalität des FX2LP veriziert
werden.
48
4.3 Tests
Treten Fehler dieser Kategorie auf, sind diese zwar in TestReleases tolerierbar, müssen
Niedrige Datenrate
Obwohl in den Anforderungen nicht explizit hohe Datenraten gefordert, jedoch sehr er-
wünscht sind, wird in diesem Test der Treiber auf die maximal mögliche Übertragungsrate
getestet. Zudem weist eine niedrige Übertragungsrate auf ein fehlerhaftes Design hin. Aus
diesem Grund wird die Übertragungsrate im Testbetrieb gemessen und angezeigt. Da das
theoretische Maximum bei Bussen selten auch praktisch erreicht wird, wird hier lediglich
qualitativ gemessen.
Die theoretische Übertragungsrate mit BulkTransfers liegt bei ca. 50 MiByte/s. Jedoch
wird im Cypress FX2LP im Testmodus jeder Datenblock durch die Firmware getriggert,
was bei der niedrigen Taktfrequenz von 48 MHz des integrierten Mikrocontrollers zu
Verzögerungen in der Übertragung führen kann. Eine Application Note[6] von Cypress
beschreibt einen ähnlichen Test, der ein Ergebnis von 22 MiByte/s lieferte. In Foren im
Internet sind von möglichen 38 MiByte/s die Rede [20]. Die originale USB2.DLL erreicht
Nach einem Test mit einer Dauer von 286 Sekunden betrug die durchschnittliche Über-
tragungsrate ca. 35 MiByte/s. Dieser Wert entspricht knapp 70% des theoretischen Ma-
ximums und nahezu dem Dreifachen der originalen USB2.DLL. Dieses Ergebnis ist daher
als akzeptabel einzustufen. Dies erlaubt es mit einer Filterbreite von 8 MHz aufzuzeich-
nen, was einem Vielfachen der geforderten 600 kHz entspricht. Abbildung 4.5 zeigt einen
Trotz der hohen Datenrate hat sich auf dem verwendeten Testsystem lediglich eine CPU
Hohe Latenzen
Dieser Test misst die Dauer des Aufrufs der APIFunktion UsbParIn() und demzufolge
die Dauer zwischen Anforderung eines Datenblockes und dem Zeitpunkt, ab dem dieser
Datenblock für die Anwendung zur Verfügung steht. Diese Dauer wird im Weiteren auch
49
4.3 Tests
50
4.3 Tests
Wie in den Anforderungen beschrieben, muss die Latenz bei der Übertragung möglichst
niedrig gehalten werden. Daher ist der Fehlerfall Hohe Latenz ebenso wie Niedrige Da-
so dass 20 Transfers pro Sekunde und damit ca. 20 FFT/s in der Bedienanwendung gerade
Getestet wurden die Latenzen bei Transfers von Datenblöcken unterschiedlicher Gröÿe.
Aus der Ausgabe des Testcodes (siehe Abbildung 4.6) ist die Aufrufdauer der API
ist zu entnehmen dass die maximale Aufrufdauer bei Blöcken von 128 KiByte Gröÿe
Nach weiteren Optimierungen wurde eine Lösung gefunden, diese Verzögerung in diesem
Test konstant auf ca. 2 ms zu reduzieren. Diese Lösung fordert den nächsten Datenblock
schon beim Verlassen von UsbParIn() an, so dass dieser bereits beim nächsten Aufruf
zur Verfügung steht. Diese Optimierung birgt den Nachteil, dass die der Anwendung
gelieferten Daten bereits einen Aufrufzyklus alt sind. Die Dauer der Übertragung selbst
ändert sich jedoch dadurch nicht, diese wird lediglich asynchron durchgeführt und ndet
somit statt, während die Anwendung die letzten Daten auswertet. Daher wird von einer
51
4.3 Tests
1 KiByte 3 ms
2 KiByte 3 ms
4 KiByte 3 ms
8 KiByte 3 ms
64 KiByte 5 ms
128 KiByte 7 ms
52
Kapitel 5
Verteilungsschicht
Eine Verteilungsschicht soll die Verteilung der durch das Gerät USBRX gewonnenen
die den Austausch von Daten zwischen Prozessen und Threads erleichtern, diese sind je-
doch betriebssystemabhängig und erlauben es nicht, Puergröÿen und das das Verhalten
z. B. bei vollen Puern anzupassen. Auch ist davon auszugehen, dass diese sehr stark mit
tieferen Betriebssystemschichten verknüpft sind und dies bei hohen Datenraten zu uner-
wünschten Latenzen führen kann. Eine geforderte Rekonguration während des Betriebs
aus einer beliebigen Instanz heraus ist bei diesen Mechanismen nicht vorgesehen.
Daher wurde eine eigenständige Lösung entwickelt, die in diesem Kapitel beschrieben
wird. Diese Lösung wird wegen der Verwendung von Shared Memory und der möglichen
5.1 Konzept
Für das grundlegende Design der SHMemChainBibliothek wurden mehrere Ziele festge-
legt, die diese weiter charakterisieren sollen. Diese gelten Ziele gelten als Ergänzung zu
17 Microsoft Windows bietet mit Pipes[16], Mailslots[14] und Sockets[18] mehrere solcher Mechanismen
zur Kommunikation zwischen Prozessen an.
53
5.1 Konzept
Daten wartet oder beschäftigt ist, der Schreibvorgang in Anwendung A mit mög-
Anwendung B bereits auf Daten, so müssen diese mit möglichst kurzer Gesamt-
gemacht werden. Die Verwendung von Puern und einer geeigneten Synchronisati-
zu erleichtern.
Eine Anwendung, die Daten mit einer anderen Anwendung austauschen soll, muss sich
zunächst bei der Verteilungsschicht registrieren und wird in deren Kontext als Node be-
zeichnet. Diese Node wird über einen Handle identiziert, welcher bei der Registrierung
zurückgegeben wird und bei jedem weiteren APIAufruf als Referenz angegeben werden
muss. Dabei kann sich eine Anwendung auch mehrfach registrieren und bekommt dement-
Jede Node ist in der Lage, Daten zu lesen und zu schreiben. Woher eine Node Daten liest,
bzw. wohin sie Daten schreibt, wird über Channels angegeben. Zu jeder Node gibt es einen
Source und einen Destination Channel, die bei der Registrierung angegeben werden. Diese
bestimmen Quelle und Ziel der Daten und werden durch beliebige Zahlen im positiven
54
5.1 Konzept
Abbildung 5.1: Beispielaufbau einer Verteilung. ( Source und Destination Channel sind
Source oder Destination Channels einer Node können deaktiviert werden, indem ihnen
Diese Channels dienen rein zur logischen Zuordnung, an welche Nodes die Daten einer
schreibenden Node geleitet werden sollen und benötigen keine weiteren Verwaltungsin-
formationen. Es wird jedoch sichergestellt, dass ein bestimmter Channel nur von jeweils
einer Node beschrieben werden kann. Könnten mehrere Nodes auf einen Channel schrei-
ben, würde dies zu einer unerwünschten Vermengung der Daten führen. Dies wird nicht
als Einschränkung betrachtet, da die Bibliothek ohnehin nur zur Übertragung von Daten-
Schreibt, wie in Abbildung 5.1 dargestellt, die Node A mit Destination Channel 2 Daten,
so können diese Daten von allen Nodes gelesen werden, die ihren Source Channel eben-
falls auf 2 eingestellt haben. Dabei erhalten alle Nodes die gleichen Daten die zeitliche
Abfolge, in der die Nodes die Daten lesen, ist unerheblich. Sind keine Nodes vorhanden,
die diesen Source Channel besitzen, werden die geschriebenen Daten verworfen.
Nodes, die Daten verarbeiten, wie z. B. Filter oder Verstärker, lesen demnach Daten
vom Source Channel, modizieren diese und schreiben sie wieder über den Destination
Channel an weitere Nodes. So können mehrere Verarbeitungsschritte aneinandergereiht
werden, die in unterschiedlichen Anwendungen implementiert wurden. Die notwendige
erledigt.
Der Vorteil durch die Verwendung von Channels ist, dass so die Daten kategorisiert werden
können. So ist z. B. vorgesehen, dass die durch den USBRXTreiber gelieferten Rohdaten
immer auf Channel 0 ausgegeben werden. Weitere Anwendungen können so diese Roh-
55
5.1 Konzept
daten lesen, ohne zu wissen, von welcher Node diese Daten stammen. Auch könnte eine
Kombination aus MessAnwendungen z. B. immer auf Channel 128 auf Daten warten.
Sollte eine Analyse von Daten erforderlich sein, kann eine Anwendung ihren Destination
Channel auf 128 setzen, so dass der Anwender diese Daten in den MessAnwendungen
Dieses Konzept ist vergleichbar mit dem Prinzip des Multicasting in Computernetzwerken.
Shared Memory bezeichnet einen Speicherbereich, auf den von mehreren Prozessen gleich-
zeitig zugegrien werden kann. Da jedoch jeder Prozess durch Speichervirtualisierung sei-
nen eigenen Adressraum besitzt, ndet sich in diesem keine Adresse, die mit Sicherheit
bei allen anderen Prozessen frei ist. Daher werden Shared MemoryBereiche in einen be-
liebigen, freien Speicherbereich des Prozesses eingeblendet, der aber für jeden Prozess
verschieden ist.
Zum Erstellen oder Önen eines solchen Bereichs reichen seine Gröÿe und ein eindeutiger
Name, die alle Prozesse beim Aufruf der entsprechenden Betriebssystemfunktionen ver-
wenden müssen. Das Betriebssystem liefert dabei neben der Speicheradresse auch einen
Handle zurück, der diesem Bereich zugeordnet und nur für den aktuellen Prozess gültig
ist. Dieser Handle wird benötigt, um diesen Shared MemoryBereich später wieder zu
schlieÿen.
Da der Shared MemoryBereich bei jedem Prozess an einer anderen Speicheradresse liegt,
können zum einen keine direkten Speicherzeiger (engl.: Pointer) auf Shared Memory
Bereiche unter den Prozessen ausgetauscht werden und zum anderen muss jeder Prozess
selbst verwalten, welchen Handle und welche Adresse ein Shared MemoryBereich in sei-
56
5.2 Realisierung
5.2 Realisierung
NodeKonguration
Die Informationen und Konguration aller Nodes muss wie gefordert in einem Shared
greifen und diese bearbeiten können. Die Informationen und Konguration zu einer Node
werden weiterhin als Nodeinfo bezeichnet, der Shared MemoryBereich in dem diese ge-
Dieser Bereich muss von der ersten Instanz der Bibliothek alloziert und initialisiert werden,
alle weiteren Instanzen können daraufhin mit dem vorbereiteten Bereich arbeiten.
Bereich in Form eines Arrays gespeichert (siehe Abbildung 5.2). Dies erfordert es, vorab
zu wissen, wie viele Nodes maximal registriert werden. Daher wird von einer maximalen
Eine exiblere Lösung, bei der die maximale Anzahl der Nodes nicht festgelegt ist, wur-
de auch überlegt. Dabei würden die Nodeinfos über verkettete Shared MemoryBereiche
hinweg verteilt werden. Jedoch wäre ein Zugri auf eine bestimmte Nodeinfo mit meh-
Auslegung als Array in einem Bereich konstant nur eine Dereferenzierung kostet. Zudem
erfordert eine Lösung mit verketteten Bereichen eine aufwändige Verwaltung von Handles
und Adresszeigern zu diesen Bereichen, bietet dafür aber keine entscheidenden Vorteile.
Jede Nodeinfo in diesem Bereich entspricht einer CStruktur, die wichtige Informationen
über die jeweilige Node enthält. Tabelle 5.1 listet die wichtigsten Felder dieser Struktur
auf.
57
5.2 Realisierung
Feld Beschreibung
int version; wird bei Änderungen inkrementiert
unsigned char node_mutex[. . . ] Name des Named Mutex für diese Node
Ob eine Nodeinfo bereits benutzt wird, oder noch verfügbar ist, wird über das Feld used
festgelegt. Daneben beinhaltet diese Struktur den Source und den Destination Channel,
die dieser Node zugewiesen sind. Auch sind dort die für den Datenpuer notwendigen
Variablen untergebracht und die Namen, mit denen der Shared MemoryBereich des Da-
tenpuers und die zur Synchronisation (siehe Abschnitt 5.2.2) notwendigen Mutex und
EventObjects geönet werden können. Diese Felder werden durch diejenige Instanz der
Das Feld version wird nach jeder Änderung, die ein erneutes Önen des Datenpuers,
des Mutex oder des EventObjects erfordert, inkrementiert. Das sind insbesondere Neu
Parallel zum NodeinfoBereich führt jede Instanz der Verteilungsbibliothek ein lokales
Array, in dem nur für diese Instanz wichtige Informationen zu jeder Node in Form einer
weiteren Struktur gelistet sind. Dieses Array wird im Weiteren als Local Nodeinfo Array
bezeichnet. Es besitzt die gleiche Anzahl an Elementen wie das Nodeinfo Array, welche
Datenpuer
Da der Datenaustausch zwischen einzelnen Nodes auch über Prozesse und damit auch
über mehrere Instanzen der Verteilungsbibliothek hinweg stattnden soll, müssen die
58
5.2 Realisierung
Feld Beschreibung
int version; Version der Nodeinfo, auf die sich bezogen wird
int local; gesetzt, wenn diese Instanz der Inhaber der Node ist
sowohl der schreibende als auch der lesende Prozess auf den gleichen Speicherbereich
zugreifen, ohne dass die Daten durch Betriebssystemschichten hindurch mehrfach kopiert
werden müssen.
Jede Node besitzt einen Datenpuer, in den die Daten geschrieben, die für diese Node
bestimmt sind. Die zum Önen des Shared MemoryBereichs erforderlichen Informationen
wie Name und Gröÿe werden durch diejenige Instanz der Verteilungsbibliothek in die
Nodeinfo eingetragen, welche diese Node registriert hat. Greift eine andere Instanz auf
diese Node zu, muss zunächst der Shared MemoryBereich des Datenpuers der Node mit
Hilfe des Namens und der Gröÿe aus der Nodeinfo geönet werden. Die beim Erstellen
und Önen anfallenden Handles und Speicherzeiger verwaltet jede Instanz der Bibliothek
Da ein Ringpuer für den Verwendungszweck als Datenpuer besonders gut geeignet ist,
ndet dieser hier Anwendung. Bei Lese und Schreibzugrien auf diesen Datenpuer wird
eine für Ringpuer übliche Variante benutzt, bei der die Startposition und die Anzahl der
Daten in Variablen gehalten werden. Diese für den Ringpuer notwendigen Arbeitsvaria-
Änderungsverwaltung
In der Local Nodeinfo bendet sich das Feld version, welches dem gleichnamigen Feld
aus der Nodeinfo entspricht. Weichen bei einem Zugri auf eine Nodeinfo die Werte beider
versionFelder voneinander ab, so ist davon auszugehen, dass die in der Local Nodeinfo
59
5.2 Realisierung
gespeicherten Handles nicht mehr denen entsprechen, die zur Synchronisation bzw. zum
Puerzugri benötigt werden. Dies ist z. B. der Fall, wenn eine Node deregistriert wurde.
Daher werden alle Handles in der Local Nodeinfo geschlossen und sofern die Nodeinfo
noch benutzt wird mit den aktuellen Informationen aus der Nodeinfo neu geönet. Auf
diese Weise wird bei einer Änderung wie z. B. Deregistrierung einer Node auch der für
Durch die Verwendung des versionFelds ergibt sich jedoch ein Problem, welches zu
einem temporären Speicherleck führen kann: Registriert eine Instanz A der Verteilungs-
bibliothek eine Node mit einer beliebigen Puergröÿe und eine andere Instanz B greift
in Folge eines Schreibvorgangs auf diese Node zu, wird der Shared Memory zum Puer
auch in der Instanz B geönet. Wird nun die Node in Instanz A deregistriert, bleibt der
kein Zugri auf die deregistrierte Node, bzw. deren Nodeinfo mehr stattndet, belegt sie
Als mögliche Lösung ist hier ein weiterer Thread angedacht, welcher in jeder Instanz bei
Änderungen durch alle Nodeinfos iteriert und den Datenpuer deregistrierter Nodes auch
lokal wieder freigibt. Zur Signalisierung einer Änderung kann eine geeignete Signalisie-
anbietet.
5.2.2 Synchronisation
die Datenpuer zugreifen, ist eine ordentliche Synchronisation besonders wichtig. Dies
beinhaltet sowohl ein Sperren (Locking) der Ressourcen bei konkurrierenden Zugrien,
als auch die Signalisierung, dass neue Daten im Puer verfügbar sind.
Locking
für den NodeinfoBereich eingeführt. Dadurch wird sichergestellt, dass bei einer Änderung
einer NodeinfoStruktur nur von einem Prozess zugegrien werden kann, bei Lesezugrien
60
5.2 Realisierung
Bei einem lesenden oder schreibenden Zugri auf die Datenpuer müssen die für den
Prozess gesichert werden. Da die Zugrie auf die Datenpuer der registrierten Nodes je
nach Auslastung jedoch sehr häug stattnden können, würde ein komplettes Sperren des
NodeinfoBereichs bei jedem Zugri die Latenzen aller Prozesse stark negativ beeinus-
Deswegen wird für Zugrie auf den Datenpuer selektiver gesperrt. Für jede Nodeinfo
existiert ein Mutex, der die Zugrie auf die Puervariablen innerhalb einer Nodeinfo
absichert. Bei Zugri auf den Datenpuer einer Node wird der Semaphor des Nodeinfo
Bereichs lediglich lesend, der Mutex für die Variablen jedoch komplett gesperrt.
Später wurde eine feingranularere Sperrmethode eingesetzt, durch die die Variablen für
den Datenpuer nur für die Dauer ihrer Änderung gesperrt werden. Durch das Konzept
dieser Verteilungsschicht können nur maximal zwei Prozesse auf den Datenpuer einer
Node zugreifen - der Prozess, der Daten an diese Node schreibt und der Prozess, der
Besitzer dieser ist und die geschriebenen Daten liest. Beide können durch die Verwendung
eines Ringpuers gleichzeitig auf den Puer selbst zugreifen, lediglich bei einer nicht
atomaren Änderung der Puervariablen muss der entsprechende Mutex gesperrt werden.
Dadurch kann während des Kopiervorgangs mittels memcpy() im jeweils anderen Prozess
Abbildungen 5.3 und 5.4 stellen den Vorgang beim Schreiben und Lesen in einem Sequenz-
Signalisierung
Wartet ein Prozess auf Daten, so muss dieser benachrichtigt werden, sobald welche ver-
fügbar werden. Dazu existiert zu jeder Node ein eigenes EventObject[12], welches zur
Signalisierung dient. Sind nicht genug Daten zum Lesen vorhanden, wird im lesenden Pro-
61
5.2 Realisierung
Abbildung 5.3: Sperren beim schreibenden Zugri auf den Datenpuer einer Node
Abbildung 5.4: Sperren beim lesenden Zugri auf den Datenpuer einer Node
62
5.3 Performanceanalyse
5.2.3 API
Um den Anwendern der Verteilungsschicht möglichst freie Wahl bei der Auswahl ihrer
Programmiersprache zu lassen, wurde sich auf eine prozedurale Bibliothek mit stdcall
Aufrufkonvention beschränkt. Diese ist die für WindowsBibliotheken gebräuchlichste[19]
Tabelle 5.3 listet die wichtigsten APIFunktionen der SHMemChain Bibliothek auf. Die
API arbeitet laut Anforderungen mit sprechenden Namen, die auch ohne die Hilfe einer
Funktion Beschreibung
shmemchain_register_node registriert eine Node
welche es dem Anwender ermöglicht, diese Bibliothek auch aus Pascal oder Delphi
und Java wurden ebenfalls entwickelt. Somit kann die für den Anwendungszweck günstig-
5.3 Performanceanalyse
Eine Analyse der Ziele, die in Abschnitt 5.1.1 deniert wurden, wurde mittels eines ein-
lungsbibliothek als eine Node und ist in der Lage, Zeitstempel zu erzeugen und auszuwer-
ten. Je nach Konguration schreibt es diese Zeitstempel an einen Channel, oder empfängt
solche darüber.
So kann eine Instanz des Testprogramms Zeitstempel erzeugen und an eine weitere Instanz
schreiben, welche diese ausliest und auswertet. Auf diesen Weg können die Latenz, die
Dauer der Schreiboperation und die Dauer der Leseoperation bestimmt werden. Zusätzlich
63
5.3 Performanceanalyse
Um eine möglichst hohe Genauigkeit bei der Messung zu erzielen, wird die Funktion
wendeten Testsystem (siehe Tabelle 4.2) in etwa eine Auösung von 70 ns erreicht. Um
Einüsse durch andere Prozesse zu minimieren, wurde beim Test die Prozesspriorität auf
und das Ergebnis ist weniger von der Aktivität anderer Prozesse abhängig. Über die Er-
gebnisse des Tests wird ein arithmetisches Mittel gebildet und im Messwertbereich des
Testprogramms angezeigt.
Abbildung 5.5 zeigt die Ergebnisse bei einem Test mit einer Blockgröÿe von einem KiByte,
welcher jede Millisekunde übertragen wurde. Dieser Test ergab bei einer CPUAuslastung
je Prozess von weniger als 0.1% eine Latenz von ca. 100 µs.
Die Dauer des Schreibvorgangs allein ist mit ca. 86 µs fast so hoch wie die Latenz, was
darauf zurückzuführen ist, dass beim Schreibvorgang alle Nodes auf ihren SourceChannel
überprüft werden müssen, während die Leseoperation nur noch auf ein Signal wartet,
um die geschriebenen Daten aus dem Puer zu lesen. Abbildung 5.6 stellt diesen Ablauf
64
5.3 Performanceanalyse
Abbildung 5.6: Ablaufdiagramm bei Schreib und Lesevorgängen über die Verteilungsbi-
bliothek
grasch dar. Diese Dauer könnte durch die Einführung eines zusätzlichen Arrays, in dem zu
jedem Channel die zugehörigen Empfängernodes stehen, verringert werden. Besonders bei
groÿen Werten von MAX_NODES und kleinen Blockgröÿen der zu übertragenden Daten ist
eine solche Optimierung in Betracht zu ziehen. Dem gegenüber steht jedoch der zusätzliche
Mehrfache Wiederholungen des Tests zeigten, dass die Messergebnisse je nach Rechneraus-
lastung sehr stark variieren können. Allein das Aktivieren eines anderen Anwendungsfen-
sters verschlechtert die Messergebnisse teilweise um bis zu 50%. Dies liegt nicht in einem
fehlerhaften Design begründet, sondern ist vielmehr auf das SchedulingKonzept eines
reren Anwendungen aufgeteilt werden. Daher sind die gewonnenen Ergebnisse lediglich
als Indikator für eine gut abgestimmte Synchronisation innerhalb der Verteilungsschicht
zu betrachten.
Ein weiterer Test, bei dem groÿe Datenmengen in kurzen Zeitabständen übertragen wur-
den, ermittelte eine Übertragungsrate von mehr als 800 MiByte/s. Dieser Test verursachte
eine gesamte CPUAuslastung von ca. 90% und ergab eine gemessene Latenz von ca. 18
ms. Ein Screenshot der Testanwendung ist in Abbildung 5.7 zu sehen. Da bei groÿen Da-
tenblöcken von mehreren MiByte die Verzögerungen durch das Durchsuchen des Nodeinfo
Arrays und die Einüsse durch das Prozessscheduling relativ gering sind, schwankt dieses
Orientiert man sich an den Anforderungen an die Teilprojekte Treiber und Firmware ,
so liegen sowohl verursachte Latenz als auch die mögliche Übertragungsrate der Vertei-
65
5.3 Performanceanalyse
lungsbibliothek in Bereichen, die keinen merklichen negativen Einuss auf die anderen
Teilprojekte ausüben.
66
5.3 Performanceanalyse
vi
Literaturverzeichnis
Auflage, 1991.
[11] Meyer, Martin: Signalverarbeitung - Analoge und digitale Signale, Systeme und
Filter. Vieweg Verlag, 4. Auflage, 2006.
vii
LITERATURVERZEICHNIS
viii
Eidesstattliche Erklärung
Ich erkläre hiermit, dass ich die Arbeit selbständig verfasst, noch nicht anderweitig für
Prüfungszwecke vorgelegt, keine anderen als die angegebenen Quellen oder Hilfsmittel
benützt sowie wörtliche und sinngemäÿe Zitate als solche gekennzeichnet habe.
Ingolstadt, 04.03.2009
Georg Hofstetter
ix