6.8 KiB
MARTe Configuration Guide
This guide explains the syntax, features, and best practices for writing MARTe configurations using mdt.
1. Syntax Overview
MARTe configurations use a hierarchical object-oriented syntax.
Objects (Nodes)
Objects are defined using + (public/instantiated) or $ (template/class-like) prefixes. Every object must have a Class field.
+MyObject = {
Class = MyClass
Field1 = 100
Field2 = "Hello"
}
Fields and Values
- Fields: Alphanumeric identifiers (e.g.,
Timeout,CycleTime). - Values:
- Integers:
10,-5,0xFA - Floats:
3.14,1e-3 - Strings:
"Text" - Booleans:
true,false - References:
MyObject,MyObject.SubNode - Arrays:
{ 1 2 3 }or{ "A" "B" }
- Integers:
Comments and Documentation
- Line comments:
// This is a comment - Docstrings:
//# This documents the following node. These appear in hover tooltips.
//# This is the main application
+App = { ... }
2. Signals and Data Flow
Signals define how data moves between DataSources (drivers) and GAMs (algorithms).
Defining Signals
Signals are typically defined in a DataSource. They must have a Type.
+MyDataSource = {
Class = GAMDataSource
Signals = {
Signal1 = { Type = uint32 }
Signal2 = { Type = float32 }
}
}
Using Signals in GAMs
GAMs declare inputs and outputs. You can refer to signals directly or alias them.
+MyGAM = {
Class = IOGAM
InputSignals = {
Signal1 = {
DataSource = MyDataSource
Type = uint32 // Must match DataSource definition
}
MyAlias = {
Alias = Signal2
DataSource = MyDataSource
Type = float32
}
}
}
Threading Rules
Validation Rule: A DataSource that is not marked as multithreaded (default) cannot be used by GAMs running in different threads within the same State.
Ordering Rule: For INOUT signals (data dependency within a thread), the Producer GAM must appear before the Consumer GAM in the thread's Functions list. This ensures correct data flow within the cycle. This rule is skipped if the DataSource is marked as multithreaded: true.
To allow sharing, the DataSource class in the schema must have #meta: multithreaded: true.
3. Schemas and Validation
mdt validates your configuration against CUE schemas.
Built-in Schema
Common classes (RealTimeApplication, StateMachine, IOGAM, etc.) are built-in.
Custom Schemas
You can extend the schema by creating a .marte_schema.cue file in your project root.
4. Variables and Constants
You can define variables to parameterize your configuration.
Variables (#var)
Variables can be defined at any level and can be overridden externally (e.g., via CLI).
//# Default timeout
#var Timeout: uint32 = 100
+MyObject = {
Class = Timer
Timeout = @Timeout
}
Constants (#let)
Constants are like variables but cannot be overridden externally. They are ideal for internal calculations or fixed parameters.
//# Sampling period
#let Ts: float64 = 0.001
+Clock = {
Class = HighResClock
Period = @Ts
}
Expressions
Variables and constants can be used in expressions:
- Arithmetic:
+,-,*,/,% - Bitwise:
&,|,^ - String Concatenation:
..
#var BasePath: string = "/tmp"
#let LogFile: string = @BasePath .. "/app.log"
Docstrings
Docstrings (//#) work for variables and constants and are displayed in the LSP hover information.
5. Pragmas
Macros can be controlled via pragmas:
//! allow(implicit): Suppress warnings for implicitly defined signals.//! allow(unused): Suppress warnings for unused signals/GAMs.//! ignore(not_consumed): Suppress ordering warnings for specific signals.
Pragmas can be global (top-level) or local to a node.
Example: Adding a custom GAM
package schema
#Classes: {
MyCustomGAM: {
// Metadata for Validator/LSP
#meta: {
direction: "INOUT" // "IN", "OUT", "INOUT"
multithreaded: false
}
// Fields
Gain: float
Offset?: float // Optional
InputSignals: {...}
OutputSignals: {...}
}
}
4. Multi-file Projects
You can split your configuration into multiple files.
Namespaces
Use #package to define where the file's content fits in the hierarchy.
file1.marte
#package MyApp.Controller
+MyController = { ... }
This places MyController under MyApp.Controller.
Building
The build command merges all files.
mdt build -o final.marte src/*.marte
5. Pragmas (Suppressing Warnings)
If validation is too strict, you can suppress warnings using pragmas (//!).
-
Suppress Unused Warning:
+MyGAM = { Class = IOGAM //! ignore(unused): This GAM is triggered externally } -
Suppress Implicit Signal Warning:
InputSignals = { //! ignore(implicit) ImplicitSig = { Type = uint32 } } -
Type Casting:
Sig1 = { //! cast(uint32, int32): Intentional mismatch DataSource = DS Type = int32 }
6. Variables
You can define variables using #var. The type expression supports CUE syntax.
#var MyVar: uint32 = 100
#var Env: "PROD" | "DEV" = "DEV"
Usage
Reference a variable using $ (preferred) or @:
Field = $MyVar
// or
Field = @MyVar
Expressions
You can use operators in field values. Supported operators:
- Math:
+,-,*,/,%,^(XOR),&,|(Bitwise) - String Concatenation:
..
Field1 = 10 + 20 * 2 // 50
Field2 = "Hello " .. "World"
Field3 = $MyVar + 5
Build Override
You can override variable values during build:
mdt build -vMyVar=200 -vEnv="PROD" src/*.marte
7. Validation Rules (Detail)
Data Flow Validation
mdt checks for logical data flow errors:
- Consumed before Produced: If a GAM reads an INOUT signal that hasn't been written by a previous GAM in the same cycle, an error is reported.
- Produced but not Consumed: If a GAM writes an INOUT signal that is never read by subsequent GAMs, a warning is reported.
- Initialization: Providing a
Valuefield in anInputSignaltreats it as "produced" (initialized), resolving "Consumed before Produced" errors.
Threading Rules
A DataSource that is not marked as multithreaded (default) cannot be used by GAMs running in different threads within the same State.
To allow sharing, the DataSource class in the schema must have #meta: multithreaded: true.
Implicit vs Explicit Signals
- Explicit: Signal defined in
DataSource.Signals. - Implicit: Signal used in GAM but not defined in DataSource.
mdtreports a warning unless suppressed.