CAPL im Einsatz für CANoe und CANalyzer

Tipps & Tricks beim Einsatz von CAPL

CAPL ist eine von Vector entwickelte prozedurale, C-ähnliche Programmiersprache. Die Ausführung wird von Progammblöcken durch Ereignisse gesteuert. CAPL-Programme werden mit einem eigenen Browser entwickelt und kompiliert. Dabei kann auf alle in der Datenbasis enthaltenen Objekte (Botschaften, Signale, Umgebungsvariablen) und Systemvariablen zugegriffen werden. Darüber hinaus bietet CAPL eine Vielzahl von vordefinierten Funktionen.

CAPL wird von einigen Vector Software-Tools unterstützt. Auf dieser Webseite liegt der Fokus jedoch allein auf den Einsatz mit CANoe und CANalyzer.

Der erste Abschnitt konzentriert sich auf die Basics von CAPL. Er ist in erster Linie für Neulinge dieser Sprache interessant; für Kenner ergeben sich eventuell ein paar Einblicke in die Motivation für einzelne CAPL-Konstrukte. Danach werden fortgeschrittene Funktionsweisen von CAPL behandelt. Zuguterletzt betrachten wir die Themen Performance und  Speicherbedarf und geben Tipps und Tricks zur Verwendung von Datenbanken und assoziativen Arrays.

 

Erfahren Sie mehr über CAPL


...  schauen Sie auch in unser kurzes Video rein oder in die ausführliche Webinar-Aufzeichnung.

 

Einführung

Seit über 20 Jahren – damals zunächst in CANalyzer für DOS – lässt sich mit CAPL eine große Bandbreite von Aufgaben effizient umsetzen: von einfachen Stimuli bis zur Simulation komplexer Busteilnehmer. Im Folgenden wird CANoe stellvertretend für die beiden Produkte CANoe und CANalyzer genannt. Das Ziel von CAPL ist seit jeher, die jeweiligen Aufgabenstellungen so einfach wie möglich zu lösen. Typische Aufgaben sind das Reagieren auf empfangene Botschaften, das Testen und Setzen von Signalwerten oder das Senden von Botschaften. Hier sollte sich ein Programm auf genau diese Dinge beschränken und keinen weiteren Overhead erfordern.

Viele Programmieraufgaben, mit denen ein CANoe Anwender zu tun hat, mögen tatsächlich so kurz und trivial wie das unten aufgeführte Beispiel sein – viele andere Aufgaben sind es natürlich nicht. Deshalb wurde CAPL stetig über die Jahre erweitert, um auch bei komplexen Aufgaben als Werkzeug nach dem Grundsatz „so einfach wie möglich“ zur Verfügung zu stehen.

„CAPL“ steht dabei als Akronym für „Communication Access Programming Language“. Die ursprüngliche Ausrichtung auf CAN ist schon längst auf alle automobilen und einige weitere Bussysteme erweitert, wie beispielsweise LIN, FlexRay, MOST, J1587 aber auch ARINC und CANopen.

Die Syntax von CAPL lehnt sich – wie viele andere Sprachen auch – eng an die Syntax der Sprache C an. Wer sich mit C, C# oder verschiedenen modernen Script-Sprachen auskennt, findet sich auch in CAPL schnell zurecht. Ein paar Auffälligkeiten unterscheiden aber ein CAPL-Programm von einem C-Programm:

  • CAPL-Programme sind „eventorientiert“. Das heißt, sie bestehen aus einzelnen Funktionen, die jeweils auf ein Event innerhalb des aktuell betrachteten Systems reagieren: den Empfang einer Botschaft, die Änderung eines Signals, das Ablaufen eines Timers oder auch eine Änderung in der „Umgebung“. So wird auf die Botschaft EngineState reagiert: On message EngineState (Bild 1 weiter unten).
  • CAPL-Programme verwenden spezifische Datenbanken für die Konzepte des aktuell betrachteten Systems. Botschaften und Signale erhalten dort Namen und können direkt mit diesem im Programmcode verwendet werden. In Bild 1 sind das die Bezeichner EngineState für eine Botschaft und EngineSpeed für ein Signal auf dieser Botschaft.
  • CAPL-Programme geben dem Benutzer keine Pointertypen an die Hand. Damit sind eine Unmenge Programmierfehler und Ursachen für Programmabstürze, wie sie C-Programmierern häufig widerfahren, von vornherein ausgeschlossen. Da Pointer abgesehen von ihrer Fehleranfälligkeit auch ein sehr mächtiges Konzept darstellen, gibt es für manche Dinge in CAPL Ersatz, so zum Beispiel die assoziativen Arrays als Ersatz für dynamischen Speicher.

Eine wichtige Eigenschaft, die CAPL mit C verbindet, sei noch erwähnt: CAPL wird immer kompiliert, also in effizient ausführbaren, flexiblen Maschinencode übersetzt.

YOUTUBE VIDEO

CAPL Basics

3 Examples of CAPL programming in CANoe and CANalyzer (3:30 min)

WEBINAR-AUFZEICHNUNG

Introduction to CAPL

... for CANoe and CANalyzer (60 min.)

Beispiel

Ein simples CAPL-Programm

Bild 1: Ein einfaches CAPL-Programmbeispiel
Bild 1: Ein einfaches CAPL-Programmbeispiel

In diesem Abschnitt ist ein einfaches CAPL-Programm vorgestellt, das eine der grundlegenden Aufgaben eines Busmonitorwerkzeugs erledigt: es lauscht am Bus und bereitet ein paar der Ereignisse auf dem Bus für die Beobachtung/Überwachung durch den Anwender auf. Es handelt sich hier um ein gekürztes Beispielprogramm von CANoe: Display.can aus dem Beispiel Easy.cfg. Das zeigt das Programm. Im Folgenden wird erst die Gesamtfunktion kurz umrissen, bevor dann die einzelnen Abschnitte genauer beschrieben werden.

 

Aufgabenstellung

  • Es soll ein CAN-Bus beobachtet werden, dessen Elemente wie Busknoten, Botschaften und transportierte Signale mit einer Datenbasis beschrieben werden.
  • Wenn die Botschaft EngineState empfangen wird, dann soll das darauf enthaltene Signal EngineSpeed für die Darstellung in einem Anzeigepanel aufbereitet werden und an das Panel weitergereicht werden.
  • Wenn die Botschaft LightState empfangen wird, dann sollen die darauf enthaltenen Signale HeadLight und FlashLight für die grafische Darstellung in einem Anzeigepanel aufbereitet werden und an das Panel weitergereicht werden.

 

Genaue Betrachtung des Programms

Die Zeilennummern in Bild 1 sind nicht Bestandteil des CAPL-Programmes und sind hier nur eingefügt, um einfacher einzelne Zeilen oder Abschnitte referenzieren zu können. Um eine möglichst kompakte Darstellung zu ermöglichen, wurden hier öffnende Klammern nicht in einer separaten Zeile platziert.

In einem CAPL–Programm können globale Variablen und Konstanten definiert werden. Dies geschieht in dem Abschnitt variables (Zeilen 1..5). Global sind diese Konstanten und Variablen für dieses Programm: sie sind überall im Programm verwendbar, aber nicht in anderen Programmen innerhalb derselben Anwendung von CANoe. Die weiteren Abschnitte definieren Reaktionen auf Ereignisse (Zeilen 7..17) und eine Hilfsfunktion (Zeilen 19..28).

Die Zeilen 7..9 zeigen eine minimale Form einer Botschafts-Event-Prozedur. Diese Funktion wird genau dann aufgerufen, wenn diese Botschaft auf dem Bus übertragen wurde. Spezifisch für CAN bedeutet das: Der genaue Zeitpunkt ist der TX bzw. RX–Interrupt des CAN-Controllers, also direkt nach korrekt erfolgter Übertragung der Botschaft. Die Botschaft aufgrund derer die aktuelle Funktion aufgerufen wird, wird mit der Syntax this bezeichnet.

In Zeile 8 wird der Wert des Signals EngineSpeed aus der soeben empfangenen Botschaft this ausgelesen und mit einer Umrechnung / 1000.0 an eine Systemvariable zugewiesen.

Die Zeilen 11..17 zeigen eine Botschaftseventprozedur für die Botschaft LightState, die die Informationen zu einem Blinker überträgt. Die Verarbeitung ist ähnlich wie bei der Botschaft EngineState mit folgenden Besonderheiten: In Zeile 12 wird nun in der gerade übertragenen Botschaft this das RichtungsFlag .dir geprüft. Es sollen in diesem Programm nur empfangene Botschaften betrachtet werden (Wert RX), da auch eine vom Knoten selbst versendete Botschaft eine Event-Prozedur auslöst (Wert TX). In diesem Fall würde in Zeile 15 gegebenenfalls eine Fehlermeldung ausgegeben.

Da die Aufarbeitung des Signals für die Darstellung an der Oberfläche (einem Panel, in dem verschiedene Zustände mit verschiedenen Bitmaps dargestellt werden) etwas aufwändiger ist, wird die Implementierung in eine eigene Funktion ausgelagert: In Zeile 13 wird SetLightDsp mit den beiden benötigten Signalen der Botschaft als Parameter aufgerufen.

Die Zeilen 19 bis 28 schließlich definieren eine eigene Funktion, die je nach Wert der übergebenen Signale unterschiedliche Werte in die Systemvariable LightDisplay im Namensraum Lights schreibt. Diese Variable wählt dann in dieser Demokonfiguration in einem Anzeigepanel die jeweils passende Bitmap aus.

Ausführungsmodell

Ein wichtiger Unterschied zwischen CAPL und C sowie C++ ergibt sich aus der Vorgehensweise, wann und wie Programmelemente aufgerufen werden. In C beginnen beispielsweise alle Verarbeitungsabläufe mit der zentralen Startfunktion main(). In CAPL hingegen enthält ein Programm eine ganze Sammlung gleichberechtigter Prozeduren, die jeweils auf externe Ereignisse reagieren:

  • Vom System ausgelöst: Diese Ereignisse sind einerseits die zur Initialisierung und Nachbereitung des Messungslaufs nutzbaren Ereignisse on preStart, on start, on preStop und on stopMeasurement, andererseits die Zeitsteuerungs- und Tastaturereignisse on timer und on key.
  • Durch Buskommunikation ausgelöst: Die Ereignisprozeduren, die durch Busereignisse wie Kommunikation oder Fehlerbehandlung auftreten, sind vielfältig und stark bustypabhängig. Beispiele sind hier on message und on busOff bei CAN oder on frFrame und on frStartCycle bei FlexRay.
  • Durch Zugriff auf ein Value Object ausgelöst: Hierbei handelt es sich einerseits um System- und Umgebungsvariablen, die in CANoe/CANalyzer global zur Verfügung stehen, sowie andererseits um Signalwerte, die einer Dateninterpretation der Buskommunikation entsprechen. Das Interpretieren führen spezielle Datenbanken aus. Auf dieses Konzept wird der hintere Abschnitt eingehen.

 

Ereignisprozeduren sind atomar: Auch das Simulationsmodell von CANoe ist ereignisorientiert. In Ereignisprozeduren führt CANoe aus Modellsicht alle Aktionen gleichzeitig aus, nämlich zum Zeitpunkt des auslösenden Ereignisses. Die tatsächliche Berechnungsdauer auf einem realen PC wird also vernachlässigt.

Simulationszeit und Zeitstempel: Ein im PC erzeugtes reales Ereignis, etwa eine Busausgabe durch output(), erhält allerdings einen Zeitstempel von der Echtzeituhr. Die Reihenfolge und Zeitpunkte dieser Ereignisse können dabei durch Busprotokolle, Treiber- und Hardware-Eigenschaften beeinflusst werden.Im Falle eines simulierten Busses entfallen einige der genannten Einflussgrößen. Dort werden die Busereignisse gleichzeitig initiiert, was zum Beispiel bei CAN zu einem gesicherten Arbitrieren mehrerer durch output() ausgegebener Botschaften führt.

Aktualisieren von Systemvariablen: Mit CAPL können Anwender auch außerhalb des Programmes sichtbare Umgebungs- oder Systemvariablen ändern. CAPL vollzieht Wertänderungen einer Variablen erst nach Ende der aktuellen Ereignisbearbeitung, aber weiterhin mit der Zeit des eben behandelten Ereignisses. Ein lesender Zugriff innerhalb der aktuellen Prozedur liefert also auch nach scheinbarer Änderung einer solchen Variablen noch den alten Wert. Das hat den Vorteil, dass zu einem Zeitpunkt nicht mehrere Wertänderungen auftreten.

Das Ausführungsmodell ist situationsabhängig: CAPL ist in CANoe und CANalyzer vielfältig einsetzbar. Daher variiert auch das Ausführungsmodell etwas: Die Simulationsknoten einer CANoe Simulation befinden sich parallel am Bus. Entsprechend sind sie unabhängig. Einmal ausgelöste Ereignisse werden immer an alle Programme verteilt. Im Unterschied dazu sind die Knoten im Messaufbau und in CANalyzer seriell hintereinander angeordnet: Jeder Knoten reicht seine Ausgaben an den nächsten weiter. Eintreffende Ereignisse benötigen zur weiteren Verarbeitung eine explizite Weiterleitung an den nächsten Knoten. Dafür stehen die Prozeduren on * und on [*] bereit.
 

Ein weiterer Programmtyp sind die Testprogramme, deren Testprozeduren auf externe Ereignisse warten können. Bei Eintritt eines solchen Ereignisses fährt CAPL dann mit dessen Simulationszeit fort. Im Gegensatz dazu legt ein Warten in normalen Ereignisprozeduren das gesamte Simulationssystem brach. Dies ist eine häufige Fehlerquelle bei der Anwendung von CAPL. Es ist daher nicht sinnvoll, ein Busy-Wait oder einen Wartebefehl in einer externen DLL zu verwenden.

Effizientes Programmieren in CAPL

Der Präprozessor ist in der Sprache C ein mächtiges Hilfsmittel, das aber auch zu Unübersichtlichkeit und damit zu Fehlern führen kann. In CAPL gibt es deswegen nur eine Auswahl der von C bekannten Präprozessor-Direktiven mit vergleichbarer Semantik.

#include: Include-Dateien enthalten beliebige, aber vollständige, Abschnitte eines CAPL-Programmes: includes, variables und procedures. Im Gegensatz zu C wird hier nicht einfach der Text der Include-Dateien in die CAPL-Datei eingefügt, sondern die Abschnitte. Dabei gelten alle Abschnitte der Include-Datei in der gesamten inkludierenden CAPL-Datei „als ob“ sie darin enthalten wären. Die Reihenfolge der Abschnitte ist in CAPL sowieso unerheblich. Das bedeutet, der Compiler mahnt doppelt vorhandene Symbole als Fehler an. Außerdem dürfen sich Code und Daten aus inkludierender und Include-Datei gegenseitig verwenden. Als Ausnahme des eben erklärten Verbots doppelter Symbole dürfen on start, on preStart, on preStop und on stopMeasurement in der inkludierenden und in der Include-Datei koexistieren. Bei diesen Funktionen wird der Code nacheinander ausgeführt, erst der Code aus der Include-Datei, dann der Code aus der inkludierenden Datei.

Include-Dateien übernehmen damit drei Aufgaben: das Deklarieren von Datentypen, das Definieren von Variablen und das Bereitstellen einer (inline-) Funktionsbibliothek.

#pragma library: CAPL-Programme können in anderen Sprachen erstellte Windows-DLLs mit einer passenden CAPL-DLL-Schnittstelle verwenden. Diese DLLs lassen sich direkt mit der Direktive #pragma library("capldll.dll") einbinden.

Makros: In CAPL stehen den Anwendern mehrere vordefinierte Makros im Code und für bedingtes Kompilieren zur Verfügung. Makros für den Einsatz im Code lassen sich uneingeschränkt überall im Code verwenden. Im Gegensatz zu C ist der Einsatz auch beispielsweise völlig frei innerhalb von String-Konstanten, Variablen- und Funktionsnamen. Sie beginnen und enden immer mit einem %-Zeichen und dienen hauptsächlich zum Schreiben von generischen Programmen.

Die verfügbaren Code-Makros umfassen unter anderem den Knotennamen, den Index des aktuellen Kanals, den Namen des aktuellen Netzwerks und den Typ des verwendeten Busses. Auf den Namen der enthaltenden Datei kann der Code mit %FILE_NAME% zugreifen, auf den Namen der aktuell übersetzten Programmdatei mit %BASE_FILE_NAME%. Letzteres ist bei Include-Dateien die inkludierende Datei.

Hier zwei einfache Beispiele:

write("The node name is %NODE_NAME%");
putValue(envChannel%CHANNEL%Var1, %CHANNEL%);


Für das bedingte Kompilieren von Code-Abschnitten gibt es einen eigenen Satz vordefinierter Makros. Diese sind #if, #else, #elif oder #endif. Sie erlauben es, innerhalb eines Programmes nach den Programmarten Simulationsknoten, Messknoten und Testprogramm sowie der verwendeten CANoe-Version zu unterscheiden.

Hier ein Beispiel zusammen mit einem #pragma message:

#if (TOOL_MAJOR_VERSION < 8)
#pragma message(“This program needs at least CANoe V 8 “)
#endif

 

#pragma message: Die Direktive #pragma message ermöglicht es den Anwendern, eine eigene Meldung während eines Übersetzungsvorganges auszugeben, zum Beispiel die Versionsnummer für das gerade übersetzte CAPL-Programm. Diese erscheint zusammen mit den anderen Meldungen, Warnungen, Fehlern und allgemeinen Meldungen des Compilers.

Assoziative Arrays

CAPL kennt keine Pointertypen und damit auch keine dynamische Speicherverwaltung, wie sie in anderen Sprachen, beispielsweise C, üblich ist. Dadurch ist CAPL sehr robust und auch für Ablaufumgebungen geeignet, die knapp an Speicher und umständlich zu debuggen sind. Davon profitiert insbesondere das CANoe Feature „CAPL-on-Board“, das die Programme zur Verbesserung des Echtzeitverhaltens direkt auf der Hardware bestimmter Bus-Interfaces ausführt. In der zumeist verwendeten Windows-Ablaufumgebung hingegen ist Speicher selten knapp. Darum können hier Daten, deren Umfang vor Programmstart nicht feststeht, mit Assoziativen Arrays gespeichert werden.
Assoziative Arrays sind Container, die den Maps oder Dynamischen Arrays in anderen Programmiersprachen entsprechen. Intern verwendet CAPL für diese Arrays eine effiziente Hashtable. Diese speziellen Arrays ermöglichen damit das Speichern von Busbotschaften oder Messwerten, auch wenn vorher nicht bekannt ist, welche Botschaften oder wie viele Messwerte überhaupt auftreten.
Das Deklarieren von Assoziativen Arrays erfolgt in CAPL als einfache Arrays, allerdings mit einem Schlüsseltyp anstatt der sonst üblichen Größenangabe.

Zwei Beispiele für Assoziative Arrays:

long lastTime [long];
char[30] translate[ char[] ];


Der Bezeichner lastTime steht für ein Array, das long-Schlüssel auf long-Werte abbildet. Während translate für eines steht, das Zeichenkettenschlüssel (ohne Längenbegrenzung!) auf char[30]-Zeichenkettenwerte abbildet. Eine mögliche Anwendung von lastTime besteht darin, für jede auf dem CAN-Bus auftretende Botschafts-ID einen Wert abzulegen:

on message CAN1.*{
  lastTime [this.id]
    = this.time;
}

 

Für den komfortablen Umgang mit Assoziativen Arrays enthält CAPL noch weitere Funktionen:

  • containsKey fragt ab, ob ein spezifischer Schlüssel bereits enthalten ist.
  • size liefert die Anzahl der enthaltenen Schlüssel.
  • clear leert ein Assoziatives Array komplett, während remove einen einzelnen Schlüssel entfernt. Beide Funktionen geben Speicher frei.

 

Zu guter Letzt existiert eine Spezialform der for-Anweisung für Assoziative Arrays. Diese Form iteriert über alle tatsächlich enthaltenen Schlüssel in lastTime:

for (long akey: lastTime)
    {[…]} …

Datenbankenzugriff

In dem Abschnitt Einführung wurde bereits die Hauptanwendung von busspezifischen Datenbanken in CAPL aufgezeigt: es werden Namen für Botschaften und Signale eingeführt. Das Komplizierte an Signalen aus Programmierersicht ist, dass sie in den Nutzdaten von Botschaften aus Effizienzgründen meistens recht eng gepackt sind. Deshalb weisen sie im Allgemeinen beliebige Bit-Längen und Offsets innerhalb der Nutzdaten auf. Zudem lassen sie sich im Intel- oder im Motorola-Format ablegen.

Der symbolbasierte Zugriff über den Namen entlastet den CAPL-Anwender von all diesen Details. Bei einem lesenden oder schreibenden Zugriff wird der nötige Code für den bit-genauen Zugriff, das Maskieren, das Drehen und das Schieben vom Compiler eingefügt.

Datenbanken enthalten noch weitere Objekte, die dem Anwender in CAPL-Programmen zur Verfügung stehen. Insbesondere lassen sich Signale symbolischen Wertetabellen zuordnen. Damit sind als Werte kodierte Zustände mit ihren Klarnamen nutzbar. Außerdem steht es dem Ersteller einer Datenbank völlig frei, eigene weitere Attribute zu definieren, die er dann im Programmcode verwenden kann.

Anhand der symbolischen Namen ist CAPL in der Lage, bekannte Datenbankobjekte direkt zu verwenden. Manchmal sind die potentiell interessierenden Objekte aber beim Erstellen des Programmes noch gar nicht bekannt. Deshalb kann CAPL zusätzlich zur Laufzeit auf die Gesamtheit aller Botschaften eines Knotens zugreifen. Außerdem kann es zu beliebigen Botschaften und Signalen die Datenbankdefinitionen liefern.

Ein kurzes Beispiel:

message * m;
int i, mx;
mx=elcount(aNet::aNode.Tx);
for (i = 0; i < mx; ++i)
{
  m.id=aNet::aNode.TX[i];
  write(DBLookup(m).Name);
}


Diese Zugriffstechniken erlauben es dem Anwender, zusammen mit den zuvor eingeführten Assoziativen Arrays, bei Bedarf generische Programme zu schreiben.

Performance

Die meisten CAPL-Programme müssen nicht-triviale Echtzeitbedingungen einhalten. Das Ausführungsmodell eines mit CAPL simulierten Knotens verwendet sogar die Modellvorstellung, dass CAPL-Programme beliebig schnell ablaufen. Um diesem Idealbild ausreichend nahe zu kommen, werden CAPL-Programme kompiliert, also in die Maschinensprache des jeweils ausführenden Prozessors übersetzt. Außerdem werden für den oft komplexen Zugriff auf Signale optimierte Codesequenzen verwendet.

 

Nachfolgend gibt es ein paar Tipps, wie der Anwender die Performance beeinflussen kann:

writeEx(): Die Funktion write dient zur Ausgabe einzelner Meldungen in das Write-Fenster von CANoe und CANalyzer. Für das Ausgeben größerer Datenmengen steht als Alternative die Funktion writeEx zur Verfügung. Mit ihr kann unter anderem direkt in das Trace-Fenster oder in eine Logging-Datei geschrieben werden. Das Zeitverhalten von Meldungen zu diesen Zielen ist identisch zu dem Zeitverhalten von Busereignissen.

Ereignisprozeduren: Ein CAPL-Programm besteht aus einer beliebigen Anzahl von Prozeduren, die auf Ereignisse reagieren. Einige dieser Ereignisse treten ausgesprochen häufig auf. Die Performance eines Programmes ist daher signifikant besser, wenn nur die jeweils interessierenden Ereignisse verarbeitet werden. Sollten zum Beispiel nur solche Slots interessieren, die ein bestimmtes Signal enthalten, ist es besser on frSlot signalname zu schreiben, als on frSlot *.

Signalflanken: Für Signale und Systemvariablen existieren jeweils zwei Varianten für die Ereignisprozeduren. on signal_update und on sysvar_update werden bei jedem schreibendem Zugriff auf die jeweiligen Datenobjekte aufgerufen, auch dann, wenn sich der Wert dabei gar nicht ändert. Im Gegensatz dazu bringen on signal_change und on sysvar_change einen Performancevorteil, sofern nur Wertänderungen interessieren. Diese beiden Prozedurarten werden nur dann aufgerufen, wenn sich der jeweilige Wert auch tatsächlich geändert hat. Die Kurzformen on signal und on sysvar entsprechen dabei schon den optimierten Formen, die nur auf echte Flanken reagieren.

Speicherbedarf

In CAPL sind alle Variablen statisch. Das heißt, sie werden alle bei Programmstart angelegt und der Speicherplatz erst bei Programmende wieder freigegeben. Das ist ein Unterschied zu den meisten blockorientierten Sprachen, wie beispielsweise C, bei denen lokale Variablen nur existieren, bis der sie enthaltene Block verlassen wird. Dadurch kann CAPL überraschend viel Speicher benötigen, wenn viele Prozeduren gleichartige große Variablen anlegen, die sie sich eigentlich teilen könnten.

Ein Beispiel:

testcase test789()
{
  char outBuffer[1024];
  [..]


Es gibt CAPL-Programme mit tausenden solcher Testprozeduren, von denen stets nur eine auf einmal laufen kann. Ein Puffer, etwa um Meldungen zu formatieren, sollte in diesem Fall nur einmal global im variables-Abschnitt angelegt werden.

Eine andere nicht sinnvolle Verwendung ist das Anlegen von übergroßen Arrays, etwa um Daten von Ereignissen unter ihrer jeweiligen ID abzulegen. Eine extended ID bei CAN umfasst 29 Bit, kann also über 500 Millionen Werte annehmen. Hierfür ein fast leeres Array zu verwenden, ist Speicherverschwendung. Besser ist es, für solche Zwecke Assoziative Arrays wie weiter oben beschrieben zu verwenden. Sie benötigen zwar für jedes tatsächlich verwendete Element etwas mehr Speicher, brauchen dafür aber keinen Speicher für nicht verwendete Elemente.

Nützliche, aber weniger bekannte Features

Abschließend eine kurze Aufzählung eher weniger bekannter Features:

  • Mit Structs lassen sich ähnlich wie in C Strukturen definieren. Zusammen mit Kopieroperationen, die auch zwischen Intel- und Motorola-Format innerhalb einer struct umwandeln können, bilden sie eine flexible Möglichkeit zur Datenkonvertierung.
  • Beim Aufruf von CAPL- Funktionen hat der Anwender die Möglichkeit außer Werte–Parameter auch Referenz–Parameter zu übergeben. Wichtigste Anwendung ist die Rückgabe von mehr als einem Ergebniswert aus einer Funktion. Auch von CAPL–DLLs aus lassen sich Referenz–Parameter nutzen.

 

  • CAPL-Programme sollen auch bei fehlerhafter Anwendung nicht abstürzen. Diese Robustheit wird einerseits durch die Sprachstruktur erreicht, etwa indem es keine allgemeinen Pointer gibt. Andererseits verbessern automatische Laufzeittests von Array-Grenzen, Stack-Grenzen und benötigter Rechenzeit die Stabilität.
  • Es steht eine eigene Kommandozeilenversion des Compilers zur Verfügung. Diese Version ist sehr hilfreich zum Automatisieren von Abläufen in Skriptsprachen.

Mehr CAPL Know-How

Besuchen Sie unsere Schulungswebseit, um ein CAPL-Training für CANoe oder CANaylzer zu finden, dass zu Ihnen passt.

CAPL-Training in Anwendung mit vTESTstudio bieten wir ebenfalls an. Schauen Sie sich das Angebot mal an.

Bei Fragen stehen Ihnen unsere Trainingskollegen jederzeit gern zur Verfügung.

Mehr anzeigen

Produkte

CANoe

Entwickeln und Testen von Steuergeräten und Netzwerken auf höchstem Niveau.

Zur Seite gehen
CANalyzer

Steuergeräte- und Netzwerk-Analyse auf höchstem Niveau

Mehr erfahren