Sicherheitskritische Echtzeitanwendungen

Einfacher Programmieren mit Ada

19. Februar 2015, 8:08 Uhr | Ralf Higgelke
Diesen Artikel anhören

Fortsetzung des Artikels von Teil 2

Blinker in der »Timer«-Version

Bild 5: Code der Spezifikation des Package »Timer_Setup«
Bild 5: Code der Spezifikation des Package »Timer_Setup«
© Berger IT Cosmos

Bei der Blinker-Anwendung in der »Timer«-Version wird mit der Procedure »Timer_Setup.Pulser.Start« (Zeile 41 in Bild 4) der Timer gestartet. Die Hauptprozedur läuft wiederum in einer leeren Programmschleife.

In Bild 5 ist die Spezifikation des Package »Timer_Setup« dargestellt. Hier wird das Child-Package »Ada.Real_Time.Timing_Events« benutzt (Zeile 1), das es seit Ada 2005 gibt. Besondere Aufmerksamkeit gilt dem sogenannten »protected object«, eine Eigenschaft, die kongruente Programmierung in Ada erleichtert. Auf die privaten Elemente eines »protected objects« kann man nur von einem Task zu einer bestimmten Zeit zugreifen. Das vereinfacht die in anderen Sprachen oft nicht-triviale Implementierung von Mutexes. Das »pragma Interrupt_Priority« in Zeile 7 ist nötig, um die Priorität des Timer-Interrupts auf den höchsten Wert zu setzen.

passend zum Thema

Bild 6: Code des »Package Body« von Timer_Task bei der »Timer«-Version
Bild 6: Code des »Package Body« von Timer_Task bei der »Timer«-Version
© Berger IT Cosmos

Innerhalb des Bodys (Bild 6) haben wir »Pulse« und »Pulse_Interval« (Zeilen 6 und 7) als lokale Variablen deklariert, also sind diese nur innerhalb des Bodys sichtbar. Die Berechnung der neuen Zeit (»Next_Time«) und »Toggle_Led« sind in den Prozeduren »Start« 
(Zeilen 10 bis 15) und »Timer« (Zeilen 17 bis 22) dieselben wie in der Task-Version, nur dass anstatt eines Tasks nun ein Handler benutzt wird, um das periodische Verhalten zu implementieren. In »Start« wird als nächster Handler beim nächsten Timeout auf die »Timer«-Prozedur verwiesen, die dann wiederum auf sich selbst verweist. »Timer‘Access« (Zeilen 14 und 21) bedeutet, dass der Zeiger (Pointer) an die Prozedur übergeben wird. So wird erreicht, dass die LED bei jedem Timeout wechselt, also das gleiche Verhalten zeigt wie im »Task«-Beispiel.

Hier ein kleines Beispiel 

function Toggle_Value(Value : Unsigned_32; V_Toggle : Unsigned_32)
        return Unsigned_32 is (Value xor V_Toggle)

with
        Post => Toggle_Value‘Result = (Value xor V_Toggle);

 

^

Mit Ada 2012 wurde die Contract-basierte Programmierung mithilfe von »Aspects« eingeführt. Hiermit lässt sich das Design einer Anwendung in die Sprache einbetten und nicht nur in Kommentaren Designanforderungen (Low Level Requirements) vermerken. Der große Vorteil hier ist, dass man mit statischen Analysewerkzeugen (z.B. CodePeer und Spark 2014) den Code auf diese Anforderungen analysieren kann und so ihre Erfüllung nachweisen kann, ohne den Code auf diese testen zu müssen. Natürlich kann man auch die Assertions zur Laufzeit mit dem Compiler-Switch »-gnata« einschalten, der eine Fehlermeldung liefert, wenn die Assertion nicht erfüllt wird.

Die Anweisung »Post=>« überprüft, ob die Bedingung erfüllt ist, wenn die Funktion zurückkehrt. In gleicher Weise wird mit der Anweisung »Pre=>« die Bedingung für die Eingabeparameter überprüft.

Bemerkenswert ist die kurze Form der Funktionsdeklaration in der Spezifikation nach der Anweisung »return«: Sie ist in diesem Fall kein Wert, sondern ein kurzer Ausdruck. Auch diese Form der schnellen Funktionsdeklaration ist mit Ada 2012 eingeführt worden. Dadurch lassen sich diese Funktionen beispielsweise in Pre- und Post-Conditions aufrufen, was nicht möglich wäre, wenn ihre Definition im »body« wäre.


  1. Einfacher Programmieren mit Ada
  2. Blinker in der »Task«-Version
  3. Blinker in der »Timer«-Version
  4. Ravenscar-Profil und Restrictions

Das könnte Sie auch interessieren

Jetzt kostenfreie Newsletter bestellen!