Navigation

deutsche Version english version

Die Echtzeit Programmiersprache PEARL

Der Name PEARL steht für Process and Experiment Automation Realtime Language und darf nicht mit Perl, der Practical Extraction and Report Language, verwechselt werden.

PEARL ist eine höhere Programmiersprache, die eine komfortable, sichere und weitgehend rechnerunabhängige Programmierung von Multitasking- und Echtzeit-Aufgaben erlaubt, und wurde seit 1977 in verschiedenen Entwicklungsstufen genormt, zuletzt 1998 als PEARL-90 (DIN 66253-2 1998, Berlin, Beuth-Verlag, 1998).

Wichtiger Grundsatz bei der Entwicklung von PEARL war, neben einer möglichst leichten Abbildbarkeit der prozeßrechentechnischen Probleme, die einfache Erlernbarkeit für den Programmierer. Jeder, der schon eine prozedurale Programmiersprache kennt, wird sich in sehr kurzer Zeit mit PEARL anfreunden können.

Alle grundlegenden Datentypen und Sprachstrukturen anderer prozeduraler Programmiersprachen sind in PEARL vorhanden. PEARL bietet darüber hinaus komfortable Sprachelemente zur Bearbeitung von Multitasking- und Echtzeitaufgaben.

Grundlegende Datentypen und Sprachstrukturen

Datentypen:

  • Grunddatentypen
    • Festkomma, Gleitkomma
    • Zeichen, Zeichenketten
    • Bitvariablen, Bitketten
  • Zusammengesetzte Datentypen
    • Strukturen
    • Felder beliebiger Dimension mit vorgebbaren Unter- und Obergrenzen bei den einzelnen Dimensionen.
  • Funktionen, Prozeduren (Parameterübergabe per Value, per IDENT und als Zeiger)
  • typbehaftete Zeiger auf alle Objekte, auch auf Funktionen und Prozeduren
  • Typfreie Zeiger und Type-Casting

Blockstruktur, Gültigkeit von Objekten:

  • Objektdeklarationen innerhalb eines BEGIN-END-Blockes
  • Prozedur- und funktionsweite Objekte
  • Modulweite Objekte
  • Zugriff auf Objekte anderer Module durch globale Spezifikation von Daten
  • Bekanntmachung von Objekten für andere Module durch globale Deklaration

Kontrollstrukturen:

  • Bedingte Anweisungen
    • IF-THEN-ELSE-FIN
    • CASE-ALT-...-ALT-OUT-FIN
  • Wiederholungen
    • FOR-REPEAT-END
    • WHILE-REPEAT-END

Genaue Informationen über den Aufbau von PEARL sind in

  • DIN 66253-2 1998, Berlin, Beuth-Verlag, 1998
  • PEARL 90 - Sprachreport, Version 2.2., GI-Fachgruppe 4.4.2, Bonn, GI Gesellschaft für Informatik e.V., 1998

enthalten

Back on top ^

Bessere Hardwareunabhängigkeit

Um eine Entkopplung von hardwareabhängigen Komponenten, wie z.B. Ein-/ und Ausgabeschnittstellen, zu dem hardwareunabhängigen Programm zu erreichen, wird ein PEARL-Modul in zwei Sektionen unterteilt:

  • Im sogenannten Systemteil, der ab dem Schlüsselwort SYSTEM beginnt, werden die Namen für die hardwareabhängigen I/O-Schnittstellen bekannt gemacht, und ihre Eigenschaften definiert. Auch Interruptquellen sind hier zu definieren.
  • Der sogenannte Problemteil, welcher mit PROBLEM beginnt, enthält beispielsweise Variablen, Konstanten, Tasks und Prozeduren. Tasks und Prozeduren können auf die im SYSTEM-Teil definierten Schnittstellen zugreifen.

Back on top ^

Multitasking-Anweisungen

Dem Betriebssystem bekannte Tasks können aus einem PEARL-Programm beliebig in ihrem Zustand verändert werden.

  • ACTIVATE Taskname
    Startet die Task mit dem Namen Taskname sofort.
  • TERMINATE Taskname
    Die Task mit dem Namen Taskname wird abgebrochen.
  • SUSPEND Taskname
    Die Task mit dem Namen Taskname wird angehalten.
  • CONTINUE Taskname
    Die angehaltene Task mit dem Namen Taskname wird fortgesetzt.
  • PREVENT Taskname
    Die Task mit dem Namen Taskname, deren Aktivierung mit einem Ereignis gekoppelt wurde, wird wieder ausgeplant. Sie wird also nicht mehr von diesem Ereignis aktiviert bzw. fortgesetzt.

Back on top ^

Einplanung auf Ereignisse und Zeitpunkte

Die Aktivierung und die Fortsetzung von Tasks läßt sich auch an externe Ereignisse oder Zeitpunkte koppeln. Einplanungen zu einer festen Uhrzeit, aber auch Einplanungen beim Auftreten äußerer Ereignisse (Interrupts), sind möglich.

Beispiele:

  • ALL 0.00005 SEC ACTIVATE Highspeedregler;
    Zyklische Aktivierung eines Reglers mit einer Frequenz von 20 kHz
  • AT 12:00 ALL 4 SEC UNTIL 12:30 ACTIVATE Mittagspause PRIO 1;
    Zyklische Einplanung, alle 4 Sekunden zwischen 12:00 Uhr und 12:30 mit einer hohen Priorität
  • WHEN Feuer ACTIVATE Loesch;
    Aktivierung der Task Loesch, wenn Interrupt Feuer eintrifft.

Back on top ^

Tasksynchronisation

Eine Synchronisation von Tasks ist immer dann notwendig, wenn diese Daten gemeinsam nutzen, da sonst Inkonsistenzen auftreten können. Die drei folgenden Beispiele zeigen, wie sich mit Hilfe von Semaphor- und Boltvariablen Tasks synchronisieren lassen. Beabsichtigt eine Task A den Zugriff auf einen Datensatz, der gerade von einer Task B bearbeitet wird, so blockiert das Betriebssystem die Task A solange, bis B die Daten freigibt. Bei Semaphoren erlaubt PEARL an Stelle einer Blockade auch das Testen mit Eintritt bei Freiheit (Schlüsselwort TRY im Beispiel).


	PROBLEM;
	  DCL A      CHAR(255);        ! String: 255 Bytes 
	  DCL SEMVAR SEMA  PRESET(1);  ! Init: Zugriff erlaubt
	  DCL FAILED FIXED INIT(0);
	
	T1: TASK;
	  DCL B1 CHAR(255);
	  REQUEST SEMVAR;    A=B1;  RELEASE SEMVAR;
	END;
	
	T2: TASK;
	  DCL B2 CHAR(255);
	  REQUEST SEMVAR;    A=B2;  RELEASE SEMVAR;
	END;
	
	TEST: TASK;
	  IF TRY SEMVAR THEN
	    RELEASE SEMVAR;  !Semaphor wieder freigeben
	  ELSE
	    FAILED=FAILED+1;
	  FIN;
	  ! Selbstaktivierung nach 10 Sekunden
	  AFTER 10 SEC ACTIVATE TEST;   
	END;
	

Back on top ^

Producer-Consumer-Schemata

Produziert eine Task A Daten, die zur Weiterverarbeitung durch eine oder mehrere andere Tasks vorgesehen sind, so spricht man von einem Producer-Consumer-Schema. Hier ein Beispiel eines Ringspeichers mit 1024 Zeichen, von denen die lesende Task immer 2 gleichzeitig braucht.


	PROBLEM;
	  DCL PLATZDA   SEMA PRESET(1024);  ! Init: 1024 frei
	  DCL ZEICHENDA SEMA PRESET(0);     ! Init: Am Anfang leer
	
	HOLDATEN: TASK;
	  REQUEST ZEICHENDA; REQUEST ZEICHENDA;
	  HOLE_ZWEI_ZEICHEN_AUS_DEM_RINGPUFFER;
	  RELEASE PLATZDA; RELEASE PLATZDA; 
	END;
	
	SCHREIBDATEN: TASK; 
	  REQUEST PLATZDA; 
	  SCHREIB_EIN_ZEICHEN_IN_RINGPUFFER;
	  RELEASE ZEICHENDA;
	END;
	

Producer-Consumer-Schemata entstehen auch bei der Meßwerterfassung und der Automatisierung von Fertigungsprozessen.

Back on top ^

Datenbanken

Möchte der Programmierer erlauben, daß mehrere Tasks gleichzeitig einen Datensatz lesen dürfen (im Beispiel die Tasks LESER1 und LESER2), aber jeweils nur eine schreiben kann, und dies auch nur, falls keine andere liest, sind BOLT-Variablen das Mittel der Wahl.


	PROBLEM;
	  DCL A CHAR(255);  ! String: 255 Bytes 
	  DCL BOLTVAR BOLT; ! Default: frei
	
	LESER1: TASK;          
	  DCL L1 CHAR(255);
	  ! ENTER erlaubt, dass alle weiteren Tasks mit ENTER 
	  ! ebenfalls weiterlaufen  koennen
	  ENTER BOLTVAR;    L1=A;   LEAVE BOLTVAR;
	END;
	
	LESER2: TASK;
	  DCL L2 CHAR(255);
	  ENTER BOLTVAR;    L2=A;   LEAVE BOLTVAR;
	END;
	
	SCHREIBER1: TASK;
	  DCL S1 CHAR(255);
	  ! Nach einem RESERVE laeuft eine Task nur weiter, 
	  ! wenn kein anderer Leser oder Schreiber einen 
	  ! ENTER/RESERVE durchgefuehrt hat.
	  RESERVE BOLTVAR;  A=S1;   FREE  BOLTVAR;
	END;
	
	SCHREIBER2: TASK;
	  DCL S2 CHAR(255);
	  RESERVE BOLTVAR;  A=S2;   FREE  BOLTVAR;
	END;
	

Back on top ^

Ein- und Ausgabe

PEARL sieht für die verschiedenen Ein- und Ausgabeformen jeweils eigene Schlüsselworte vor. In den folgenden Beispielen steht eine alphic_dation z.B. für eine Festplatte, Terminal, LCD-Display und serielle oder parallele Schnittstelle, eine basic_dation z.B. für eine analoge oder digitale Prozeß-Ein-/Ausgabe.

  • Ausgabe
    • Formatierte Ausgabe
      PUT objekt1, ... TO alphic_dation BY formatliste;
    • Binäre Ausgabe
      WRITE objekt1, ... TO alphic_dation;
    • Ausgabe an Prozeßperipherie
      SEND objekt1, ... TO basic_dation;
  • Eingabe
    • Formatiertes Einlesen
      GET objekt1, ... FROM alphic_dation BY formatliste;
    • Binäres Einlesen
      READ objekt1, ... FROM alphic_dation;
    • Einlesen aus der Prozeßperipherie
      TAKE objekt1, ... FROM basic_dation;

Back on top ^

Spezielle Datentypen

  • CLOCK, DURATION
    Diese beiden Datentypen beschreiben Zeitpunkte und -räume. Bei den zeitlichen Einplanungen treten diese Datentypen ebenfalls auf. In den angegebenen Beispielen ist 12:00 eine Konstante vom Typ CLOCK und 0.00005 SEC eine Konstante vom Typ DURATION. Auch Berechnungen zwischen diesen Datentypen sind möglich, wie die beiden folgenden Beispiele zeigen.
    • durationvar = clockvar - clockvar
    • clockvar = clockvar + durationvar
  • INTERRUPT
    Diese Datentypen müssen im Systemteil eines Modules mit einem Hardware- Interrupteingang verbunden werden. Im Problemteil können sie dann mit den oben beschriebenen Mitteln (WHEN ..) zum Ändern eines Taskzustandes verwendet werden.
  • SEMA
    Semaphor-Variablen dienen zur Synchronisation zwischen verschiedenen Tasks. Hauptsächlich dienen sie zum Schutz von Verbunddatenobjekten, die von mehreren Tasks gleichzeitig genutzt werden. Sie werden bei kritischen Pfaden oder Producer-Consumer-Schemata benutzt. Eine Semaphor-Nachbildung läßt sich ohne Betriebssystem-Unterstützung nicht erreichen, da die gewöhnlichen Hochsprach-Operationen belegen, ggf. blockieren bzw. freigeben oder blockierte Task fortsetzen in einem Multitasking-System nicht unteilbar sind.
  • BOLT
    Boltvariablen erlauben im Gegensatz zu Semaphoren einen gleichzeitigen Lesezugriff auf Daten von mehreren Tasks und blockieren schreibende Tasks, wenn eine andere einen Lese- oder Schreibzugriff begonnen hat. Bezüglich der Nachbildung von diesen Variablen ohne Betriebssystemunterstützung gelten die Ausführung zu Semaphoren entsprechend.

Back on top ^