Interested in this topic? ETAS Inc. is holding a two-day workshop that will further explore this subject. Learn more and register here.
Have you ever wondered how you can bring all steps of model-based design together in one development environment? Model creation, starting a PC experiment and finally building the generated code for an embedded device can all be accomplished in the Eclipse environment of ETAS ASCET-DEVELOPER. This blog explains how it’s done. (If you have never heard of ASCET-DEVELOPER, you may want to check out our ASCET-DEVELOPER page on www.etas.com.)
In this example we will create an ASCET project which can be used for both PC experimentation as well as for flashing and running the generated code on an Aurix board (TriCore from Infineon). The ASCET model itself remains unchanged. To demonstrate the workflow, we use the state machine example from the ASCET tutorial for controlling a traffic light. The ECU example is running on an Infineon TriCore board, using the open source real-time OS Erika, the code framework BIFACES from Infineon, the HighTec build tool chain and the Universal Debug Engine (UDE®) from PLS for flashing and debugging the program.
The same generated code runs on a TriCore board and in the PC experiment:
Prepare the ASCET Model with a Generic Interface
We start in our example with the state machine ‘LightControl’ from the ASCET tutorial.
In the graphical part of the state machine we just replace the I/O commands (e.g. red = false) by function calls (e.g. setLight(red, false)) which will later also be used as interface to the real hardware.
The part of the normal mode looks now like this:
In the ESDL code for the state machine we add the respective code for the interface:
… representation EnumRep { datatype = sint8; } type LightColor is enum { Red = 0, Yellow = 1, Green = 2 } using EnumRep; class LightControl { Timer localTimer; Timer errorTimer; @set private boolean error = false; @get private boolean greenOn = false; @get private boolean redOn = false; @get private boolean yellowOn = false; characteristic real GreenTime = 3.0; characteristic real RedTime = 6.0; characteristic real YellowTime = 1.5; characteristic real RedYellowTime = 1.0; characteristic real BlinkTime = 0.5; private const LightColor red = LightColor.Red; private const LightColor yellow = LightColor.Yellow; private const LightColor green = LightColor.Green; @no_side_effect public LightsStatemachineStates currentState() { return LightsStatemachine.getState(); } public void setLight(LightColor color, boolean bright) { integer numLED = 0; switch (color) { case LightColor.Red : { numLED = 0; redOn = bright; } case LightColor.Yellow : { numLED = 1; yellowOn = bright; } case LightColor.Green : { numLED = 2; greenOn = bright; } } if (bright) { LED.setLED(numLED, 1); } else { LED.setLED(numLED, 0); } } @generated("statemachine") …
LED is realized as an ESDL class which in turn will call c code.
LED.esdl:
package controller; representation c_unsigned_char { datatype = uint8; } type c_uint8 is integer 0 .. 255 using c_unsigned_char; static class LED { @symbol("setLED") @c_code extern public void setLED(c_uint8 numLED, c_uint8 bright); }
This means that we now need two different pairs of C code files (setLED.c and setLED.h) for the PC experiment build and the build for the TriCore, respectively.
For the ASCET experiment we put the code into a subfolder of our ASCET project, e.g. LightControl\additionalSrc.
In case of the PC experiment the c code needs to be there but in our example does not have to do anything:
setLED.c:
#include "setLED.h" void setLED(uint8 numLED, uint8 bright) { }
setLED.h:
#include "esdl_types.h" extern void setLED(uint8 numLED, uint8 bright);
Then we add a make file (build_settings.mk) to take care of the additional compile for the build and add the respective commands, e.g. with our current folder structure:
## DEFINE A LIST (space separated) OF ADDITIONAL INCLUDE PATHS AdditionalIncPath=$(ExternalCodeProjPath)/include ## DEFINE A LIST (space separated) OF ADDITIONAL C SOURCE FILES TO COMPILE AND LINK THEM AdditionalSrcFiles=$(ExternalCodeProjPath)/src/LED.c
Finally our structure of the project looks like this:
PC Experimentation
The ASCET-PC experiment can be used the same way as before:
Use Infineon’s BIFACES Framework Together with ASCET
Exchange Eclipse Folder with ASCET folder
The BIFACES framework is independent from the Eclipse version and works with the complete installed ASCET features together. We just replace the standard eclipse version which is delivered with BIFACES by the complete ASCET directory:
Adapt the StartBifaces.bat file
Instead of eclipse.exe we now want to start ASCET.exe, so we change the file SartBifaces.bat to match the path:
@SET BINUTILS_PATH=C:\ETAS\BIFACES_ASCET\bin @SET MAKECMD_WITH_APP=C:\ETAS\BIFACES_ASCET\ASCET7\ASCET.exe ::----------------------------------------------------- @SET PATH=%BINUTILS_PATH%;%PATH% @START %MAKECMD_WITH_APP% @EXIT
Start with the Standard ERIKA Example for BIFACES
Follow the instructions of the Infineon’s pdf manual “ERIKA_OS_Integration.pdf” to get a basic code framework for your TriCore board including a setup for the ERIKA OS.
Adaptations to the Code Framework
Renaming os.h file to osek.h
The standard naming of Erika/Infineon’s header operating system’s header file is os.h whereas the one from ASCET is called osek.h. The easiest way is to rename the one from the framework and adapt the reference in
Adapt the OIL File
In our case we just reuse the 10ms example and call it Task0. Changes in the file …\1_ToolEnv\0_Build\1_Config\CfgErikaOS.oil:
… APPMODE TRICORE_CPU { TASK = Task0; }; … TASK Task0{ PRIORITY = 16; ACTIVATION = 1; AUTOSTART = FALSE; SCHEDULE = FULL; STACK = SHARED; }; … ALARM Task0_ALARM { ACTION = ACTIVATETASK { TASK = Task0; }; COUNTER = IFX_OSTASK_COUNTER; AUTOSTART = TRUE { APPMODE = TRICORE_CPU; ALARMTIME = 50; CYCLETIME = 100; }; };
Add the I/O Target Code
The setLED.c and setLED.h files need to be in the folder structure for the source code of the framework, e.g. … \LightControl_TC297TF\0_Src\BaseSw\IO
As an example of the TC297TF we may use the following code:
setLED.c:
#include "setLED.h" void setLED(uint8 numLED, uint8 bright) { IfxPort_setPinState(&MODULE_P13, numLED, bright ? IfxPort_State_low : IfxPort_State_high); }
setLED.h:
#include "IfxStm.h" extern void setLED(uint8 numLED, uint8 bright);
Create the ASCET folder
Create the folder \0_Src\AppSw\ASCET
ASCET’s code generator will fill the subfolders include, lib and src.
Add the Hardware Initialization Code
If there is code which initializes the hardware I/O of the board, this can be done in the init task which is already defined in the OSTasks.c file and can be extended respectively. In our example we may initialize the LED ports as follows:
TASK(IFX_OSTASK_INIT) { __enable(); /*Add your initialization code here*/ P13_OUT.B.P0 = 1; IfxPort_setPinMode(&MODULE_P13, 0, IfxPort_Mode_outputPushPullGeneral); P13_OUT.B.P1 = 1; IfxPort_setPinMode(&MODULE_P13, 1, IfxPort_Mode_outputPushPullGeneral); P13_OUT.B.P2 = 1; IfxPort_setPinMode(&MODULE_P13, 2, IfxPort_Mode_outputPushPullGeneral); P13_OUT.B.P3 = 1; IfxPort_setPinMode(&MODULE_P13, 3, IfxPort_Mode_outputPushPullGeneral); ActivateTask(IFX_OSTASK_BACKGROUND); Ifx_OSTask_initStm0Ticks (); TerminateTask(); }
Add the Defines to the Make file
In Config_Gnuc.mk we extend the compiler flags to:
B_GNUC_TRICORE_CC_OPTIONS= -mtc161 -g -O2 -fno-common -fstrict-volatile-bitfields \ -ffunction-sections -fdata-sections -Wall -std=c99 \ -DASCET_PLATFORM_BUILD -DASCET_DELTA_T_SUPPORT=ASCET_DELTA_T_STATIC
Build the Code for the ECU
ASCET Code Generation for ECU
In ASCET’s Project Explorer select the application (LightControlTest.app). In the context menu we select Run_As / Run Configurations…
Here we can create a new configuration ‘LightControlTest_ECU’
In the Main tab we change the output to let ASCET generate the code into the prepared BIFACES framework code:
Finally we check in the OS tab the OSEK option:
Run starts the generation process and in the Console tab of ASCET we see if it was successful:
[INFO] [10:29:14.792] Output folder: E:\ETASData\Ascet_DemoTri\LightControl_TC297TF\0_Src\AppSw\ASCET [INFO] [10:29:14.795] Finished successfully ECU code generation (took: 2,927 s)
Build Target Code with BIFACES
From the context menu of our ECU project (LightControl_TC297TF) we select build in order to trigger BIFACES’ build process. Again we will see the result in the Console pane:
Building output 2_Out/Tricore_Gnuc/LightControl_TC297TF_tc.elf Building output 2_Out/Tricore_Gnuc/LightControl_TC297TF_tc.hex 10:33:12 Build Finished (took 21s.807ms)
Run the ECU code
You may use one of the common debuggers to flash and run the program, e.g. PLS’ Universal Debug Engine (UDE®):
After ‘Program All’ you should get a confirmation that programming was successful:
We can now exit the ‘Memtool’ and ‘Programming Tool’ windows and start debugging, with F5:
Switching on and off the LEDs of our board simulates our traffic light control.
Feedback or Questions?
This procedure should definitely make your life as a developer easier. What do you think? Please write your feedback and questions in the comments below. I look forward to hearing from you.
Interesting. If I wanted to try this out, what exactly do I need to get started?
Hi Kevin, when you purchase the Aurix board it comes with a starter kit. Other than that, you just need ASCET-DEVELOPER. If you’d like to try it out, we can give you an evaluation license for ASCET-DEVELOPER.