Initial release

This commit is contained in:
Martino Ferrari
2026-05-29 13:29:59 +02:00
commit 617b5bd712
110 changed files with 29234 additions and 0 deletions
@@ -0,0 +1,7 @@
all:
$(MAKE) -C UDPStreamer -f Makefile.gcc
clean:
$(MAKE) -C UDPStreamer -f Makefile.gcc clean
.PHONY: all clean
@@ -0,0 +1 @@
# DataSources intermediate Makefile.inc
@@ -0,0 +1,25 @@
#############################################################
#
# Copyright 2015 F4E | European Joint Undertaking for ITER
# and the Development of Fusion Energy ('Fusion for Energy')
#
# Licensed under the EUPL, Version 1.1 or - as soon they
# will be approved by the European Commission - subsequent
# versions of the EUPL (the "Licence");
# You may not use this work except in compliance with the
# Licence.
# You may obtain a copy of the Licence at:
#
# http://ec.europa.eu/idabc/eupl
#
# Unless required by applicable law or agreed to in
# writing, software distributed under the Licence is
# distributed on an "AS IS" basis,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied.
# See the Licence for the specific language governing
# permissions and limitations under the Licence.
#
#############################################################
include Makefile.inc
@@ -0,0 +1,56 @@
#############################################################
#
# Copyright 2015 F4E | European Joint Undertaking for ITER
# and the Development of Fusion Energy ('Fusion for Energy')
#
# Licensed under the EUPL, Version 1.1 or - as soon they
# will be approved by the European Commission - subsequent
# versions of the EUPL (the "Licence");
# You may not use this work except in compliance with the
# Licence.
# You may obtain a copy of the Licence at:
#
# http://ec.europa.eu/idabc/eupl
#
# Unless required by applicable law or agreed to in
# writing, software distributed under the Licence is
# distributed on an "AS IS" basis,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied.
# See the Licence for the specific language governing
# permissions and limitations under the Licence.
#
#############################################################
OBJSX = UDPStreamer.x
PACKAGE=Components/DataSources
ROOT_DIR=../../../../
MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
INCLUDES += -I.
INCLUDES += -I$(ROOT_DIR)/Common/UDP
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L0Types
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L2Objects
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L3Streams
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Configuration
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L3Services
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L3Streams
all: $(OBJS) \
$(BUILD_DIR)/UDPStreamer$(LIBEXT) \
$(BUILD_DIR)/UDPStreamer$(DLLEXT)
echo $(OBJS)
include depends.$(TARGET)
include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,472 @@
/**
* @file UDPStreamer.h
* @brief Header file for class UDPStreamer
* @date 13/05/2026
* @author Martino Ferrari
*
* @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
* the Development of Fusion Energy ('Fusion for Energy').
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence")
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
*
* @warning Unless required by applicable law or agreed to in writing,
* software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the Licence permissions and limitations under the Licence.
*
* @details This header file contains the declaration of the class UDPStreamer
* with all of its public, protected and private members. It may also include
* definitions for inline methods which need to be visible to the compiler.
*/
#ifndef UDPSTREAMER_H_
#define UDPSTREAMER_H_
/*---------------------------------------------------------------------------*/
/* Standard header includes */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Project header includes */
/*---------------------------------------------------------------------------*/
#include "BasicTCPSocket.h"
#include "BasicUDPSocket.h"
#include "CompilerTypes.h"
#include "EmbeddedServiceMethodBinderI.h"
#include "EventSem.h"
#include "FastPollingMutexSem.h"
#include "MemoryDataSourceI.h"
#include "SingleThreadService.h"
#include "StreamString.h"
/*---------------------------------------------------------------------------*/
/* Class declaration */
/*---------------------------------------------------------------------------*/
namespace MARTe {
/**
* @brief Publishing mode for the background sender thread.
*
* - Strict: send one packet every Synchronise() call (default).
* - Accumulate: buffer N successive snapshots and flush either when the next
* snapshot would exceed MaxPayloadSize or when 1/MinRefreshRate
* has elapsed. Scalars expand to arrays; the first scalar with
* Unit="us"/"ns" is auto-promoted as the FullArray time reference.
* - Decimate: send one packet every Ratio Synchronise() calls.
*/
typedef enum {
UDPStreamerPublishStrict = 0u, /**< Send on every RT cycle (default) */
UDPStreamerPublishAccumulate = 1u, /**< Accumulate until size/time limit; then flush */
UDPStreamerPublishDecimate = 2u /**< Send 1 packet every Ratio cycles */
} UDPStreamerPublishMode;
/**
* @brief Quantization types for float signals.
*/
typedef enum {
UDPStreamerQuantNone = 0u, /**< No quantization; raw wire format */
UDPStreamerQuantUint8 = 1u, /**< Quantize to uint8 [0, 255] */
UDPStreamerQuantInt8 = 2u, /**< Quantize to int8 [-127, 127] */
UDPStreamerQuantUint16 = 3u, /**< Quantize to uint16 [0, 65535] */
UDPStreamerQuantInt16 = 4u /**< Quantize to int16 [-32767, 32767] */
} UDPStreamerQuantType;
/**
* @brief Time reference modes for signals.
*/
typedef enum {
UDPStreamerTimePacket = 0u, /**< Use the packet-level timestamp (HRT at Synchronise time) */
UDPStreamerTimeFullArray = 1u, /**< Time signal has same NumberOfElements; one timestamp per element */
UDPStreamerTimeFirstSample = 2u, /**< Time signal is scalar = timestamp of first element */
UDPStreamerTimeLastSample = 3u /**< Time signal is scalar = timestamp of last element */
} UDPStreamerTimeMode;
/**
* @brief Per-signal metadata used at runtime for serialization.
*/
struct UDPStreamerSignalInfo {
StreamString name; /**< Signal name */
TypeDescriptor type; /**< MARTe2 type descriptor */
UDPStreamerQuantType quantType; /**< Quantization type (none = raw copy) */
uint8 numDimensions; /**< Number of dimensions (0=scalar, 1=array, 2=matrix) */
uint32 numElements; /**< Total number of elements (rows * cols) */
uint32 numRows; /**< Number of rows */
uint32 numCols; /**< Number of columns */
float64 rangeMin; /**< Min of physical range (for quantization) */
float64 rangeMax; /**< Max of physical range (for quantization) */
UDPStreamerTimeMode timeMode; /**< How time is encoded for this signal */
float64 samplingRate; /**< Hz, used for First/LastSample modes */
uint32 timeSignalIdx; /**< Index of the time-reference signal; 0xFFFFFFFFu = PacketTime */
StreamString unit; /**< Physical unit string */
uint32 srcByteSize; /**< Bytes in MARTe2 memory */
uint32 wireByteSize; /**< Bytes on the wire (may differ when quantized) */
uint32 bufferOffset; /**< Byte offset in the flat MemoryDataSourceI memory buffer */
bool accumulated; /**< True when this scalar was expanded to flushCount elements in Auto accumulation mode */
};
/**
* @brief Magic number for UDPStreamer packets: 'UDPS' in little-endian.
*/
static const uint32 UDPS_MAGIC = 0x53504455u;
/**
* @brief Packet type codes.
*/
static const uint8 UDPS_TYPE_DATA = 0u; /**< Server → Client: signal data */
static const uint8 UDPS_TYPE_CONFIG = 1u; /**< Server → Client: signal configuration */
static const uint8 UDPS_TYPE_ACK = 2u; /**< Client → Server: acknowledge counter */
static const uint8 UDPS_TYPE_CONNECT = 3u; /**< Client → Server: connect request */
static const uint8 UDPS_TYPE_DISCONNECT = 4u; /**< Client → Server: disconnect */
/**
* @brief Wire packet header (17 bytes, packed).
*/
struct UDPSPacketHeader {
uint32 magic; /**< Must equal UDPS_MAGIC */
uint8 type; /**< One of UDPS_TYPE_* */
uint32 counter; /**< Sequence counter (per data update, not per fragment) */
uint16 fragmentIdx; /**< 0-based index of this fragment */
uint16 totalFragments; /**< Total fragments for this update (1 = no fragmentation) */
uint32 payloadBytes; /**< Bytes of payload immediately following this header */
} __attribute__((packed));
/**
* @brief Signal type codes transmitted in the CONFIG packet.
* These are simplified type codes independent of MARTe2 internals.
*/
static const uint8 UDPS_TYPECODE_UINT8 = 0u;
static const uint8 UDPS_TYPECODE_INT8 = 1u;
static const uint8 UDPS_TYPECODE_UINT16 = 2u;
static const uint8 UDPS_TYPECODE_INT16 = 3u;
static const uint8 UDPS_TYPECODE_UINT32 = 4u;
static const uint8 UDPS_TYPECODE_INT32 = 5u;
static const uint8 UDPS_TYPECODE_UINT64 = 6u;
static const uint8 UDPS_TYPECODE_INT64 = 7u;
static const uint8 UDPS_TYPECODE_FLOAT32 = 8u;
static const uint8 UDPS_TYPECODE_FLOAT64 = 9u;
static const uint8 UDPS_TYPECODE_UNKNOWN = 255u;
/**
* @brief A DataSource that streams MARTe2 signals to UDP clients.
*
* @details This output DataSource accepts signals from GAMs and forwards them
* asynchronously over the network. A dedicated background thread handles all
* network I/O so that the real-time thread is only blocked by a fast spinlock
* and a memcpy during Synchronise().
*
* Two operating modes are selected by the presence or absence of MulticastGroup:
*
* @par Unicast mode (default — no MulticastGroup)
* The server opens a single UDP socket on Port. The client initiates the session
* by sending a CONNECT packet to that port. The server replies with a CONFIG
* packet on the same socket and subsequently sends DATA packets directly to the
* client's address. Any number of clients may connect sequentially (one at a
* time); a new CONNECT evicts the previous client.
*
* @par Multicast mode (MulticastGroup specified)
* The server opens a TCP listener on Port for control traffic and a UDP socket
* aimed at MulticastGroup:DataPort for data traffic. The client:
* 1. Connects to Port via TCP and sends a CONNECT packet.
* 2. Receives the CONFIG packet over TCP.
* 3. Joins the multicast group (MulticastGroup:DataPort) to receive DATA packets.
* Multiple clients may receive data simultaneously by joining the same group.
* A new TCP CONNECT evicts the previous client from the control channel; the
* multicast data stream continues regardless.
*
* @par Packet protocol (both modes)
* - Client → Server: CONNECT (initiates session), DISCONNECT (terminates session),
* ACK (optional, for packet-loss monitoring).
* - Server → Client: CONFIG (signal metadata), DATA (signal values, possibly
* fragmented into multiple datagrams if payload exceeds MaxPayloadSize).
*
* @par Top-level configuration parameters
* | Parameter | Type | Default | Description |
* |-----------------|---------|---------|-------------|
* | Port | uint16 | 44500 | TCP control port (multicast) or UDP server port (unicast). Values ≤ 1024 produce a warning. |
* | MulticastGroup | string | *(absent)* | **Enables multicast mode.** IPv4 multicast address, e.g. `"239.0.0.1"`. Must be in 224.0.0.0/4. Absent or empty = unicast. |
* | DataPort | uint16 | Port+1 | UDP port for multicast DATA datagrams. Ignored in unicast mode. Must be non-zero and differ from Port. |
* | MaxPayloadSize | uint32 | 1400 | Maximum bytes of signal payload per UDP datagram (excluding the 17-byte header). Larger signals are fragmented. |
* | PublishingMode | string | Strict | `Strict`: send one packet every Synchronise() call. `Auto`: rate-limited; flush only when MinRefreshRate interval has elapsed. |
* | MinRefreshRate | float64 | — | Required when PublishingMode = Auto. Flush frequency in Hz (e.g. 120.0). |
* | MaxBatchSize | uint32 | 1 | Optional when PublishingMode = Auto. Number of RT cycles to accumulate before flushing one packet. Scalar signals are expanded to arrays of MaxBatchSize elements; the first scalar with Unit="us" or "ns" is auto-promoted as the per-sample FullArray timestamp reference for all other scalars. When omitted or 1, the most-recent single value is sent at MinRefreshRate. |
* | CPUMask | uint32 | 0xFFFFFFFF | CPU affinity bitmask for the background thread. |
* | StackSize | uint32 | (MARTe2 default) | Stack size in bytes for the background thread. |
*
* @par Per-signal configuration parameters
* | Parameter | Type | Default | Description |
* |------------------|---------|-------------|-------------|
* | Type | string | — | MARTe2 type name (uint8, int16, float32, float64, …). Mandatory. |
* | NumberOfDimensions | uint8 | 0 | 0 = scalar, 1 = array, 2 = matrix. |
* | NumberOfElements | uint32 | 1 | Total element count (rows × cols for matrices). |
* | Unit | string | "" | Physical unit label, e.g. `"Pa"` or `"m/s"`. Transmitted in CONFIG for display purposes. |
* | RangeMin | float64 | 0.0 | Minimum of the physical range. Required when QuantizedType is not `none`. |
* | RangeMax | float64 | 1.0 | Maximum of the physical range. Required when QuantizedType is not `none`. |
* | QuantizedType | string | none | Wire quantization for float signals: `none` \| `uint8` \| `int8` \| `uint16` \| `int16`. Reduces wire bandwidth at the cost of precision. Only valid for float32/float64 signals. |
* | TimeMode | string | PacketTime | How the signal's time axis is encoded (see below). |
* | TimeSignal | string | — | Name of the signal that carries timestamps. Required when TimeMode ≠ PacketTime. |
* | SamplingRate | float64 | — | Signal sampling rate in Hz. Required when TimeMode = FirstSample or LastSample. |
*
* @par TimeMode values
* | Value | Description |
* |--------------|-------------|
* | PacketTime | Uses the HRT counter captured at Synchronise() time as the single packet timestamp. No dedicated time signal needed. |
* | FullArray | TimeSignal has the same NumberOfElements as this signal; one timestamp per element. |
* | FirstSample | TimeSignal is a scalar = timestamp of the first element; subsequent elements are spaced by 1/SamplingRate. |
* | LastSample | TimeSignal is a scalar = timestamp of the last element; elements are spaced backwards by 1/SamplingRate. |
*
* @par Example — unicast mode
* <pre>
* +Streamer = {
* Class = UDPStreamer
* Port = 44500
* MaxPayloadSize = 1400
* PublishingMode = "Strict"
* Signals = {
* Time = {
* Type = uint64
* }
* Pressure = {
* Type = float32
* NumberOfDimensions = 1
* NumberOfElements = 100
* Unit = "Pa"
* RangeMin = 0.0
* RangeMax = 1000000.0
* QuantizedType = uint16
* TimeMode = LastSample
* TimeSignal = Time
* SamplingRate = 10000.0
* }
* Temperature = {
* Type = float64
* Unit = "degC"
* TimeMode = PacketTime
* }
* }
* }
* </pre>
*
* @par Example — multicast mode
* <pre>
* +Streamer = {
* Class = UDPStreamer
* Port = 44500 // TCP control port
* MulticastGroup = "239.0.0.1" // Enables multicast mode
* DataPort = 44501 // UDP data port (default: Port+1)
* MaxPayloadSize = 1400
* PublishingMode = "Auto"
* MinRefreshRate = 60
* Signals = {
* Time = {
* Type = uint64
* }
* Voltage = {
* Type = float32
* NumberOfDimensions = 1
* NumberOfElements = 1000
* Unit = "V"
* RangeMin = -10.0
* RangeMax = 10.0
* QuantizedType = int16
* TimeMode = FirstSample
* TimeSignal = Time
* SamplingRate = 100000.0
* }
* }
* }
* </pre>
*/
class UDPStreamer : public MemoryDataSourceI, public EmbeddedServiceMethodBinderI {
public:
CLASS_REGISTER_DECLARATION()
/**
* @brief Constructor. Initialises all members to safe defaults.
*/
UDPStreamer();
/**
* @brief Destructor. Stops the background thread and frees allocated memory.
*/
virtual ~UDPStreamer();
/**
* @brief Parses top-level configuration parameters.
* @details Reads Port, MaxPayloadSize, CPUMask, StackSize, PublishingMode,
* MinRefreshRate, MulticastGroup, and DataPort from the configuration node.
* Sets useMulticast and dataPort when MulticastGroup is present and valid.
* @return true if all mandatory parameters are valid and consistent.
*/
virtual bool Initialise(StructuredDataI &data);
/**
* @brief Validates signal types and builds the per-signal metadata array.
* @details Reads per-signal custom fields (Unit, RangeMin, RangeMax, QuantizedType,
* TimeMode, TimeSignal, SamplingRate) from signalsDatabase and populates signalInfos[].
* @return true if all signal configurations are valid.
*/
virtual bool SetConfiguredDatabase(StructuredDataI &data);
/**
* @brief Allocates signal memory (via parent) plus readyBuffer, scratchBuffer, wireBuffer.
* @return true if all memory allocations succeed.
*/
virtual bool AllocateMemory();
/**
* @brief Returns the broker name for the given signal direction.
* @return "MemoryMapSynchronisedOutputBroker" for OutputSignals; "" otherwise.
*/
virtual const char8 *GetBrokerName(StructuredDataI &data,
const SignalDirection direction);
/**
* @brief Called by the RT thread after all GAMs have written output signals.
* @details Copies signal memory to readyBuffer under a fast spinlock, then posts
* the dataSem to wake the background thread. Returns immediately.
* @return true always.
*/
virtual bool Synchronise();
/**
* @brief Opens the server socket and starts the background thread.
* @return true if the socket and thread start successfully.
*/
virtual bool PrepareNextState(const char8 *const currentStateName,
const char8 *const nextStateName);
/**
* @brief Background thread entry point.
* @details Handles client CONNECT/DISCONNECT/ACK and sends DATA packets.
*/
virtual ErrorManagement::ErrorType Execute(ExecutionInfo &info);
/**
* @brief Returns the listening port number.
*/
uint16 GetPort() const;
/**
* @brief Returns the maximum payload size per UDP datagram.
*/
uint32 GetMaxPayloadSize() const;
/**
* @brief Returns true if a client is currently connected.
*/
bool IsClientConnected() const;
/**
* @brief Returns true when multicast mode is active (MulticastGroup was set in config).
*/
bool IsMulticast() const;
private:
/**
* @brief Serializes the CONFIG payload into buf and sets payloadSize.
* @return true if serialization succeeds.
*/
bool BuildConfigPayload(uint8 *buf, uint32 bufSize, uint32 &payloadSize);
/**
* @brief Quantizes and serializes all signals from srcBuf into wireBuffer.
* @param[in] srcBuf Flat source buffer (signal data in MARTe2 format).
* @param[in] timestamp HRT counter to embed as packet timestamp.
*/
void QuantizeAndSerialize(const uint8 *srcBuf, uint64 timestamp);
/**
* @brief Sends payload as one or more fragmented UDP datagrams to the connected client.
* @return true if all datagrams were sent without error.
*/
bool SendFragmented(uint8 type, uint32 counter, const uint8 *payload, uint32 payloadSize);
/**
* @brief Handles a single received command packet from a client (unicast mode).
*/
void HandleClientCommand(const uint8 *buf, uint32 size);
/**
* @brief Handles a CONNECT received on the TCP control socket (multicast mode).
* @details Validates magic+type, sets clientConnected, builds and sends CONFIG via tcpClient.
*/
void HandleTCPConnect(const uint8 *buf, uint32 size);
/**
* @brief Serializes an accumulated batch into wireBuffer.
* @param src Flat buffer [numSamples × totalSrcBytes], slot 0 = oldest.
* @param timestamps HRT counters per slot; timestamps[0] is the packet timestamp.
* @param numSamples Actual number of filled slots to serialize.
*/
void SerializeAccumulated(const uint8 *src, const uint64 *timestamps, uint32 numSamples);
/**
* @brief Maps a MARTe2 TypeDescriptor to the UDPS_TYPECODE_* constants.
*/
static uint8 TypeDescriptorToCode(TypeDescriptor td);
/* Configuration parameters */
uint16 port; /**< UDP server port */
uint32 maxPayloadSize; /**< Max payload bytes per UDP packet (excluding header) */
uint32 cpuMask; /**< Background thread CPU affinity */
uint32 stackSize; /**< Background thread stack size */
UDPStreamerPublishMode publishMode; /**< Strict or Auto publishing mode */
float64 minRefreshRate; /**< Minimum flush rate (Hz) for Auto mode */
uint64 flushPeriodTicks; /**< HRT ticks per flush interval (computed from minRefreshRate) */
/* Accumulate mode — dynamic batch parameters */
uint32 maxBatchCount; /**< Max snapshots that fit in MaxPayloadSize (Accumulate) */
uint32 singleCycleWireBytes; /**< Wire bytes for all accumulated signals per snapshot */
uint32 fixedWireBytes; /**< Wire bytes for non-accumulated signals (arrays, once per packet) */
volatile uint64 lastPublishTs; /**< HRT counter of last successful flush (Accumulate mode) */
uint8 *accumBuffer; /**< Heap: [maxBatchCount × totalSrcBytes] linear fill */
uint64 *accumTimestamps; /**< Heap: [maxBatchCount] HRT counter per snapshot */
uint32 accumFill; /**< Slots filled in accumBuffer (0..maxBatchCount) */
uint64 *readyTimestamps; /**< Heap: [maxBatchCount] HRT for completed ready batch */
uint64 *scratchTimestamps; /**< Heap: [maxBatchCount] background-thread local copy */
uint32 readyFill; /**< Snapshot count in the ready batch */
/* Decimate mode */
uint32 decimateRatio; /**< Send 1 packet every decimateRatio Synchronise() calls */
uint32 decimateCounter; /**< Current decimate cycle counter */
/* Signal metadata */
uint32 numSigs; /**< Number of signals */
UDPStreamerSignalInfo *signalInfos; /**< Per-signal metadata array */
/* Double-buffering for RT safety */
uint8 *readyBuffer; /**< Protected copy of signal memory for background thread */
uint8 *scratchBuffer; /**< Local copy used during serialization (avoids holding lock) */
uint32 totalSrcBytes; /**< Total bytes of signal data (= stateMemorySize) */
FastPollingMutexSem bufMutex; /**< Protects readyBuffer against concurrent access */
EventSem dataSem; /**< Wakes background thread when new data is ready */
volatile uint64 syncTimestamp; /**< HRT counter captured in Synchronise() */
/* Wire serialization buffer */
uint8 *wireBuffer; /**< Pre-allocated buffer for the serialized DATA payload */
uint32 totalWireBytes; /**< Total bytes of all signals after quantization + 8-byte timestamp prefix */
/* Networking — unicast mode */
BasicUDPSocket serverSocket; /**< Bound to port; receives client commands (unicast) */
BasicUDPSocket clientSocket; /**< Configured to send to the connected client (unicast) */
volatile bool clientConnected; /**< True when a client has successfully connected */
/* Networking — multicast mode (only used when useMulticast == true) */
StreamString multicastGroup; /**< Multicast group IP, e.g. "239.0.0.1"; empty = unicast */
uint16 dataPort; /**< UDP port for DATA datagrams in multicast mode */
bool useMulticast; /**< Derived from multicastGroup.Size() > 0 in Initialise() */
BasicTCPSocket tcpListener; /**< TCP server socket: accepts control connections */
BasicTCPSocket *tcpClient; /**< Accepted TCP control connection (heap by WaitConnection) */
BasicUDPSocket dataSocket; /**< UDP socket aimed at multicastGroup:dataPort */
/* Thread management */
SingleThreadService executor; /**< Background thread service */
/* Packet sequencing */
uint32 packetCounter; /**< Incremented for each DATA update sent */
};
} /* namespace MARTe */
#endif /* UDPSTREAMER_H_ */
@@ -0,0 +1,142 @@
../../../..//Build/x86-linux/Components/DataSources/UDPStreamer/UDPStreamer.o: UDPStreamer.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/ExecutionInfo.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/Threads.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ThreadsB.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/ExceptionHandler.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ProcessorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitSet.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapSynchronisedOutputBroker.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapOutputBroker.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapBroker.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/BrokerI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/DataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyObject.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabaseNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Fnv1aHashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/HashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Reference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/UnorderedMap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilterObjectName.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TypeConversion.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/StatefulI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/ExecutableI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
UDPStreamer.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicTCPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetHostCore.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetMulticastCore.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HandleI.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/SocketCore.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicUDPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/EventSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryDataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/SingleThreadService.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThread.h
@@ -0,0 +1,142 @@
UDPStreamer.o: UDPStreamer.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/ExecutionInfo.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/Threads.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ThreadsB.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/ExceptionHandler.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ProcessorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitSet.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapSynchronisedOutputBroker.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapOutputBroker.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryMapBroker.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/BrokerI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/DataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyObject.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabaseNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Fnv1aHashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/HashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Reference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/UnorderedMap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilterObjectName.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TypeConversion.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/StatefulI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/ExecutableI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
UDPStreamer.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicTCPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicSocket.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/InternetHost.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetHostCore.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/InternetMulticastCore.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HandleI.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/Environment/Linux/SocketCore.h \
/home/martino/workspace/MARTe2/Source/Core/FileSystem/L1Portability/BasicUDPSocket.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceMethodBinderI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L1Portability/EventSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/MemoryDataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/SingleThreadService.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedServiceI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThreadI.h \
/home/martino/workspace/MARTe2/Source/Core/Scheduler/L3Services/EmbeddedThread.h
+9
View File
@@ -0,0 +1,9 @@
all:
$(MAKE) -C SineArrayGAM -f Makefile.gcc
$(MAKE) -C TimeArrayGAM -f Makefile.gcc
clean:
$(MAKE) -C SineArrayGAM -f Makefile.gcc clean
$(MAKE) -C TimeArrayGAM -f Makefile.gcc clean
.PHONY: all clean
+1
View File
@@ -0,0 +1 @@
# GAMs intermediate Makefile.inc
@@ -0,0 +1,25 @@
#############################################################
#
# Copyright 2015 F4E | European Joint Undertaking for ITER
# and the Development of Fusion Energy ('Fusion for Energy')
#
# Licensed under the EUPL, Version 1.1 or - as soon they
# will be approved by the European Commission - subsequent
# versions of the EUPL (the "Licence");
# You may not use this work except in compliance with the
# Licence.
# You may obtain a copy of the Licence at:
#
# http://ec.europa.eu/idabc/eupl
#
# Unless required by applicable law or agreed to in
# writing, software distributed under the Licence is
# distributed on an "AS IS" basis,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied.
# See the Licence for the specific language governing
# permissions and limitations under the Licence.
#
#############################################################
include Makefile.inc
@@ -0,0 +1,52 @@
#############################################################
#
# Copyright 2015 F4E | European Joint Undertaking for ITER
# and the Development of Fusion Energy ('Fusion for Energy')
#
# Licensed under the EUPL, Version 1.1 or - as soon they
# will be approved by the European Commission - subsequent
# versions of the EUPL (the "Licence");
# You may not use this work except in compliance with the
# Licence.
# You may obtain a copy of the Licence at:
#
# http://ec.europa.eu/idabc/eupl
#
# Unless required by applicable law or agreed to in
# writing, software distributed under the Licence is
# distributed on an "AS IS" basis,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
# express or implied.
# See the Licence for the specific language governing
# permissions and limitations under the Licence.
#
#############################################################
OBJSX = SineArrayGAM.x
PACKAGE=Components/GAMs
ROOT_DIR=../../../../
MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
INCLUDES += -I.
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L0Types
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L2Objects
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L3Streams
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Configuration
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L3Services
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4Messages
all: $(OBJS) \
$(BUILD_DIR)/SineArrayGAM$(LIBEXT) \
$(BUILD_DIR)/SineArrayGAM$(DLLEXT)
echo $(OBJS)
-include depends.$(TARGET)
include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET)
@@ -0,0 +1,118 @@
/**
* @file SineArrayGAM.cpp
* @brief Source file for class SineArrayGAM
* @date 15/05/2026
* @author Martino Ferrari
*
* @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
* the Development of Fusion Energy ('Fusion for Energy').
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence")
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
*
* @warning Unless required by applicable law or agreed to in writing,
* software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the Licence permissions and limitations under the Licence.
*/
#define DLL_API
/*---------------------------------------------------------------------------*/
/* Standard header includes */
/*---------------------------------------------------------------------------*/
#include <cmath>
/*---------------------------------------------------------------------------*/
/* Project header includes */
/*---------------------------------------------------------------------------*/
#include "AdvancedErrorManagement.h"
#include "SineArrayGAM.h"
/*---------------------------------------------------------------------------*/
/* Method definitions */
/*---------------------------------------------------------------------------*/
namespace MARTe {
SineArrayGAM::SineArrayGAM() :
GAM(),
frequency(1.0),
amplitude(1.0),
offset(0.0),
phase(0.0),
samplingRate(1000000.0),
nElements(0u),
sampleOffset(0ull),
outputBuf(NULL_PTR(float32 *)) {
}
SineArrayGAM::~SineArrayGAM() {
}
bool SineArrayGAM::Initialise(StructuredDataI &data) {
bool ok = GAM::Initialise(data);
if (ok) {
if (!data.Read("Frequency", frequency)) {
frequency = 1.0;
}
if (!data.Read("Amplitude", amplitude)) {
amplitude = 1.0;
}
if (!data.Read("Offset", offset)) {
offset = 0.0;
}
if (!data.Read("Phase", phase)) {
phase = 0.0;
}
if (!data.Read("SamplingRate", samplingRate)) {
samplingRate = 1000000.0;
}
if (samplingRate <= 0.0) {
REPORT_ERROR(ErrorManagement::InitialisationError,
"SineArrayGAM: SamplingRate must be greater than zero");
ok = false;
}
}
return ok;
}
bool SineArrayGAM::Setup() {
bool ok = (GetNumberOfOutputSignals() == 1u);
if (!ok) {
REPORT_ERROR(ErrorManagement::InitialisationError,
"SineArrayGAM: exactly one output signal is required");
return false;
}
uint32 sz = 0u;
ok = GetSignalByteSize(OutputSignals, 0u, sz);
if (ok) {
nElements = sz / static_cast<uint32>(sizeof(float32));
outputBuf = reinterpret_cast<float32 *>(GetOutputSignalMemory(0u));
ok = (outputBuf != NULL_PTR(float32 *)) && (nElements > 0u);
if (!ok) {
REPORT_ERROR(ErrorManagement::InitialisationError,
"SineArrayGAM: failed to resolve output signal memory");
}
}
return ok;
}
bool SineArrayGAM::Execute() {
static const float64 TWO_PI = 6.28318530717958647692;
const float64 twoPiF = TWO_PI * frequency;
const float64 invSr = 1.0 / samplingRate;
for (uint32 i = 0u; i < nElements; i++) {
float64 t = static_cast<float64>(sampleOffset + static_cast<uint64>(i)) * invSr;
outputBuf[i] = static_cast<float32>(amplitude * std::sin(twoPiF * t + phase) + offset);
}
sampleOffset += static_cast<uint64>(nElements);
return true;
}
CLASS_REGISTER(SineArrayGAM, "1.0")
} /* namespace MARTe */
@@ -0,0 +1,105 @@
/**
* @file SineArrayGAM.h
* @brief GAM that fills a float32 array with a continuous sinusoidal waveform.
* @date 15/05/2026
* @author Martino Ferrari
*
* @copyright Copyright 2015 F4E | European Joint Undertaking for ITER and
* the Development of Fusion Energy ('Fusion for Energy').
* Licensed under the EUPL, Version 1.1 or - as soon they will be approved
* by the European Commission - subsequent versions of the EUPL (the "Licence")
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at: http://ec.europa.eu/idabc/eupl
*
* @warning Unless required by applicable law or agreed to in writing,
* software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the Licence permissions and limitations under the Licence.
*
* @details Each Execute() call fills one float32 output array with N samples of:
* v[k] = Amplitude * sin(2π * Frequency * (sampleOffset + k) / SamplingRate + Phase) + Offset
*
* The sampleOffset accumulates across calls so the waveform phase is continuous.
*
* Configuration:
* <pre>
* +MyGAM = {
* Class = SineArrayGAM
* Frequency = 1000.0 // Signal frequency in Hz (default 1.0)
* Amplitude = 1.0 // Signal amplitude (default 1.0)
* Offset = 0.0 // DC offset (default 0.0)
* Phase = 0.0 // Phase in radians (default 0.0)
* SamplingRate = 1000000.0 // Sample rate in Hz; must match UDPStreamer signal (default 1000000.0)
* OutputSignals = {
* Ch1 = { DataSource = DDB; Type = float32; NumberOfElements = 1000 }
* }
* }
* </pre>
*
* Exactly one output signal of type float32 is required.
*/
#ifndef SINEARRAYGAM_H_
#define SINEARRAYGAM_H_
/*---------------------------------------------------------------------------*/
/* Standard header includes */
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/* Project header includes */
/*---------------------------------------------------------------------------*/
#include "CompilerTypes.h"
#include "GAM.h"
/*---------------------------------------------------------------------------*/
/* Class declaration */
/*---------------------------------------------------------------------------*/
namespace MARTe {
class SineArrayGAM : public GAM {
public:
CLASS_REGISTER_DECLARATION()
/**
* @brief Constructor. Sets safe defaults.
*/
SineArrayGAM();
/**
* @brief Destructor.
*/
virtual ~SineArrayGAM();
/**
* @brief Reads Frequency, Amplitude, Offset, Phase, SamplingRate from config.
*/
virtual bool Initialise(StructuredDataI &data);
/**
* @brief Resolves the output signal pointer and element count.
* @return true if exactly one float32 output signal is present.
*/
virtual bool Setup();
/**
* @brief Fills the output array with the next N sinusoidal samples.
* @return true always.
*/
virtual bool Execute();
private:
float64 frequency; /**< Signal frequency [Hz] */
float64 amplitude; /**< Signal amplitude */
float64 offset; /**< DC offset */
float64 phase; /**< Phase offset [radians] */
float64 samplingRate; /**< Sample rate [Hz] */
uint32 nElements; /**< Number of output elements per cycle */
uint64 sampleOffset; /**< Cumulative sample count for continuous phase */
float32 *outputBuf; /**< Pointer to the output signal memory */
};
} /* namespace MARTe */
#endif /* SINEARRAYGAM_H_ */
@@ -0,0 +1,113 @@
../../../..//Build/x86-linux/Components/GAMs/SineArrayGAM/SineArrayGAM.o: SineArrayGAM.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
SineArrayGAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/DataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyObject.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabaseNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Fnv1aHashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/HashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Reference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/UnorderedMap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilterObjectName.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TypeConversion.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/StatefulI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/ExecutableI.h
@@ -0,0 +1,113 @@
SineArrayGAM.o: SineArrayGAM.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
SineArrayGAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/DataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyObject.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabaseNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Fnv1aHashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/HashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Reference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/UnorderedMap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilterObjectName.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TypeConversion.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/StatefulI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/ExecutableI.h
@@ -0,0 +1 @@
include Makefile.inc
@@ -0,0 +1,28 @@
OBJSX = TimeArrayGAM.x
PACKAGE=Components/GAMs
ROOT_DIR=../../../../
MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
INCLUDES += -I.
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L0Types
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L2Objects
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L3Streams
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Configuration
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L3Services
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4Messages
all: $(OBJS) \
$(BUILD_DIR)/TimeArrayGAM$(LIBEXT) \
$(BUILD_DIR)/TimeArrayGAM$(DLLEXT)
echo $(OBJS)
-include depends.$(TARGET)
include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET)
@@ -0,0 +1,108 @@
/**
* @file TimeArrayGAM.cpp
* @brief Source file for class TimeArrayGAM
* @date 19/05/2026
* @author Martino Ferrari
*/
#define DLL_API
#include "AdvancedErrorManagement.h"
#include "TimeArrayGAM.h"
namespace MARTe {
TimeArrayGAM::TimeArrayGAM() :
GAM(),
samplingRate(1000000.0),
anchorIsFirst(true),
nElements(0u),
inputTime(NULL_PTR(uint32 *)),
outputBuf(NULL_PTR(uint64 *)) {
}
TimeArrayGAM::~TimeArrayGAM() {
}
bool TimeArrayGAM::Initialise(StructuredDataI &data) {
bool ok = GAM::Initialise(data);
if (ok) {
if (!data.Read("SamplingRate", samplingRate) || samplingRate <= 0.0) {
REPORT_ERROR(ErrorManagement::InitialisationError,
"TimeArrayGAM: SamplingRate > 0 is required.");
ok = false;
}
}
if (ok) {
StreamString anchor;
(void) data.Read("Anchor", anchor);
if (anchor.Size() == 0u || anchor == "FirstSample") {
anchorIsFirst = true; /* default */
}
else if (anchor == "LastSample") {
anchorIsFirst = false;
}
else {
REPORT_ERROR(ErrorManagement::InitialisationError,
"TimeArrayGAM: Anchor must be 'FirstSample' or 'LastSample'.");
ok = false;
}
}
return ok;
}
bool TimeArrayGAM::Setup() {
bool ok = (GetNumberOfInputSignals() == 1u) && (GetNumberOfOutputSignals() == 1u);
if (!ok) {
REPORT_ERROR(ErrorManagement::InitialisationError,
"TimeArrayGAM: exactly one input and one output signal are required.");
return false;
}
inputTime = reinterpret_cast<uint32 *>(GetInputSignalMemory(0u));
outputBuf = reinterpret_cast<uint64 *>(GetOutputSignalMemory(0u));
ok = (inputTime != NULL_PTR(uint32 *)) && (outputBuf != NULL_PTR(uint64 *));
if (!ok) {
REPORT_ERROR(ErrorManagement::InitialisationError,
"TimeArrayGAM: failed to resolve signal memory.");
return false;
}
uint32 sz = 0u;
ok = GetSignalByteSize(OutputSignals, 0u, sz);
if (ok) {
nElements = sz / static_cast<uint32>(sizeof(uint32));
ok = (nElements > 0u);
}
if (!ok) {
REPORT_ERROR(ErrorManagement::InitialisationError,
"TimeArrayGAM: output signal must be a non-empty uint32 array.");
}
return ok;
}
bool TimeArrayGAM::Execute() {
/* Period in nanoseconds — uint64 preserves sub-microsecond resolution
* even at sampling rates > 1 MHz where the µs period would be < 1. */
uint64 periodNs = static_cast<uint64>(1000000000.0 / samplingRate + 0.5);
/* Input is uint32 microseconds (LinuxTimer); convert to nanoseconds. */
uint64 anchorNs = static_cast<uint64>(*inputTime) * 1000u;
if (anchorIsFirst) {
/* out[k] = anchorNs + k * periodNs */
for (uint32 k = 0u; k < nElements; k++) {
outputBuf[k] = anchorNs + static_cast<uint64>(k) * periodNs;
}
}
else {
/* out[k] = anchorNs - (N-1-k) * periodNs */
for (uint32 k = 0u; k < nElements; k++) {
outputBuf[k] = anchorNs - static_cast<uint64>(nElements - 1u - k) * periodNs;
}
}
return true;
}
CLASS_REGISTER(TimeArrayGAM, "1.0")
} /* namespace MARTe */
@@ -0,0 +1,64 @@
/**
* @file TimeArrayGAM.h
* @brief GAM that expands a scalar timer value into a per-sample uint32 time array.
* @date 19/05/2026
* @author Martino Ferrari
*
* @details Each Execute() call reads one uint32 scalar input (time in microseconds,
* e.g. from LinuxTimer) and fills a uint32[N] output array where element[k] holds
* the reconstructed timestamp of sample k:
*
* Anchor = FirstSample: out[k] = input + k * period_us
* Anchor = LastSample: out[k] = input - (N-1-k) * period_us
*
* The resulting time array is suitable as the TimeSignal for a UDPStreamer signal
* configured with TimeMode = FullArray, providing exact per-sample timestamps.
*
* Configuration:
* <pre>
* +TimeArrayGAM1 = {
* Class = TimeArrayGAM
* SamplingRate = 1000000.0 // Sample rate in Hz (must match data signal)
* Anchor = FirstSample // FirstSample (default) or LastSample
* InputSignals = {
* Time = { DataSource = DDB; Type = uint32 }
* }
* OutputSignals = {
* TimeArray = { DataSource = DDB; Type = uint32; NumberOfElements = 1000 }
* }
* }
* </pre>
*
* Exactly one uint32 input signal and one uint32 output array are required.
*/
#ifndef TIMEARRAYGAM_H_
#define TIMEARRAYGAM_H_
#include "CompilerTypes.h"
#include "GAM.h"
namespace MARTe {
class TimeArrayGAM : public GAM {
public:
CLASS_REGISTER_DECLARATION()
TimeArrayGAM();
virtual ~TimeArrayGAM();
virtual bool Initialise(StructuredDataI &data);
virtual bool Setup();
virtual bool Execute();
private:
float64 samplingRate; /**< Sample rate [Hz] */
bool anchorIsFirst; /**< true = FirstSample anchor, false = LastSample */
uint32 nElements; /**< Number of output elements */
uint32 *inputTime; /**< Pointer to scalar input (microseconds, uint32 from LinuxTimer) */
uint64 *outputBuf; /**< Pointer to output array (nanoseconds, uint64) */
};
} /* namespace MARTe */
#endif /* TIMEARRAYGAM_H_ */
@@ -0,0 +1,113 @@
../../../..//Build/x86-linux/Components/GAMs/TimeArrayGAM/TimeArrayGAM.o: TimeArrayGAM.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
TimeArrayGAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/DataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyObject.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabaseNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Fnv1aHashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/HashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Reference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/UnorderedMap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilterObjectName.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TypeConversion.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/StatefulI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/ExecutableI.h
@@ -0,0 +1,113 @@
TimeArrayGAM.o: TimeArrayGAM.cpp \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/AdvancedErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Architecture/x86_gcc/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TypeCharacteristics.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/TemplateParametersVerificator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CompilerTypes.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorInformation.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ErrorType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/HighResolutionTimerA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HighResolutionTimer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/HighResolutionTimerCalibrator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeStamp.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamMemoryReference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/BufferedStreamI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TimeoutType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassProperties.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectsDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/GlobalObjectI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/StandardHeap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../../GeneralDefinitions.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Environment/Linux/../Generic/StandardHeap_Generic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FastPollingMutexSem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Atomic.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Architecture/x86_gcc/AtomicA.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/ErrorManagement.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/Sleep.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItem.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/CString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Introspection.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/IntrospectionEntry.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/TypeDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BasicType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/FractionalInteger.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitRange.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/BitBoolean.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/ZeroTerminatedArray.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/IteratorT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Iterator.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListable.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SortFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/SearchFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/LoadableLibrary.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticList.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StaticListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Matrix.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/MemoryOperationsHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/FormatDescriptor.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/IOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/CharBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StreamI.h \
TimeArrayGAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/GAM.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/DataSourceI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabase.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/AnyObject.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/AnyType.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/CLASSREGISTER.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ClassRegistryItemT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ObjectBuilderT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/ConfigurationDatabaseNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Fnv1aHashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/HashFunction.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/LinkedListHolder.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Object.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/Reference.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilter.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerNode.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceT.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/UnorderedMap.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/HeapManager.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L1Portability/StringHelper.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainerFilterObjectName.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/ReferenceContainer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L2Objects/StructuredDataI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L4Configuration/TypeConversion.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L0Types/Vector.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamString.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L3Streams/StreamStringIOBuffer.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/StatefulI.h \
/home/martino/workspace/MARTe2/Source/Core/BareMetal/L5GAMs/ExecutableI.h
@@ -0,0 +1,590 @@
#ifndef DEBUGBROKERWRAPPER_H
#define DEBUGBROKERWRAPPER_H
#include "BrokerI.h"
#include "DataSourceI.h"
#include "DebugServiceI.h"
#include "FastPollingMutexSem.h"
#include "HighResolutionTimer.h"
#include "MemoryMapBroker.h"
#include "ObjectBuilder.h"
#include "ObjectRegistryDatabase.h"
#include "Threads.h"
// Original broker headers
#include "MemoryMapAsyncOutputBroker.h"
#include "MemoryMapAsyncTriggerOutputBroker.h"
#include "MemoryMapInputBroker.h"
#include "MemoryMapInterpolatedInputBroker.h"
#include "MemoryMapMultiBufferInputBroker.h"
#include "MemoryMapMultiBufferOutputBroker.h"
#include "MemoryMapOutputBroker.h"
#include "MemoryMapSynchronisedInputBroker.h"
#include "MemoryMapSynchronisedMultiBufferInputBroker.h"
#include "MemoryMapSynchronisedMultiBufferOutputBroker.h"
#include "MemoryMapSynchronisedOutputBroker.h"
namespace MARTe {
// Recursive search for any object with a given name anywhere in the registry.
// Used to find GAMs regardless of nesting level.
static Reference FindByNameRecursive(ReferenceContainer *container,
const char8 *name) {
if (container == NULL_PTR(ReferenceContainer *))
return Reference();
uint32 n = container->Size();
for (uint32 i = 0; i < n; i++) {
Reference child = container->Get(i);
if (!child.IsValid())
continue;
if (StringHelper::Compare(child->GetName(), name) == 0)
return child;
ReferenceContainer *sub =
dynamic_cast<ReferenceContainer *>(child.operator->());
if (sub != NULL_PTR(ReferenceContainer *)) {
Reference found = FindByNameRecursive(sub, name);
if (found.IsValid())
return found;
}
}
return Reference();
}
/**
* @brief Helper for optimized signal processing within brokers.
*/
class DebugBrokerHelper {
public:
// Evaluate a break condition against the current live value of a signal.
// Returns true if the condition is met and execution should be paused.
// Only called when signal->breakOp != BREAK_OFF; reads memoryAddress directly.
static bool EvaluateBreak(const DebugSignalInfo *s) {
if (s->memoryAddress == NULL_PTR(void *)) return false;
float64 val = 0.0;
const TypeDescriptor &t = s->type;
if (t == Float64Bit) val = *static_cast<const float64 *>(s->memoryAddress);
else if (t == Float32Bit) val = *static_cast<const float32 *>(s->memoryAddress);
else if (t == UnsignedInteger32Bit) val = *static_cast<const uint32 *>(s->memoryAddress);
else if (t == SignedInteger32Bit) val = *static_cast<const int32 *>(s->memoryAddress);
else if (t == UnsignedInteger64Bit) val = static_cast<float64>(*static_cast<const uint64 *>(s->memoryAddress));
else if (t == SignedInteger64Bit) val = static_cast<float64>(*static_cast<const int64 *>(s->memoryAddress));
else if (t == UnsignedInteger16Bit) val = *static_cast<const uint16 *>(s->memoryAddress);
else if (t == SignedInteger16Bit) val = *static_cast<const int16 *>(s->memoryAddress);
else if (t == UnsignedInteger8Bit) val = *static_cast<const uint8 *>(s->memoryAddress);
else if (t == SignedInteger8Bit) val = *static_cast<const int8 *>(s->memoryAddress);
else return false; // unsupported type — skip
const float64 thr = s->breakThreshold;
switch (s->breakOp) {
case BREAK_GT: return val > thr;
case BREAK_LT: return val < thr;
case BREAK_EQ: return val == thr;
case BREAK_GEQ: return val >= thr;
case BREAK_LEQ: return val <= thr;
case BREAK_NEQ: return val != thr;
default: return false;
}
}
// Spin-wait point for output brokers — called from Execute() AFTER Process().
// Spins while paused, then consumes one step counter tick (if stepping).
// Input brokers must NOT call this — they complete normally to avoid blocking
// cross-thread EventSem posts (RealTimeThreadSynchBroker would time out).
static void OutputPauseAndStep(DebugServiceI *service, const char8 *gamName) {
if (service == NULL_PTR(DebugServiceI *)) return;
// Fast path: nothing to do when neither paused nor stepping.
// Avoids Threads::Name() lookup (and its mutex) on every 1000 Hz cycle.
if (!service->IsPaused() && !service->IsStepPending()) return;
// Wait if already paused (manual PAUSE or breakpoint from a previous cycle)
while (service->IsPaused()) Sleep::MSec(10);
// Pass the OS thread name so per-thread step filtering works.
const char8 *tName = Threads::Name(Threads::Id());
service->ConsumeStepIfNeeded(gamName, tName);
while (service->IsPaused()) Sleep::MSec(10);
}
static void Process(DebugServiceI *service,
DebugSignalInfo **signalInfoPointers,
Vector<uint32> &activeIndices, Vector<uint32> &activeSizes,
FastPollingMutexSem &activeMutex,
volatile bool *anyBreakFlag,
Vector<uint32> *breakIndices) {
if (service == NULL_PTR(DebugServiceI *))
return;
// NOTE: No spin here. Spinning for paused state is handled in Execute() of
// OUTPUT brokers only (see OutputPauseAndStep). Input brokers must not block
// because that prevents cross-thread EventSem posts from completing.
activeMutex.FastLock();
uint32 n = activeIndices.GetNumberOfElements();
if (n > 0 && signalInfoPointers != NULL_PTR(DebugSignalInfo **)) {
// Capture timestamp ONCE per broker cycle for lowest impact
uint64 ts = (uint64)((float64)HighResolutionTimer::Counter() *
HighResolutionTimer::Period() * 1.0e9);
for (uint32 i = 0; i < n; i++) {
uint32 idx = activeIndices[i];
uint32 size = activeSizes[i];
DebugSignalInfo *s = signalInfoPointers[idx];
if (s != NULL_PTR(DebugSignalInfo *)) {
service->ProcessSignal(s, size, ts);
}
}
}
// FIX #3: copy break indices under lock into a local stack array, then
// release activeMutex BEFORE evaluating. EvaluateBreak reads signal
// memory which can stall (cache miss); holding activeMutex during that
// stall would block UpdateBrokersBreakStatus() in the Server thread and
// cause unnecessary priority inversion on the RT path.
bool shouldCheckBreak = (*anyBreakFlag && !service->IsPaused() &&
breakIndices != NULL_PTR(Vector<uint32> *) &&
signalInfoPointers != NULL_PTR(DebugSignalInfo **));
static const uint32 MAX_BREAK_INDICES = 64u;
uint32 localBreakIdx[MAX_BREAK_INDICES];
uint32 nb = 0u;
if (shouldCheckBreak) {
nb = breakIndices->GetNumberOfElements();
if (nb > MAX_BREAK_INDICES) nb = MAX_BREAK_INDICES;
for (uint32 i = 0; i < nb; i++) {
localBreakIdx[i] = (*breakIndices)[i];
}
}
activeMutex.FastUnLock();
// Evaluate break conditions outside the lock — safe because
// EvaluateBreak only reads signalInfoPointers[idx]->memoryAddress,
// which is RT data-bus memory and is never freed during the RT cycle.
if (shouldCheckBreak && nb > 0u) {
for (uint32 i = 0; i < nb; i++) {
uint32 idx = localBreakIdx[i];
DebugSignalInfo *s = signalInfoPointers[idx];
if (s != NULL_PTR(DebugSignalInfo *) && s->breakOp != BREAK_OFF &&
EvaluateBreak(s)) {
service->SetPaused(true);
break;
}
}
}
}
// Pass numCopies explicitly so we can mock it
static void
InitSignals(BrokerI *broker, DataSourceI &dataSourceIn,
DebugServiceI *&service, DebugSignalInfo **&signalInfoPointers,
uint32 numCopies, MemoryMapBrokerCopyTableEntry *copyTable,
const char8 *functionName, SignalDirection direction,
volatile bool *anyActiveFlag, Vector<uint32> *activeIndices,
Vector<uint32> *activeSizes, FastPollingMutexSem *activeMutex,
volatile bool *anyBreakFlag, Vector<uint32> *breakIndices) {
if (numCopies > 0) {
signalInfoPointers = new DebugSignalInfo *[numCopies];
for (uint32 i = 0; i < numCopies; i++)
signalInfoPointers[i] = NULL_PTR(DebugSignalInfo *);
}
// Use the singleton registered by DebugService::Initialise() — no ORD
// search on the Init path, and no dependency on a concrete type.
service = DebugServiceI::GetInstance();
if (service && (copyTable != NULL_PTR(MemoryMapBrokerCopyTableEntry *))) {
StreamString dsPath;
DebugServiceI::GetFullObjectName(dataSourceIn, dsPath);
fprintf(stderr, ">> %s broker for %s [%d]\n",
direction == InputSignals ? "Input" : "Output", dsPath.Buffer(),
numCopies);
MemoryMapBroker *mmb = dynamic_cast<MemoryMapBroker *>(broker);
if (mmb == NULL_PTR(MemoryMapBroker *)) {
fprintf(stderr, ">> Impossible to get broker pointer!!\n");
}
for (uint32 i = 0; i < numCopies; i++) {
void *addr = copyTable[i].dataSourcePointer;
TypeDescriptor type = copyTable[i].type;
uint32 dsIdx = i;
if (mmb != NULL_PTR(MemoryMapBroker *)) {
dsIdx = mmb->GetDSCopySignalIndex(i);
}
StreamString signalName;
if (!dataSourceIn.GetSignalName(dsIdx, signalName))
signalName = "Unknown";
fprintf(stderr, ">> registering %s.%s [%p]\n", dsPath.Buffer(),
signalName.Buffer(), mmb);
uint8 dims = 0;
uint32 elems = 1;
(void)dataSourceIn.GetSignalNumberOfDimensions(dsIdx, dims);
(void)dataSourceIn.GetSignalNumberOfElements(dsIdx, elems);
// Register canonical name
StreamString dsFullName;
dsFullName.Printf("%s.%s", dsPath.Buffer(), signalName.Buffer());
service->RegisterSignal(addr, type, dsFullName.Buffer(), dims, elems);
// Register alias
if (functionName != NULL_PTR(const char8 *)) {
StreamString gamFullName;
const char8 *dirStr =
(direction == InputSignals) ? "InputSignals" : "OutputSignals";
const char8 *dirStrShort = (direction == InputSignals) ? "In" : "Out";
// Search recursively through the entire registry for the GAM by name.
// Direct Find("GAM1") only checks top-level; the GAM may be nested
// several levels deep inside a RealTimeApplication container.
Reference gamRef =
FindByNameRecursive(ObjectRegistryDatabase::Instance(),
functionName);
fprintf(stderr, ">> GAM lookup '%s': %s\n", functionName,
gamRef.IsValid() ? "FOUND" : "NOT FOUND");
if (gamRef.IsValid()) {
StreamString absGamPath;
DebugServiceI::GetFullObjectName(*(gamRef.operator->()), absGamPath);
// Register short path (In/Out) for GUI compatibility
gamFullName.Printf("%s.%s.%s", absGamPath.Buffer(), dirStrShort,
signalName.Buffer());
signalInfoPointers[i] =
service->RegisterSignal(addr, type, gamFullName.Buffer(), dims, elems);
} else {
// Fallback to short form
gamFullName.Printf("%s.%s.%s", functionName, dirStrShort,
signalName.Buffer());
signalInfoPointers[i] =
service->RegisterSignal(addr, type, gamFullName.Buffer(), dims, elems);
}
} else {
signalInfoPointers[i] =
service->RegisterSignal(addr, type, dsFullName.Buffer(), dims, elems);
}
}
// Register broker in DebugService for optimized control
bool isOutputBroker = (direction == OutputSignals);
service->RegisterBroker(signalInfoPointers, numCopies, mmb, anyActiveFlag,
activeIndices, activeSizes, activeMutex,
anyBreakFlag, breakIndices,
(functionName != NULL_PTR(const char8 *)) ? functionName : dsPath.Buffer(),
isOutputBroker);
}
}
};
/**
* @brief Template class to instrument any MARTe2 Broker.
*/
template <typename BaseClass> class DebugBrokerWrapper : public BaseClass {
public:
DebugBrokerWrapper() : BaseClass() {
service = NULL_PTR(DebugServiceI *);
signalInfoPointers = NULL_PTR(DebugSignalInfo **);
numSignals = 0;
anyActive = false;
anyBreakActive = false;
isOutput = false;
gamName[0] = '\0';
}
virtual ~DebugBrokerWrapper() {
if (signalInfoPointers)
delete[] signalInfoPointers;
}
virtual bool Execute() {
bool ret = BaseClass::Execute();
if (ret && (anyActive || anyBreakActive)) {
DebugBrokerHelper::Process(service, signalInfoPointers, activeIndices,
activeSizes, activeMutex,
&anyBreakActive, &breakIndices);
}
// Output brokers are the safe pause point: base Execute has already
// committed data / posted any cross-thread EventSems.
if (ret && isOutput) {
DebugBrokerHelper::OutputPauseAndStep(service, gamName);
}
return ret;
}
virtual bool Init(SignalDirection direction, DataSourceI &ds,
const char8 *const name, void *gamMem) {
bool ret = BaseClass::Init(direction, ds, name, gamMem);
fprintf(stderr, ">> INIT BROKER %s %s\n", name,
direction == InputSignals ? "In" : "Out");
if (ret) {
numSignals = this->GetNumberOfCopies();
isOutput = (direction == OutputSignals);
StringHelper::CopyN(gamName, name, 255u);
DebugBrokerHelper::InitSignals(this, ds, service, signalInfoPointers,
numSignals, this->copyTable, name,
direction, &anyActive, &activeIndices,
&activeSizes, &activeMutex,
&anyBreakActive, &breakIndices);
}
return ret;
}
virtual bool Init(SignalDirection direction, DataSourceI &ds,
const char8 *const name, void *gamMem, const bool optim) {
bool ret = BaseClass::Init(direction, ds, name, gamMem, false);
fprintf(stderr, ">> INIT optimized BROKER %s %s\n", name,
direction == InputSignals ? "In" : "Out");
if (ret) {
numSignals = this->GetNumberOfCopies();
isOutput = (direction == OutputSignals);
StringHelper::CopyN(gamName, name, 255u);
DebugBrokerHelper::InitSignals(this, ds, service, signalInfoPointers,
numSignals, this->copyTable, name,
direction, &anyActive, &activeIndices,
&activeSizes, &activeMutex,
&anyBreakActive, &breakIndices);
}
return ret;
}
DebugServiceI *service;
DebugSignalInfo **signalInfoPointers;
uint32 numSignals;
volatile bool anyActive;
volatile bool anyBreakActive;
bool isOutput;
char8 gamName[256];
Vector<uint32> activeIndices;
Vector<uint32> activeSizes;
Vector<uint32> breakIndices;
FastPollingMutexSem activeMutex;
};
template <typename BaseClass>
class DebugBrokerWrapperNoOptim : public BaseClass {
public:
DebugBrokerWrapperNoOptim() : BaseClass() {
service = NULL_PTR(DebugServiceI *);
signalInfoPointers = NULL_PTR(DebugSignalInfo **);
numSignals = 0;
anyActive = false;
anyBreakActive = false;
isOutput = false;
gamName[0] = '\0';
}
virtual ~DebugBrokerWrapperNoOptim() {
if (signalInfoPointers)
delete[] signalInfoPointers;
}
virtual bool Execute() {
bool ret = BaseClass::Execute();
if (ret && (anyActive || anyBreakActive)) {
DebugBrokerHelper::Process(service, signalInfoPointers, activeIndices,
activeSizes, activeMutex,
&anyBreakActive, &breakIndices);
}
if (ret && isOutput) {
DebugBrokerHelper::OutputPauseAndStep(service, gamName);
}
return ret;
}
virtual bool Init(SignalDirection direction, DataSourceI &ds,
const char8 *const name, void *gamMem) {
bool ret = BaseClass::Init(direction, ds, name, gamMem);
if (ret) {
numSignals = this->GetNumberOfCopies();
isOutput = (direction == OutputSignals);
StringHelper::CopyN(gamName, name, 255u);
DebugBrokerHelper::InitSignals(this, ds, service, signalInfoPointers,
numSignals, this->copyTable, name,
direction, &anyActive, &activeIndices,
&activeSizes, &activeMutex,
&anyBreakActive, &breakIndices);
}
return ret;
}
DebugServiceI *service;
DebugSignalInfo **signalInfoPointers;
uint32 numSignals;
volatile bool anyActive;
volatile bool anyBreakActive;
bool isOutput;
char8 gamName[256];
Vector<uint32> activeIndices;
Vector<uint32> activeSizes;
Vector<uint32> breakIndices;
FastPollingMutexSem activeMutex;
};
class DebugMemoryMapAsyncOutputBroker : public MemoryMapAsyncOutputBroker {
public:
DebugMemoryMapAsyncOutputBroker() : MemoryMapAsyncOutputBroker() {
service = NULL_PTR(DebugServiceI *);
signalInfoPointers = NULL_PTR(DebugSignalInfo **);
numSignals = 0;
anyActive = false;
anyBreakActive = false;
gamName[0] = '\0';
}
virtual ~DebugMemoryMapAsyncOutputBroker() {
if (signalInfoPointers)
delete[] signalInfoPointers;
}
virtual bool Execute() {
bool ret = MemoryMapAsyncOutputBroker::Execute();
if (ret && (anyActive || anyBreakActive)) {
DebugBrokerHelper::Process(service, signalInfoPointers, activeIndices,
activeSizes, activeMutex,
&anyBreakActive, &breakIndices);
}
// Async output brokers are always output direction
if (ret) {
DebugBrokerHelper::OutputPauseAndStep(service, gamName);
}
return ret;
}
virtual bool InitWithBufferParameters(const SignalDirection direction,
DataSourceI &dataSourceIn,
const char8 *const functionName,
void *const gamMemoryAddress,
const uint32 numberOfBuffersIn,
const ProcessorType &cpuMaskIn,
const uint32 stackSizeIn) {
bool ret = MemoryMapAsyncOutputBroker::InitWithBufferParameters(
direction, dataSourceIn, functionName, gamMemoryAddress,
numberOfBuffersIn, cpuMaskIn, stackSizeIn);
if (ret) {
numSignals = this->GetNumberOfCopies();
StringHelper::CopyN(gamName, (functionName != NULL_PTR(const char8 *)) ? functionName : "", 255u);
DebugBrokerHelper::InitSignals(
this, dataSourceIn, service, signalInfoPointers, numSignals,
this->copyTable, functionName, direction, &anyActive, &activeIndices,
&activeSizes, &activeMutex, &anyBreakActive, &breakIndices);
}
return ret;
}
DebugServiceI *service;
DebugSignalInfo **signalInfoPointers;
uint32 numSignals;
volatile bool anyActive;
volatile bool anyBreakActive;
char8 gamName[256];
Vector<uint32> activeIndices;
Vector<uint32> activeSizes;
Vector<uint32> breakIndices;
FastPollingMutexSem activeMutex;
};
class DebugMemoryMapAsyncTriggerOutputBroker
: public MemoryMapAsyncTriggerOutputBroker {
public:
DebugMemoryMapAsyncTriggerOutputBroker()
: MemoryMapAsyncTriggerOutputBroker() {
service = NULL_PTR(DebugServiceI *);
signalInfoPointers = NULL_PTR(DebugSignalInfo **);
numSignals = 0;
anyActive = false;
anyBreakActive = false;
gamName[0] = '\0';
}
virtual ~DebugMemoryMapAsyncTriggerOutputBroker() {
if (signalInfoPointers)
delete[] signalInfoPointers;
}
virtual bool Execute() {
bool ret = MemoryMapAsyncTriggerOutputBroker::Execute();
if (ret && (anyActive || anyBreakActive)) {
DebugBrokerHelper::Process(service, signalInfoPointers, activeIndices,
activeSizes, activeMutex,
&anyBreakActive, &breakIndices);
}
if (ret) {
DebugBrokerHelper::OutputPauseAndStep(service, gamName);
}
return ret;
}
virtual bool InitWithTriggerParameters(
const SignalDirection direction, DataSourceI &dataSourceIn,
const char8 *const functionName, void *const gamMemoryAddress,
const uint32 numberOfBuffersIn, const uint32 preTriggerBuffersIn,
const uint32 postTriggerBuffersIn, const ProcessorType &cpuMaskIn,
const uint32 stackSizeIn) {
bool ret = MemoryMapAsyncTriggerOutputBroker::InitWithTriggerParameters(
direction, dataSourceIn, functionName, gamMemoryAddress,
numberOfBuffersIn, preTriggerBuffersIn, postTriggerBuffersIn, cpuMaskIn,
stackSizeIn);
if (ret) {
numSignals = this->GetNumberOfCopies();
StringHelper::CopyN(gamName, (functionName != NULL_PTR(const char8 *)) ? functionName : "", 255u);
DebugBrokerHelper::InitSignals(
this, dataSourceIn, service, signalInfoPointers, numSignals,
this->copyTable, functionName, direction, &anyActive, &activeIndices,
&activeSizes, &activeMutex, &anyBreakActive, &breakIndices);
}
return ret;
}
DebugServiceI *service;
DebugSignalInfo **signalInfoPointers;
uint32 numSignals;
volatile bool anyActive;
volatile bool anyBreakActive;
char8 gamName[256];
Vector<uint32> activeIndices;
Vector<uint32> activeSizes;
Vector<uint32> breakIndices;
FastPollingMutexSem activeMutex;
};
template <typename T> class DebugBrokerBuilder : public ObjectBuilder {
public:
virtual Object *Build(HeapI *const heap) const { return new (heap) T(); }
};
typedef DebugBrokerWrapper<MemoryMapInputBroker> DebugMemoryMapInputBroker;
// LCOV_EXCL_START
typedef DebugBrokerWrapper<MemoryMapOutputBroker> DebugMemoryMapOutputBroker;
typedef DebugBrokerWrapper<MemoryMapSynchronisedInputBroker>
DebugMemoryMapSynchronisedInputBroker;
typedef DebugBrokerWrapper<MemoryMapSynchronisedOutputBroker>
DebugMemoryMapSynchronisedOutputBroker;
typedef DebugBrokerWrapperNoOptim<MemoryMapInterpolatedInputBroker>
DebugMemoryMapInterpolatedInputBroker;
typedef DebugBrokerWrapper<MemoryMapMultiBufferInputBroker>
DebugMemoryMapMultiBufferInputBroker;
typedef DebugBrokerWrapper<MemoryMapMultiBufferOutputBroker>
DebugMemoryMapMultiBufferOutputBroker;
typedef DebugBrokerWrapper<MemoryMapSynchronisedMultiBufferInputBroker>
DebugMemoryMapSynchronisedMultiBufferInputBroker;
typedef DebugBrokerWrapper<MemoryMapSynchronisedMultiBufferOutputBroker>
DebugMemoryMapSynchronisedMultiBufferOutputBroker;
// LCOV_EXCL_STOP
typedef DebugBrokerBuilder<DebugMemoryMapInputBroker>
DebugMemoryMapInputBrokerBuilder;
// LCOV_EXCL_START
typedef DebugBrokerBuilder<DebugMemoryMapOutputBroker>
DebugMemoryMapOutputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapSynchronisedInputBroker>
DebugMemoryMapSynchronisedInputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapSynchronisedOutputBroker>
DebugMemoryMapSynchronisedOutputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapInterpolatedInputBroker>
DebugMemoryMapInterpolatedInputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapMultiBufferInputBroker>
DebugMemoryMapMultiBufferInputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapMultiBufferOutputBroker>
DebugMemoryMapMultiBufferOutputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapSynchronisedMultiBufferInputBroker>
DebugMemoryMapSynchronisedMultiBufferInputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapSynchronisedMultiBufferOutputBroker>
DebugMemoryMapSynchronisedMultiBufferOutputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapAsyncOutputBroker>
DebugMemoryMapAsyncOutputBrokerBuilder;
typedef DebugBrokerBuilder<DebugMemoryMapAsyncTriggerOutputBroker>
DebugMemoryMapAsyncTriggerOutputBrokerBuilder;
// LCOV_EXCL_STOP
} // namespace MARTe
#endif
@@ -0,0 +1,188 @@
#ifndef DEBUGCORE_H
#define DEBUGCORE_H
#include "CompilerTypes.h"
#include "TypeDescriptor.h"
#include "StreamString.h"
#include <string.h>
namespace MARTe {
// Break condition operators stored in DebugSignalInfo::breakOp
enum BreakOp {
BREAK_OFF = 0,
BREAK_GT = 1, // >
BREAK_LT = 2, // <
BREAK_EQ = 3, // ==
BREAK_GEQ = 4, // >=
BREAK_LEQ = 5, // <=
BREAK_NEQ = 6 // !=
};
struct DebugSignalInfo {
void* memoryAddress;
TypeDescriptor type;
StreamString name;
uint8 numberOfDimensions;
uint32 numberOfElements;
volatile bool isTracing;
volatile bool isForcing;
uint8 forcedValue[1024];
uint8 forcedMask[32]; // bit e set → element e is forced; supports up to 256 elements
uint32 internalID;
volatile uint32 decimationFactor;
volatile uint32 decimationCounter;
// Conditional break fields (zero-cost when breakOp == BREAK_OFF)
volatile uint8 breakOp; // BreakOp enum value
float64 breakThreshold; // comparison threshold
};
#pragma pack(push, 1)
struct TraceHeader {
uint32 magic; // 0xDA7A57AD
uint32 seq; // Sequence number
uint64 timestamp; // HighRes timestamp
uint32 count; // Number of samples in payload
};
#pragma pack(pop)
/**
* @brief Ring buffer for high-frequency signal tracing.
* @details New format per sample: [ID:4][Timestamp:8][Size:4][Data:N]
*/
class TraceRingBuffer {
public:
TraceRingBuffer() {
bufferSize = 0;
buffer = NULL_PTR(uint8*);
readIndex = 0;
writeIndex = 0;
}
~TraceRingBuffer() {
if (buffer != NULL_PTR(uint8*)) {
delete[] buffer;
}
}
bool Init(uint32 size) {
if (buffer != NULL_PTR(uint8*)) {
delete[] buffer;
}
bufferSize = size;
buffer = new uint8[bufferSize];
readIndex = 0;
writeIndex = 0;
return (buffer != NULL_PTR(uint8*));
}
bool Push(uint32 signalID, uint64 timestamp, void* data, uint32 size) {
uint32 packetSize = 4 + 8 + 4 + size; // ID + TS + Size + Data
uint32 read = readIndex;
uint32 write = writeIndex;
uint32 available = 0;
if (read <= write) {
available = bufferSize - (write - read) - 1;
} else {
available = read - write - 1;
}
if (available < packetSize) return false;
uint32 tempWrite = write;
WriteToBuffer(&tempWrite, &signalID, 4);
WriteToBuffer(&tempWrite, &timestamp, 8);
WriteToBuffer(&tempWrite, &size, 4);
WriteToBuffer(&tempWrite, data, size);
writeIndex = tempWrite;
return true;
}
bool Pop(uint32 &signalID, uint64 &timestamp, void* dataBuffer, uint32 &size, uint32 maxSize) {
uint32 read = readIndex;
uint32 write = writeIndex;
if (read == write) return false;
uint32 tempRead = read;
uint32 tempId = 0;
uint64 tempTs = 0;
uint32 tempSize = 0;
ReadFromBuffer(&tempRead, &tempId, 4);
ReadFromBuffer(&tempRead, &tempTs, 8);
ReadFromBuffer(&tempRead, &tempSize, 4);
if (tempSize > maxSize) {
// FIX #5: Skip only the current entry rather than discarding the
// entire ring buffer. tempRead is already past the 16-byte header;
// advancing by tempSize lands at the start of the next entry.
//
// Safety fallback: if tempSize >= bufferSize the stored size field
// is corrupt (it can never be that large). In that case we cannot
// locate the next entry safely, so fall back to discarding everything
// to avoid reading garbage as sample headers on future Pop() calls.
if (tempSize >= bufferSize) {
readIndex = write; // corrupt ring — discard all
} else {
readIndex = (tempRead + tempSize) % bufferSize;
}
return false;
}
ReadFromBuffer(&tempRead, dataBuffer, tempSize);
signalID = tempId;
timestamp = tempTs;
size = tempSize;
readIndex = tempRead;
return true;
}
uint32 Count() {
uint32 read = readIndex;
uint32 write = writeIndex;
if (write >= read) return write - read;
return bufferSize - (read - write);
}
private:
void WriteToBuffer(uint32 *idx, void* src, uint32 count) {
uint32 current = *idx;
uint32 spaceToEnd = bufferSize - current;
if (count <= spaceToEnd) {
memcpy(&buffer[current], src, count);
*idx = (current + count) % bufferSize;
} else {
memcpy(&buffer[current], src, spaceToEnd);
uint32 remaining = count - spaceToEnd;
memcpy(&buffer[0], (uint8*)src + spaceToEnd, remaining);
*idx = remaining;
}
}
void ReadFromBuffer(uint32 *idx, void* dst, uint32 count) {
uint32 current = *idx;
uint32 spaceToEnd = bufferSize - current;
if (count <= spaceToEnd) {
memcpy(dst, &buffer[current], count);
*idx = (current + count) % bufferSize;
} else {
memcpy(dst, &buffer[current], spaceToEnd);
uint32 remaining = count - spaceToEnd;
memcpy((uint8*)dst + spaceToEnd, &buffer[0], remaining);
*idx = remaining;
}
}
volatile uint32 readIndex;
volatile uint32 writeIndex;
uint32 bufferSize;
uint8 *buffer;
};
}
#endif
@@ -0,0 +1,618 @@
#include "BasicTCPSocket.h"
#include "ConfigurationDatabase.h"
#include "DebugService.h"
#include "GlobalObjectsDatabase.h"
#include "HighResolutionTimer.h"
#include "LoggerService.h"
#include "Message.h"
#include "ObjectRegistryDatabase.h"
#include "ReferenceT.h"
#include "Sleep.h"
#include "StreamString.h"
#include "StringHelper.h"
#include "Threads.h"
#include "TimeoutType.h"
#include "UDPSProtocol.h"
namespace MARTe {
CLASS_REGISTER(DebugService, "1.0")
// C++98 ODR definitions for static constants
const uint32 DebugService::CMD_RATE_LIMIT;
const uint32 DebugService::CLIENT_IDLE_TIMEOUT_MS;
const uint32 DebugService::INPUT_BUFFER_MAX;
// ---------------------------------------------------------------------------
// Constructor / Destructor
// ---------------------------------------------------------------------------
DebugService::DebugService()
: DebugServiceBase(),
EmbeddedServiceMethodBinderI(),
binderServer(this, ServiceBinder::ServerType),
binderStreamer(this, ServiceBinder::StreamerType),
threadService(binderServer),
streamerService(binderStreamer) {
controlPort = 0u;
streamPort = 8081u;
logPort = 8082u;
streamIP = "127.0.0.1";
isServer = false;
suppressTimeoutLogs = true;
activeClient = NULL_PTR(BasicTCPSocket *);
cmdCountInWindow = 0u;
cmdWindowStartMs = 0u;
lastDataTimeMs = 0u;
inputBuffer = "";
// UDPS members
udpsNumSlots = 0u;
udpsDataPayload = NULL_PTR(uint8 *);
udpsDataPayloadSize = 0u;
udpsPacketCounter = 0u;
udpsConfigPending = false;
}
DebugService::~DebugService() {
if (DebugServiceI::GetInstance() == this) {
DebugServiceI::SetInstance(NULL_PTR(DebugServiceI *));
}
threadService.Stop();
streamerService.Stop();
tcpServer.Close();
udpSocket.Close();
if (activeClient != NULL_PTR(BasicTCPSocket *)) {
activeClient->Close();
delete activeClient;
activeClient = NULL_PTR(BasicTCPSocket *);
}
if (udpsDataPayload != NULL_PTR(uint8 *)) {
delete[] udpsDataPayload;
udpsDataPayload = NULL_PTR(uint8 *);
}
// signals owned by DebugServiceBase destructor
}
// ---------------------------------------------------------------------------
// Initialise
// ---------------------------------------------------------------------------
bool DebugService::Initialise(StructuredDataI &data) {
if (!ReferenceContainer::Initialise(data)) return false;
uint32 port = 0u;
if (data.Read("ControlPort", port)) {
controlPort = (uint16)port;
} else {
(void)data.Read("TcpPort", port);
controlPort = (uint16)port;
}
if (controlPort > 0u) {
isServer = true;
DebugServiceI::SetInstance(this);
}
port = 8081u;
if (data.Read("StreamPort", port)) {
streamPort = (uint16)port;
} else {
(void)data.Read("UdpPort", port);
streamPort = (uint16)port;
}
port = 8082u;
if (data.Read("LogPort", port)) {
logPort = (uint16)port;
} else {
(void)data.Read("TcpLogPort", port);
logPort = (uint16)port;
}
StreamString tempIP;
if (data.Read("StreamIP", tempIP)) {
streamIP = tempIP;
} else {
streamIP = "127.0.0.1";
}
uint32 suppress = 1u;
if (data.Read("SuppressTimeoutLogs", suppress)) {
suppressTimeoutLogs = (suppress == 1u);
}
// Capture only the local subtree — do NOT call MoveToRoot() on the shared CDB.
(void)data.Copy(fullConfig);
if (isServer) {
if (!traceBuffer.Init(8 * 1024 * 1024)) return false;
PatchRegistry();
ConfigurationDatabase threadData;
threadData.Write("Timeout", (uint32)1000);
threadService.Initialise(threadData);
streamerService.Initialise(threadData);
if (!tcpServer.Open()) return false;
if (!tcpServer.Listen(controlPort)) return false;
if (!udpSocket.Open()) return false;
// Note: do NOT bind udpSocket to streamPort here. The Go client
// must own that port to receive streamed data. The socket sends
// via an ephemeral source port, which is fine for UDP.
if (threadService.Start() != ErrorManagement::NoError) return false;
if (streamerService.Start() != ErrorManagement::NoError) return false;
// Send initial (empty) CONFIG so clients know the schema version
SendUDPSConfig();
}
return true;
}
// ---------------------------------------------------------------------------
// Transport config hook (called by RebuildConfigFromRegistry in base)
// ---------------------------------------------------------------------------
void DebugService::RebuildTransportConfig() {
const char8 *myName = GetName();
if (myName != NULL_PTR(const char8 *)) {
if (fullConfig.MoveRelative(myName)) {
(void)fullConfig.Write("ControlPort", static_cast<uint32>(controlPort));
(void)fullConfig.Write("UdpPort", static_cast<uint32>(streamPort));
(void)fullConfig.Write("LogPort", static_cast<uint32>(logPort));
if (streamIP.Size() > 0u)
(void)fullConfig.Write("StreamIP", streamIP.Buffer());
(void)fullConfig.MoveToAncestor(1u);
}
}
}
// ---------------------------------------------------------------------------
// SERVICE_INFO hook
// ---------------------------------------------------------------------------
void DebugService::GetServiceInfo(StreamString &out) {
out.Printf("OK SERVICE_INFO TCP_CTRL:%u UDP_STREAM:%u TCP_LOG:%u STATE:%s\n",
controlPort, streamPort, logPort,
isPaused ? "PAUSED" : "RUNNING");
}
// ---------------------------------------------------------------------------
// Execute / HandleMessage (framework boilerplate)
// ---------------------------------------------------------------------------
ErrorManagement::ErrorType DebugService::Execute(ExecutionInfo &info) {
(void)info;
return ErrorManagement::FatalError;
}
ErrorManagement::ErrorType DebugService::HandleMessage(ReferenceT<Message> &data) {
(void)data;
return ErrorManagement::NoError;
}
// ---------------------------------------------------------------------------
// TraceSignal override — sets config-pending flag after base handling
// ---------------------------------------------------------------------------
uint32 DebugService::TraceSignal(const char8 *name, bool enable, uint32 decimation) {
uint32 ret = DebugServiceBase::TraceSignal(name, enable, decimation);
udpsConfigPending = true;
return ret;
}
// ---------------------------------------------------------------------------
// InjectTcpLoggerIfNeeded
// ---------------------------------------------------------------------------
void DebugService::InjectTcpLoggerIfNeeded() {
if (logPort == 0u) return;
Reference existing = ObjectRegistryDatabase::Instance()->Find("LoggerService");
if (existing.IsValid()) {
ReferenceContainer *rc =
dynamic_cast<ReferenceContainer *>(existing.operator->());
if (rc != NULL_PTR(ReferenceContainer *)) {
for (uint32 i = 0u; i < rc->Size(); i++) {
Reference child = rc->Get(i);
// Check by class name to avoid a direct symbol dependency on TcpLogger.so
if (child.IsValid()) {
const ClassProperties *cp = child->GetClassProperties();
if (cp != NULL_PTR(const ClassProperties *)) {
if (StringHelper::Compare(cp->GetName(), "TcpLogger") == 0) {
return; // already has a TcpLogger
}
}
}
}
}
}
ConfigurationDatabase lsCdb;
(void)lsCdb.Write("Class", "LoggerService");
uint32 cpus = 1u;
(void)lsCdb.Write("CPUs", cpus);
if (lsCdb.CreateRelative("+DebugConsumer")) {
(void)lsCdb.Write("Class", "TcpLogger");
uint32 p = static_cast<uint32>(logPort);
(void)lsCdb.Write("Port", p);
(void)lsCdb.MoveToAncestor(1u);
}
(void)lsCdb.MoveToRoot();
ReferenceT<LoggerService> ls(
"LoggerService", GlobalObjectsDatabase::Instance()->GetStandardHeap());
if (!ls.IsValid()) return;
ls->SetName("LoggerService");
if (!ls->Initialise(lsCdb)) return;
(void)ObjectRegistryDatabase::Instance()->Insert(ls);
}
// ---------------------------------------------------------------------------
// Server thread
// ---------------------------------------------------------------------------
ErrorManagement::ErrorType DebugService::Server(ExecutionInfo &info) {
if (info.GetStage() == ExecutionInfo::TerminationStage)
return ErrorManagement::NoError;
if (info.GetStage() == ExecutionInfo::StartupStage) {
serverThreadId = Threads::Id();
Sleep::MSec(500u);
InjectTcpLoggerIfNeeded();
return ErrorManagement::NoError;
}
uint64 nowMs = (uint64)((float64)HighResolutionTimer::Counter() *
HighResolutionTimer::Period() * 1000.0);
if (activeClient == NULL_PTR(BasicTCPSocket *)) {
BasicTCPSocket *newClient = tcpServer.WaitConnection(TimeoutType(100));
if (newClient != NULL_PTR(BasicTCPSocket *)) {
clientMutex.FastLock();
activeClient = newClient;
clientMutex.FastUnLock();
cmdCountInWindow = 0u;
cmdWindowStartMs = nowMs;
lastDataTimeMs = nowMs;
}
} else {
if (nowMs - lastDataTimeMs > CLIENT_IDLE_TIMEOUT_MS) {
REPORT_ERROR_STATIC(ErrorManagement::Warning,
"Server: TCP client idle for >%u ms — closing connection.",
CLIENT_IDLE_TIMEOUT_MS);
inputBuffer = "";
clientMutex.FastLock();
activeClient->Close();
delete activeClient;
activeClient = NULL_PTR(BasicTCPSocket *);
clientMutex.FastUnLock();
cmdCountInWindow = 0u;
} else if (!activeClient->IsConnected()) {
inputBuffer = "";
clientMutex.FastLock();
activeClient->Close();
delete activeClient;
activeClient = NULL_PTR(BasicTCPSocket *);
clientMutex.FastUnLock();
} else {
char buffer[1024];
uint32 size = 1024u;
if (activeClient->Read(buffer, size)) {
if (size > 0u) {
lastDataTimeMs = nowMs;
if (nowMs - cmdWindowStartMs >= 1000u) {
cmdWindowStartMs = nowMs;
cmdCountInWindow = 0u;
}
if (inputBuffer.Size() + (uint32)size > INPUT_BUFFER_MAX) {
REPORT_ERROR_STATIC(ErrorManagement::Warning,
"Server: input buffer overflow (>%u bytes without newline) "
"— disconnecting.", INPUT_BUFFER_MAX);
inputBuffer = "";
clientMutex.FastLock();
activeClient->Close();
delete activeClient;
activeClient = NULL_PTR(BasicTCPSocket *);
clientMutex.FastUnLock();
cmdCountInWindow = 0u;
} else {
(void)inputBuffer.Seek(inputBuffer.Size());
uint32 writeSize = (uint32)size;
inputBuffer.Write(buffer, writeSize);
const char8 *raw = inputBuffer.Buffer();
uint32 total = (uint32)inputBuffer.Size();
uint32 lineStart = 0u;
bool rateLimitExceeded = false;
for (uint32 pos = 0u; pos < total && !rateLimitExceeded; pos++) {
if (raw[pos] != '\n') continue;
uint32 len = pos - lineStart;
if (len > 0u && raw[lineStart + len - 1u] == '\r') len--;
if (len > 0u) {
cmdCountInWindow++;
if (cmdCountInWindow > CMD_RATE_LIMIT) {
REPORT_ERROR_STATIC(ErrorManagement::Warning,
"Server: client exceeded rate limit (%u cmd/s) "
"— disconnecting.", CMD_RATE_LIMIT);
rateLimitExceeded = true;
break;
}
StreamString command;
uint32 cmdLen = len;
command.Write(raw + lineStart, cmdLen);
// Dispatch via base HandleCommand, write response to socket.
StreamString out;
HandleCommand(command, out);
if (out.Size() > 0u) {
const char8 *wPtr = out.Buffer();
uint32 remaining = (uint32)out.Size();
lastDataTimeMs = (uint64)((float64)HighResolutionTimer::Counter() *
HighResolutionTimer::Period() * 1000.0);
while (remaining > 0u) {
uint32 wrote = remaining;
if (!activeClient->Write(wPtr, wrote) || wrote == 0u) {
break;
}
wPtr += wrote;
remaining -= wrote;
lastDataTimeMs = (uint64)((float64)HighResolutionTimer::Counter() *
HighResolutionTimer::Period() * 1000.0);
}
}
}
lineStart = pos + 1u;
}
if (rateLimitExceeded) {
inputBuffer = "";
clientMutex.FastLock();
activeClient->Close();
delete activeClient;
activeClient = NULL_PTR(BasicTCPSocket *);
clientMutex.FastUnLock();
cmdCountInWindow = 0u;
} else {
StreamString newInputBuffer;
if (lineStart < total) {
uint32 remLen = total - lineStart;
newInputBuffer.Write(raw + lineStart, remLen);
}
inputBuffer = newInputBuffer;
}
}
}
} else {
inputBuffer = "";
clientMutex.FastLock();
activeClient->Close();
delete activeClient;
activeClient = NULL_PTR(BasicTCPSocket *);
clientMutex.FastUnLock();
}
}
}
return ErrorManagement::NoError;
}
// ---------------------------------------------------------------------------
// Streamer thread — UDPS binary telemetry
// ---------------------------------------------------------------------------
ErrorManagement::ErrorType DebugService::Streamer(ExecutionInfo &info) {
if (info.GetStage() == ExecutionInfo::TerminationStage) {
if (udpsDataPayload != NULL_PTR(uint8 *)) {
delete[] udpsDataPayload;
udpsDataPayload = NULL_PTR(uint8 *);
}
return ErrorManagement::NoError;
}
if (info.GetStage() == ExecutionInfo::StartupStage) {
streamerThreadId = Threads::Id();
return ErrorManagement::NoError;
}
// Set UDP destination
InternetHost dest(streamPort, streamIP.Buffer());
(void)udpSocket.SetDestination(dest);
// a) If config has changed, rebuild and send CONFIG packet
if (udpsConfigPending) {
SendUDPSConfig();
udpsConfigPending = false;
}
// b) Drain traceBuffer — pack each sample into udpsDataPayload
bool anyData = false;
uint32 id, size;
uint64 ts;
uint8 udpsSampleBuf[UDPS_MAX_SAMPLE_BYTES];
while (traceBuffer.Pop(id, ts, udpsSampleBuf, size, UDPS_MAX_SAMPLE_BYTES)) {
// Find matching slot by internalID
for (uint32 i = 0u; i < udpsNumSlots; i++) {
if (udpsSlots[i].internalID == id) {
if ((udpsDataPayload != NULL_PTR(uint8 *)) &&
(8u + udpsSlots[i].wireOffset + udpsSlots[i].wireSize <= udpsDataPayloadSize)) {
uint32 copySize = size;
if (copySize > udpsSlots[i].wireSize) copySize = udpsSlots[i].wireSize;
memcpy(udpsDataPayload + 8u + udpsSlots[i].wireOffset, udpsSampleBuf, copySize);
udpsSlots[i].everFilled = true;
}
anyData = true;
break;
}
}
}
// c) If we have data, stamp with HRT and send
if (anyData && udpsNumSlots > 0u && udpsDataPayload != NULL_PTR(uint8 *)) {
uint64 hrt = HighResolutionTimer::Counter();
memcpy(udpsDataPayload, &hrt, 8u);
SendUDPSFragmented(UDPS_TYPE_DATA, udpsDataPayload, udpsDataPayloadSize);
udpsPacketCounter++;
}
if (!anyData) {
Sleep::MSec(1u);
}
return ErrorManagement::NoError;
}
// ---------------------------------------------------------------------------
// SendUDPSConfig — build and send a UDPS CONFIG packet
// ---------------------------------------------------------------------------
bool DebugService::SendUDPSConfig() {
// Snapshot traced signals under mutex
mutex.FastLock();
// Count traced signals
uint32 tracedCount = 0u;
for (uint32 i = 0u; i < signals.GetNumberOfElements(); i++) {
if (signals[i]->isTracing) {
tracedCount++;
}
}
// Build CONFIG payload into udpsTxBuf starting at UDPS_HEADER_SIZE offset
uint8 *payload = udpsTxBuf + UDPS_HEADER_SIZE;
// Write numTraced (uint32 LE)
memcpy(payload, &tracedCount, 4u);
uint32 payloadOffset = 4u;
// Build slot table in parallel
uint32 currentOffset = 0u;
uint32 newNumSlots = 0u;
uint32 totalWireBytes = 0u;
for (uint32 i = 0u; i < signals.GetNumberOfElements(); i++) {
if (!signals[i]->isTracing) continue;
if (newNumSlots >= UDPS_MAX_SLOTS) break;
uint8 typeCode = UDPSTypeDescriptorToCode(signals[i]->type);
if (typeCode == UDPS_TYPECODE_UNKNOWN) {
// Skip unsupported types
continue;
}
uint32 numElements = signals[i]->numberOfElements;
if (numElements == 0u) numElements = 1u;
uint32 numRows, numCols;
if (signals[i]->numberOfDimensions >= 2u) {
// For matrix: approximate square root
numCols = numElements;
numRows = 1u;
} else if (signals[i]->numberOfDimensions == 1u) {
numRows = numElements;
numCols = 1u;
} else {
numRows = 1u;
numCols = 1u;
}
uint32 wireSize = UDPSTypeCodeByteSize(typeCode) * numElements;
// Write signal descriptor (136 bytes) to payload
if (payloadOffset + UDPS_SIGNAL_DESC_SIZE <= sizeof(udpsTxBuf) - UDPS_HEADER_SIZE - 1u) {
UDPSSignalDescriptor *desc = reinterpret_cast<UDPSSignalDescriptor *>(payload + payloadOffset);
memset(desc, 0, UDPS_SIGNAL_DESC_SIZE);
if (signals[i]->name.Size() > 0u) {
strncpy(desc->name, signals[i]->name.Buffer(), UDPS_MAX_SIGNAL_NAME - 1u);
}
desc->typeCode = typeCode;
desc->quantType = UDPS_QUANT_NONE;
desc->numDimensions = signals[i]->numberOfDimensions;
desc->numRows = numRows;
desc->numCols = numCols;
desc->rangeMin = 0.0;
desc->rangeMax = 0.0;
desc->timeMode = UDPS_TIMEMODE_PACKET;
desc->samplingRate = 0.0;
desc->timeSignalIdx = UDPS_NO_TIME_SIGNAL;
// unit stays zero
payloadOffset += UDPS_SIGNAL_DESC_SIZE;
}
// Fill slot table entry
udpsSlots[newNumSlots].internalID = signals[i]->internalID;
udpsSlots[newNumSlots].wireOffset = currentOffset;
udpsSlots[newNumSlots].wireSize = wireSize;
udpsSlots[newNumSlots].everFilled = false;
newNumSlots++;
currentOffset += wireSize;
totalWireBytes += wireSize;
}
// Write publish mode byte
if (payloadOffset < sizeof(udpsTxBuf) - UDPS_HEADER_SIZE) {
payload[payloadOffset] = UDPS_PUBLISH_STRICT;
payloadOffset++;
}
udpsNumSlots = newNumSlots;
mutex.FastUnLock();
// Reallocate data payload buffer
if (udpsDataPayload != NULL_PTR(uint8 *)) {
delete[] udpsDataPayload;
udpsDataPayload = NULL_PTR(uint8 *);
}
udpsDataPayloadSize = 8u + totalWireBytes; // 8 bytes HRT + signal data
if (udpsDataPayloadSize > 0u) {
udpsDataPayload = new uint8[udpsDataPayloadSize];
memset(udpsDataPayload, 0, udpsDataPayloadSize);
}
// Send CONFIG packet
SendUDPSFragmented(UDPS_TYPE_CONFIG, payload, payloadOffset);
return true;
}
// ---------------------------------------------------------------------------
// SendUDPSFragmented — fragment and send a UDPS packet
// ---------------------------------------------------------------------------
bool DebugService::SendUDPSFragmented(uint8 type, const uint8 *payload, uint32 payloadSize) {
if (payloadSize <= UDPS_MAX_PAYLOAD) {
// Single datagram
UDPSBuildHeader(udpsTxBuf, type, udpsPacketCounter, 0u, 1u, payloadSize);
if (payload != (udpsTxBuf + UDPS_HEADER_SIZE)) {
memcpy(udpsTxBuf + UDPS_HEADER_SIZE, payload, payloadSize);
}
uint32 toWrite = UDPS_HEADER_SIZE + payloadSize;
(void)udpSocket.Write(reinterpret_cast<char8 *>(udpsTxBuf), toWrite);
} else {
// Fragmented
uint32 numFrags = (payloadSize + UDPS_MAX_PAYLOAD - 1u) / UDPS_MAX_PAYLOAD;
uint32 offset = 0u;
for (uint32 i = 0u; i < numFrags; i++) {
uint32 chunkSize = UDPS_MAX_PAYLOAD;
if (offset + chunkSize > payloadSize) {
chunkSize = payloadSize - offset;
}
UDPSBuildHeader(udpsTxBuf, type, udpsPacketCounter,
static_cast<uint16>(i),
static_cast<uint16>(numFrags),
chunkSize);
memcpy(udpsTxBuf + UDPS_HEADER_SIZE, payload + offset, chunkSize);
uint32 toWrite = UDPS_HEADER_SIZE + chunkSize;
(void)udpSocket.Write(reinterpret_cast<char8 *>(udpsTxBuf), toWrite);
offset += chunkSize;
}
}
return true;
}
} // namespace MARTe
@@ -0,0 +1,183 @@
#ifndef DEBUGSERVICE_H
#define DEBUGSERVICE_H
#include "BasicTCPSocket.h"
#include "BasicUDPSocket.h"
#include "DebugServiceBase.h"
#include "EmbeddedServiceMethodBinderI.h"
#include "MessageI.h"
#include "ReferenceT.h"
#include "SingleThreadService.h"
#include "UDPSProtocol.h"
namespace MARTe {
/**
* @brief TCP/UDP implementation of DebugServiceI (via DebugServiceBase).
*
* Signal tracing now uses the UDPS binary protocol (same wire format as
* UDPStreamer) so that the same Go web client can consume both sources.
*
* Flow:
* 1. The Go client listens on udpPort.
* 2. DebugService binds the same port on its end (or uses the client's
* configured IP:port as destination for the old push model).
* 3. On startup and on every TRACE change, DebugService sends a CONFIG
* packet listing the currently-traced signals.
* 4. For each RT drain cycle that contains new data, DebugService sends
* one DATA packet (Strict mode) with the most-recent value per signal.
*/
class DebugService : public DebugServiceBase,
public MessageI,
public EmbeddedServiceMethodBinderI {
public:
friend class DebugServiceTest;
CLASS_REGISTER_DECLARATION()
DebugService();
virtual ~DebugService();
virtual bool Initialise(StructuredDataI &data);
virtual ErrorManagement::ErrorType Execute(ExecutionInfo &info);
virtual ErrorManagement::ErrorType HandleMessage(ReferenceT<Message> &data);
/**
* @brief Override TraceSignal to trigger a CONFIG re-send after each change.
*/
virtual uint32 TraceSignal(const char8 *name, bool enable, uint32 decimation = 1u);
protected:
virtual void GetServiceInfo(StreamString &out);
virtual void RebuildTransportConfig();
private:
void InjectTcpLoggerIfNeeded();
ErrorManagement::ErrorType Server (ExecutionInfo &info);
ErrorManagement::ErrorType Streamer(ExecutionInfo &info);
/**
* @brief Build and transmit a CONFIG packet for the current traced-signal set.
* @details Iterates over all registered signals, selects those with
* isTracing == true, builds UDPSSignalDescriptor array, and sends
* a (possibly fragmented) UDPS CONFIG packet. Also rebuilds the
* udpsSlots table and udpsWirePayload buffer.
* @return true on success.
*/
bool SendUDPSConfig();
/**
* @brief Fragment and send a payload as one or more UDPS datagrams.
* @param type Packet type (UDPS_TYPE_CONFIG or UDPS_TYPE_DATA).
* @param payload Pointer to fully-built payload.
* @param payloadSize Byte count of payload.
* @return true if all datagrams were written without error.
*/
bool SendUDPSFragmented(uint8 type, const uint8 *payload, uint32 payloadSize);
// -----------------------------------------------------------------------
// TCP/UDP transport configuration
// -----------------------------------------------------------------------
uint16 controlPort;
uint16 streamPort;
uint16 logPort;
StreamString streamIP;
bool isServer;
bool suppressTimeoutLogs;
BasicTCPSocket tcpServer;
BasicUDPSocket udpSocket;
// -----------------------------------------------------------------------
// Server-thread helper class
// -----------------------------------------------------------------------
class ServiceBinder : public EmbeddedServiceMethodBinderI {
public:
enum ServiceType { ServerType, StreamerType };
ServiceBinder(DebugService *parent, ServiceType type)
: parent(parent), type(type) {}
virtual ErrorManagement::ErrorType Execute(ExecutionInfo &info) {
if (type == StreamerType) return parent->Streamer(info);
return parent->Server(info);
}
private:
DebugService *parent;
ServiceType type;
};
ServiceBinder binderServer;
ServiceBinder binderStreamer;
SingleThreadService threadService;
SingleThreadService streamerService;
ThreadIdentifier serverThreadId;
ThreadIdentifier streamerThreadId;
FastPollingMutexSem clientMutex;
BasicTCPSocket *activeClient;
// -----------------------------------------------------------------------
// TCP server rate limiting and idle detection
// -----------------------------------------------------------------------
static const uint32 CMD_RATE_LIMIT = 100u;
static const uint32 CLIENT_IDLE_TIMEOUT_MS = 120000u;
static const uint32 INPUT_BUFFER_MAX = 8192u;
uint32 cmdCountInWindow;
uint64 cmdWindowStartMs;
uint64 lastDataTimeMs;
StreamString inputBuffer;
// -----------------------------------------------------------------------
// UDPS streaming state (replaces the old custom-format streamer buffers)
// -----------------------------------------------------------------------
/**
* @brief Per-slot descriptor for DATA packet assembly.
* One slot per currently-traced signal; index mirrors CONFIG order.
*/
struct UDPSSlot {
uint32 internalID; ///< DebugSignalInfo::internalID
uint32 wireOffset; ///< Byte offset in udpsDataPayload (after 8-byte HRT)
uint32 wireSize; ///< Bytes occupied by this signal in the DATA payload
bool everFilled; ///< True once at least one sample has been placed
};
/** Maximum number of simultaneously traced signals. */
static const uint32 UDPS_MAX_SLOTS = 512u;
/** Maximum payload per UDP datagram (signal data bytes, excluding header). */
static const uint32 UDPS_MAX_PAYLOAD = 1400u;
/** Hard cap on a single signal's data: 65535 - header(17) - HRT(8). */
static const uint32 UDPS_MAX_SAMPLE_BYTES = 65510u;
UDPSSlot udpsSlots[UDPS_MAX_SLOTS]; ///< Slot table (valid for [0, udpsNumSlots))
uint32 udpsNumSlots; ///< Number of active slots
/** Heap-allocated DATA payload buffer: [HRT:8][sig0_data]...[sigN_data].
* Re-allocated by SendUDPSConfig(). NULL when no signals are traced. */
uint8 *udpsDataPayload;
uint32 udpsDataPayloadSize;
/** Staging buffer: a single sample popped from traceBuffer. */
uint8 udpsSampleBuf[65535u];
/** General-purpose TX buffer for CONFIG and DATA packet assembly. */
uint8 udpsTxBuf[65535u];
/** Packet sequence counter (incremented per DATA/CONFIG datagram group). */
uint32 udpsPacketCounter;
/**
* @brief Set to true by TraceSignal() to request a CONFIG re-send.
* Read and cleared by the Streamer thread.
*/
volatile bool udpsConfigPending;
};
} // namespace MARTe
#endif // DEBUGSERVICE_H
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,214 @@
#ifndef DEBUGSERVICEBASE_H
#define DEBUGSERVICEBASE_H
/**
* @file DebugServiceBase.h
* @brief Shared base class for DebugService and WebDebugService.
*
* Extracts all signal-management, command-handling and config logic that is
* common to both the TCP/UDP transport (DebugService) and the HTTP/SSE
* transport (WebDebugService), eliminating the previous code duplication.
*/
#include "ConfigurationDatabase.h"
#include "DataSourceI.h"
#include "DebugServiceI.h"
#include "FastPollingMutexSem.h"
#include "ReferenceContainer.h"
#include "ReferenceT.h"
#include "StreamString.h"
namespace MARTe {
/**
* @brief Intermediate base class that holds all shared debugging logic.
*
* Inherits from ReferenceContainer (to be a MARTe2 Object) and DebugServiceI
* (to expose the RT-path / control-path interface). Transport subclasses
* (DebugService, WebDebugService) inherit from this class and add only their
* transport-specific threading and socket logic.
*/
class DebugServiceBase : public ReferenceContainer, public DebugServiceI {
public:
friend class DebugServiceTest;
DebugServiceBase();
virtual ~DebugServiceBase();
// =========================================================================
// DebugServiceI RT-path overrides (shared implementation)
// =========================================================================
virtual DebugSignalInfo *RegisterSignal(void *memoryAddress,
TypeDescriptor type,
const char8 *name,
uint8 numberOfDimensions = 0,
uint32 numberOfElements = 1);
virtual void ProcessSignal(DebugSignalInfo *signalInfo, uint32 size,
uint64 timestamp);
virtual void RegisterBroker(DebugSignalInfo **signalPointers,
uint32 numSignals,
MemoryMapBroker *broker,
volatile bool *anyActiveFlag,
Vector<uint32> *activeIndices,
Vector<uint32> *activeSizes,
FastPollingMutexSem *activeMutex,
volatile bool *anyBreakFlag,
Vector<uint32> *breakIndices,
const char8 *gamName = NULL_PTR(const char8 *),
bool isOutput = false);
virtual bool IsPaused() const { return isPaused; }
virtual void SetPaused(bool paused) { isPaused = paused; }
virtual bool IsStepPending() const { return stepRemaining > 0u; }
virtual void ConsumeStepIfNeeded(const char8 *gamName,
const char8 *threadName = NULL_PTR(const char8 *));
// =========================================================================
// DebugServiceI control-path overrides (shared implementation)
// =========================================================================
virtual uint32 ForceSignal (const char8 *name, const char8 *valueStr);
virtual uint32 UnforceSignal(const char8 *name);
virtual uint32 TraceSignal (const char8 *name, bool enable, uint32 decimation = 1);
virtual uint32 SetBreak (const char8 *name, uint8 op, float64 threshold);
virtual uint32 ClearBreak (const char8 *name);
virtual bool IsInstrumented(const char8 *fullPath, bool &traceable, bool &forcable);
virtual uint32 RegisterMonitorSignal(const char8 *path, uint32 periodMs);
virtual uint32 UnmonitorSignal (const char8 *path);
// =========================================================================
// Shared control-path methods (used by transport subclasses)
// =========================================================================
/**
* @brief Parse and dispatch a debug command; write text response to @p out.
*
* Handles: TRACE, FORCE, UNFORCE, BREAK, PAUSE, RESUME, STEP, STEP_STATUS,
* VALUE, DISCOVER, TREE, INFO, LS, CONFIG, MONITOR, UNMONITOR,
* SERVICE_INFO, MSG.
*
* SERVICE_INFO delegates to GetServiceInfo() so each transport can fill in
* its own port/state information.
*/
void HandleCommand(const StreamString &cmdIn, StreamString &out);
void GetStepStatus(StreamString &out);
void GetSignalValue(const char8 *name, StreamString &out);
void Discover (StreamString &out);
void InfoNode (const char8 *path, StreamString &out);
void ListNodes (const char8 *path, StreamString &out);
void ServeConfig (StreamString &out);
void SetFullConfig(ConfigurationDatabase &config);
void RebuildConfigFromRegistry();
// =========================================================================
// Struct shared by both transports
// =========================================================================
struct MonitoredSignal {
ReferenceT<DataSourceI> dataSource;
uint32 signalIdx;
uint32 internalID;
uint32 periodMs;
uint64 lastPollTime;
uint32 size;
StreamString path;
};
// =========================================================================
// Constants
// =========================================================================
static const uint32 GET_VALUE_MAX_ELEMENTS = 256u;
/**
* @brief Pre-build DISCOVER and TREE response caches.
*
* Called automatically by SetFullConfig() once the application is fully
* initialised. After this point, DISCOVER and TREE are served from the
* pre-built string with no mutex contention and no JSON generation cost.
* Both caches are invalidated whenever a new signal is registered (which
* normally only happens during broker init, before SetFullConfig).
*/
void BuildDiscoverCache();
void BuildTreeCache();
// Number of signals per DISCOVER_PART TCP chunk. Responses larger than
// this are split so the Go client can start parsing immediately.
static const uint32 DISCOVER_CHUNK_SIGNALS = 256u;
protected:
// =========================================================================
// Virtual hooks for transport subclasses
// =========================================================================
/**
* @brief Fill the SERVICE_INFO response text (transport-specific).
*
* Called by HandleCommand when the SERVICE_INFO command is received.
* The base implementation writes nothing; subclasses override to append
* e.g. "OK SERVICE_INFO TCP_CTRL:8080 UDP_STREAM:8081 STATE:RUNNING\n".
*/
virtual void GetServiceInfo(StreamString &out) = 0;
/**
* @brief Write back transport-specific config keys after RebuildConfigFromRegistry().
*
* Called at the end of RebuildConfigFromRegistry() so that port numbers
* and other transport parameters that were read in Initialise() are
* reflected back into fullConfig (ExportData on ReferenceContainers
* doesn't re-emit config-file parameters).
*/
virtual void RebuildTransportConfig() {}
// =========================================================================
// Shared protected helpers
// =========================================================================
void Step(uint32 n, const char8 *threadName = NULL_PTR(const char8 *));
void UpdateBrokersActiveStatus();
void UpdateBrokersBreakStatus();
void PatchRegistry();
uint32 ExportTree(ReferenceContainer *container, StreamString &json,
const char8 *pathPrefix);
void ExportTreeNode(const char8 *path, StreamString &out);
void EnrichWithConfig(const char8 *path, StreamString &json);
static void JsonifyDatabase(ConfigurationDatabase &db, StreamString &json);
// =========================================================================
// Shared data members
// =========================================================================
Vector<DebugSignalInfo *> signals;
Vector<SignalAlias> aliases;
Vector<BrokerInfo> brokers;
Vector<MonitoredSignal> monitoredSignals;
FastPollingMutexSem mutex;
FastPollingMutexSem tracePushMutex;
TraceRingBuffer traceBuffer;
volatile bool isPaused;
volatile uint32 stepRemaining;
StreamString pausedAtGam;
StreamString stepThreadFilter;
ConfigurationDatabase fullConfig;
bool manualConfigSet;
// Pre-built response caches. Guarded by mutex (brief lock for swap,
// none needed for reads once cacheValid is true and construction is done).
StreamString discoverCache; // full chunked DISCOVER_PART+DISCOVER payload
StreamString treeCache; // full TREE payload including sentinel
volatile bool discoverCacheValid;
volatile bool treeCacheValid;
};
} // namespace MARTe
#endif // DEBUGSERVICEBASE_H
@@ -0,0 +1,188 @@
#ifndef DEBUGSERVICEI_H
#define DEBUGSERVICEI_H
/**
* @file DebugServiceI.h
* @brief Abstract interface for the MARTe2 debug/instrumentation service.
*
* All broker wrappers (DebugBrokerWrapper) depend solely on this interface,
* decoupling them from the concrete TCP/UDP implementation. Alternative
* transports — TTY, WebSocket, shared-memory ring, etc. — can be plugged in
* by providing a new concrete implementation without touching any broker or
* application code.
*
* The interface is split into two logical groups:
*
* RT-path API
* Called from broker threads on every RT cycle. Implementations must
* keep these methods as cheap as possible; the only permissible
* synchronisation primitive is a fast spinlock (FastPollingMutexSem).
*
* Control-path API
* Called from server / command-handler threads (TCP, TTY, Web …).
* Latency here is acceptable; correctness and thread-safety matter.
*
* Concrete implementations register themselves during Initialise() via
* SetInstance(). Broker wrappers retrieve the active instance via
* GetInstance(); there is no ORD search on the hot path.
*/
#include "DebugCore.h"
#include "FastPollingMutexSem.h"
#include "Object.h"
#include "StreamString.h"
#include "TypeDescriptor.h"
namespace MARTe {
// Forward declarations — concrete types are only needed in the implementation.
class MemoryMapBroker;
struct SignalAlias {
StreamString name;
uint32 signalIndex;
};
struct BrokerInfo {
DebugSignalInfo **signalPointers;
uint32 numSignals;
MemoryMapBroker *broker;
volatile bool *anyActiveFlag;
Vector<uint32> *activeIndices;
Vector<uint32> *activeSizes;
FastPollingMutexSem *activeMutex;
volatile bool *anyBreakFlag;
Vector<uint32> *breakIndices;
StreamString gamName;
bool isOutput;
};
/**
* @brief Abstract debug-service interface.
*/
class DebugServiceI {
public:
// -------------------------------------------------------------------------
// Static instance registry
// -------------------------------------------------------------------------
/**
* @brief Return the currently registered debug-service instance, or NULL.
*
* Called on every broker Init() path and from OutpautPauseAndStep().
* Returns NULL when no debug service has been initialised, in which case
* all instrumentation is a no-op.
*/
static DebugServiceI *GetInstance() { return instance; }
/**
* @brief Register @p inst as the global debug-service.
*
* Concrete implementations call this from their Initialise() method.
* Passing NULL deregisters the current instance (called from the
* destructor so dangling pointers are never visible to broker threads).
*/
static void SetInstance(DebugServiceI *inst) { instance = inst; }
virtual ~DebugServiceI() {}
// =========================================================================
// RT-path API (called from broker execute threads every cycle)
// =========================================================================
/**
* @brief Register a signal memory region with the debug service.
*
* Called once per signal during broker Init(). Returns a pointer to the
* internal DebugSignalInfo that the broker caches for use on the hot path.
* Thread-safe; must not be called after the RT loop has started.
*/
virtual DebugSignalInfo *RegisterSignal(void *memoryAddress,
TypeDescriptor type,
const char8 *name,
uint8 numberOfDimensions = 0,
uint32 numberOfElements = 1) = 0;
/**
* @brief Process one signal on the RT path.
*
* Applies forced values (memcpy into signal memory) and, when tracing is
* enabled and the decimation counter fires, pushes a sample to the trace
* ring buffer. Called under the broker's activeMutex; implementations
* must not acquire any lock that is also held by the Server thread.
*/
virtual void ProcessSignal(DebugSignalInfo *signalInfo,
uint32 size,
uint64 timestamp) = 0;
/**
* @brief Register a broker so the service can push active/break index
* updates to it without iterating every signal.
*/
virtual void RegisterBroker(DebugSignalInfo **signalPointers,
uint32 numSignals,
MemoryMapBroker *broker,
volatile bool *anyActiveFlag,
Vector<uint32> *activeIndices,
Vector<uint32> *activeSizes,
FastPollingMutexSem *activeMutex,
volatile bool *anyBreakFlag,
Vector<uint32> *breakIndices,
const char8 *gamName = NULL_PTR(const char8 *),
bool isOutput = false) = 0;
/** @brief Return true if the RT loop is currently held at a pause/breakpoint. */
virtual bool IsPaused() const = 0;
/** @brief Set or clear the paused state (called by break-condition logic). */
virtual void SetPaused(bool paused) = 0;
/** @brief Return true if a step count is pending (stepRemaining > 0). */
virtual bool IsStepPending() const = 0;
/**
* @brief Consume one step credit for the current output-broker cycle.
*
* Called by every output broker after Execute(). No-op when stepRemaining
* is zero (the common case); only acquires a mutex when stepping is active.
*/
virtual void ConsumeStepIfNeeded(
const char8 *gamName,
const char8 *threadName = NULL_PTR(const char8 *)) = 0;
// =========================================================================
// Control-path API (called from server / command-handler threads)
// =========================================================================
virtual uint32 ForceSignal (const char8 *name, const char8 *valueStr) = 0;
virtual uint32 UnforceSignal(const char8 *name) = 0;
virtual uint32 TraceSignal (const char8 *name, bool enable, uint32 decimation = 1) = 0;
virtual uint32 SetBreak (const char8 *name, uint8 op, float64 threshold) = 0;
virtual uint32 ClearBreak (const char8 *name) = 0;
virtual bool IsInstrumented(const char8 *fullPath,
bool &traceable, bool &forcable) = 0;
virtual uint32 RegisterMonitorSignal(const char8 *path, uint32 periodMs) = 0;
virtual uint32 UnmonitorSignal (const char8 *path) = 0;
// =========================================================================
// Utility (implementation-agnostic, defined in DebugService.cpp)
// =========================================================================
/**
* @brief Resolve the fully-qualified ORD path of @p obj into @p fullPath.
*
* Static so it can be called without a service instance. All concrete
* implementations (and InitSignals in DebugBrokerWrapper.h) use this
* to build canonical signal names. The definition lives in
* DebugService.cpp alongside FindPathInContainer().
*/
static bool GetFullObjectName(const Object &obj, StreamString &fullPath);
protected:
/** Pointer to the single active debug-service instance. */
static DebugServiceI *instance;
};
} // namespace MARTe
#endif // DEBUGSERVICEI_H
@@ -0,0 +1 @@
include Makefile.inc
@@ -0,0 +1,36 @@
#############################################################
# MARTe2 Integrated Components — DebugService
#############################################################
OBJSX=DebugService.x DebugServiceBase.x
PACKAGE=Components/Interfaces
ROOT_DIR=../../../../
MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
# Shared UDPS protocol header (from Common/)
INCLUDES += -I$(ROOT_DIR)/Common/UDP
INCLUDES += -I$(ROOT_DIR)/Source/Components/Interfaces/TCPLogger
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L0Types
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L2Objects
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L3Streams
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Logger
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Configuration
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L3Services
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4LoggerService
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L3Streams
all: $(OBJS) $(SUBPROJ) \
$(BUILD_DIR)/DebugService$(LIBEXT) \
$(BUILD_DIR)/DebugService$(DLLEXT)
echo $(OBJS)
include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET)
@@ -0,0 +1,9 @@
all:
$(MAKE) -C TCPLogger -f Makefile.gcc
$(MAKE) -C DebugService -f Makefile.gcc
clean:
$(MAKE) -C TCPLogger -f Makefile.gcc clean
$(MAKE) -C DebugService -f Makefile.gcc clean
.PHONY: all clean
@@ -0,0 +1 @@
# Interfaces intermediate Makefile.inc
@@ -0,0 +1 @@
include Makefile.inc
@@ -0,0 +1,31 @@
OBJSX=TcpLogger.x
PACKAGE=Components/Interfaces
ROOT_DIR=../../../../
MAKEDEFAULTDIR=$(MARTe2_DIR)/MakeDefaults
include $(MAKEDEFAULTDIR)/MakeStdLibDefs.$(TARGET)
INCLUDES += -I.
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L0Types
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L2Objects
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L3Streams
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Logger
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L4Configuration
INCLUDES += -I$(MARTe2_DIR)/Source/Core/BareMetal/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L3Services
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4Messages
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L4LoggerService
INCLUDES += -I$(MARTe2_DIR)/Source/Core/Scheduler/L5GAMs
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L1Portability
INCLUDES += -I$(MARTe2_DIR)/Source/Core/FileSystem/L3Streams
all: $(OBJS) $(SUBPROJ) \
$(BUILD_DIR)/TcpLogger$(LIBEXT) \
$(BUILD_DIR)/TcpLogger$(DLLEXT)
echo $(OBJS)
include $(MAKEDEFAULTDIR)/MakeStdLibRules.$(TARGET)
@@ -0,0 +1,163 @@
#include "TcpLogger.h"
#include "Threads.h"
#include "StringHelper.h"
#include "ConfigurationDatabase.h"
namespace MARTe {
CLASS_REGISTER(TcpLogger, "1.0")
TcpLogger::TcpLogger() :
ReferenceContainer(), LoggerConsumerI(), EmbeddedServiceMethodBinderI(),
service(*this)
{
port = 8082;
readIdx = 0;
writeIdx = 0;
workerThreadId = InvalidThreadIdentifier;
for (uint32 i=0; i<MAX_CLIENTS; i++) {
activeClients[i] = NULL_PTR(BasicTCPSocket*);
}
}
TcpLogger::~TcpLogger() {
service.Stop();
server.Close();
clientsMutex.FastLock();
for (uint32 i=0; i<MAX_CLIENTS; i++) {
if (activeClients[i] != NULL_PTR(BasicTCPSocket*)) {
activeClients[i]->Close();
delete activeClients[i];
activeClients[i] = NULL_PTR(BasicTCPSocket*);
}
}
clientsMutex.FastUnLock();
}
bool TcpLogger::ExportData(StructuredDataI & data) {
bool ok = data.Write("Port", static_cast<uint32>(port));
return ok;
}
bool TcpLogger::Initialise(StructuredDataI & data) {
if (!ReferenceContainer::Initialise(data)) return false;
if (!data.Read("Port", port)) {
(void)data.Read("TcpPort", port);
}
(void)eventSem.Create();
ConfigurationDatabase threadData;
threadData.Write("Timeout", (uint32)1000);
if (!service.Initialise(threadData)) return false;
if (!server.Open()) return false;
if (!server.Listen(port)) {
return false;
}
printf("[TcpLogger] Listening on port %u\n", port);
if (service.Start() != ErrorManagement::NoError) {
return false;
}
return true;
}
void TcpLogger::ConsumeLogMessage(LoggerPage *logPage) {
if (logPage == NULL_PTR(LoggerPage*)) return;
// 1. Mirror to stdout
StreamString levelStr;
ErrorManagement::ErrorCodeToStream(logPage->errorInfo.header.errorType, levelStr);
printf("[%s] %s\n", levelStr.Buffer(), logPage->errorStrBuffer);
fflush(stdout);
// 2. Queue for TCP
InsertLogIntoQueue(logPage->errorInfo, logPage->errorStrBuffer);
}
void TcpLogger::InsertLogIntoQueue(const ErrorManagement::ErrorInformation &info, const char8 * const description) {
uint32 next = (writeIdx + 1) % QUEUE_SIZE;
if (next != readIdx) {
TcpLogEntry &entry = queue[writeIdx % QUEUE_SIZE];
entry.info = info;
StringHelper::Copy(entry.description, description);
writeIdx = next;
(void)eventSem.Post();
}
}
ErrorManagement::ErrorType TcpLogger::Execute(ExecutionInfo & info) {
if (info.GetStage() == ExecutionInfo::TerminationStage) return ErrorManagement::NoError;
if (info.GetStage() == ExecutionInfo::StartupStage) {
workerThreadId = Threads::Id();
return ErrorManagement::NoError;
}
// Each Execute() call does one cycle. The MARTe2 framework loops Execute()
// so we must NOT spin in an infinite internal loop here — doing so prevents
// the framework from ever delivering the TerminationStage and causes
// Stop() to time out, leaving threads running after the destructor.
// 1. Check for new connections (1 ms timeout → returns promptly)
BasicTCPSocket *newClient = server.WaitConnection(1);
if (newClient != NULL_PTR(BasicTCPSocket *)) {
clientsMutex.FastLock();
bool added = false;
for (uint32 i=0; i<MAX_CLIENTS; i++) {
if (activeClients[i] == NULL_PTR(BasicTCPSocket*)) {
activeClients[i] = newClient;
added = true;
break;
}
}
clientsMutex.FastUnLock();
if (!added) {
newClient->Close();
delete newClient;
} else {
(void)newClient->SetBlocking(false);
}
}
// 2. Stream queued entries to clients
bool hadData = false;
while (readIdx != writeIdx) {
hadData = true;
uint32 idx = readIdx % QUEUE_SIZE;
TcpLogEntry &entry = queue[idx];
StreamString level;
ErrorManagement::ErrorCodeToStream(entry.info.header.errorType, level);
StreamString packet;
packet.Printf("LOG %s %s\n", level.Buffer(), entry.description);
uint32 size = packet.Size();
clientsMutex.FastLock();
for (uint32 j=0; j<MAX_CLIENTS; j++) {
if (activeClients[j] != NULL_PTR(BasicTCPSocket*)) {
uint32 s = size;
if (!activeClients[j]->Write(packet.Buffer(), s)) {
activeClients[j]->Close();
delete activeClients[j];
activeClients[j] = NULL_PTR(BasicTCPSocket*);
}
}
}
clientsMutex.FastUnLock();
readIdx = (readIdx + 1) % QUEUE_SIZE;
}
if (!hadData) {
// Brief wait so we don't busy-spin; return so Stop() can take effect
(void)eventSem.Wait(TimeoutType(10));
eventSem.Reset();
}
return ErrorManagement::NoError;
}
}
@@ -0,0 +1,67 @@
#ifndef TCPLOGGER_H
#define TCPLOGGER_H
#include "LoggerConsumerI.h"
#include "ReferenceContainer.h"
#include "EmbeddedServiceMethodBinderI.h"
#include "BasicTCPSocket.h"
#include "SingleThreadService.h"
#include "FastPollingMutexSem.h"
#include "EventSem.h"
namespace MARTe {
struct TcpLogEntry {
ErrorManagement::ErrorInformation info;
char8 description[MAX_ERROR_MESSAGE_SIZE];
};
/**
* @brief Logger consumer that publishes framework logs to TCP and stdout.
* @details Implements LoggerConsumerI to be used inside a LoggerService.
*/
class TcpLogger : public ReferenceContainer, public LoggerConsumerI, public EmbeddedServiceMethodBinderI {
public:
CLASS_REGISTER_DECLARATION()
TcpLogger();
virtual ~TcpLogger();
virtual bool Initialise(StructuredDataI & data);
virtual bool ExportData(StructuredDataI & data);
/**
* @brief Implementation of LoggerConsumerI.
* Called by LoggerService.
*/
virtual void ConsumeLogMessage(LoggerPage *logPage);
/**
* @brief Worker thread method for TCP streaming.
*/
virtual ErrorManagement::ErrorType Execute(ExecutionInfo & info);
private:
void InsertLogIntoQueue(const ErrorManagement::ErrorInformation &info, const char8 * const description);
uint16 port;
BasicTCPSocket server;
static const uint32 MAX_CLIENTS = 8;
BasicTCPSocket* activeClients[MAX_CLIENTS];
FastPollingMutexSem clientsMutex;
SingleThreadService service;
ThreadIdentifier workerThreadId;
static const uint32 QUEUE_SIZE = 1024;
TcpLogEntry queue[QUEUE_SIZE];
volatile uint32 readIdx;
volatile uint32 writeIdx;
EventSem eventSem;
};
}
#endif
+11
View File
@@ -0,0 +1,11 @@
all:
$(MAKE) -C DataSources -f Makefile.gcc
$(MAKE) -C GAMs -f Makefile.gcc
$(MAKE) -C Interfaces -f Makefile.gcc
clean:
$(MAKE) -C DataSources -f Makefile.gcc clean
$(MAKE) -C GAMs -f Makefile.gcc clean
$(MAKE) -C Interfaces -f Makefile.gcc clean
.PHONY: all clean
+1
View File
@@ -0,0 +1 @@
# Components intermediate Makefile.inc