Run eTrice on a Custom Target
eTrice can be customized to run on a variety of targets, from high-level operating systems to bare-metal microcontrollers with limited resource. This document outlines the necessary changes to the eTrice runtime library.
To get started, you need the minimal eTrice setup with an application project (e.g. org.eclipse.etrice.template.c) and the runtime library org.eclipse.etrice.runtime.c. If you have finished one of the Getting Started, then you are already set up.
To run eTrice on your OS and microcontroller, you can follow these steps
- Call eTrice main function
- Provide a OSAL implementation
- Configure logging
In this document you will also find two examples for an embedded system
- Single-threaded bare metal without OS
- Multi-threaded with FreeRTOS
The Main Function
By default, the eTrice generated code contains the standard C main function. Therefore, an eTrice desktop application for Windows or Linux compiles to an executable out-of-the-box.
For embedded targets which already define the main function, you can call the eTrice function manually. The function signature can be configured with ET_MAIN_FUNCTION_NAME
and ET_DO_NOT_USE_ARGC_ARGV
, the former sets the function name and the letter turns it parameterless. Both defines can be found in the etRuntimeConfig.h at org.eclipse.etrice.runtime.c/src/runtime/. Here is an example how to start an eTrice application manually.
First, configure the eTrice function name to etStart(void)
in etRuntimeConfig.h
/* main function */
/** sets generated main function name, default is 'main' */
#define ET_MAIN_FUNCTION_NAME etStart
/** switches generated main function parameters to (void) */
#define ET_DO_NOT_USE_ARGC_ARGV
The eTrice function can be found in the generated source file node_*_Runner.c
. Call this function to start the eTrice application.
extern int etStart(void);
int main(void) {
/* startup, e.g. HAL init*/
etStart();
/* application exit */
}
OSAL Implementation
The second step is to adapt the eTrice runtime to your target. The runtime is based on an OS abstraction layer (OSAL), which is a set of header files in src/common/osal/ in project org.eclipse.etrice.runtime.c. The structure is shown in the screenshot right-handed.
The remaining documentation will focus on these four built-in OSAL variants:
System | OS / Compiler | Threading | eTrice Implementation |
---|---|---|---|
Desktop | Windows MinGW | Multi | MT_WIN_MINGW |
Desktop / Embedded | Linux/POSIX GCC | Multi | MT_POSIX_GENERIC_GCC |
Embedded | FreeRTOS | Multi | MT_32Bit_FreeRTOS_Generic |
Embedded | None - Bare Metal | Single | ST_32Bit_Generic |
All available OSAL implementations can be found in src/platforms/. The subfolders have a naming convention to describe the platform characteristics like threading type or MCU name (see readme.txt in src/platforms) as well.
The first two variants can be used to run your eTrice application on a desktop PC. You might use these platforms to rapid prototype the application layer for an eTrice embedded system. The POSIX variant can be adapted for embedded (Linux) systems.
For embedded systems, there are two implementation. First, a multithreaded application with FreeRTOS and second, a single-threaded bare metal system without OS. For both platforms, most of the required interfaces are already implemented. But there are some microcontroller specific functions that still need to be provided (e.g. target time). For concrete examples, you can have a look in the subfolder "examples/".
The eTrice OSAL
This section provides a brief description for the header files in src/common/osal/ project org.eclipse.etrice.runtime.c.
- etPlatformLifecycle.h
When the eTrice system is started, the generated code takes control of the main thread. The life cycle functions are hooks to customize the execution. The most important function isetUserMainRun(argc, argv)
, which is executed while the state machines are running. Here you can call the OS schedular or if bare metal perform basic tasks. In addition, there are more life cycle hooks available. You can look at the User Code Life Cycle to see when the functions are called in the eTrice application. - etTime.h
ThegetTimeFromTarget(etTime *t)
function provides the current time for the eTrice system. The time is necessary to schedule timer on a regular basis. Therefore, the implementation should be reasonable fast. Further, the resolution (e.g. 1ms or 5us) should satisfy the timing accuracy of your application. The time must not be necessarily absolute, it can be relative to the system starting point, but always incrementing. - etTimer.h
TheetTimer
triggers OS-timers, e.g. used for polled execution. - etThread.h
TheetThread
provides the threading to execute the state machines concurrently. An eTrice system has at least oneetThread
instance. In a multithreaded system, the threads are started asynchronously from the main thread. In a single-threaded system, the onlyetThread
instance must be called from the main thread (etUserMainRun
). - etSema.h
This interface provides a signal mechanism foretThread
. UsuallyetSema
wraps the semaphore provided by the OS. Required for multithreaded systems. - etMutex.h
Used for resource locking, mostly to protect data structures from race-conditions. Required for multithreaded systems. - etDatatypes.h
Defines the typedefs and data structured needed for the OSAL implementation. - etLogger.h (*)
Implements the optional logging infrastructure. The most simple implementation is to callprintf
. This topic is explained with more details in Logging Configuration.
Logging Configuration
eTrice comes with two built-in loggers
- textual logger
- sequence message chart (MSC) trace logger
Both can be deactivated by its switches in the etRuntimeConfig.h.
// requires printable stream
#define ET_LOGGER_ACTIVATE
// not suited for small/real-time embedded targets
#undef ET_MSC_LOGGER_ACTIVATE
The logging is optional and can be deactivated to get started. The MSC logger instruments the generated code with the cost of memory and performance. Therefore, it is usually not suited for embedded targets.
In order to be functional, the logging interface osal/etLogger.h
must be implemented.
Examples Embedded Platform
Single-threaded Bare Metal
The ST_32bit_Generic platform is a simple generic implementation for microcontrollers without operating system and threading. To get started, you have to provide an implementation for the target time.
- etTime.h
Implement thegetTimeFromTarget(etTime *t)
function based on the microcontroller timing mechanism, e.g. compute the time based on the HAL Clock or SysTick. You can find concrete implementations in theexamples/
subfolder. - The remaining OSAL functions are not required and implemented empty
- etThread.h
No modifications needed. At start, the pointer to the single instance ofetThread
is saved. - etPlatformLifeCycle.h
TheetUserMainRun(argc, argv)
function calls thread function of singleetThread
instance. As a result, the eTrice Actors and State Machines are executed on the main thread. The flow is described in the diagram below. - etTimer.h
No modifications needed. Whenever the execution is idle, the pending timers and timeouts are scheduled (etCheckSinglethreadedTimers
).
Multi-threaded with OS
The MT_32bit_FreeRTOS_Generic platform is a generic implementation for an embedded system with FreeRTOS. It should be possible to get started without or only minor adjustments. Anyway, be sure to implement the required FreeRTOS hooks for your microcontroller.
- The OSAL functions are delegating to FreeRTOS
- etPlatformLifecycle.h
TheetUserMainRun(argc, argv)
function calls the FreeRTOS scheduler. At this point, the eTrice system is running. The flow is described in the diagram below.
User Code Life Cycle
In the eTrice application, you can insert custom code and hooks
- Runtime hooks
etUserEntry
andetUserMainRun(argc, argv)
in etPlatformLifeCycle.h - Model user code ctor in ActorClasses
- Model user code action in StateMachine transitions
- Model user codes entry, exit and do in StateMachine states
The following diagram shows the eTrice application life cycle including when and in which order the different codes are called.