Seite 1 Unterlagen zur Vorlesung Fakultät Elektrotechnik ... · Potentiometer Tachomaschinen...

61
Prozessdatenverarbeitung Wintersemester 2017/18 Seite 1 Unterlagen zur Vorlesung Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas Inhaltsverzeichnis 1 Einführung ................................................................................................................................................. 2 1.1 Einordnung in die Automatisierungstechnik ..................................................................................... 2 1.2 Einordnung in die Elektrotechnik und die praktische Informatik ...................................................... 3 1.3 Übertragungsmodelle, Signaltypen, Zeitabhängigkeit ..................................................................... 4 1.3.1 Signalformen ................................................................................................................................ 4 1.3.2 Zeitverhältnisse in der Prozesssignalkette .................................................................................. 5 1.3.3 Diskretisierung der Eingabesignale, Abtasttheorem.................................................................... 6 1.3.4 Echtzeit (Realzeit) ........................................................................................................................ 7 1.3.4.1 Zyklische Verarbeitung analoger Prozessgrößen in Echtzeit ............................................. 9 1.3.4.2 Zyklische Verarbeitung von Schaltgrößen in Echtzeit......................................................... 9 1.3.4.3 Beispiel: automatische Erkennung und Navigation fahrerloser Fahrzeuge ...................... 10 1.3.4.4 Ereignisorientierte Verarbeitung von Schaltgrößen in Echtzeit ........................................ 11 1.3.4.5 Echtzeiteingabe, Pufferung und Weiterverarbeitung von Prozessdaten .......................... 12 1.3.5 Programme für analoger Prozesse am Beispiel Regelung........................................................ 13 1.3.5.1 Signalflussbetrachtung ...................................................................................................... 13 1.3.5.2 Mathematisches Modell .................................................................................................... 14 1.3.5.3 Programmentwurf .............................................................................................................. 16 1.3.5.4 Programmrealisierung ....................................................................................................... 16 1.3.6 Programme für digitale Prozesssignale am Beispiel digitale Steuerung ................................... 17 1.3.6.1 Sequentieller Zustandsautomat ........................................................................................ 17 1.3.6.2 Programmentwurf eines MOORE-Automatenen............................................................... 17 1.3.6.3 Programmrealisierung ....................................................................................................... 19 2 Ablauf eines Hauptprogramms ............................................................................................................... 20 2.1 Hauptprogrammzyklus mit Endlosschleife ..................................................................................... 20 2.2 Kontrolliertes Warten ...................................................................................................................... 20 2.2.1 Diskontinuierlicher Ablauf durch Unterbrechungen aus der Peripherie..................................... 20 2.2.2 Quasi kontinuierlicher Ablauf mit isochronem Timing................................................................ 22 3 Ein- und Ausgabe ................................................................................................................................... 23 3.1 Hardwareaufbau und Adressräume ............................................................................................... 23 3.2 Speicheradressierter Zugriff auf Interfacehardware....................................................................... 25 3.2.1 Real adressierende Zielsysteme ............................................................................................... 26 3.2.2 Virtuell adressierende Zielsysteme ............................................................................................ 27 3.2.3 Kritischer Abschnitt und Semaphore ......................................................................................... 29 3.3 Höhere Schichten der Ein- und Ausgabe ....................................................................................... 31 3.4 Kommunikationsprotokolle ............................................................................................................. 31 4 Unterbrechungen .................................................................................................................................... 32 4.1 Ablauf einer Unterbrechungsanforderung ...................................................................................... 32 4.2 Synchrone Unterbrechungen ......................................................................................................... 35 4.3 Asynchrone Unterbrechung ........................................................................................................... 40 5 Timerprogrammierung ............................................................................................................................ 42 5.1 Wartezeitfunktionen........................................................................................................................ 42 5.2 Dynamische Wartekorrektur der Wartezeit für isochrones Timing................................................. 43 5.3 Selbstständig ablaufender Standardzeitgeber ............................................................................... 49 5.4 "Timer Ticksize": Einstellung des Betriebssystems auf hohe Zykluswiederholraten ..................... 53 6 Interprozesskommunikation .................................................................................................................... 54 6.1 Prinzipieller Ablauf mit gegenseitiger Synchronisation Sender - Empfänger................................. 54 6.2 Beispiel eines Servers .................................................................................................................... 55 6.3 Beispiel des zugehörigen Clients ................................................................................................... 60 6.4 Andere Formen der Interprozesskommunikation ........................................................................... 61

Transcript of Seite 1 Unterlagen zur Vorlesung Fakultät Elektrotechnik ... · Potentiometer Tachomaschinen...

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 1 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Inhaltsverzeichnis

1  Einführung ................................................................................................................................................. 2 

1.1  Einordnung in die Automatisierungstechnik ..................................................................................... 2 1.2  Einordnung in die Elektrotechnik und die praktische Informatik ...................................................... 3 1.3  Übertragungsmodelle, Signaltypen, Zeitabhängigkeit ..................................................................... 4 

1.3.1  Signalformen ................................................................................................................................ 4 1.3.2  Zeitverhältnisse in der Prozesssignalkette .................................................................................. 5 1.3.3  Diskretisierung der Eingabesignale, Abtasttheorem .................................................................... 6 1.3.4  Echtzeit (Realzeit) ........................................................................................................................ 7 

1.3.4.1  Zyklische Verarbeitung analoger Prozessgrößen in Echtzeit ............................................. 9 1.3.4.2  Zyklische Verarbeitung von Schaltgrößen in Echtzeit ......................................................... 9 1.3.4.3  Beispiel: automatische Erkennung und Navigation fahrerloser Fahrzeuge ...................... 10 1.3.4.4  Ereignisorientierte Verarbeitung von Schaltgrößen in Echtzeit ........................................ 11 1.3.4.5  Echtzeiteingabe, Pufferung und Weiterverarbeitung von Prozessdaten .......................... 12 

1.3.5  Programme für analoger Prozesse am Beispiel Regelung ........................................................ 13 1.3.5.1  Signalflussbetrachtung ...................................................................................................... 13 1.3.5.2  Mathematisches Modell .................................................................................................... 14 1.3.5.3  Programmentwurf .............................................................................................................. 16 1.3.5.4  Programmrealisierung ....................................................................................................... 16 

1.3.6  Programme für digitale Prozesssignale am Beispiel digitale Steuerung ................................... 17 1.3.6.1  Sequentieller Zustandsautomat ........................................................................................ 17 1.3.6.2  Programmentwurf eines MOORE-Automatenen ............................................................... 17 1.3.6.3  Programmrealisierung ....................................................................................................... 19 

2  Ablauf eines Hauptprogramms ............................................................................................................... 20 2.1  Hauptprogrammzyklus mit Endlosschleife ..................................................................................... 20 2.2  Kontrolliertes Warten ...................................................................................................................... 20 

2.2.1  Diskontinuierlicher Ablauf durch Unterbrechungen aus der Peripherie ..................................... 20 2.2.2  Quasi kontinuierlicher Ablauf mit isochronem Timing ................................................................ 22 

3  Ein- und Ausgabe ................................................................................................................................... 23 3.1  Hardwareaufbau und Adressräume ............................................................................................... 23 3.2  Speicheradressierter Zugriff auf Interfacehardware ....................................................................... 25 

3.2.1  Real adressierende Zielsysteme ............................................................................................... 26 3.2.2  Virtuell adressierende Zielsysteme ............................................................................................ 27 3.2.3  Kritischer Abschnitt und Semaphore ......................................................................................... 29 

3.3  Höhere Schichten der Ein- und Ausgabe ....................................................................................... 31 3.4  Kommunikationsprotokolle ............................................................................................................. 31 

4  Unterbrechungen .................................................................................................................................... 32 4.1  Ablauf einer Unterbrechungsanforderung ...................................................................................... 32 4.2  Synchrone Unterbrechungen ......................................................................................................... 35 4.3  Asynchrone Unterbrechung ........................................................................................................... 40 

5  Timerprogrammierung ............................................................................................................................ 42 5.1  Wartezeitfunktionen ........................................................................................................................ 42 5.2  Dynamische Wartekorrektur der Wartezeit für isochrones Timing................................................. 43 5.3  Selbstständig ablaufender Standardzeitgeber ............................................................................... 49 5.4  "Timer Ticksize": Einstellung des Betriebssystems auf hohe Zykluswiederholraten ..................... 53 

6  Interprozesskommunikation .................................................................................................................... 54 6.1  Prinzipieller Ablauf mit gegenseitiger Synchronisation Sender - Empfänger ................................. 54 6.2  Beispiel eines Servers .................................................................................................................... 55 6.3  Beispiel des zugehörigen Clients ................................................................................................... 60 6.4  Andere Formen der Interprozesskommunikation ........................................................................... 61 

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 2 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

1 Einführung

1.1 Einordnung in die Automatisierungstechnik

PLT: Koordinierende "höhere" Ebene

Leitsystem

ErgebnisseZiele

...

ProduktmengeProduktqualitätFertigstellungsterminetc.

Automatisierungs-gerät

Automatisierungs-gerät

Automatisierungs-gerät

Prozess Prozess

Stell-größen

Mess-größen

Prozess

"Soll"

"Ist"

PDV - Digitale Steuerungstechnik - Industrielle Messtechnik: prozessnahe ausführende Ebene

Automatisi-serungsgerät

Anlage

BedienenBeobachten

Prozess

Aggregat

Störung

Maschine

Programmierte Anwendungen:

RegelungSteuerung

Überwachung

Informationmaterielle oder energetische

Wirkung

Nebenläufiges / übergeordnetes DV-System

Aktoren

SensorenPro

zess

per

iph

erie

Einwirkung

Rückwirkung

Aktion

Messung

Eingabe

Ausgabe

Eingabe

Ausgabe

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 3 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

1.2 Einordnung in die Elektrotechnik und die praktische Informatik

Computer als "Embedded" (eingebettetes) Automatisierungsgerät

...

Programm

Computer

Bedienfeld

...

Bedienfeld

Steuer-/Regel-bauglieder

ComputergestütztesAutomatisierungsgerät

Automatisierungsgerätmit simultan wirkenden Baugruppen

Technische Entwicklung

Mess-größen

Stell-größen

"Prozessdaten"

Automatisierte technische Einrichtung

Sequentielle Arbeitsweise eines Computers

per Schaltungstechnik

Aufgabenneutral

per Computer:

Schaltung

Bauelemente

Schaltung und Baulemente

"Software": Speicherinhalt Programme/Daten

Bearbeiten vonInformationsverarbeitungsaufgaben

Aufgabenneutral

Aufgabenspezifisch

Aufgabenspezifisch

Zeit

Zeit Zeit Zeit

Eingabe

Verarbeitung

Ausgabe

Herkömmliches Automatisierungsgerät: simultane Verarbeitung

Computer: sequentielle Verarbeitung

simultan

sequentiell

Prozess-zyklus des Automatisierungs-programms

Verarbeitung AusgabeEingabe

Starten

Beenden

Wiederholen

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 4 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Zeitabhängige gegenseitige Beeinflussung von Prozessrechner (Automatisierungsgerät) und Prozess

Prozessrechner / Steuer-/

Regelschaltung

Automatisierte technische Einrichtung

Stellgrößen

Technischer Prozess

Regelung / Steuerung /

Überwachung

Zeit

ProzessgrößenFührungsgrößen

Messgrößen

Fachgebiete entlang des Signalflusses vom Sensor über den Prozessrechner bis zum Aktor:

werden in der Vorlesung ausgeführt. Entwicklungssystem, Zielsystem, Cross Development:

Erklärungen in der Vorlesung

1.3 Übertragungsmodelle, Signaltypen, Zeitabhängigkeit

1.3.1 Signalformen

Analoge Signale Name Form Eingabeglieder Verarbeitungsglie-

der Eigenschaften

amplituden-analog

Potentiometer Tachomaschinen DC-Wandler

Operationsverstär-ker in Summen und Differenzschaltun-gen

geringer Messaufwand

störempfindlich nicht speicherbar aufwendige

Potentialtrennung aufwendige Um-

wandlung in Daten frequenz- analog

Frequenzgenerator inkrementelle Dreh-

zahlgeber (ohne Zeitbasis)

Tachomaschinen

Zähler Komparatoren

sehr genau nicht störempfind-

lich einfache Umwand-

lung in Daten phasen- analog

Drehmelder Resolver

Verstärker

sehr genau störempfindlich einfache Umwand-

lung in Daten impuls-breiten moduliert

Grenzwertgeber

Schaltverstärker

sehr geringer Gerä-teaufwand

einfache Umwand-lung in Daten

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 5 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Diskrete Signale

Name Form Eingabeglieder Verarbeitungsglie-der

Eigenschaften

Binär

Schalter Relais Grenzwertgeber

Logikschaltkreise Relais Komparatoren

sehr geringer Ge-räteaufwand

einfache Umwand-lung in Daten

digital parallel

Absolut codierte Wegmesssysteme

Lochkarten, -streifen

Computer

Daten Genauigkeit ent-

spricht der Stellen-zahl

gut speicherbar digital seriell

wie bei digital parallel

Datenübertra-gungsmedien

wie bei digital parallel

Impuls-zählung

Frequenzgenerator inkrementeller

Drehzahlgeber (mit Zeitbasis)

Zähler, Register

sehr geringer Geräteaufwand

einfache Umwand-lung in Daten

Signalformen von Prozessgrößen (Quelle: Böhm, 1977)

1.3.2 Zeitverhältnisse in der Prozesssignalkette

Signalfluss einer ungestörten analogen Prozesseingabegröße

1/TADC

Messwert-aufnehmer

Computer

Abtast-periodendauer

1/Ta

fProzess, MAX im Fourierspektrum

1/TProg

AnalogerProzess

Abtast-und

HaltegliedADC

N*2*fMAX, Prozess fa fADC

Programm

fProg

Verarbeitungsrate f muss gleich bleiben oder zunehmen!

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 6 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Signalfluss einer hochfrequent gestörten analogen Prozesseingabegröße

TiefpassMesswert-aufnehmer

Abtast-periodendauer

1/TAbtast&Halte

ComputerfG

Abtast-und

Halteglied

Störfrequenzgang

N*2*fG fa

fG

AStör(f)

...mit fG so, dass

AStör(fG) / ANutz(fG) << 1

ANutz(f)+A Stör(f)

...Nutzsignal

Störung

1.3.3 Diskretisierung der Eingabesignale, Abtasttheorem

Die Verarbeitung von Prozessgrößen durch einen Computer setzt deren Digitalisierung voraus. ► Dabei wird einerseits die theoretisch beliebig feine Auflösung der Wertachse in mehr oder weniger viele

Stufen reduziert, was die Genauigkeit eines Werts beeinträchtigen kann. ► Andererseits kann ein digitalisierter Wert nur zu diskreten Abtastzeitpunkten erzeugt werden und nicht

beliebig oft. Auch auf der Zeitachse muss also die theoretisch beliebig hohe Auflösung reduziert wer-den. Diese Einschränkung kann in Konflikt mit der Dynamik der erfassten Größe geraten: zu seltenes Abtasten erzeugt einen falschen Verlauf der Größe über der Zeit (sog. Aliasing).

Das Abtasttheorem (Claude Shannon, 1948) liefert eine Aussage über die mindestens nötige Abtastrate einer erfassten Größe und bezieht sich dabei auf die Dynamik der Messgröße. Man unterscheidet dabei analoge Größen, deren Wert im Prozess kontinuierlich veränderlich ist digitale Größen, deren Wert im Prozess in Stufen veränderlich ist a) Analoge Größen: Verlauf der höchsten im Signal enthaltenen Har-monischen beim Ab-tasten eines Analogsig-nals mit hinreichend hoher Zyklusrate (Überabtastung) (Quelle: Tietze/Schenk)

Entstehung eines Alias-Signals durch zu lang-same zeitdiskrete Ver-arbeitung eines zeit-kontinuierlichen Ana-logsignals (Quelle: Tietze/Schenk)

b) Digitale Größen

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 7 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Abtasten eines Binär-signals mit hinreichend hoher Abtastrate

Abtastperiodendauer Tv < T/2

Zeit

Signal

Verarbeitung

Min. Impulsperiodendauer T

In der Messtechnik kommt die Abtastung binärer Signale in der Praxis nicht vor, weil sie unnötig ist. Ein AD-Wandler wird ja nicht gebraucht. Weiterverarbeitende Systeme, z.B. Multiplexer für die Übertragung mehre-rer solcher Messsignale, und im besonderen Prozessrechner (Mikrorechner, SPS), die nicht mit den Schalt-ereignissen der Signale synchronisiert sind, müssen sich aber entsprechend der oben gezeigten Grafik ver-halten, damit keine Information verloren geht.

1.3.4 Echtzeit (Realzeit)

Datenverarbeitung in "Echtzeit" oder "Realzeit" bedeutet folgendes: Tritt in der Peripherie ein Ereignis ein, das der Zielcomputer bzw. ein auf ihm laufendes Programm verarbeiten soll, dann liegt das Verarbeitungs-ergebnis innerhalb eines vom Anwender definierten i.d.R. kurzen Zeitintervalls nach dem Ereignis vor.

tt0 t1 t2Zeitpunkte für die Fertigstellung der Bearbeitung

zu früh richtig zu spät

t0 Prozessereignis trifft ein

t1 Frühester Zeitpunkt

t2 Spätester Zeitpunkt

Mit dem Prozessereignis zum Zeitpunkt t0 beginnt eine Frist, zum Zeitpunkt t2 läuft sie ab. Innerhalb der Frist muss ein echtzeitfähiges System das Prozessereignis verarbeitet haben. Zu späte Reaktion, aber in manchen Fällen auch zu frühe, führt zu Fehlern in der Peripherie. Solche Fehler können sich sehr unterschiedlich darstellen. Abstrakt kann man versuchen, sie über Kosten-funktionen darzustellen. Entsprechend dargestellte Kosten kommen durch nicht eingehaltene Zeitvor-gaben zustande.

Pragmatische Einteilung in "harte" und "weiche" Echtzeit; "weiche" Echtzeit:

Die Kosten beschränken sich hauptsächlich auf den Betreiber des Echtzeitsystems. Kennzeichen "weicher" Echtzeit sind (deutliche) Minderung der Produktqualität (deutliche) Minderung der Produktivität des Betriebspersonals und der Betriebsmittel, z.B. wenn

Personal bzw. technische Einrichtungen sind nicht wie vorgesehen ausgelastet sind. Die Kostenfunktion (Anstieg über der Zeit) liefert für jedes mögliche Zeitargument einen definierten

Wert, bzw. der Kostenwert liegt immer unter einer Schranke, die konstant oder durch einfache Grenzkurve abschätzbar ist.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 8 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Nicht eingehaltene Zeiten durch das Zielsystems treten dabei nur "gelegentlich" auf. Die Kosten für die Einhaltung der Forderung nach "harter Echtzeit", siehe unten, sind unverhältnis-

mäßig hoch.

Fallbeispiele: ► Antwortzeiten eines Informationssystems. Ergonomisch günstige Antwortzeiten liegen im Be-

reich 0,8 s ... 1,3 s. Außerhalb dieses Bereichs nehmen Konzentration und Motivation der Mitarbeiter ab, und die Fehlerrate ihrer Eingaben nimmt zu.

► Produktionsprozesse mit großen verfahrensbedingten Zeittoleranzen wie z.B. Temperier- oder Klimatisierungsvorgänge: Zielsysteme hier sind ohne Echtzeitprogrammierung schnell genug.

► Abfolge der Bearbeitungsschritte einer CNC (aber nicht die Aktivität während eines Bearbeitungsschritts!):

Zwei typische Kostenkurven bei "weicher" Echtzeit:

t0 t2

Kosten

Zeit

Kostenasymptote

zugelassenes Kostenmaximum

Asymptotisch konstante "harmlose" Kostencharakteristik

t0 t2

Kosten

Zeit

zugelassenes Kostenmaximum

Zeitproportional verteuerte aber abschätzbare Kostencharakteristik

"Harte" Echtzeit

Die Folgekosten beschränken sich nicht auf die Betreiber des Echtzeitsystems. Sie sind entstehen durch Schaden oder Zerstörung von Einsatzstoffen (Ausschussproduktion) Schaden oder Zerstörung von Betriebsmitteln, wie z.B. Werkzeugen, Werkzeugmaschinen gesundheitliche Schädigung des Betriebspersonals, möglicherweise bis zur Todesfolge Schäden in benachbarter oder weiter entfernter Umgebung an Menschen, Einrichtungen und Ma-

terial. Ökologische Schäden. Die Schadenskosten sind u.U. nur noch zum Teil direkt monetär; man denke an Todesfälle, an

Konsequenzen aus strafrechtlicher Verfolgung der Schadensursachen oder an die Langzeitwir-kung großer Umweltschäden. Im Ganzen lässt sich schon bei relativ kleinen Verspätungen keine vertretbare Obergrenze der Schadenskosten mehr schätzen

Kostenkurvenform für Forderung nach "harter" Echtzeit

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 9 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

t0 t2

Kosten

Zeit

Bereich mit abschätzbarem aber unscharfen Kostenverlauf

zugelassenes Kostenmaximum

Bereich mit unwägbaren

Kosten

Beispiele:

► Verarbeitung kostenintensiver Einsatzstoffe ► Lenkung und Navigation schneller/schwerer Land- oder Luftfahrzeuge ► Offener Betrieb von Robotersystemen in Industrie und Medizin ► Verfahrenstechnische Prozesse mit hoher innerer Energie und phasenweise schnellen

Reaktionen (Kernreaktoren, chemische Produktion) Hier ist jeder Aufwand gerechtfertigt, damit die geforderten Zeitgrenzen stets und ohne Ausnahme eingehalten werden.

1.3.4.1 Zyklische Verarbeitung analoger Prozessgrößen in Echtzeit

Analoge Eingabesignale verändern sich stetig. Den Wertänderungen eines Analogsignals kann ein Pro-gramm ohne Informationsverluste nur folgen, indem es "genügend oft" seine Verarbeitungsschleife wie-derholt. Genügend oft heißt, mindestens mit der (korrekten) Abtastfrequenz des vorgeschalteten AD-Wand-lers. Das vom System einzuhaltende Reaktionszeitintervall { t2 - t0 } ist daher gleich der Abtastperiodendauer nach Shannon, wie weiter oben erklärt In hier relevanten Anwendungen, z.B. bei numerisch digitalisierten Reglern mit original analoger Übertragungsfunktion, muss ein echtzeitfähiges Zielsystem darüber hinaus auch isochron ausführen, d.h. es wiederholt in festen immer gleichen Zeitabständen seine Verarbeitung der Prozessgrößen. Dazu werden Softwarezeitgeber ("Timer") benötigt. Diese stehen Programmen über Standardbibliotheken als Ressourcen des Zielsystems zur Verfügung. Auch eine von der Echtzeituhr der Hardware ausgelöste Unterbrechung kann verwendet werden. Die Einzelheiten der Programmierung zyklisch ablaufender isochron echtzeitfähiger Programme behandelt dieser Umdruck weiter unten ausführlich. 1.3.4.2 Zyklische Verarbeitung von Schaltgrößen in Echtzeit

Auch digitale (wertdiskrete) Eingabesignale lassen sich zyklisch verarbeiten. Das hat den Vorteil, dass die Hard- und Software des Zielcomputers die Umschaltzeitpunkte der Prozessgrößen nicht erfassen muss, also keine Verarbeitung von Interrupt nötig ist. Umschaltungen des betrachteten Prozesssignals und Beginn der Verarbeitungsschleife sind dann aber nicht synchron, d.h. die "Schwingungen" beider Vorgänge haben eine zueinander zufällige Phasenlage. Damit trotzdem keine Information verloren geht, muss das Programm muss seine Verarbeitungsschleife schnell genug wiederholen, damit es alle Umschaltungen registriert. Die dazu hinreichende Bedingung erklärt die folgende Grafik.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 10 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

min. Progammzyklusdauer TProg <= T/2

Signal

Zeit

Rechner

fiktive Periodendauer T des schnellsten veränderlichen Schaltsignals

Das Reaktionszeitintervall { t2 - t0 } ist hier die halbe Periodendauer des schnellst veränderlichen Schalt-signals, bzw. bei veränderlichen Schaltzeiten die kleinste mögliche Halbimpulsdauer, also min { HIGH, LOW} dieses Signals. Diese Regel gilt, wenn ein Ereignis innerhalb einer gegebenen Frist lediglich zu erfassen ist. Wenn auch Reaktionen (Ausgaben an die Peripherie) gefordert sind, verkleinert sich die Reaktionsfrist um den Faktor ½. Ein Beispiel soll das deutlich machen. 1.3.4.3 Beispiel: automatische Erkennung und Navigation fahrerloser Fahrzeuge

Für ein werksinternes Transportsystem soll eine automatische Navigation fahrerloser Fahrzeuge entwickelt werden. Die Fahrzeuge fahren spurgeführt auf Einbahnstraßen mit maximaler Geschwindigkeit von 10m/s und halten einen Mindestabstand zum vorausfahrenden Fahrzeug von 5m stets ein. Vor jeder Verzweigung bzw. Kreuzung gibt es eine 10m lange Kontrollstrecke, hier im Bild dick markiert. Innerhalb dieser Strecke kann ein Fahrzeug registriert werden.

Kontrollstrecke

5m

10m/s 10m/s

Erfassung

Auswertung

Navigations-befehl

Bremsweg

5m

Die Fahrzeugankünfte sind ein Zufallsprozess. Wird ein Fahrzeug in der Kontrollstrecke erkannt, erfasst ein stationärer Mikrorechner über ein Funkinterface die Kenndaten jedes ankommenden Fahrzeugs, darunter die eindeutige Kennung des Exemplars und das Fahrziel, und wertet beides aus. Für jedes neu angekom-mene Fahrzeug stellt der Mikrorechner die Richtung der Weiterfahrt fest und prüft, ob ein Konflikt mit einem Fahrzeug aus der kreuzenden Richtung vorliegt. Dann sendet er die entsprechenden Befehle zurück an das Fahrzeug. Der zweite 5m lange Abschnitt dient bei Bedarf als Bremsweg. An seinem Ende biegt das Fahrzeug ggf. ab. Vereinfachte Aufgabenvariante a): jedes Fahrzeug, das ein Verzweigung passiert, muss erfasst werden.

Die Aufenthaltsdauer in der Kontrollstrecke beträgt (höchstens) 0,5 s. Dies ist die halbe Impulsperioden-dauer eines fiktiven Schaltsignals "Fahrzeugdurchfahrt". Die andere "Hälfte" der Impulsperiode hat, auf ein bestimmtes Fahrzeug bezogen, im ungünstigsten Fall wegen des einzuhaltenden Bremsabstands dieselbe Dauer. Die Annahme einer Impulsperiode im Gegensatz zu einem Einzelereignis ergibt sich aus der zyklischen Programmwiederholung, die ohne Synchronisation mit dem Ereignis "Fahrzeug trifft ein"

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 11 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

auskommen muss. Statt dessen muss eine Wiederholrate dafür sorgen, dass ein Fahrzeug sicher irgendwo auf der Kontrollstrecke erfasst wird, und sei es beliebig kurz vor deren Ende. Mit diesem Ansatz haben wir eine Impulsperiodendauer (Schaltfrequenz) des Signals "Fahrzeug in der Kontrollstrecke" von tFZ = 1,0 s. Gemäß Abtastgesetz für Schaltgrößen ergibt sich die max. Zyklusdauer für die im Mikrorechner ablaufende Erfassungssoftware auf tErfass ≤ ½ tFZ = 500 ms. Mit dieser Zyklus-zeit "verliert" das verarbeitende System kein einziges Fahrzeug.

Volle Aufgabenvariante b): Jedes Fahrzeug, das auf eine Verzweigung zufährt, muss erfasst und navigiert werden.

Mit der Zykluszeit 500 ms bemerkt das System im ungünstigsten Fall ein Fahrzeug erst unmittelbar vor seiner Ausfahrt aus der Kontrollstrecke. Da dann die Berechnungen für eine Brems- und Richtungs-entscheidung noch nicht stattgefunden haben, kommt die Ausgabe des Navigationsbefehls erst, wenn das Fahrzeug sich mit 10m/s irgendwo schon innerhalb des Bremswegs befindet, also nicht rechtzeitig. Damit der Bremsweg eingehalten wird, muss jedes Fahrzeug spätestens am Ende der Kontrollstrecke seinen Bremsbefehl haben. Der Richtungsbefehl ist weniger zeitkritisch und kommt zeitgleich mit der Ent-scheidung zum Bremsen immer rechtzeitig. Man muss also die Zyklusdauer tErfass um eine Dauer tVA verkürzen, in der die Berechnungen für eine Brems- und Richtungsentscheidung ausgeführt werden und der Befehl in das Fahrzeug übertragen wird. Dies ist die Zyklusdauer für eine Programmierung mit Erfassung, Bremsen und Navigation der Fahrzeuge auf der Strecke: tBREMS ≤ tErfass - tVA. tVA hängt ab vom Typ der Hardware (Maschinenbefehlsrate des Zielrechners, Bitrate der Datenübertra-gung zum Fahrzeug) und von der Implementierung des Programms (Anzahl Befehle). Beides ändert sich im Produktlebenszyklus, und mit ihr der kritische Wert der maximalen Zyklusdauer, und das ist nicht be-friedigend. Einen sicheren Wert, der nur von der Impulsperiodendauer des Prozesssignals abhängt, liefert die folgen-de Überlegung. Wir nehmen einen sehr kleinen Wert für tVA, der die Dauer tErfass nicht merklich verlän-gert. Bei einem solchen tVA, wissen wir aber, dass es zu kurz geschätzt sein kann und also seinen Zweck nicht erfüllt. Wir verlängern nun tVA und können dennoch nie ausschließen, dass dies Intervall immer noch zu kurz ist, d.h. die Zykluszeit für die Entscheidung zum Bremsen tBREMS zu lang ist. Irgend-wann erreichen wir tBREMS ≤ tErfass - tVA = 1/2 tErfass = 250 ms, ohne dass die Annahme für tVA grundsätzlich sicherer wird. Lediglich die Wahrscheinlichkeit nimmt irgendwie zu, dass wir den Wert nicht unterschätzen. Nun dürfen wir aber tVA nicht weiter vergrößern, denn sonst dauert die Verarbeitung länger als das Intervall, in dem sie sich wiederholen soll, und damit geht die Echtzeiteigenschaft verloren. Daraus folgt in diesem Beispiel: Jedes Computersystem, das es schafft, für Berechnung zur Bremsentscheidung weniger als die halbe

Impulsperiodendauer eines fiktiven Schaltsignals "Fahrzeugdurchfahrt" zu verbrauchen, genügt der gestellten Aufgabe. Systeme, die dies nicht schaffen, sind im Sinne der Aufgabe nicht echtzeitfähig.

Die sichere Schätzung hängt nun nur von der Dynamik des Prozesssignals ab. Sie fasst das ungünstigste Zeitverhalten des technischen Prozesses und des Computersystems für

die Automatisierungsaufgabe zusammen. 1.3.4.4 Ereignisorientierte Verarbeitung von Schaltgrößen in Echtzeit

Wertänderungen digitaler Größen enthalten Umschaltvorgänge. Diese können als "Ereignisse" betrachtet werden. Ereignisse im softwaretechnischen Sinn sind durch Programmunterbrechungen darstellbar. Über seinen Unterbrechungseingang kann ein CPU benachrichtigt und aufgefordert werden, das Ereignis sofort mit dem vorgesehenen Programmcode zu behandeln. Nötig ist das, weil das gerade laufende Programm bzw. die CPU zum Zeitpunkt des Ereigniseintritts im Allgemeinen andere Aufgaben bearbeitet, als z.B. die sofortige Erfassung und Verarbeitung soeben neu eingetroffener Daten (Werte) in Echtzeit. Eine Unterbrechungsanforderung wirkt wie ein Prozeduraufruf und kann per Software oder von Komponen-ten der Zielhardware ausgelöst werden, in dieser von einem Eingabeinterface. Die "aufgerufene" Prozedur ist ein geeignet programmierte Interrupt Service Routine (IRS) und behandelt das kritische Datenereignis,

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 12 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

bevor das unterbrochene Programm fortgesetzt wird. Anstelle einer zyklischen programmierten Abfrage mit mehr oder minder sicher geschätzter Wiederholrate genügt es, einmal das benachrichtigende Ereignis zu behandeln und bis zum nächsten Ereignis zu warten.

Verarbeitungsintervall

Interrupt-latenzzeit

Interrupt-latenzzeit

Umschaltung Umschaltung

Signal

Programm

Zeit

Interrupt Service Routine

Detaillierte Erklärungen zur Programmentwicklung mit Unterbrechungsanforderungen folgen weiter unten. 1.3.4.5 Echtzeiteingabe, Pufferung und Weiterverarbeitung von Prozessdaten

Fallen Reaktionszeitforderungen an ein Programm deutlich großzügiger aus als es der Abtastfrequenz fa des Messsystems entspricht, kann die Datenerfassung durch eine Pufferung von der Weiterverarbeitung entkoppelt werden. Die Datenerfassung folgt wie bisher dem Abtastgesetz für die vorhandene Signalform und speichert die Eingabedaten in Echtzeit in den Speicher. Die Weiterverarbeitung der gepufferten Daten muss der Erfassung einzelner Werte nicht Schritt halten. Dennoch muss die langfristige mittlere Datenverarbeitungsrate [Bit/s] der Weiterverarbeitung mindestens gleich oder größer sein als diejenige der Datenerfassung. Sie kann dabei aber anderen zeitlichen Mustern folgen. Je größer der Datenpuffer ist, desto seltener muss die Weiterverarbeitung auf den Puffer zugreifen. Zum Ausgleich muss aber dann die Verarbeitungsrate während des Zugriffs entsprechend hoch sein. Allgemein gilt: in der Mindestzeit einer Pufferfüllung muss die Weiterverarbeitung mindestens zweimal wiederholt werden, damit keine Information im Puffer verloren geht. Unterschiedliche Zeitbedingungen bei der Prozesseingabe und der Weiterverarbeitung können also über geeignet dimensionierte Puffer entkoppelt werden. Diese Art der Weiterverarbeitung ist typisch für Prozess-leitsysteme: Prozessnahe Automatisierungsgeräte arbeiten und puffern eine kleine Informationsmenge schritthaltend mit hoher Änderungsfrequenz der Prozessgrößen. Überlagerte Prozessleitsysteme lesen und verarbeiten pro Zugriff eine große Informationsmenge aus dem Puffer bei vergleichsweise kleiner Zugriffsfrequenz.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 13 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

1.3.5 Programme für analoger Prozesse am Beispiel Regelung

1.3.5.1 Signalflussbetrachtung

Signalflussschema einer Regelung

w e=w-r y

z1

y+z1 x

x

-r

x+z2

z2

ReglerRegel-strecke

Rückführung

Stellglied und Prozess

Mess- undÜbertragungssystem

Programm auf Leit-, Führungs-,Steuerrechner

Mikrorechner mitReglerprogramm

Hilfsenergie

Informationsfluss

Energiefluss

mit den (quasi) analogen Signalen

w oder u "Sollwert" oder Führungsgröße r "Istwert" oder Rückführgröße e = w - r Regelabweichung y Stellgröße x Prozessgröße oder Regelgröße z1, z2 Störgrößen

Signalfluss einer Steuerkette

U: Führungsgrößen

Diskrete Grenzzustände

R: Ausnahmesignale

Steuer-gerät

Steuer-strecke

A Priori - Kenntnis derSteuerung über das

Verhalten der Strecke

keine Störungen

DigitalesMesssystem

X: Analoge Prozessgrößen

Man bezeichnet eine solche Signalflussstruktur auch als Steuerkette:

Verkettung (quasi-) analoger Übertragungsglieder ohne übergreifende Rückkopplung Vorgabe analoger Führungsgrößen an ungestört folgende Strecken. Keine Rückführung analoger Prozessgrößen, sondern nur diskreter Grenzzustände.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 14 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Bsp. Handhabungssystem mit gesteuerter Zielpositionierung und geregelter Bewegung an die Zielposition z.B. mit Servoantrieben:

Lageregelkreis X

Berechnung desnächsten

Lagesollwerts

ZeitlicheVorgaben

DatentechnischeBeschreibung

einer Bewegungsbahn

Lageregelkreis Y

geregelte Lage des Prozessobjekts

Lageregelkreis Z

x(x)

x(y)

x(z)

u(y)

u(z)

u(x)

Regelungen als Blöcke in einer analogen Steuerkette

1.3.5.2 Mathematisches Modell

Ein Regler verarbeitet die zeitveränderlichen Größen w, y, z und x. Computerprogrammierte Regelungen ar-beiten zeitdiskret, d.h. nur zu bestimmten Zeitpunkten bildet das Programm den Wert der Stellgröße y aus Werte der Regel-, Führungs- und Störgröße. Falls diese Zeitpunkte auch für die "schnellsten" spektralen An-teile der verarbeiteten Größen das Abtasttheorem erfüllen, dürfen die im Zeitbereich üblicherweise als Diffe-rentialgleichungen vorliegenden Übertragungsfunktionen von Regler und Strecke durch Differenzengleichun-gen ersetzt werden. Dabei entsteht ein Fehler, der mit vergrößerter Abtastrate abnimmt.

Regler-Übertragungs-

funktion

Strecken-Übertragungs-

funktion

1

z

yx

w

x

-us

Mathematisch exakt im Zeitbereich entsteht die Übertragungsfunktion einer abgetasteten Größe, indem man die kontinuierliche Übertragungsfunktion einer z-Transformation unterzieht, die transformierte Funktion nach der Zielgröße y auflöst und die dadurch entstandene Funktion in den Zeitbereich zurücktransformiert. Den mathematischen Hintergrund dazu erklärt die Regelungstechnik. Hier soll anstelle der Z-Transformation nur eine grob approximierte Diskretisierung mit sehr hoher Überabta-stung erklärt werden. Im Folgenden wird der Wert einer zeitvarianten Größe x(tn) zum diskreten Abtastzeitpunkt tn auch mit

x(n) bezeichnet. Der Zeitabstand zweier Abtastzeitpunkte tn - tn-1 = ∆t ist konstant. Das Differential dx(t) wird durch die Differenz der Werte an benachbarten Abtastzeitpunkten ersetzt:

dx(t) wird zu x(n) - x(n-1) , und dt

tdx )( wird zu

t

xx nn

)1()(

Anstelle der Differentialgleichung entsteh damit eine algebraische Gleichung für jedes Übertragungs-glied, die lässt man nach folgendem Schema auflöst:

XA

(n) = F ( XA(n-1) , XA

(n-2) , … , XE1(n), XE2

(n), ... ) "Neue Ergebnisgröße = Funktion von alten Ergebnisgrößen und aktuellen Eingangsgrößen".

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 15 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

In einem Programm werden die "alten" Ergebnisgrößen im den vorigen Rechenzyklen in Puffer-variablen gespeichert. Ist eine lineare Differentialgleichungen n. Ordnung ("analog"), benötigt ein Programm n-2 Puffervariablen zusätzlich zur Ergebnisgröße.

Es folgen Beispiel für Übertragungsfunktionen von Regler, Strecke und geschlossenem Kreis.

P-Regler: )())()(( )()( nnPP xwKtxtwKy (1)

I-Regler: dttxtwKty I )()(()( ))()(()(

txtwKdt

tdyI

Daraus wird durch zeitliche Diskretisierung:

)( )()()1()(

nnI

nn

xwKt

yy

)( )()()1()( nnI

nn xwKtyy (2)

PI-Regler: dttxtwKtxtwKty IP ))()(())()(()(

))()(())()(

()(

txtwKdt

tdx

dt

tdwK

dt

tdyIP

Daraus wird durch zeitliche Diskretisierung:

)()()1()()1()(

)()()1()(

t

xx

t

wwKxwK

t

yy nnnn

Pnn

I

nn

)(

)()1()()1()(

)()()1()(

nnnnP

nnI

nn

xxwwK

xwKtyy

P

nPI

n

Pn

PInnn

KxKKtx

KwKKtwyy

)1()(

)1()()1()(

)(

)( (3)

PT1-Strecke: )( )()()()1()(

nnS

nnn

S zyKxt

xxT

)( )()()1()( nnS

S

n

S

Sn zyKtT

tx

tT

Tx

(4)

Mit simulierter Schnittstelle Regler-Strecke-Messsystem Abtasttheorem beachten:

Streckentask "sehr viel" öfter ausführen als Reglertask! Reglertask so oft ausführen, dass Abtasttheorem bezüglich PT1-Frequenzgang der Strecke ( = des

Objektprozesses) erfüllt ist! fAbtast(Streckentask) >> fAbtast(Reglertask) > 2.n . 10 T1

wobei n der Überabtastung entspricht, z.B. n=5 und die Relation >> als Faktor 10 oder mehr gelten kann.

Ohne Schnittstelle: eine Gleichung für Regler und Strecke. Technisch unrealistisch, aber zu Simulations-zwecken geeignet. Vorteil: konstante "optimale" Phasenlage zwischen Regler und Strecke vermeidet Zeit-probleme. Geschlossener Kreis mit P-Regler und PT1-Strecke:

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 16 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

(1) in (4) eingesetzt ergibt

SPS

nS

nPS

nSn

TKKtt

zKtwKKtxTx

)()()1()( (4)

Geschlossener Kreis mit I-Regler und PT1-Strecke:

(2) in (4) eingesetzt ergibt

( 1) 2 ( ) ( 1) ( )

( )2

n n n nn S S I S S

S I S

T x t K K w K y t K zx

t t K K T

(5)

Geschlossener Kreis mit PI-Regler und PT1-Strecke:

(3) in (4) eingesetzt ergibt (6)

ISPSS

nS

nS

npS

nISPS

nPSSn

KKtKKttT

ztKytKwKtKwKKtKtKxKtKTx

2

)()1()1()(2)1()(

)()(

1.3.5.3 Programmentwurf

Das Hauptprogrammflussschema eines Regelkreises mit PI-Regler zeigt grob aufgelöst das folgende Struk-togramm.

Der Regelalgorithmus hier entspricht einer linearen Differenzialgleichung erster Ordnung mit konstanten Koeffizienten. Sie wird mit einer nicht näher definierten Differenzengleichung mathematisch angenähert wie in dem entsprechenden Abschnitt weiter oben erklärt. 1.3.5.4 Programmrealisierung

Wird anhand des über die Webseite zur Vorlesung erreichbaren Beispielprogramms erklärt.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 17 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

1.3.6 Programme für digitale Prozesssignale am Beispiel digitale Steuerung

1.3.6.1 Sequentieller Zustandsautomat

Der Begriff Steuerung steht hier für die Automatisierung technischer Schaltprozesse, d.h. die Strecke ist selbst digital. Hier das bekannte schaltlogische Grobmodell eines MOORE-Automaten:

Speicher Schaltnetz Schaltnetz

DiskretertechnischerProzess

BinäreStellgrößen

Binäre Messgrößen Rückführung

Binäre Anzeigegrößen

Binäre Führungsgrößen

Y = f (Q(T))

Q(T+1)=g(X,Q(T))

X

Q(T)YQ(T+1)

Q(T)

1.3.6.2 Programmentwurf eines MOORE-Automatenen

Hier läuft im Hauptprogrammzyklus kein Regler, sondern ein Zustandsautomat ab. Wir bleiben bei dem Linearbeweger aus der Vorlesung Industrielle Steuerungen. Zu dem früher schon behandelten Codebeispiel soll hier das Beispielprogramm struktografisch erklärt werden.

Aus dieser groben Auflösung nehmen wir nur die Hauptfunktion verfeinert in den Blick. Die Hauptschleife enthält nun auch eine Fehlerbehandlung der Eingabe. Der Verarbeitungsteil ist der Zustandsautomat des Linearbeweger.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 18 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Da es hier im Gegensatz zur Regelung keine algorithmisch definierten Zeiten gibt, könnte der Block mit der Zeitkontrolle auch entfallen. Damit könnten aber auf schneller Rechnerhardware zu hohe Wiederholraten entstehen. Diese würden auf Zielen mit Einprogrammbetrieb (Single Tasking) u.U. Interfaces überfordern, also die Echtzeitanforderung "nicht früher als t1" verletzen. Darüber hinaus würde ein evtl. Multitaskbetrieb von einem solchen Programm erheblich gestört werden, denn die ausführende Task versucht, alle Rechenleistung der CPU allein für sich in Anspruch zu nehmen. Dadurch kommen andere Task überhaupt nicht zu Zug, oder die hier programmierte Task wird irgendwann während einer Dauer gestoppt, die keine Rücksicht auf die Echtzeitanforderungen t2 der Peripherie nimmt. Also: immer 1x blockiert im Hauptprorammzyklus blockiert warten, Ausnahme: die SPS.

Das nächste Struktogramm zeigt die Verfeinerung des Blocks mit dem Zustandsautomaten. Es wird in der Vorlesung ausführlich erklärt.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 19 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

1.3.6.3 Programmrealisierung

Wird anhand des über die Webseite zur Vorlesung erreichbaren Beispielprogramms erklärt. Die Aufgabe ist der Linearbeweger aus dem Umdruck der Vorlesung "Industrielle Steuerungen".

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 20 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

2 Ablauf eines Hauptprogramms

Programmierung symbolisch Programmquelle als Text formulieren in einer Programmiersprache, Erstellung mit

Entwicklungsumgebung, Beispiel C/C++ oder Ausführung durch einen Interpreter (virtuelle Maschine), Beispiel JAVA

grafisch in Form von Blockdiagrammen wie bei Matlab, Simulink, Grafcet, FUP Hier: symbolische Programmierung in (nicht objektorientiertem) C.

2.1 Hauptprogrammzyklus mit Endlosschleife

Zyklische Wiederholung von Eingabe, Verarbeitung, Ausgabe (E-V-A) mit kontrolliertem Warten

Der mit Verarbeitung bezeichnete Block enthält den Kern der Prozessautomatisierungsaufgabe. In den meisten Fällen lässt sich dieser entweder auf Regelungen oder auf Zustandsautomaten oder eine Kom-bination beider zurückführen. Softwaretechnisch entsprechen diesen beiden Grundtypen der Prozess-automatisierung recht unterschiedliche Programmflüsse, wie weiter unten gezeigt wird.

2.2 Kontrolliertes Warten

2.2.1 Diskontinuierlicher Ablauf durch Unterbrechungen aus der Peripherie

Machen Sie sich zunächst klar, dass ein Unterschied besteht zwischen einem Programm und dem Prozess seiner Ausführung. Letzteren nennt man auch "Prozess" oder "Task". Er stellt ein Grundkonzept aller Betriebssysteme dar.

Achtung, der Begriff "Prozess" hat hier eine andere Bedeutung als in "Prozessdatenverarbeitung". Er steht sinngemäß für eine die virtuelle CPU, die das jeweils betrachtete Programm ausführt. Sie ist ein

Bestimmte Elemente im Code eines Programms bestimmen, in welchem Zustand sich die Task befindet, während sie das Programm ausführt. Während ihren Laufzeit (in der Zeit nach Programmstart und vor Programmende) kann eine Task unter-schiedliche Zustände annehmen, in die es sein Programm bringen kann: in Ausführung befindlich: das Programm wird ausgeführt.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 21 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

laufbereit wartend: das Programm wurde unterbrochen und kann fortgesetzt werden, es wartet aber auf

die CPU. Dieser Zustand hat Ähnlichkeit mit dem Zustand einer aufrufenden Funktion, die auf das Ende der von ihr aufgerufenen Funktion wartet.

blockiert wartend: das Programm wurde unterbrochen und kann nicht ausgeführt werden, denn es war-tet auf die Erfüllung bestimmter Bedingungen, die zu seiner Fortsetzung notwendig sind. Dies ist z.B. der Fall nach Aufruf einer Wartezeitfunktion, bevor die im Argument übergebene Zeit abgelaufen ist, oder nach Aufruf einer Eingabefunktion, bevor die Eingabedaten bereitstehen.

Diese blockierende Synchronisation beruht auf Unterbrechungen (genauer: Unterbrechungsanforderungen) und macht es möglich, dass eine Task passiv auf Eintritt eines bestimmten Ereignisses wartet. D.h., das Programm ist unterbrochen und führt keine Abfrage aus (kein "Polling"). Auslöser der Unterbrechung ist das Programm selbst, indem es eine Wartefunktion aufruft, in deren Maschinenprogrammcode eine sog. Softwareunterbrechung (Trap) enthalten ist.

in Ausführung blockiertwartend

auf Ereignis

Latenz

in Ausführung

Anwendungs-programm

...Interface oderZeitgeber

...

Blockierung beendendes

Ereignis

blockierende Wartefunktion

Zeit

Sobald ein definiertes Ereignis eintritt, wird das Anwendungsprogramm aktiviert, so dass es dann seine Be-arbeitung ausführt. Ereignisse werden in der programmierten Ein- Ausgabe in den Standardfunktionen "ver-steckt": z.B. wird ein von der Standardperipherie lesendes Programm durch Aufruf der Eingabemethode (in C/C++ fscanf oder cin >> ) in seiner weiteren Programmausführung gestoppt ("blockiert"). Das betref-fende Interface für die Eingabekonsole hebt später mit einer Unterbrechungsanforderung diesen Stopp-zustand (die Blockierung) wieder auf, sobald eine Person die erwarteten Daten über die Bedienkonsole eingegeben hat.

Zeit

Anwendungs-programm

Interface oder Zeitgeber

Ein Problem kann dabei entstehen, wenn aus mehreren Interfaces Dateneingabe auf diese Art erfolgen soll. Langes Warten auf eine Eingabe u kann die fristgerechte Übernahme und Bearbeitung einer zweiten Ein-gabe x behindern. Daher darf ein Programm nicht ohne weiteres auf mehrere Eingabeprozesse blockierend warten, wenn nicht langsamste von diesen das Maß für die Echtzeitfrist t2 bestimmen soll. Das folgende Programm soll das illustrieren.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 22 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

// Hier werden alle Variablen deklariert: ... //

do ///////////////////////// Hauptprogrammschleife beginnt /////////////// { //

get_input_from( in_Interface1, &u ); // hier Stopp! ... // ... weiter, wenn Eingabe da get_input_from( in_Interface2, &x ); // hier wieder Stopp! ... // ... weiter, wenn Eingabe da y = control( x ); // Verarbeitung put_output( out_Interface, y ); // Ausgabe }

while( run == TRUE ); /// Hauptprogrammschleife endet ////////////////// Der kursive Programmteil bringt ein Zeitproblem, da die Task hier blockiert auf das 2. Interface wartet. Falls die Peripherie hier langsamer ist als die am 1. Interface, muss die Task hier zu lange warten. Dann kann es sein, dass im 1. Interface jeweils neue Werte von noch neueren überschrieben werden, oder dass das 1. Interface die neuesten Werte nicht annimmt. In jedem Fall geht relevante Information verloren. Grundsätzlich bringt es Zeitprobleme mit sich, wenn ein Hauptprozesszyklus auf mehr als ein Prozessereig-nisblockiert wartet. Eine Programmierung mit dieser Wirkung muss vermieden werden. Besser wäre es hier, nur auf das Interface 1 mit der "schnelleren" Peripherie zu warten und die zweite Eingabe im selben Zyklus nicht blockierend auszuführen. Aber weiß man zur Programmierzeit, wann Peripherie 1 schneller ist, und wann 2? Richtig ist, beide Interfaces nicht blockierend zu lesen. Dazu benötigt man Bibliotheksfunktionen mit nicht blockierendem Verhalten, oder direkten Speicherzugriff auf die Interfacehardware, und einen echtzeitgerecht programmierten zyklischen Timer, auf den die Task an einer Stelle des Hauptprogrammzyklus blockiert wartet. Beides wird in dieser Vorlesung später im Einzelnen erklärt. Der nächste Abschnitt zeigt dazu das Prinzip.

2.2.2 Quasi kontinuierlicher Ablauf mit isochronem Timing

Programme mit Regelungsaufgaben führen Algorithmen aus wie im Abschnitt über die Regelung weiter oben gezeigt. Weil sie quasi Ersatz für analoge Regelgeräte sind, funktionieren sie nur dann richtig, wenn ihr Hauptprogramm die Algorithmen exakt in einem Zeitmaß wiederholt, das der Übertragungsfunktion des Reglers entspricht. Das heißt, solche Programme müssen ihren Zyklus isochron wiederholen. Ideales = isochrones Wiederholungsverhalten mit konstanter Zykluszeit:

tZYKLUS tZYKLUS

tVERARBEITUNGtVERARBEITUNG tVERARBEITUNG

treserve treserve treserve

tZYKLUS

Zeit

Erreichen kann ein Programm das, indem es sich von einem im seinem Hochlauf programmierten Zeitgeber in seiner Hauptschleife zyklisch "aufwecken" lässt. Eine Erklärung in Pseudocode:

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 23 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

// Hier werden alle Variablen deklariert: ...

// Hier werden die Reglerparameter bestimmt: ... // Hier wird der Timer angefordert und so programmiert, dass er zu den // Reglerparametern passend in exakt gleichen Zeitabständen eine Nachricht // an diese Task sendet, die ihren blockierten Wartezustand beendet ...

do ///////////////////////// Hauptprogrammschleife beginnt /////////////// { //

get_input_nonblocking( in_interface1, &x ); // hier kein Stopp! get_input_nonblocking( in_interface2, &u ); // hier kein Stopp! // y = control( u, x, parameters ); // Verarbeitung im Regler put_output( out_Interface, y ); // Ausgabe an Stellgerät timer_wait( mytimer, NULL ); // hier Stopp, bis Timer sendet // weiter, wenn Nachricht da }

while( run == TRUE ); /// Hauptprogrammschleife endet //////////////////

3 Ein- und Ausgabe

3.1 Hardwareaufbau und Adressräume

Unter Ein- und Ausgabe versteht man die Datentransfers laufender Programme (d.h. CPU) mit der Computerperipherie. Die Richtungsattribute Ein und Aus gelten grundsätzlich aus Sicht der laufenden Programme bzw. der CPU.

Laufende Programme

Computer-peripherie

Externe Schnitt- stellen

AdressierbareBausteine

Systembus desComputers

Beobachtungs- undBedienprozess

Druckprozess

Datensuche und-speicherung

Datenübertragungs-prozess

Standard-peripherie

Programme

"Prozess-peripherie"

Netzwerke, Feldbusse

Terminal

CPU

Arbeits-speicher

Terminal-interface

Drucker-interface

Netzwerk-interface

Platten-speicher

Platten-controller

Technische Prozesse

Drucker

Prozess-peripherie

Ein-Ausgabe digital

Ein-Ausgabe analog

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 24 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Wie Sie hier im Bild sehen, stellen Interfaces adressierbaren Speicher bereit bzw. erweitern den von der RAM bzw.…ROM-Hardware bereitgestellten Speicher. Eine CPU kann nämlich nur Operanden in ihrem eigenen Adressraum verarbeiten. Die Interfaces stellen die Funktionen und Daten des jeweils angeschlossenen Peripheriegeräts, und ihre eigenen, im Adressraum der CPU bereit. Das folgende Blockschaltbild eines Interface und seine Erläuterung in der Vorlesung sollen das deutlich machen.

Prozessor Systembusschnittstelle

Datenregister

Interface-baugruppe

Steuerwerk undDatenumformatierung

Externe Schnittstelle(Senden/Empfangen)

InternerSystem-

bus

DatenregisterEin-/Ausgabe- daten

Lokale Dienste

Prozesse in der Peripherie

Externes Datenbertragungsmedium

Lokale Anwendung

Kontrollregister

Statusregister

Daten

Steuerung

Adressen

In den Adressraum, der aus logischer Sicht für Programmcode und deren Operanden (den nicht ganz korrekt so genannten Daten) vorgesehen ist kann ohne weiteres auch die Hardware der Interfaces einbezogen wer-den. Man nennt ihren Betrieb dann "memory mapped" oder speichergebunden. Wichtig ist dabei, dass der Code laufender Programme die Adressenbereiche korrekt zuordnet bzw. unterscheidet. Das setzt bei den Programmierteams entsprechendes Wissen über die Bestückung des Speichers im Einzelnen voraus. Je nach der Höhe des Datenaufkommens in Bit/s kann es sinnvoll sein, die CPU beim Transfer der Interface-daten von und zu den Prozessabbildern der Erzeuger- oder Verbrauchertasks im RAM zu umgehen. Diese Art der Ein- und Ausgabe läuft unter dem Titel DMA. Ihr Wirkungsprinzip wird in der Vorlesung erklärt. Manche CPU, u.a. die 80x86-Typen, können mit einer kleinen Menge spezieller Ein- und Ausgabebefehle, der sog. Port-I/O, einen zusätzlich Adressraum nur für Ein- und Ausgabe ansprechen. Diese Befehle kopie-ren Daten vom Port- in den Memoryadressraum und umgekehrt. Weitere Verarbeitung von Eingabedaten bzw. Vorverarbeitung der Ausgabe findet grundsätzlich im Memoryadressraum statt. Eine solche CPU schal-tet im entsprechenden Befehlszyklus ein Codewort oder Bit auf den Steuerleitungen des Systembusses von "Memory" in "I/O" um. Damit werden RAM, …ROM sowie die speichergebunden ("memory mapped") adres-sierten Interfaces gesperrt, und die sog. portadressierten Interfaces freigegeben. Welches Interface über eine Memory- bzw. Portadresse angesprochen werden muss, richtet sich nach deren Einbaukonfiguration bzw. deren Typ.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 25 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Ein Beispiel für eine CPU mit 32 Bit Adresswortgröße zeigt das folgende Bild. Wir gehen im folgenden nicht mehr auf die Portadressierung ein, weil sie zum Verständnis der folgenden Abschnitte nicht nötig ist und weil sie in der Praxis heutiger Systeme mit ihren großen Adressräumen nicht benötigt wird.

Adressierung mit allen Instruktionen

außer in und out

Memory-Adressraum

Programme und Daten

SpeichergebundeneEin- und Ausgabe("memory mapped")

Port- Adressraumsog.portadressierendeEin- und Ausgabe

0x FFFF FFFF

0x 0000 0000 0x 0000

0x FFFF

Adressierung ausschließlich

mit den Transfer-instruktionenin und out

3.2 Speicheradressierter Zugriff auf Interfacehardware

Programme greifen hier über deren reale Speicheradressen auf Hardwareregister zu (die "physikalischen" Adressen). Dazu ist nacheinander folgendes nötig:

(a) Definition eines Strukturdatentyps, bzw. des Datenteils einer Klasse, für die Registerstruktur des Interface: im Programmheader

(b) Anlegen eines Zeigers dieses Datentyps: im Deklarationsteil des Hauptprogramms (c) Zuweisen der realen Speicheradresse des Interfaces an den Zeiger: im Hochlauf des Haupt-

programms (d) Daten aus dem Interface per Zeiger lesen bzw. dahin schreiben: im Hauptprogrammzyklus.

Beispiel einer Definition des Strukturdatentyps für ein fiktives Interface: // Headerdatei PDV_IO_definitions.h ////////////////////////////////////////////////// // Datentypen // // typedef unsigned long UINT32; // Typ DWORD typedef unsigned short int UINT16; // Typ WORD typedef signed short int SINT16; // Typ INT // #define IFX_PNPSIGNATURE "PDV_IO_typeX" // Signatur, soll automatische // // Hardware-Erkennung unterstützen const int IO_IFX_N = 40; // Anzahl WORDS im IO-Registersatz // struct PDV_IO_typeX // Strukturtyp des hier verwendeten Interface /////////////////// { // char pnp_signatur[32]; // Signatur für PnP-Unterstützung // // // SINT16 data_inout[IO_IFX_N]; // Eingaberegistersatz, Ausgaberegistersatz // // // UINT16 control; // Steuerregister // UINT16 flags; // Statusregister // // // // Annahme: aufsteigende Adressen // // Komponten werden an fortlaufenden logischen_ (!!) Adressen angelegt. // // Ob auf- oder absteigend, muss anhand der Kenntnis der Entwicklungs- // // und Zielsysteme geklärt werden! // }; // /////////////////////////////////////////////////////////////////////////////////////

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 26 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Beispiel einer Anordnung von 2 Interfaces dieses Typs im realen Adressraum (Teil der Zielrechnerkonfigura-tion):

0x0000 0000Anfang des realen

Adressraums

"Offset" des 1. E/A-Interface

einzubindender Bereich 2

einzubindender Bereich 1

0x000C 0000Basisadresse des

2. E/A-Interface

0x000D E000Basisadresse des

2. E/A-Interface "Offset" des

2. E/A-Interface

3.2.1 Real adressierende Zielsysteme

Viele Microcontroller-Laufzeitsystem, aber auch einige Betriebssysteme adressieren in Programm: #include <sys/mman.h> #include <stdlib.h> #include <inttypes.h> // #include "PDV_IO_definitions.h" // int main( int argc, char * argv[] ) { PDV_IO_typeX * ptr_io1 = NULL; // Pointer für Interfaceobjet, noch ohne Ziel unsigned long base; // Adresse bool run; // Laufbedingung der Hauptschleife // weitere Deklarationen ... if ( argc != 2 ) { fprintf( stdout, "Nochmal aufrufen mit Interfaceadresse:\n"); fprintf( stdout, "%s <Basisadresse in hex>\n", argv[0] ); } else { base = ( unsigned long )atoh( argv[1] ); // Adresse aus argv[1] gewandelt if( base == 0 ) { // hier unplausible Werte abfangen ... } else { ptr_io1 = (PDV_IO_typeX * )base; // // Der Pointer zeigt jetzt auf das Interface an Adresse base. // Hier kann man nun Eingabe, Verarbeitung, Ausgabe programmieren: //

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 27 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

do { PDV_IO_getData( ptr_io1, & buffer_io1 ); // Eingabe per Pointer an Puffer PDV_verarbeitung_1( & buffer_io1 ); // Puffer "inout" // weitere Verarbeitungen ... PDV_IO_putData( ptr_io1, buffer_io1 ); // Ausgabe Puffer an Pointer } while( run ); // // Die Funktionen im Schleifenrumpf warden in der Vorlesung behandelt. } } }

Beispiel und weitere Diskussion in der Vorlesung.

3.2.2 Virtuell adressierende Zielsysteme

Moderne (Echtzeit-)Betriebssysteme unterscheiden reale und logische Adressen, z.B. indem der Speicher in sog. Seiten (Pages) aufgeteilt wird, wie das folgende Bild zeigt.

logischerAdress-raum fürTask A

Task A

logischerAdress-raum fürTask B

Task B

...

Reale Speicherseiten des logischenAdreßraums für Task A

Reale Speicherseiten des logischenAdreßraums für Task B

CPU

MMU

realerSpeicher

...

...

...

...

...

...

Auslagerungs-datei

0x00000000

0x00000000

Speicherverwalterdes Betriebssystems

0x0000FCAE

0x0000FCAE

0xFFFFFFFFF

0xFFFFFFFFF

0x00000000

0xFFFFFFFFF

Sie sehen hier Paging mit einstufiger Seitenumsetzung und Auslagerung. Jede neue Task erhält bei ihrem Start aus dem Vorrat freier Seiten eine bestimmte Anzahl; in seinem Ablauf fordert er weitere Seiten für loka-le Variablen aufgerufener Funktionen oder dynamische Objekte an und gibt sie wieder frei. Der Speicherver-walter des Betriebssystems bildet die logischen Adressen unter Zuhilfenahme der Memory Management Unit (Abk. MMU) der CPU auf reale Adressen im vorhandenen RAM ab. Dabei wird der Adressbereich jeder Task auch vor dem Zugriff anderer Tasks geschützt. Die Auslagerungsdatei kann das vorhandene RAM virtuell vergrößern. Das bedeutet auch: der für ein Programm sichtbare Wert einer Adresse gibt nicht den realen Speicherort in der Hardware wieder. Es genügt nicht, die Adresse eines Interfacebausteins als Zeigeziel vorzugeben, wie in real adressierenden Zielsystemen. Jetzt ist zusätzlich folgendes nötig:

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 28 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

(a) Eine Task benötigt Admin-Rechte, damit sie auf die Interfacehardware zugreifen kann. (b) Ihr Programm muss den Speicher der Interfacehardware an deren realer Adresse anfordern. Punkt (a): die Task und ihr Programm benötigen Admin-Rechte; auf der CPU das Programm, im Betriebs-system die Task, die es ausführt. Auf der CPU entstehen für das Programm diese Rechte, indem es mit der entsprechenden Option (höchste "Privity") compiliert und gelinkt wird. Auf dem Betriebssystem muss dies Programm dann vom einem Benutzer mit vollen Admin-Rechten der Benutzerverwaltung (z.B. root auf einem unixoiden System) gestartet werden. Punkt (b): Anfordern von Shared Memory an vorgegebener realer Adresse. Shared Memory ist in erster Linie von mehreren Tasks gemeinsam genutzter Speicher. Mit der POSIX-Bibliothek fordert man es mit shm_open() als Ressource mit nutzerdefiniertem Namen an, gibt ihm mit ftruncate() eine Größe vor, und bindet daran mit mmap()den Speicher an gewünschter Adresse in gewünschter Größe mit Zugriffs- und Schutzattributen. Die Programme aller Tasks, die den Speicher teilen sollen, führen diese Schritte aus. Der gemeinsame Speicher ist dann "irgendwo" im RAM, und der Rückgabewert von mmap()zeigt jeweils darauf. Die Parameter der Funktionen übergehen wir hier, da im Folgenden eine andere Funktion erklärt wird, in der die drei oben genannte für die hier interessierende reale Adressierung zusammengefasst sind. #include <sys/mman.h> #include <stdlib.h> #include <inttypes.h> // #include "PDV_IO_definitions.h" // int main( void ) { PDV_IO_typeX * ptr_io1 = NULL; // Interfaceobjekt-Pointer PDV_IO_typeX buffer_io1; // Interfaceobjekt-Puffer uint64_t base; // Adresse, hier als 64-bit-Ganzzahl size_t offset; // Speichergröße, hier benötigt bool run; // Laufbedingung der Hauptschleife // weitere Deklarationen ... offset = sizeof( * ptr_io1 ); // Größe wie Zeigeziel (oder Datentyp als Parameter) base = 0x000C0000; // das erste der beiden Interfaces oben // Realen Speicher im Memoryadressraum anfordern // ptr_io1 = (PDV_IO_typeX *)mmap_device_memory( 0, offset, /*** Größe ***/ PROT_READ|PROT_WRITE|PROT_NOCACHE, 0, base ); /*** Adresse ***/ if ( ptr_io1 == MAP_FAILED ) // Misserfolg { perror( "mmap_device_memory an realer Adresse fehlgeschlagen\n" ); exit( EXIT_FAILURE ); } else // Erfolg { // Wenn base und offset stimmen, zeigt der Pointer jetzt auf das Interface. // Hier kann man nun Eingabe, Verarbeitung, Ausgabe programmieren: do { PDV_IO_getData( ptr_io1, & buffer_io1 ); // Eingabe per Pointer an Puffer PDV_IO_verarbeitung_1( & buffer_io1 ); // Puffer als Durchlaufparameter PDV_IO_putData( ptr_io1, buffer_io1 ); // Ausgabe Puffer an Pointer } while( run ); // // wenn fertig: Speicher an das System zurückgeben // munmap_device_memory( base, offset ); } }

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 29 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Dies Programm spricht ein Interface im Memoryadressraum an. Hardwarezugriff im Portadressraum kann mit mmap_device_io() angefordert und mit munmap_device_io() wieder aufgehoben werden.

3.2.3 Kritischer Abschnitt und Semaphore

Auf virtuell adressierenden Zielsystemen findet Multitaskbetrieb statt, auch auf einigen real adressierenden System kann das möglich sein. Damit entsteht das Problem des gleichzeitigen Zugriffs auf denselben Adres-senbereich des Speichers durch mehrere Task zu etwa derselben Zeit. Wegen der Unterbrechungen und des damit einhergehenden Taskwechsels ( d.h. Umschaltung der CPU auf eine andere Task) können Daten im betreffenden Adressenbereich verfälscht werden oder verloren gehen, im hier behandelten Zusammen-hang Ein- bzw. Ausgabedaten in den Registern von Interfaces, falls mehrere Tasks dasselbe Interface be-nutzen. Den zugehörigen Programmcode dieser Task nennt man den kritischen Abschnitt. Abhilfe schaffen Semaphore. Sie sind u.a. auch in der POSIX-Bibliothek implementiert. Ein Semaphor ist eine Ressource des Zielsystems und muss vor Gebrauch angefordert werden. Mit int sem_wait(sem_t * sem); signalisiert eine Task den Eintritt in den kritischen Abschnitt, also z.B. Lesen aus dem Interface. Mit int sem_post(sem_t * sem); zeigt sie an, dass sie den kritischen Abschnitt verlässt. sem ist der Zeiger auf eine Semaphorvariable. Sie bekommt bei seiner Erzeugung (im Hochlauf des Programms) einen Anfangswert, der anzeigt, wie viele Tasks gleichzeitig den kritischen Abschnitt ausführen dürfen. Mit dem Wert 1 entsteht ein gegenseitiger Ausschluss: nur 1 Task darf zu einer Zeit den kritischen Abschnitt ausführen. Höhere Werte geben die Anzahl Tasks an, zu einer Zeit den kritischen Abschnitt ausführen dürfen. Jeder Aufruf von sem_wait(s1) bewirkt nichts außer einer Dekrementierung von s1, wenn zur Zeit des Aufrufs s1!=0 ist. Die aufrufende Task führt dann einfach weiter ihr Programm aus. Ruft eine Task sem_wait(s1) auf, wenn s1==0 ist, wird s1 mehr dekrementiert. Statt dessen wird die Task angehalten und in eine Warteschlange für s1 eingetragen (das Semaphor-FIFO). Tasks in dieser Warteschlange warten blockiert darauf, ihren Programmcode nach sem_wait(s1) auszuführen. In der Reihenfolge, in der andere Tasks sem_post(s1) ausführen, rücken sie vor. Jeweils Platz 1 der Warteschlange wird laufbereit, sobald eine laufende Task sem_post(s1) ausführt, und verlässt die Warteschlange. POSIX bietet 2 Varianten von Semaphoren: "named" und "unnamed", also unbenannt oder mit Namen. Semaphore ohne Namen werden im Shared Memory implementiert. Das ist naheliegend, wenn die zu schüt-zenden Daten durch Shared Memory dargestellt werden. Die Implementierung an einer realen Adresse ist aber nur dann möglich, wenn in der Hardware an dieser Adresse ein Semaphor-Register enthalten ist. Wenn nicht, wird für den unbenannten Semaphor ein weiteres Shared Memory im RAM benötigt. Erzeugen bzw. anmelden eines "named"-Semaphors geschieht mit der POSIX-Funktion sem_t * sem_open( const char * sem_name, int oflags, mode_t mode, unsigned value ); Abmelden vom Semaphor geschieht mit int sem_unlink( const char * sem_name ); Gelöscht aus dem System wird der Semaphor mit int sem_close( sem_t * sem ); Erklärungen passend zum bisherigen Beispiel folgen hier.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 30 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

#include <sys/mman.h> #include <stdlib.h> #include <inttypes.h> #include <semaphore.h> // #include "PDV_IO_definitions.h" #include "PDV_IO_SEMA.h" // enthält u.a. Namen des Semaphors // int main( void ) { PDV_IO_typeX * ptr_io1 = NULL; // Interfaceobjekt-Pointer PDV_IO_typeX buffer_io1; // Interfaceobjekt-Puffer uint64_t base; // Adresse, hier als 64-bit-Ganzzahl size_t offset; // Speichergröße, hier benötigt bool run; // Laufbedingung der Hauptschleife sem_t * sema1; // weitere Deklarationen ... offset = sizeof( * ptr_io1 ); // Größe wie Zeigeziel (oder Datentyp als Parameter) base = 0x000C0000; // das erste der beiden Interfaces oben // Realen Speicher im Memoryadressraum anfordern // ptr_io1 = (PDV_IO_typeX *)mmap_device_memory( 0, offset, /*** Größe ***/ PROT_READ|PROT_WRITE|PROT_NOCACHE, 0, base ); /*** Adresse ***/ if ( ptr_io1 == MAP_FAILED ) // Misserfolg { perror( "mmap_device_memory an realer Adresse fehlgeschlagen\n" ); exit( EXIT_FAILURE ); } else // Erfolg { // Vor der Hauptschleife den Semaphor anfordern: sema1 = sem_open( PDV_SEMA1, // Name aus Headerfile O_CREAT, // erzeugen, wenn nicht vorhanden S_IROTH | S_IWOTH // jeder darf lesen/schreiben 1 ); // gegenseitiger Ausschluss do { // andere Operationen ... // sem_wait( sema1 ); // kritischer Abschnitt beginnt ///////////////////////// PDV_IO_getData( ptr_io1, & buffer_io1 ); // Eingabe per Pointer an Puffer // sem_post( sema1 ); // kritischer Abschnitt endet /////////////////////////// PDV_verarbeitung_1( & buffer_io1 ); // Puffer als Durchlaufparameter // // weitere Verarbeitungen ... // sem_wait( sema1 ); // kritischer Abschnitt beginnt ///////////////////////// PDV_IO_putData( ptr_io1, buffer_io1 ); // Ausgabe Puffer an Pointer // sem_post( sema1 ); // kritischer Abschnitt endet /////////////////////////// // // weitere Operationen ... } while( run ); // sem_unlink(PDV_SEMA1 ); sem_close( sema1 ); // munmap_device_memory( base, offset ); } }

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 31 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

3.3 Höhere Schichten der Ein- und Ausgabe

"Höhere" Funktionen der Ein- und Ausgabe abstrahieren und verstecken die Details speicheradressierter E/A. Solche höheren Funktionen sind für die Standardperipherie schon in der Standardbibliothek vorhanden. Für Prozessperipherie werden für gewöhnlich herstellerspezifische Zusatzbibliotheken mit der Hardware geliefert bzw. können per WWW heruntergeladen werden, auch die zur Laufzeit ausführenden Treiber. Die softwaretechnisch beste Lösung besteht darin, Treiber und Bibliotheken der Prozessperipherie so zu entwickeln, dass die betreffenden Interfaces und Peripheriegerate als Teil der Standardperipherie ansprech-bar sind. Ein Anwendungsprogramm dann einen großen Teil seiner Ein- und Ausgabe mit den bekannten universellen Standardbibliotheken quasi hardwareneutral über das Modell einer Datei erledigen, also in C mit den Funktionen fopen(), fclose(), fread(), fwrite() bzw. open(), close(), read(), write() usw. Unixoide Systeme unterstützen diesen Ansatz über das Dateisystem mit dem dort vorhandenen Ordner /dev ("Devices"). Dort legen die entsprechenden Gerätetreiber bei ihrem Hochlauf sog. Spezialdateien an, die eigentlich quasi Fassaden vor den jeweiligen Interface darstellen und die man wie Dateien öffnen, beschreiben, lesen, und schließen kann.

3.4 Kommunikationsprotokolle

werden im Vorlesungsabschnitt Feldbusse behandelt.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 32 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

4 Unterbrechungen

Prozessereignisse der Peripherie lassen sich als "Unterbrechungen" oder "Interrupts" darstellen, falls die Technik verwendeter Interfaces eines Zielrechners diese Fähigkeit besitzt. Mit "Unterbrechung" ist genau betrachtet die Anforderung einer Programmunterbrechung gemeint. Jede Unterbrechungsanforderung geht sofort direkt an die CPU. Diese unterbricht die Programmausführung der gerade laufenden Tasks, identi-fiziert die Unterbrechungsanforderung (es gibt mehrere verschiedene) und ruft über einen in den Befehls-zyklus der CPU eingebauten Mechanismus die im Speicher hinterlegte Prozedur auf, die zur Behandlung der identifizierten Unterbrechung dienen soll. Die wird Interrupt Service Routine (ISR) oder Interrupthandler genannt. Außer über die Hardware (Interfaces) können Unterbrechungen auch per Programm angefordert werden. Man bezeichnet sie dann als "Traps", vom englischen Wort Falle: die ausführende Task geht quasi in eine von ihrem Programm gestellte Falle. Eine Trap ist eine Instruktion der Ziel-CPU. Auch auf eine Trap reagiert die CPU, indem sie die anfordernde Task unterbricht und den vorgesehenen Interrupthandler aufruft. Dieser wird mit dem Operanden der Trap-Instruktion identifiziert.

4.1 Ablauf einer Unterbrechungsanforderung

Man unterscheidet drei Typen von Unterbrechungen:

Unterbrechungstyp

Anfordernde Stelle

Ursache Beispiele

Interrupt Request (IRQ): Hardware-unterbrechung

Baugruppen des Rechners (Interfaces, Gerätecontroller)

Setzen eines IRQ-Signals auf dem Systembus

Angeforderte Daten von sind von einem externen Gerät eingetroffen

Gerät ist bereit zur Annahme neuer Aufträge

Trap: Software-unterbrechung

die laufende Task

Ausführung einer TRAP-Instruktion

Die Task soll blockiert auf das Ergebnis eines von ihr beauftragten Diensts warten.

Exception: Ausnahme-behandlung

die CPU Fehler in der Befehlsausführung

ungültige Instruktion Division durch 0 unerlaubte Adressierung

(Zeiger!) Overflow / Underflow bei

Gleitkommarechnungen Bei Eintreten einer Unterbrechung gleich welchen Typs geschieht immer folgendes:

(a) Der Prozessor beendet den aktuellen Befehl. (Der Befehlszyklus ist nicht unterbrechbar!) (b) Er bestimmt die Startadresse der Interruptserviceroutine (Abk. ISR) wie im anschließenden

Abschnitt erklärt. Die ISR ist die Prozedur, die das Unterbrechungsereignis verarbeiten soll. In unserer weiteren Betrachtung nehmen wir an, dass die Adressen der ISR in sog. Unterbrechungsvektoren gespeichert sind. Diese Technik ist sehr weit verbreitet.

(c) Der Prozessor rettet den CPU-Kontext des unterbrochenen Programms in seinen Stack und bearbeitet die Interruptserviceroutine.

(d) Nach Erreichen des return from interrupt - Befehl endet die ISR. Nachdem sein CPU-Kontext aus dem Stack wiederhergestellt ist, kann das unterbrochene Programm fortgesetzt werden. Alternativ kann das Betriebssystem die CPU einer anderen Task zuteilen.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 33 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Interrupt Request (IRQ)

...CPU

...

momentaner Befehl

Unterbrechungs-behandlungsprozedur

Befehlsadresse

Speicherausschnitt

1

2

4Steuerwerk

...

laufendesProgramm

3

nachfolgender Befehl

5

+ Adressen

1

2

3

4

Der aktuelle Befehl des laufenden Programms wird bearbeitet.

Die Unterbrechungsanforderung trifft ein.

Die Adresse der Unterbrechungsbehandlungsprozedur wird bestimmt.

Die Unterbrechungsbehandlungsprozedur wird gestartet.

5 Rückkehr aus der Unterbrechungsbehandlung.

Verfeinerte Betrachtung der Phase (3) für vektorisierte Unterbrechungsbehandlung: Während bei Traps und Exceptions die zugehörige Unterbrechungsvektornummer im Lauf der Befehlsbear-beitung als Befehlsparameter bzw. als Befehlsstatus direkt in der CPU entsteht, müssen die Verursacher von Interrupt Requests sie der CPU von außerhalb übermitteln. Folgendes Diagramm zeigt das Prinzip der Übergabe einer Unterbrechungsvektornummer:

Systembus-Baugruppez.B. Eingabeinterface CPU

Peripherie sendet Information

Interface sendet:IRQ <Nr> - beendet den

angefangenen Befehl

- ruft die zuständige Interruptserviceroutine auf

- unterbricht das soeben lfd. Programm und rettet dessen Kontext auf den Stack

- fordert den Systembus an und quittiert die Unterbrechungsanforderung

IACK <Nr>

Interface sendet seine Unterbrechungsvektornr

Die CPU führt irgendein Programm aus

<Unterbrechungsvektornr>

t

Aus der Unterbrechungsvektornummer des anfordernden Geräts bestimmt die CPU ohne Programmausfüh-rung die zugehörige Adresse der Interruptserviceroutine (ISR), also der Prozedur, welche die Aufgabe hat, die Unterbrechungsanforderung zu behandeln. Das einzige Stück Software, das ihr bei der Suche nach der Andresse hilft, ist die Unterbrechungsvektortabelle, Dort ist die Adresse der ISR, der sog. Unterbrechungs-vektor, hinterlegt. Die vektorisierte Bestimmung der Adressen bis zum Einsprung in die ISR veranschaulicht das folgende Bild anhand einer fiktiven kleinen Modell-CPU:

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 34 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

(1) Eine mit 2*8 = 16 Bit adressierende Little-Endian-CPU (wie z.B. 8086) hat gerade auf eine IRQ

von einem Interfacebaustein reagiert und empfängt nun die Unterbrechungsvektornummer 0x22.

(2) Die Vektornummer wird durch Multiplikation mit N=2 (Linksschieben des Bitmusters um 1 Stel-le) zu einem Adressabstand (Offset) bezüglich der Basisadresse der Unterbrechungsvektorta-belle (Tabellenbasis) umgerechnet.

(3) Zu der auf 0x0000 eingestellten Tabellenbasis wird der Offset addiert. Er zeigt auf das Lower Byte des Unterbrechungsvektors.

(4) Der Unterbrechungsvektor an der Adresse 0x44 und 0x45 wird in das Befehlszeigerregister IP übernommen, nachdem das bisherige Zeigeziel des IP zusammen mit anderen Registerinhalten auf den Stack der unterbrochenen Task gerettet wurde. - Vorsicht bei Little Endian: Das Lower Byte enthält hier den höherwertigen Teil der Adresse!

(5) Die CPU setzt ihre Befehlsbearbeitung an der Adresse fort, die der nun im IP geladene Unterbrechungsvektor vorgibt.

Vektornummer

34 = 0x22

0x12B0

X

Umrechnung auf16-Bit-Adresse

Offset zurTabellenbasis

0x44

+

Basisadresse derInterruptvektortabelle 0xB0

0x0000

0x0045

0x12 0x0044

. . .

0x12B0IP . . .

Unterbr.-vektor-tabelle

ISR

(1)(3)

(5)

(4)

. . .

Speicherausschnitt

Adresse

(2)

0x01FF

Adresse desUnterbrechungs-

vektors

0x44

Unterbrechungsvektor0x12B0

. . .2 0x0000

Die Unterbrechungsvektornummer wird mit der Anzahl Bytes multipliziert, mit der die CPU adressiert. D.h., fortlaufende Unterbrechungsvektoren in der Tabelle überspringen immer soviele Bytes im Speicher wie es der Größe eine Adresse entspricht. Der Unterbrechungsvektor ist ein Offset (Adressabstand) zur Basis der Unterbrechungsvektortabelle. Ergeb-nis ist die Speicheradresse mit der Adresse der ISR. Diese ISR - Adresse übernimmt die CPU in ihr Befehl-zeigerregister IP und startet die Bearbeitung der ISR. Ab hier läuft wieder die normale Befehlsbearbeitung.

Die Größe der Unterbrechungsvektortabelle im Speicher ist hier mit M=256 Vektoren vorgegeben. Da-raus ergibt sich ihre Größe zu 256*2 Bytes = 512 Byte. Ihr letzter Eintrag (Unterbrechungsvektor-nummer 255) hat die Adresse

(M-1) * N = 0x7F * 2 = 0xFE. Diese Art der Speicherverweise zur zuständigen ISR mag umständlich anmuten, bringt aber ein hohes Maß an Flexibilität mit sich: - Traps und Exceptions werden von vornherein über eine Unterbrechungsvektornummer identifiziert. Nach

Umrechnung einer IRQ-Nummer in eine Unterbrechungsvektornummer ist die Bearbeitung von IRQs, Traps und Exceptions völlig gleich.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 35 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

- Lage und Größe jeder ISR im Speicher ist beliebig, da nicht an die fortlaufendenden Unterbrechungs-

vektornummern gebunden. - Anwender- oder Systemprogramme können für die Dauer iher Ausführung eine eigene ISR anstelle

der vorgegebenen System-ISR für bestimmte Vektornummern aktivieren. Sie müssen dazu nur die Adresse in der Vektortabelle entsprechend ändern.

Die Unterbrechungsvektortabelle einer x86-CPU hat die hier gezeigte Belegung:

Im Folgenden wird die Implementierung einer ISR und ihre Kommunikation mit ihrem Anwendungsprogramm erklärt.

4.2 Synchrone Unterbrechungen

"Synchron" heißt hier, dass eine Unterbrechung genau an einer definierten Stelle des Programms eintrifft. Das ist bei dem früher erklärten blockierendem Warten genau der Fall: eine Task wartet an einer genau bestimmten Stelle ihres Programms auf das Ereignis, das den weiteren Programmfluss freigibt. Betrachten Sie dazu das noch einmal das Bild einer blockierenden Eingabe.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 36 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

...1

laufende Task

ISR des IRQ

...Interface

...

...

...

...

...

IRQ

TRAP

2 3

4

5

6

7

9

andere Tasks

B.S. mitTaskscheduler

ISR der TRAP

mit Umschalt-latenzzeit

Ausführungs-zeit

...

...

...

...

...

Twb = ? Tts = ?

8

Zeit

blockiert laufbereit

(1) Das Programm tritt in eine blockierende (Eingabe-) Funktion ein. (2) Die Funktion bereitet die erwartete Eingabe vor und ruft (3) eine TRAP-Instruktion auf. (4) Die zugehörige ISR parametriert das Interface und ruft die Taskverwaltung auf. (5) Das Betriebssystem aktualisiert den Taskzustand und teilt die CPU laufbereiten Tasks zu. (6) Nach Eintreffen der Eingabedaten aus der Peripherie erzeugt das Interface einen IRQ. Ab jetzt gilt

es, eine gegebene Echtzeitanforderung einzuhalten. (7) Die zugehörige ISR übernimmt die Daten vom Interface und ruft die Taskverwaltung auf. (8) Vorrangige d.h. höher priorisierte laufbereite Tasks führen jeweils ihr Programm aus. (9) Die hier wartende Task erhält die CPU und kann ihre Arbeit fortsetzen, um rechtzeitig mit

Verarbeitung und Ausgabe zu reagieren. Man definiert eine ISR als Prozedur (Funktion) eines Programms, das jedoch in seinem Code die ISR nie aufruft. Die Programmierung von Unterbrechungsbehandlungen ist sehr hardwarenah. Evtl. vorhandene Bibliotheken sind entsprechend auf Hardware und Betriebssystem eines zu programmierenden Ziels zugeschnitten, also nicht portabel. Wir betrachten den C-Code für die interruptgetriebene Kontrolle der Übernahme und Verarbeitung der Daten aus einem fiktiven Eingabeinterface. /* * Header ************************************************************************* */ #include <stdio.h> #include <sys/interrupt.h> #include <sys/messages.h> #include <sys/kernel.h> /* * Makros und globale Objekte *** */ #define COM1_IRQNR 4 /* Das ist die IRQ-Nr für COM1: am PC */ struct sigevent eventX_1; /* POSIX-Event fuer als Nachrichtenmedium der ISR * * als Nachricht an das wartende Hauptprogramm */

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 37 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

struct interfaceX_type {

/* ... definiert hier den Interfacetyp, der den IRQ absetzt ... */ } * interfaceX_1, pufferX_1[12]; /* Zeiger auf das Interface und Puffer im RAM; * später mehr davon */ int pufferindex = 0; /* *********************************************************************************/ */ /* * Defintion der Interrupt Service Routine (ISR, Interrupthandler) **************** */ const struct sigevent * intr_handlerX_1( void* area, int idX_1 ) {

/* * Interrupt deaktivieren. Das Hauptprogramm reaktiviert den Interrupt,

* nachdem es den Event von dieser ISR empfangen und alles erledigt hat, * was durch den Interrupt ausgelöst werden sollte.

*/ if ( (InterruptMask(COM1_IRQNR, -1)) == -1 ) {

perror("intr_mask_COM1"); return ( NULL );

}

/* ************************************************************************* * anstelle dieses Kommentars soll eine Treiber-ISR alles erledigen, was als * unmittelbare Reaktion auf den IRQ nötig ist. * Mindestens: Nachricht an den Prozess senden, zu dem diese ISR gehört. * Evtl. mehr: * - Daten aus dem Interface in einen Hauptspeicherpuffer übernehmen * - Pufferfeldindex aktualisieren: if(++pufferindex >= 12) pufferindex=0; * - Interfacestatus auswerten und Betriebsarten neu setzen; * - zeitkritische Gerätebedienung (Treiberaktionen) */ /* Aber: * - Keine Funktionsaufrufe, die intern andere ISR benötigen! * - Keine blockierenden Funktionen oder Operationen! * - Am sichersten gar keine Funktionen. * - Schleifen _nur_, um IF-Registersätze zu adressieren (Lesen/Schreiben), * d.h. erlaubt ist * for( i=0 ; i<ANZAHL_REGISTER ; ++i ) { /* */ } * verboten ist * while( weiss_nicht_genau_wie_lange ==_true ) { /* */ } * Alles, was lange dauert! * Alles, was vor dem return irgendwie "hängenbleiben" kann! * Denn: jede ISR setzt bis zum Erreichen ihres return * das Taskscheduling außer Betrieb! * Nur andere ISR für IRQ mit höherer Priorität können noch laufen! * ***********************************************************************

*/ /* * Die in der main-Funktion blockiert wartende Task benachrichtigen: * return( & eventX_1 );

} /* *********************************************************************************/ */

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 38 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

/* * ***** Hauptprogramm: ********************************************************** */ int main( void ) {

int ever = 1; int com1_irqid; /* Rückgabewert der Interrupt-Anmeldung*/ /* * Interrupt als Quelle für POSIX-Event definieren: */

SIGEV_INTR_INIT( & eventX_1 ); /*

* ISR fuer die IRQs anmelden; * dabei wird hier die Interruptvektortabelle verändert: */ com1_irqid = InterruptAttach ( COM1_IRQNR, intr_handlerX_1, NULL, 0, 0 );

if (com1_irqid == -1) { perror ("intr_attach_COM1"); exit( EXIT_FAILURE ); } /* * Hauptschleife E-V-A: ***************************************************** */

for( ; ever ; ) { /* blockierendes Warten auf Interrupt: */ if ( ( InterruptWait( 0, NULL ) ) == -1 ) { perror ("intr_wait"); exit( EXIT_FAILURE ); } /* ******************************************************************* * Hier soll unter normalen Zeitanforderungen der Pufferinhalt mit den * Eingabedaten aus dem Interface verarbeitet werden, sowie das * fortgesetzt werden, was die ggf. ISR unter zeit- und betriebskritischen * Randbedingungen (Sonderbehandlung der ISR durch das Betriebssystem) * begonnen hat. * Im besonderen können hier alle die Dinge erledigt werden, * - die blockierend wirken * - deren Dauer mehr oder minder stark variiert (Schleifen) * - die Betriebssystemdienste aufrufen * - allgemein: die mit normaler Programmierung erledigt werden können * und sollen. * Dazu gehört auch die Überprüfung der Laufbedingung ever. * *******************************************************************/

/* * COM1-Interrupt reaktivieren: */ if ( (InterruptUnmask(COM1_IRQNR, -1)) == -1 )

{ perror("intr_unmask_COM1"); exit( EXIT_FAILURE ); } }

/*************************************************************************** /* geordneter Rückzug nach Ende der Hauptschleife: */ if ( (InterruptDetach (com1_irqid)) == -1 ) { perror("intr_detach_COM1"); exit( EXIT_FAILURE ); } return 0; /* Ende des Hauptprogramms wenn keine Fehler auftraten */ } /* *********************************************************************************/ */

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 39 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Ablauf eines IRQ und seiner Folgen:

2

TLatenz

TReaktion

Hier läuft die

Echtzeitfrist!

3

ISR

main-Funktion

4 5 6 7

t

TBlockiert

1

(1) Unsere Task wird gestartet und wartet auf die CPU. (2) Das Programm durchläuft seine Hochlaufphase. (3) Das Programm ist in seine Prozessschleife eingetreten und ruft InterruptWait auf. Damit gelangt die

Task in den blockierten Wartezustand. (4) Der IRQ trifft ein. Die CPU unterbricht eine andere Task und startet unsere ISR. (5) Die ISR hat ihren Teil der Verarbeitung des IRQ erledigt und sendet das Event an die im

Hauptprogramm blockiert wartende Task. Diese wird daraufhin laufbereit. (6) In Abhängigkeit von den Zuständen und Prioritäten anderer Tasks teilt der Scheduler unserer Task die CPU zu. Diese setzt in der Prozessschleife fort, was die ISR begonnen hat. (7) Im folgenden Schleifendurchlauf ruft unsere Task InterruptWait auf und wartet auf das nächste

Event. Zum Problem "gleichzeitig" auftretender IRQ und seiner Lösung durch Priorisierung:

ISR 9

wartendeTask 9

IRQIRQ9 IRQ2

ISR-/ Taskzustände: laufend unterbrochen / laufbereit

ISR 2

wartendeTask 2

ISR 1

wartendeTask 1

IRQ1

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 40 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

4.3 Asynchrone Unterbrechung

Analog zu "synchron" im vorigen Abschnitt heißt asynchron hier, dass es keinen Bezug zwischen Eintreten der Unterbrechung und einer bestimmten Programmstelle gibt. Das Hauptprogramm wird irgendwo in seinem Code unterbrochen, weil es nirgendwo auf diese Unterbrechung wartet. Die per Unterbrechung aufgerufene ISR führt quasi im Hintergrund eine Veränderung an den mit dem Hauptprogramm gemein-samen globalen Daten aus und kehrt ins Hauptprogramm "zurück". Das dann weiterlaufende Hauptpro-gramm kommt im Lauf seines Prozesszyklus an die Programmstelle, an der es die von der ISR veränderten Werte, z.B. aktualisierte Eingaben, in den globalen Datenobjekten vorfindet, und kann diese verarbeiten. Nach diesem Muster werden typischerweise Unterbrechungsbehandlungen für Microcontroller und andere Einprogrammsysteme implementiert. Ein auf das Prinzip reduziertes Programm (DOS, Borland C) folgt. #include <stdio.h> #include <dos.h> void interrupt get_out(__CPPARGS); /* interrupt function prototype */ void interrupt (*oldfunc)(__CPPARGS); /* interrupt function pointer */ int loop = 1; int main(void) { puts("Press <Shift><PrtSc> to terminate"); /* tell user how to fire an interrupt */ oldfunc = _dos_getvect(5); /* save the old interrupt vector */ _dos_setvect(5,get_out); /* install new interrupt vector */ while (loop); /* empty main loop */ _dos_setvect(5,oldfunc); /* restore old interrrupt vector */ puts("Success"); return 0; } void interrupt get_out(__CPPARGS) { looping = 0; /* change global var to get out of loop */ } Sequenzdiagramm einer Eingabe-/Ausgabeprogrammierung für Single-Task-Betrieb mit Unterbrechung bei Eintreffen einer Eingabe:

Die Unterbrechung tritt asynchron ein! Diese Programmstelle ist nicht vorherbestimmbar.

IRQ

t1 t2

t3 t4

Programm

ISR

2 3 4 5 61

Eine ProzessschleifeZeit

mit den Intervallen t1 Interruptlatenzzeit t2 Bearbeitungsdauer der ISR t3 Treiberprozess wartet auf Zuteilung der CPU t4 Bearbeitungsdauer der Treiberprozess für diesen IRQ Ereignisse bzw. Arbeitsphasen: (1) Das Programm läuft im Polling-Betrieb; die Daten des letzten IRQ sind bearbeitet.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 41 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

(2) Der IRQ trifft ein und unterbricht das Programm irgendwo in seinem Code. (3) Die ISR läuft und stellt die neuen Daten zum IRQ-Ereignis in globalen

Speicherobjekten bereit. (4) Das Programm setzt seinen Ablauf fort. (5) Es tritt in den Teil seiner Prozessschleife ein, der die per IRQ aktualisierten Daten

bearbeitet. (6) Das Programm hat die per IRQ aktualisierten Daten vollständig bearbeitet und

wiederholt von nun an bis zum nächsten IRQ nur noch die Abfrage der schon vor-handenen Daten.

Analyse zur Abschätzung des ungünstigsten Zeitpunkts für das Eintreffen des Eingabe-IRQ relativ zur Phase der Prozessschleife im Single-Task-Betrieb:

IRQ

t1 t2

t3

t4

Programm

ISR

1

2

Bearbeitungszyklus i Bearbeitungszyklus i+1

3

4 5 6 7 8 9

Zeit

mit den Intervallen t1 Interruptlatenzzeit t2 Bearbeitungsdauer der ISR t3 Treiberprozess wartet auf Zuteilung der CPU t4 Bearbeitungsdauer der Treiberprozess für diesen IRQ und den Programmbearbeitungsphasen

(1) Einlesen der Interfacedaten (2) Eintreffen aktualisierter Daten im Interface (3) ISR stellt aktualisierte Interfacedaten im gemeinsamen Speicherbereich bereit (4) Einlesen der anderen Eingabedaten (5) Verarbeitung und (6) Ausgabe von Daten auf Basis der bei (1) eingelesenen und inzwischen nicht

mehr aktuellen Daten des Interface (7) nun erst Einlesen der aktuellen Interfacedaten und aller anderen Eingabeda-

ten (8) Verarbeitung und (9) Ausgabe von Daten auf Basis der aktuellen Daten

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 42 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

5 Timerprogrammierung

Dieser Abschnitt behandelt die Programmierung isochroner Abtastzyklen mittels Timerprogrammierung.

5.1 Wartezeitfunktionen

Die folgenden Standardfunktionen blockieren eine Task ab dem Aufrufzeitpunkt um die im Argument ange-gebene Zeit:

unsigned sleep ( unsigned seconds ); unsigned delay ( unsigned milliseconds ); unsigned Sleep ( unsigned milliseconds ); int nanosleep ( struct timespec *nanoseconds,

struct timespec *nanoseconds_remaining ); ► nanosleep übernimmt die Wartezeit über den ersten Parameter und gibt die Restdauer über den

zweiten Parameter zurück. Beide Zeitangaben in Nanosekunden. ► struct timespec enthält sowohl die Sekunden als auch die Nanosekundenanteile der aktuellen

Systemzeit, deren Anfang am 1.1.1970 um 0:00 Uhr liegt. Weitere Erklärungen zum Typ struct timespec folgen im nächsten Abschnitt Fehler! Verweisquelle konnte nicht gefunden werden., wo die praktische Programmierung vorgestellt wird.

► Verwechseln Sie sleep (ANSI) nicht mit Sleep (MS-Windows). "Klein" sleep übernimmt die Wartezeit ► Verwechseln Sie sleep (ANSI) nicht mit Sleep (MS-Windows). "Klein" sleep übernimmt die Wartezeit in Sekunden, "groß" Sleep in Millisekunden.

Alle Funktionen liefern die 0 (Zahl Null), wenn sie nach Ablauf der übergebenen Wartezeit in die aufrufende Funktion zurückkehren. Andere Werte zeigen vorzeitige fehlerbedingte Rückkehr an: sleep und delay liefen dann die Anzahl Sekunden bzw. Millisekunden, die bis zum programmierten

Ende der Wartezeit übrig sind. nanosleep liefert dann -1. Die restliche Zeit bis zum Weckzeitpunkt geht in diesem Fall über den Refe-

renzparameter nanoseconds_remaining zurück. Reales Verhalten der hier vorgestellten Funktionen:

Zeit

...

tw tLatenz tEXE

tZYKLUS, EFF(i)

variableScheduling-

latenz

2 31 2

variable Pro-grammaus-führungszeit

tZYKLUS, EFF(i+1)

tw tLatenz

Zeitparameter derWartefunktion

Zeitparameter derWartefunktion

variableScheduling-

latenz

variable Pro-grammaus-führungszeit

tEXE

1 3

mit den Ereignissen (1) Aufruf der Wartezeitfunktion für ein Zeitinkrement relativ zum Aufrufzeitpunkt (2) Ablauf der Wartezeit: die Task wird laufbereit (3) Umschaltung der CPU auf die laufbereite Task durch das Betriebssystem

und den Zeitintervallen tw Programmierte Wartezeit tLatenz Nicht direkt beeinflussbare veränderliche Latenzzeit durch Task Scheduling tEXE Ausführungsdauer eines Programmzyklus, verlängert durch nicht direkt vom Pro-

gramm kontrollierbare Unterbrechungsphasen tZYKLUS, EFF (i) effektive Zyklusdauer im Zyklus i

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 43 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Alle Wartezeiten dieser Funktionen wirken ein Mal relativ zum Aufrufzeitpunkt. Bei fester von Zyklus zu Zyk-lus unveränderter Wartezeit ist das Verhalten der Anwendung in einer Prozessschleife vergleichbar einem Asynchronmotor unter veränderlicher Last: die effektive Zyklusdauer tZYKLUS, EFF nimmt mit zunehmender Belastung der CPU zu, entsprechend dem Schlupf der Asynchronmaschine. Damit die Hauptschleife mit fester mittlerer Frequenz wiederholt wird, muss ein Programm die Wartezeit in jeder Wiederholung der Prozessschleife neu bestimmen: "dynamische Zeitkorrektur".

5.2 Dynamische Wartekorrektur der Wartezeit für isochrones Timing

Es ist möglich, die einfachen Wartezeitfunktionen mit einer von Zyklus zu Zyklus neu bestimmten "dynami-schen" Wartezeit aufzurufen, um zu erreichen, dass die Wiederholfrequenz der Prozessschleife konstant wird: die Wartezeit tw muss in jedem Zyklus so berechnet werden, dass immer gilt:

tZYKLUS, EFF(i) = const

Das folgende Bild soll dies anschaulich machen:

1

Letzter theoretischerWecktermin t ALARM , i

Dynamische Wartezeit

3

Momentane Echtzeit tN

Effektiver Weckzeitpunkt

7

tN - tALARM , i tZYKLUS - ( tN - tALARM , i )

2

Nächster theoretischerWecktermin t ALARM , i+1

4

tZYKLUS

5

6

Effektiver Weckzeitpunkt

Aktionen und Ereignisse in der Prozessschleife: (1) Aktion: theoretisch nächsten Zyklusbeginn vorausberechnen, Wartezeit daraus errechnen und einfache

Wartezeitfunktion aufrufen.Details: siehe unten bei (5) und (6)) (2) Ereignis: Wartezeit ist abgelaufen; die Task wird laufbereit. (3) Nach einer durch die Tastverwaltung des Betriebssystems bedingten Latenzzeit wird die CPU zugeteilt:

Die Task beginnt den nächsten Prozesszyklus. (4) Ein Blick auf die aktuelle Echtzeituhr: die Zeit ist jetzt tN. (5) Berechnung des nächsten Wartezeitintervalls: tW = tZYKLUS - (tN - tALARM

(i) ) und der theoretisch nächsten Weckzeit: tALARM

(i+1) = tALARM (i) + tZYKLUS .

tW läuft ab, wenn die aktuelle Zyklusdauer tZYKLUS abläuft. Die theoretische nächste Weckzeit tALARM

(i+1) ist eine reine Rechengröße und daher unabhängig vom praktischen Verhalten des Systems auch nach beliebiger Dauer immer korrekt. Die mitlau-fende Berechnung von tALARM

(i+1) stabilisiert die Berechnung des nächsten Wartezeitintervalls, so dass die Frequenz fZYKLUS = 1 / tZYKLUS tatsächlich konstant bleibt, solange das System nicht in Überlast läuft.

Überlast heißt hier konkret: zwischen 2 Weckereignissen für eine betrachtete Task kann die Warteschlange laufbereiter anderer Tasks nicht vollständig abgearbeitet werden. Es entsteht ein Stau unbearbeiteter Ereignisse.

(6) Wie (1): Falls tW > 0 : Aufruf der Wartezeitfunktion mit dem Parameter tW .

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 44 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Sonst : nächste Wiederholung der Prozessschleife ohne Wartezeit; ggf. Fehler-

behandlung. (7) Wie (2): die Wartezeit läuft ab. Die Task wird laufbereit. Scheinbare und echte Probleme dabei: 1. Jede Berechnung des nächsten Wartezeitintervalls tW = tZYKLUS - (tN - tALARM

(i) ) benötigt selbst Zeit. Dieser Fehler F ist aber in einem normal belasteten System klein, d.h. praktisch immer F < ½tZYKLUS . Gleichzeit ist im nächsten Zyklus immer bekannt, wann der Zyklus hätte anfangen sollen: tALARM

(i+1) = tALARM

(i) + tZYKLUS . Diese Zeit tALARM (i+1) wird die im nächsten Zyklus zu tALARM

(i) . Erste Weckalarmzeit tALARM

(0) und tZYKLUS sind reine Vorgabewerte, also ist für beliebige i der Wert tALARM (i+1) völlig unab-

hängig von jeder späteren technischen Realität. Auf diese Weise haben ausführungsbedingte Zeitfehler jedes aktuellen Zyklus bei normal belasteten Systemen keine Auswirkung auf die Wiederholfrequenz des Prozesszyklus ("Zykluszeit"). Lediglich der Beginn einer Ausführung verzögert sich innerhalb des nächsten Intervalls mehr oder weniger, d.h. es gibt einen Phasenfehler.

2. Während das Programm läuft, können Unterbrechungen und Taskwechsel eintreten; Folge: die Warte-

zeitfunktion wird evtl. bedeutend später aufgerufen, als es die Berechnung vorsieht. Dieser Fehler ist möglicherweise groß. Drei Fälle sollten unterschieden werden, abhängig davon, ob sie sich der Zeitfeh-ler im nächsten Zyklus wieder einholen lässt oder nicht. - Ist am Ende der Ausführungsdauer des darauf folgenden Zyklus

a) tW > 0 : kein Problem. b) - tZYKLUS < tW < 0 : das Programm hat einen Zyklus verschlafen c) tW < - ( N . tZYKLUS, ) < 0 : das Programm hat mehrere Zyklen "verschlafen"

Die Fälle b) und c) stellen die Echtzeitfähigkeit des Systems in Frage. Es kommt nun darauf an, zu betrach-ten, wie häufig der Zeitfehler auftritt. Allgemein gilt (leider), dass weniger portable Methoden, wie sie in den nächsten Abschnitten dargestellt werden, für die Realzeitfähigkeit günstiger sind. Die Programmierung einer isochron wiederholten Prozessschleife nach dem Standard IEEE 1003 "POSIX" wird im Folgenden vorgestellt. Einzelne Zeitangaben sind vom Typ long . Mit

#include <time.h> gelten die Typdefinitionen struct timespec und struct itimerspec . Sie definieren Echtzeit mit den beiden Komponenten "Anteil der Zeit in Sekunden" und Anteil der Zeit in Nanosekunden":

struct timespec { long tv_secs; /* Zeitanteil in Sekunden */ long tv_nsecs; /* Zeitanteil in Nanosekunden */ };

Nutzerdefinierte Makros können den Umgang mit großen Zahlen erleichtern:

#define GIGA 1000000000L /* Achtung, das sind hier */ #define MEGA 1000000L /* keine dualen, sondern */ #define KILO 1000L /* dezimale Größenordnungen! */

Die dynamische Wartezeitberechnung benötigt folgende Progarmmaktionen:

1. Erfassung der aktuellen Echtzeit 2. Berechnung eines Zeitintervalls 3. Verschiebung eines Zeitpunkts 4. Aufruf der dynamischen Wartezeit mit nanosleep()

Zu 1.: Erfassung der aktuellen Echtzeit

Headerdatei: #include <time.h> Funktion: int clock_gettime (CLOCK_REALTIME, struct timespec *now);

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 45 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

clock_gettime liefert in der als Referenz übergebenen Struktur now die aktuelle Zeit mit folgen-der Bedeutung:

now.tv_secs; /* Systemzeit in Sekunden seit 1.1.1970 00:00 */ now.tv_nsecs; /* Nanosekunden der jetzt angefangenen Sekunde */

Zu 2.: Berechnung eines Zeitintervalls aus der Differenz zweier Echtzeitpunkte.

t = t2 - t1 mit t2 > 0 und t1 > 0 ergibt ein Zeitintervall. Je nachdem, ob t2 > t1 oder t2 < t1 ist t positiv oder negativ.

t = {t_s, t_ns }

t2 = {t2_s, t2_ns}t1 = {t1_s, t1_ns}

Zeit

Die Nanosekundenkomponente kann überlaufen. Der Überlauf muss dann auf die Sekunde umge-rechnet werden. Folgende Fälle sind möglich: a) t_s > 0 && tns ≥ 0: OK b) t_s > 0 && t_ns < 0: umrechnen! c) t_s = 0 && t_ns ≥ 0: OK d) t_s = 0 && t_ns < 0: OK e) t_s < 0 && t_ns ≥ 0: umrechnen! f) t_s < 0 && t_ns < 0: OK Die obigen Fälle b) und e) erfordern die hier unten in C dargestellte Programmierung der Differenzbil-dung. Die Variablen t2 und t1 sind vom Strukturtyp struct timespec . deltat_s und deltat_ns haben den Typ long.

deltat_s = t2.tv_s - t1.tv_s; deltat_ns = t2.tv_ns - t1.tv_ns; if (deltat_s > 0 && deltat_ns < 0 ) { deltat_s--; deltat_ns += GIGA; } if (deltat_s < 0 && deltat_ns > 0) { deltat_s++; deltat_ns -= GIGA; }

Zu 3.: Verschiebung eines Zeitpunkts t1 > 0 um ein Echtzeitintervall t.

Der neue Zeitpunkt ist tNEU = t1 + t. Das Intervall t kann positiv oder negativ sein. Für tNEU gelten einerseits dieselben Fälle a) - f) wie bei der Berechnung des Zeitintervalls oben. Zusätzlich kann aber hier die Nanosekundenkomponente größer als 1 Giga werden. Die Berechnung folgt also dem Muster in C: tneu_s = t1.tv_s + deltat.tv_s; tneu_ns = t1.tv_ns + deltat.tv_ns; if (tneu_s > 0 && tneu_ns < 0 ) { tneu_s--; tneu_ns += GIGA; } if (tneu_s < 0 && tneu_ns > 0) { tneu_s++;

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 46 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

tneu_ns -= GIGA; } if (tneu_ns >= GIGA ) {

tneu_s++; tneu_ns -= GIGA; } Zu 4.: Aufruf einer (hoch auflösenden) dynamischen Wartezeit. Hier kommt die oben unter Fehler! Verweisquelle konnte nicht gefunden werden.Standardfunktion nanosleep zum Einsatz.

Den Entwurf einer Kontrollstruktur für eine zeitgesteuerte Prozessschleife nach dieser Technik zeigt das obige Struktogramm. Unabhängig von der hier vorgestellten Zeitgeberprogrammierung übernimmt das Programm mit seinem Auf-ruf die Zyklusdauer in Form der beiden Werte für die Anzahl Sekunden und die Anzahl Nanosekunden. Dann wartet es auf eine Startfreigabe durch den Anwender oder den technischen Prozess, hier modellhaft implementiert durch Warten auf Eingabe von RETURN über die Konsole. Danach wird die momentane Systemzeit erfasst und bei Erfolg wird die Prozessschleife initialisiert. Das hier wesentliche daran sind die Blöcke (9) und (10). Danach folgt die Prozessschleife, in der die Anwendung mit

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 47 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Eingabe-Verarbeitung-Ausgabe - Schema sowie die Neuberechnung der nächsten Weckzeit für feste Zyklus-frequenz enthalten sind. Der komplette Code eines Beispielprogramms folgt hier. /********************************************************************** * Timing-Beispiel für isochrone Zyklusdauer * mit POSIX nanosleep () und dynamisch angepasster Wartezeit **********************************************************************/ #include <stdio.h> #include <stdlib.h> #include <sys/time.h> #include <conio.h> #define GIGA 1000000000L #define MEGA 1000000L #define KILO 1000L #define EVER 1 #define ERR_ARGC 1 // 0x0001 #define ERR_ARGV1 1<<1 // 0x0002 #define ERR_ARGV1 1<<2 // 0x0004 void shutdown_process_safely( void ); // Prototype für sicheres Ende /**********************************************************************/ int main (int argc, char *argv[]) { struct timespec cycletime; // geforderte Zyklusdauer struct timespec now, next; // Zeitpunkte: jetzt, nächster Zyklus struct timespec sleeptime, difftime; // Wartezeit, Abstand z. nächsten Zyklus long seconds_carry; // Hilfsgröße Zeitübertrag unsigned short error = 0; char * p; // Hilfsgröße Programmargumentprüfung int run = 1; // Laufvariable der Hauptschleife /* Programmargument mit Zyklusdauer übernehmen: ******************************* */ if ( argc != 3 ) { error |= ERR_ARGC; } else { cycletime.tv_sec = strtol (argv[1], & p, 10); if ( * p != '\0' ) { error|= ERR_ARGV1; } cycletime.tv_nsec = strtol (argv[2], & p, 10); if ( * p != '\0' ) { error|= ERR_ARGV2; } } if ( error ) { fprintf( stderr, "*** richtig aufrufen: nanosleep_timer <sec nsec>\n" ); exit( EXIT_SUCCESS ); } /******************************************************************************* */ /* * hier passend zu den Anforderungen programmieren: * die gegenseitige Startsynchronisation Task - Peripherie * ... */ // ersten Zyklusbeginn + erste Wartezeit bestimmen.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 48 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

// if ( clock_gettime( CLOCK_REALTIME, & now ) == -1 ) { perror( "Fehler bei Systemzeitabfrage, Ende" ); exit( EXIT_FAILURE ); } // t_now ist Referenzzeit für alle folgenden Zykluszeiten // t_next ist der rechnerische Beginn des ersten Zyklusintervalls // next.tv_sec = now.tv_sec + cycletime.tv_sec; next.tv_nsec = now.tv_nsec + cycletime.tv_nsec; // if ( (seconds_carry = next.tv_nsec / GIGA) > 0 ) { // Korrektur mit Zeitsummenübertrag next.tv_sec += seconds_carry; next.tv_nsec = next.tv_nsec % GIGA; } // sleeptime = cycletime; /* * Hauptschleife *************************************************************** */ do{ if ( nanosleep( & sleeptime, NULL ) == -1 ) { perror( "vorzeitige Rückkehr aus nanosleep" ); } /*************************************************************************** * hier einfügen: die Programmblöcke E-V-A der Automatisierungsaufgabe ... * ***************************************************************************/ // nächsten Zyklusbeginn und nächste Wartezeit berechnen. // das nächste Zyklusintervall ist nun das jetzige: // next.tv_sec = next.tv_sec + cycletime.tv_sec; next.tv_nsec = next.tv_nsec + cycletime.tv_nsec; // // t_next ist nun der rechnerische Beginn des nächsten Zyklusintervalls // if ( (seconds_carry = next.tv_nsec / GIGA) > 0 ) { // Korrektur mit Zeitsummenübertrag next.tv_sec += seconds_carry; next.tv_nsec = next.tv_nsec % GIGA; } // if ( clock_gettime( CLOCK_REALTIME, & now ) == -1 ) { perror( "Fehler bei Systemzeitabfrage, Ende" ); run = 0; // Hauptschleife über die Laufbedingung verlassen continue; // zur Laufbedingung } // // Zeitabstand zum nächsten Zyklusbeginn: // difftime.tv_sec = next.tv_sec - now.tv_sec; difftime.tv_nsec = next.tv_nsec - now.tv_nsec; if ( difftime.tv_nsec < 0 && difftime.tv_sec > 0 ) { // Korrektur mit Zeitdifferenzübertrag difftime.tv_sec--; difftime.tv_nsec += GIGA; } else {

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 49 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

if ( difftime.tv_nsec > 0 && difftime.tv_sec < 0 ) { // Korrektur mit Zeitdifferenzübertrag difftime.tv_sec++; difftime.tv_nsec -= GIGA; } } if ( (difftime.tv_sec < 0) || ( (difftime.tv_sec == 0) && (difftime.tv_nsec <= 0) ) ) { // Zykluszeit überzogen, gleich weiter // in den nächsten Schleifenlauf mit sleeptime.tv_sec = 0; sleeptime.tv_nsec = 0; continue; // zur Laufbedingung } else { sleeptime.tv_sec = difftime.tv_sec; sleeptime.tv_nsec = difftime.tv_nsec; } }while ( run ); /* * Hauptschleife – Ende ******************************************************* */ // Prozessanwendung herunterfahren // shutdown_process_safely(); // return 0; } Die hier vorgestellte Kontrolle der Zyklusdauer mit einer hoch auflösenden Wartezeitfunktion funktioniert, indem die Verantwortung für die Einhaltung der Forderung nach konstanter Zyklusdauer an das Programm bzw. an seine Gestaltung abgegeben wird. Angesichts der Alternative, einen systemeigenen Timer zu verwenden, ist dies nicht die beste Lösung. Ein weiterer Nachteil liegt darin, dass das Programm während der Wartezeit nicht auf andere ggf. relevante Ereignisse reagieren kann. Beide Nachteile hebt die im folgenden Abschnitt vorgestellte Verwendung eines Timers auf.

5.3 Selbstständig ablaufender Standardzeitgeber

Hier wird die Verwendung des POSIX-Timers erklärt. Er stellt eine Systemressource dar, die der anwen-denden Task eigenständig Benachrichtigungen sendet. Das Programm muss nicht wie oben in jedem Prozesszyklus neu für das korrekte Timing sorgen, sondern nur einmal im Hochlauf die Ressource anfordern und richtig parametrieren und dann im Prozesszyklus blockiert auf die Nachricht des Timers warten. In dieser blockierten Wartezeit kann die Task bei geeigneter Einrichtung des "Nachrichtenkanals" (s.u.) auch andere Nachrichten empfangen. Das ist mit nanosleep() etc. nicht ohne weiteres möglich. Signalflussschema:

Timer Event Pulse Connection Channel empfangsbereiter Anwendungsprozess Pseudocodiertes Struktogramm eines Anwendungsbeispiels: Ein Struktogramm soll das Prinzip des eben vorgestellten Programms noch einmal in anderer Form zeigen.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 50 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

Dem Struktogramm entspricht konkret das folgende Programm für das Echtzeit-Zielsystem QNX Neutrino. Es wird in der Vorlesung erklärt. /********************************************************************** * Rahmenprogramm für eine isochrone Echtzeitanwendung * Hier kommt der POSIX-Real Time Timer als Auslöser einer zyklischen * Interprozess-Nachricht (Pulse) zum Einsatz **********************************************************************/ #include <stdlib.h> #include <stdio.h> #include <time.h> #include <unistd.h> #include <termios.h> #include <sys/neutrino.h> #include <sys/netmgr.h> #include <sys/siginfo.h> #define GIGA 1000000000L #define MEGA 1000000L #define KILO 1000L #define EVER 1

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 51 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

/* * Benutzerdefinierte Codes für Pulses müssen * immer im Bereich zwischen _PULSE_CODE_MINAVAIL * und _PULSE_CODE_MAXAVAIL liegen. */ #define PULSE_CODE_TIMER _PULSE_CODE_MINAVAIL int main (int argc, char *argv[]) { struct timespec zyklusdauer, jetzt, weckzeit; struct itimerspec sollzeit; // Diese struct-Typen sind in <time.h> definiert struct sigevent Event; // POSIX-Event // Dieser struct-Typ ist in <sys/siginfo.h> definiert timer_t Zeitgeber; // POSIX-Timer double interval; short error; char * p_enddef; int chid; // IPC-Channel-ID int coid; // IPC-Connection-ID struct _pulse pulse; // Pulse-Daten if ( argc != 3 ) { fprintf (stderr, "*** use: %s <sec nsec>\n", argv[0]); return EXIT_FAILURE; } else { error = 0; zyklusdauer.tv_sec = strtol (argv[1], &p_enddef, 10); if ( *p_enddef != '\0' ) { error = 1; } zyklusdauer.tv_nsec = strtol (argv[2], &p_enddef, 10); if ( *p_enddef != '\0' ) { error = 1; } if ( error == 1 ) { fprintf (stderr, "*** seconds and nanoseconds must be entire numbers!\n"); exit (EXIT_FAILURE); } else { interval = (double) zyklusdauer.tv_nsec / GIGA + zyklusdauer.tv_sec; /* * 1. Einen Kanal für die Interprozess-Kommunikation erstellen. */ chid = ChannelCreate( /* flags: */ 0 ); if ( chid == -1 ) { perror ("*** error: ChannelCreate()"); return EXIT_FAILURE; } else { /* * 2. Eine Verbindung zum erzeugten Kanal herstellen um * Interprozess-Nachrichten (hier: Pulses) senden zu können. */

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 52 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

coid = ConnectAttach (

/* node: */ ND_LOCAL_NODE, // lokale Verbindung /* PID: */ 0, // zu sich selbst /* Channel-ID: */ chid, /* index: */ 0 | _NTO_SIDE_CHANNEL,

// minimale Verbindungsnummer (coid/Connection-ID), // sollte immer mit | _NTO_SIDE_CHANNEL // verknüpft werden! /* flags: */ 0 ); if ( coid == -1 ) { perror ("*** error: ConnectAttach()"); return EXIT_FAILURE; } else { /* * 3. Das POSIX-Event wird so konfiguriert, so dass beim Eintreten * ein Pulse mit einem definierten Pulse-Code (und Pulse-Value) an * die angegebene Interprozess-Verbindung gesendet wird. */ SIGEV_PULSE_INIT( /* struct sigevent *: */ &Event, /* sigev_coid: */ coid, // Connection-ID /* sigev_priority: */ SIGEV_PULSE_PRIO_INHERIT, // Priorität des Pulses // SIGEV_PULSE_PRIO_INHERIT: // gleiche Priorität wie der // aufrufende Prozess/Thread /* sigev_code: */ PULSE_CODE_TIMER, // Pulse-Code /* sigev_value: */ 0 // Wert, der vom Pulse-Handler // verwendet werden kann // (in diesem Beispiel wird // dieser ignorert) ); /* * 4. POSIX-Timer mit Echtzeiteigenschaft erzeugen * und Bezug zum POSIX-Event herstellen: */ error = timer_create (CLOCK_REALTIME, &Event, &Zeitgeber); if ( error == -1 ) { perror ("*** failing to create timer!"); exit (EXIT_FAILURE); } else { /* * 5. Jetzt die Parameter des Zeitgebers vorbereiten. * * Dauer des 1. Wartezeitintervalls * nach Aufruf von timer_settime(...) */ sollzeit.it_value.tv_sec = zyklusdauer.tv_sec; sollzeit.it_value.tv_nsec = zyklusdauer.tv_nsec; /* * Wiederholzeit für das periodische Wecken danach: */ sollzeit.it_interval.tv_sec = zyklusdauer.tv_sec; sollzeit.it_interval.tv_nsec = zyklusdauer.tv_nsec;

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 53 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

/*

* 6. Zeitgeber programmieren und aktivieren: */ timer_settime ( Zeitgeber, 0, &sollzeit, NULL ); /* * Ab jetzt läuft die Weckzeit * des 1. Wartezeitintervalls */ for ( ; EVER ; ) { do{ error = MsgReceivePulse ( chid, // Channel-ID &pulse, // Puffer für Pulse-Daten sizeof(pulse), // Größe des Puffers NULL // immer NULL ); if ( error == -1 )

{ perror("*** error: MsgReceivePulse()"); return EXIT_FAILURE; } }while ( pulse.code != PULSE_CODE_TIMER ); /**************************************************** * insert here: ... your application code ... */ /****************************************************/ } timer_delete (Zeitgeber); } ConnectDetach(coid); ChannelDestroy(chid); } } } } return (0); } Vorteile:

In der Prozessschleife beschränkt sich sich der Programmcode weitestgehend auf die Steuerungs- bzw. Regelungsanwendung. Keine komplizierte Neuberechnung der Wartezeit! Der Timer läuft parallel und sendet in fester Frequenz seine Pulse.

Während der blockierten Wartezeit kann der Anwendungsprozess auch von anderen Ereignissen "aufgeweckt" werden und darauf reagieren, z.B. in einem Notfall.

Nachteile dieser Programmiervariante:

- komplizierte Anforderungen verketteter Ressource im Hochlauf: Timer, Event, Pulse, Channel, Connection

- Pulse, Channel, Connection sind proprietäre QNX-Ressourcen; im Fall einer Portierung müssten die Äquivalente des neuen Zielsystems in entsprechenden Programmbibliotheken gesucht werden, um damit das hier vorgestellte Programm anzupassen.

5.4 "Timer Ticksize": Einstellung des Betriebssystems auf hohe Zykluswiederholraten

Nicht nur eine laufende Anwendungstask, sondern auch das Betriebssystem des Zielrechners muss sich an eine mindeste Arbeitsfrequenz (Wiederholrate) halten. Für das Betriebssystem bestimmt sich deren Sollwert aus der Zyklusdauer der "schnellsten" Anwendungstask. Soll die Task z.B. vom Timer gesteuert alle TZYKLUS = 500 µs wiederholt werden, dann ist das Betriebssystem zu langsam, wenn es mit einer (Default-) Zyklus-dauer von 1 ms oder 10 ms (zwei typische Werte) arbeitet. Vielmehr ist die min. Schaltrate der Vorgänge bei der Task- und Ressourcenverwaltung maßgeblich. Diese beträgt hier 2N/TZYKLUS bei gegebenem TZYKLUS der Anwendung, mit einem schwierig abschätzbaren Wert N. Mit speziellen i.d.R. nicht portablen Systemaufrufen, z.B. QNX: ClockPeriod(), ist es möglich, die Arbeits-frequenz des Betriebssystems zu verändern. Ein Beispielprogramm wird in der Vorlesung demonstriert.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 54 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

6 Interprozesskommunikation

6.1 Prinzipieller Ablauf mit gegenseitiger Synchronisation Sender - Empfänger

Bei der Programmierung der Reaktion auf Unterbrechungen und des POSIX-Timers haben wir bereits Elemente der Interprozesskommunikation (Abk. IPC) benutzt. Der Austausch von Nachrichten und Daten nur zwischen Tasks soll im folgenden Text anhand des sogenannten Ada-Rendezvous erklärt werden. Bei dieser Variante der IPC läuft die Datenübertragung zwischen Sender und Empfänger synchronisiert ab. Als Empfänger ruft eine Task "Message Receive" auf und wartet blockiert, bis eine andere Task als Ab-sender "Message Send" aufruft. Damit wird der Empfänger wieder laufbereit, und der Absender wartet blockiert auf die Antwort. Der Empfänger sollte dann den Typ der Nachricht unterscheiden: Absender ist ISR?

Verzweige in den Programmteil zur Behandlung von IRQ. Absender ist Task?

Verzweige in den Programmteil zur Behandlung von Nachrichten anderer Task und bearbeite die empfangenen Daten aus der Nachricht.

Absender ist Timer? Verzweige in den Programmteil zur Behandlung eines Timernachricht Von Fall zu Fall kann es auch mehrere ISR bzw. Timer geben, die (wie oben erklärt z.B. über POSIX-Events) Nachrichten an eine Task senden. Also muss dann die Behandlung des jeweiligen Falls weiter verfeinert unterschieden werden. In diesem Sinn gilt auch, dass nicht alle Tasks, deren Nachricht eingetroffen ist, das Recht auf eine Bear-beitung ihrer Nachricht haben, z.B. aus Sicherheitsgründen. Ferner können auch berechtigte Tasks Unsinn senden. Also muss auch dieser Fall im Programm der Empfängertask weiter unterschieden werden. Task A: Empfänger bzw. Server Task B: Sender bzw. Client Hcohaluf (1) (2) (3)

channel= name_attach("NameX",GLOBAL);

Möglich, aber nicht zwingend: Schritte 2. - 5. im Timerbeispielcode oben

connect= name_open("NameX",GLOBAL);

Haupt-schleife (4)

recvid = MsgReceive(channel,NULL);

(5) (blockiert) (6) MsgSend(connect,&request,&reply) (7) Empfang und Verarbeitung der

Nachricht (blockiert)

(8) MsgReply(recvid,0,&msg); (9) weitere Programmaktionen (laufbereit) (10) Empfang und Verarbeitung der Antwort,

weitere Programmaktionen (11) nach Gebrauch bzw. vor Programmende:

alle erfolgreich angeforderten Ressourcen LIFO zurückgeben. Die IPC-Standardfunktionen sind hier mit vereinfachten Pseudocode-Argumenten aufgerufen. Die korrekten Aufrufe finden Sie im Code weiter unten.

(1) Beim IPC-/Namensdienst des Betriebssystems Namen registrieren und Kanal anlegen. Der Parameter GLOBAL ermöglicht es Prozessen auf anderen ggf. vorhandenen Zielrechnern desselben LAN, mit Task A Verbindung aufzunehmen und zu kommunizier, falls das Betriebs-system verteilt konfiguriert ist.

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 55 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

(2) Beim IPC-/Namensdienst des Betriebssystems: Namen der Task A identifizieren und zu ihr

Verbindung aufbauen (3) Task A kann einen Timer und die für den Empfang des Timersignals nötige IPC-Verbindung

anlegen, muss es aber nicht. Mit dieser Maßnahme kann der Timer Task A zyklisch dazu bringen, eigenitiative Aktionen auszuführen. Ohne diese Maßnahme durchläuft das Programm der Task A seine Hauptschleife nur dann, wenn eine andere Task eine Nachricht sendet bzw. ein Client einen Dienst anfragt.

(4) Task A tritt in die Hauptschleife ein und ruft die IPC-Empfangsfunktion auf. Die empfangene Nachricht kann von einer Task oder vom Timer kommen. Das folgende Beispielprogramm zeigt, wie man beides unterscheidet.

(5) Empfangsbereit blockiert warten (6) Task B sendet ihre Nachricht mit Informationsteil an Task A, (7) geht in den Reply-blockierten Zustand und wird empfangsbereit für Task A (8) Task A antwortet Task B (9) Task B wird laufbereit, (10) empfängt die Antwort und führt weitere Programmaktionen aus. (11) Rückgabe der nicht mehr benötigen Ressourcen: Timer, Verbindungen, Kanäle. LIFO: Last In First Out. Was zuletzt zugeteilt wurde, muss i.d.R . .zuerst wieder abgemeldet

werden, sonst kann es zu instabilem Verhalten kommen. Wie im Schritt (3), in dem Task A sich einen Timer und dessen Verbindung zu sich selbst anlegt, sie zusätz-lich oder alternativ einen IRQ mit ISR und deren Verbindung anlegen. Der IRQ könnte dann die azyklisch Aktionen des Programms auslösen, während der Timer dies zyklisch bewirkt, und eine sendende Task je nach dem Kontrollfluss ihres Programms azyklisch oder zyklisch sendet.

6.2 Beispiel eines Servers

Headerdatei für den Server und alle Clientprogramme: // Headerfile X-Server_simple.h /////////////////////////////////////////// // // Beim QNX Global Name Service angemeldeter Server-Name #define SERVERNAME "X-Server_simple" // typedef unsigned long UINT32; // // Format eines Nachrichtentelegramms Client - Server struct servicemessage_type { struct _pulse header; // QNX: Verbindungsauf- und -abbau int request, confirm; // Server: Dienstanfrage, -quittung UNINT status; // weitere Attribute ... }; // // Codierung der Dienstanfragen und Quittungen // #define REQUESTCODE_1 1 #define REQUESTCODE_2 2 // weitere Anfragecodes von Clients... #define COMFIRMCODE_1_NEG -1 #define COMFIRMCODE_1_POS 1 #define COMFIRMCODE_2_NEG -2 #define COMFIRMCODE_2_POS 2 // weitere Quittungscodes an Clients... // /////////////////////////////////////////////////////////////////////////// Programmdatei: /////////////////////////////////////////////////////////////////////////// Header des Serverprogramms /////////////////////////////////////////////////////////////////////////// //

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 56 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> #include <time.h> #include <unistd.h> #include <termios.h> #include <limits.h> #include <sys/iofunc.h> #include <sys/dispatch.h> #include <sys/netmgr.h> #include <sys/siginfo.h> /* * Benutzerdefinierte Codes für Pulses müssen * immer im Bereich zwischen _PULSE_CODE_MINAVAIL * und _PULSE_CODE_MAXAVAIL liegen. */ #define PULSE_CODE_TIMER _PULSE_CODE_MINAVAIL // #include <sys/neutrino.h> // für struct _pulse #include "X-Server_simple.h" // Prototypen // int run_service_X1( struct service_type * service ); // Dienst 1 für Clients int action_X1( struct service_type * service ); // eigene Aktion des Servers // /////////////////////////////////////////////////////////////////////////// Hauptprogamm /////////////////////////////////////////////////////////////////////////// // int main(int argc, char *argv[]) { int i; // universelle Zählgröße name_attach_t * attach; // Kanalobjekt int recvid; // Client-PID struct servicemessage_type msg; // Puffer für Nachrichten von/zu Client short shutdown; // wenn TRUE terminiert der Server int coid; // Connect-ID für Timer-Event-Pulse struct sigevent Event; // vom Timer ausgelöster POSIX-Event timer_t Zeitgeber; // POSIX-Timer struct itimerspec zykluszeit; // Typ in <timer> definiert int error; // allgemeiner Fehlermerker // // Wenn die Flags (3. Parameter) *nicht* NAME_FLAG_ATTACH_GLOBAL enthalten, // dann wird der Name nur auf dem aktuellen Host bekannt gemacht. Sonst gilt er // auf allen Hosts im QNX-LAN. // // IPC-Kanal anlegen // attach = name_attach(NULL, SERVERNAME, NAME_FLAG_ATTACH_GLOBAL); // attach -> chid ist die Channel ID des IPC-Kanals zu diesem Prozess if ( attach == NULL ) { perror("*** Fehler: name_attach()"); exit( EXIT_FAILURE ); } /* * Die folgendes Schritte nur, wenn ein eigener Timer der Task zyklisch senden soll: */ /* 1 */

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 57 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

/* Verbindung zum IPC-Kanal herstellen: */ coid = ConnectAttach ( /* node: */ ND_LOCAL_NODE, // ND_LOCAL_NODE: eine lokale Verbindung /* PID: */ 0, // 0: Verbindung zu sich selbst /* Channel-ID: */ attach -> chid, // über den oben angelegten Kanal /* index: */ 0 | _NTO_SIDE_CHANNEL, // minimale Verbindungsnummer coid /* flags: */ 0 ); if ( coid == -1 ) { perror ("*** Fehler: ConnectAttach()"); exit( EXIT_FAILURE ); } /* 2 */ /* * Nun das POSIX-Event wird so konfigurieren, dass bei seinem Eintreten * ein sog. Pulse mit einem definierten Pulse-Code (und Pulse-Value) an die * angegebene IPC-Verbindung (Connection) gesendet wird: */ SIGEV_PULSE_INIT ( /* struct sigevent *: */ & Event, /* sigev_coid: */ coid, // Verbindung (Connection-ID) /* sigev_priority: */ SIGEV_PULSE_PRIO_INHERIT, // Priorität, mit der der Pulse // empfangen wird // SIGEV_PULSE_PRIO_INHERIT: // Priorität beibehalten /* sigev_code: */ PULSE_CODE_TIMER, // Pulse-Code /* sigev_value: */ 0 // Wert, der vom Pulse-Handler // verwendet werden kann // (in diesem Beispiel wird // dieser ignorert) ); // Ende des Funktionsarguments /* 3 */ * Nun den POSIX-Timer mit Echtzeiteigenschaft erzeugen * und als Signalquelle des POSIX-Event definieren: */ if( timer_create( CLOCK_REALTIME, & Event, & Zeitgeber ) == -1 ) { perror ("*** Fehler: timer_create()"); exit (EXIT_FAILURE); } /* * ab hier gilt die Signalverkettung * Zeitgeber * --> Event * --> Pulse * --> Verbindung * --> IPC-Kanal * --> dieser Anwendungsprozess */ /* 4 */ * Nun die Parameter des Zeitgebers: * * Dauer des 1. Wartezeitintervalls nach Aufruf von timer_settime(...) */ zykluszeit.it_value.tv_sec = 2; zykluszeit.it_value.tv_nsec = 0; /* hier konstante 2s 0ns */ /* * Wiederholzeit für das periodische Wecken danach: */

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 58 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

zykluszeit.it_interval.tv_sec = 2; zykluszeit.it_interval.tv_nsec = 0; /* wie oben */ /* 5 */ * Zeitgeber programmieren und aktivieren: */ timer_settime( Zeitgeber, 0, & zykluszeit, NULL ); /* * Ab jetzt läuft die Weckzeit * des 1. Wartezeitintervalls */ /* * falls die Task auch Nachrichten von einer eigenen ISR empfangen soll, * muss das vor der Marke /* 1 */ oben mit einer weiteren Connection (Verbindung) * wie in den Programmbeispiel zur Interruptverarbeitung codiert werden, */ // // Ende des Hochlaufs //////////////////////////////////////////////// for ( shutdown=0 ; !shutdown ; ) { recvid = MsgReceive(attach->chid, &msg, sizeof(msg), NULL); if ( recvid == -1 ) { perror("*** Fehler: MsgReceive()"); } else // im folgenden die hier möglichen Quellen der Nachricht unterscheiden { if ( recvid == 0 ) // ein Pulse ist eingetroffen { if ( msg.header.code == _PULSE_CODE_DISCONNECT ) { // // Client fordert an, Verbindung zu schließen. // ConnectDetach(recvid); } else { if ( msg.header.code == PULSE_CODE_TIMER ) { // Der Timer hat einen neuen Pulse gesendet, // Server startet seine eigeninitiative Aktion: if ( ! action_X1( & msg ) ) { // Misserfolg. Fehler behandeln ... } else { // Erfolg. } } else { // unbekannter Pulse: ignorieren } } } else // eine Nachricht mit Daten ist eingetroffen { // Da jedes Programm in der Lage ist, eine Verbindung zu // diesem Server herzustellen, können beliebige Nachrichten // (und Pulses) ankommen. Ein name_open() durch den Client sendet // z.B. eine Connect-Nachricht. Solche I/O-Messages müssen // herausgefiltert werden, um an die benutzerdefinierte Nachricht zu // gelangen. // if ( msg.header.type == _IO_CONNECT ) { //

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 59 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

// Ein Client hat Verbindung aufgenommen. // Connnect-Nachrichten müssen beantwortet werden, // da sonst der Client für immer blockiert. // Der Server sollte hier den Client in einer Liste eintragen. // MsgReply( recvid, EOK, NULL, 0 ); } else { if ( (msg.header.type > _IO_BASE) && (msg.header.type <= _IO_MAX) ) { // // Dem Client mit einer Fehlermeldung antworten, dass // diese I/O-Nachricht nicht unterstützt wird. Andernfalls // würde dieser auf unbestimmte Zeit blockieren. // MsgError(recvid, ENOSYS); } else { // Dienst für den Client erbringen oder ablehnen ///////////// // run_service_X( & msg ); // Quittung pos./neg. steckt in msg // /////////////////////////////////////////////// if ( MsgReply(recvid, 0, & msg, sizeof(msg)) == -1 ) { perror("*** Fehler: MsgReply()"); } } } } } } timer_delete( Zeitgeber ); name_detach( attach, 0 ); return EXIT_SUCCESS; } // // Hilfsfunktionen des Servers // int run_service_X1( struct service_type * service ) { int retval; // hier der Code für die Verzweigung in den angeforderten Dienst, // seine Erledigung oder Ablehnung, Rückgabe des Ergebnisobjekts als // Komponente des Objekts service. return retval;; } // int action_X1( struct service_type * service ) { int retval; // hier der Code für die Aktionen, die der Server // auch ohne Clientanfragen eigeninitiativ ausführen soll. // Ergbebnisse sind in Komponenten des Objekts service gespeichert // und können bei der nächsten Anfrage eines Client in der Antwort // gesendet werden. return retval;; }: // Ende des Serverprogramms ///////////////////////////////////////////////////

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 60 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

6.3 Beispiel des zugehörigen Clients

Es folgt das Programm der Task B, die gegenüber Task A die Rolle eines Clients annimmt. // Standardheader /////////////////////////////////////////////////////////////// #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/iofunc.h> #include <sys/dispatch.h> // // Header für Regalserver-Kommunikation ///////////////////////////////////////// #include <system/Server/X-Server_simple.h> // int main(int argc, char *argv[]) { int go = 1, retry_send; int coid_srv; // Verbindungsnummer zum Server X struct servicemessage_type msend, mreply; // Nachrichtenobjekte // // Verbindung zum Server herstellen if ( ( coid_srv = name_open( SERVERNAME, NAME_FLAG_ATTACH_GLOBAL ) ) == -1 ) { // Misserfolg. Statt wie hier sofort das Programm zu beenden, kann auch // eine Anzahl Wiederholungen sinnvoll sein. perror("*** Fehler: name_open( Server X )"); exit( EXIT_FAILURE ); } else // Erfolg: { // Hauptschleife /////////////////////////////////////////////////////// // go = 1; retry_send = 0; do{ message_produce( & msend ); // Hier entsteht die Nachricht // an den Server msg.header.type = _IO_MAX + 1; // msg.request = REQUESTCODE_1; // // // Absenden: // while( MsgSend( coid_srv, & msend, sizeof(msend), & mreply, sizeof(mreply) ) == -1 ) { perror("*** Fehler: MsgSend( Server X)"); // weitere Behandlung dieses Fehlers hier einsetzen ... if ( ++retry_send >= 10 ) { go = 0; // Ende break; } else { delay( 2 ); // nochmal Senden nach 2 ms block. Warten } } if( go ) // Schleife mit MsgSend ohne Fehler beendet { retry_send = 0; // hier das zurückgesendete Dienstergebnis verarbeiten message_consume( & mreply ); } }while ( go ); // // Hauptschleife beendet. ////////////////////////////////////////////// //

Prozessdatenverarbeitung Wintersemester 2017/18 Seite 61 Unterlagen zur Vorlesung

Ostfalia Hochschule für angewandte Wissenschaften Fakultät Elektrotechnik Prof. Dr.-Ing. M. Haas

close( coid_srv ); // Verbindung zum Regalserver abbauen return EXIT_SUCCESS; } } void message_produce( struct servicemessage_type * sendmsg ); { // hier entsteht der Bedarf für eine Dienstanfrage ... } void message_consume( struct servicemessage_type * replymsg ) { // hier wird die Antwort des Servers verarbeitet ... } Die Rückkehr aus MsgSend mit Fehler geschieht normalerweise sofort, weswegen eine kurze Wartezeit angebracht ist. In vielen Anwendungen Senden Clients nicht in jedem Zyklus ihrer Hauptschleife eine Nachricht an ihre(n) Server, sondern nur dann, wenn ein konkreter Dienst benötigt wird. Das ist hier vereinfachend nicht berücksichtigt. Die ausführliche Besprechung der Programme findet in der Vorlesung statt.

6.4 Andere Formen der Interprozesskommunikation

Pipes, Fifos, POSIX-Message Queues und Socket IPC sind verschiedene andere Formen der IPC. Im Rahmen einer kurzen Übersicht können sie in der Vorlesung vorgestellt werden.