1 %% Copyright (C) 2013-2015 Czech Technical University in Prague
4 %% - Carlos Jenkins <carlos@jenkins.co.cr>
5 %% - Michal Sojka <sojkam1@fel.cvut.cz>
6 %% - Michal Horn <hornmich@fel.cvut.cz>
8 %% Permission is hereby granted, free of charge, to any person
9 %% obtaining a copy of this software and associated documentation
10 %% files (the "Software"), to deal in the Software without
11 %% restriction, including without limitation the rights to use,
12 %% copy, modify, merge, publish, distribute, sublicense, and/or sell
13 %% copies of the Software, and to permit persons to whom the
14 %% Software is furnished to do so, subject to the following
17 %% The above copyright notice and this permission notice shall be
18 %% included in all copies or substantial portions of the Software.
20 %% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 %% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
22 %% OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 %% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 %% HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25 %% WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 %% FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
27 %% OTHER DEALINGS IN THE SOFTWARE.
29 %% File : rpp_mrmain.tlc
31 %% Custom TLC file to generate an RPP "main" file.
33 %% This file generates the "main" file for the RPP target on top of the RPP
34 %% library and the FreeRTOS operating system.
36 %% The mr prefix is standard to mark Multi Tasking main, which is the case. See
37 %% rpp_file_process.m description above for more information about this.
40 %% Example in <matlabroot>/rtw/c/tlc/mw/bareboard_mrmain.tlc
45 %function FcnMultiTaskingMain() void
47 %if GenerateSampleERTMain
48 %assign CompiledModel.GenerateSampleERTMain = TLC_FALSE
51 %assign cFile = LibCreateSourceFile("Source", "Custom", "ert_main")
53 %if LibIsSingleTasking()
57 %assign taskCount = numSampleTimes - tid01Eq
58 %assign firstTask = tid01Eq
66 #include "%<LibGetMdlPubHdrBaseName()>.h"
68 /* RPP runtime includes */
69 #include "rpp_simulink_runtime.h"
72 /* External mode header file */
79 %<LibSetSourceFileSection(cFile, "Includes", tmpBuf)>
87 #define STEP_SIZE_MILLIS (%<CompiledModel.FundamentalStepSize>*1000.0)
88 #define NUM_TASKS %<taskCount>
89 #define CONTROL_PRIORITY (configMAX_PRIORITIES - 1)
91 %% Worker task priority assignment - rate transition block
92 %% requires rate monotonic priority assignment
93 %foreach i = taskCount
94 #define WORKING%<i + firstTask>_PRIORITY (configMAX_PRIORITIES - %<2 + i>)
98 #define EXTMODE_PRIORITY 1
100 #define IDLE_PRIORITY 0
101 #define EXTMODE_PRIORITY IDLE_PRIORITY /* Extmode not used */
104 %foreach i = taskCount
105 %assign j = i + firstTask
106 #if (WORKING%<j>_PRIORITY <= EXTMODE_PRIORITY) || (WORKING%<j>_PRIORITY >= CONTROL_PRIORITY)
107 #error Too many tasks. Increase configMAX_PRIORITIES.
112 %<LibSetSourceFileSection(cFile, "Defines", tmpBuf)>
118 typedef struct sub_rate_st {
120 xSemaphoreHandle sem;
124 static xSemaphoreHandle ext_mode_ready = NULL;
126 static uint32_t steps_control = 0;
127 static uint32_t steps_working[NUM_TASKS];
128 boolean_t overrun_flag = FALSE;
129 static sub_rate_t sub_rate[NUM_TASKS];
130 static boolean_t simulationFinished = 0;
133 %<LibSetSourceFileSection(cFile, "Declarations", tmpBuf)>
141 * Model step control and overrun detection task.
143 void control_task(void* p)
146 %if !LibIsSingleTasking()
149 %% Variables used by LibCallSetEventForThisBaseStep (static => zero initialized)
150 static uint32_t taskCounter[NUM_TASKS];
151 static boolean_t eventFlags[NUM_TASKS];
152 static boolean_t OverrunFlags[NUM_TASKS];
154 (void)OverrunFlags; /* Not used in multitasking mode, but required by TLC macro */
159 xSemaphoreTake(ext_mode_ready, portMAX_DELAY);
162 /* Initialize model */
163 %<LibCallModelInitialize()>\
165 /* Start periodic execution */
166 static const portTickType freq_ticks = STEP_SIZE_MILLIS / portTICK_RATE_MS;
167 portTickType last_wake_time = xTaskGetTickCount();
169 %% This condition has been added because of the warning:
170 %% "ert_main.c", line 46: warning #238-D: controlling expression is constant
171 %% caused by the expression (void*) 0 passed to the while statement. The rtmGetStopRequested
172 %% macro is defined to this constant if and only if the GenerateSampleERTMain is not set. So
173 %% The condition is not needed in this case as well.
175 %% See <MATLAB_ROOT>/rtw/c/tlc/mw/rtmspecmacs.tlc at line 198.
177 %if !GenerateSampleERTMain
178 while (rtmGetErrorStatus(%<modelName>_M) == NULL) {
180 while (rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
182 /* Wait until next step */
183 vTaskDelayUntil(&last_wake_time, freq_ticks);
185 %if !LibIsSingleTasking()
186 /* Mark rates that need to run this time step */
187 %<LibCallSetEventForThisBaseStep("eventFlags")>\
190 /* Trigger working threads */
191 %foreach j = taskCount
192 %assign i = j + firstTask
193 %assign s = CompiledModel.SampleTime[i].PeriodAndOffset[0]
194 %assign o = CompiledModel.SampleTime[i].PeriodAndOffset[1]
195 /* Sampling rate %<i>, sample time = %<s>, offset = %<o> */
198 %if LibIsSingleTasking()
202 for (%<i> = %<firstTask>; %<i> < NUM_TASKS; %<i>++) {
203 if (%<i> == 0 || eventFlags[%<i>]) {
204 eventFlags[%<i>] = FALSE;
206 uint32_t step_sem_value = uxQueueMessagesWaiting(sub_rate[%<i>].sem);
207 if (step_sem_value) {
208 %% Commented out so that overrun does stop the whole execution
209 %% rtmSetErrorStatus(%<modelName>_M, "Overrun");
213 xSemaphoreGive(sub_rate[%<i>].sem);
214 xSemaphoreGive(sub_rate[%<i>].sem);
215 %if !LibIsSingleTasking()
223 rtExtModeCheckEndTrigger();
227 simulationFinished = 1;
230 %if !LibIsSingleTasking()
231 for (%<i> = %<firstTask>; %<i> < NUM_TASKS; %<i>++) {
233 xSemaphoreGive(sub_rate[%<i>].sem);
234 xSemaphoreGive(sub_rate[%<i>].sem);
235 %if !LibIsSingleTasking()
239 /* In case of shutdown, delete this task */
243 %foreach j = taskCount
244 %assign i = j + firstTask
246 * Model step logic execution task for sample time %<CompiledModel.SampleTime[i].ClockTickStepSize>.
248 void working_task%<i>(void *p)
250 steps_working[%<i>] = 0;
252 while(!simulationFinished) {
253 xSemaphoreTake(sub_rate[%<i>].sem, portMAX_DELAY); /* Sem_val = 1 */
254 %<LibCallModelStep(i)>\
255 steps_working[%<i>]++;
256 xSemaphoreTake(sub_rate[%<i>].sem, portMAX_DELAY); /* Sem_val = 0 */
259 %% /* In case of shutdown, delete this task */
265 void ext_mode_comm_task(void* p)
267 drv_sci_set_crlf_conv_en(FALSE); /* Disable CR->CRLF conversion */
268 rtParseArgsForExtMode(0, NULL);
270 %<SLibGenERTExtModeInit()>
271 xSemaphoreGive(ext_mode_ready);
273 while (rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
274 rtExtModeOneStep(rtmGetRTWExtModeInfo(%<modelName>_M), %<numSampleTimes>, (boolean_T *)&rtmGetStopRequested(%<modelName>_M));
276 rtExtModeShutdown(%<numSampleTimes>);
277 /* In case of shutdown, delete this task */
283 * Hardware initialization, task spawning and OS scheduler start.
287 /* Initialize RPP board */
288 /* Initialize RPP board */
289 %if EXISTS(::rpp_ain_present)
292 %if EXISTS(::rpp_aout_present)
295 %if EXISTS(::rpp_din_present)
298 %if EXISTS(::rpp_hbr_present)
301 %if EXISTS(::rpp_irc_present)
304 %if EXISTS(::rpp_lout_present)
307 %if EXISTS(::rpp_mout_present)
310 %if EXISTS(::rpp_sdr_present)
313 %if EXISTS(::rpp_gio_in_present) || EXISTS(::rpp_gio_out_present)
314 rpp_gio_init(RPP_GIO_PORT_ALL);
323 rpp_sci_setup(115200);
326 %assign model_info = SPRINTF("'%s' - %s (TLC %s)\\r\\n", LibGetMdlPubHdrBaseName(), TLC_TIME, TLC_VERSION)
327 rpp_sci_printk("%<model_info>");
331 vSemaphoreCreateBinary(ext_mode_ready);
332 xSemaphoreTake(ext_mode_ready, 0);
335 %foreach j = taskCount
336 %assign i = j + firstTask
337 %assign s = CompiledModel.SampleTime[i].PeriodAndOffset[0]
338 %assign o = CompiledModel.SampleTime[i].PeriodAndOffset[1]
340 /* Initializing the step semaphore of the loop %<i> */
341 sub_rate[%<i>].sem = xSemaphoreCreateCounting(2, 0);
342 if (sub_rate[%<i>].sem == NULL) {
343 rpp_sci_printk("ERROR: Can not create semaphore for task %<i>.\r\n");
347 /* Starting loop %<i> thread for sample time = %<s>s, offset = %<o>s. */
348 if (xTaskCreate(working_task%<i>, "working_task%<i>",
349 %<rppModelTaskStack>, NULL, WORKING%<i>_PRIORITY,
350 &sub_rate[%<i>].thread ) != pdPASS) {
351 rpp_sci_printk("ERROR: Cannot spawn working task %<i>.\r\n");
356 /* Create tasks to step model and model task */
358 if (xTaskCreate(control_task, "control_task",
359 %<rppModelTaskStack>, NULL, CONTROL_PRIORITY,
361 rpp_sci_printk("ERROR: Cannot spawn control task.\r\n");
368 if (xTaskCreate(ext_mode_comm_task, "ext_mode_comm_task", 1024, NULL, EXTMODE_PRIORITY, NULL) != pdPASS) {
369 rpp_sci_printk("ERROR: Cannot spawn model task.\r\n");
374 /* Start FreeRTOS Scheduler */
375 vTaskStartScheduler();
377 /* We should never get here */
378 %<LibCallModelTerminate()>\
379 rpp_sci_printk("ERROR: Problem allocating memory for idle task.\r\n");
384 #if configUSE_MALLOC_FAILED_HOOK == 1
386 * FreeRTOS malloc() failed hook.
388 void vApplicationMallocFailedHook(void) {
389 rpp_sci_printk("ERROR: Memory allocation failed.\r\n");
395 #if configCHECK_FOR_STACK_OVERFLOW > 0
397 * FreeRTOS stack overflow hook.
399 void vApplicationStackOverflowHook(xTaskHandle xTask, signed portCHAR *pcTaskName)
401 rpp_sci_printk("ERROR: Stack overflow : \"%s\".\r\n", pcTaskName);
407 %<LibSetSourceFileSection(cFile, "Functions", tmpBuf)>