]> rtime.felk.cvut.cz Git - jenkicar/rpp-simulink.git/blob - rpp/rpp/rpp_mrmain.tlc
c93e9f4ba921430d8bebcfffc17cd0036cec1d1f
[jenkicar/rpp-simulink.git] / rpp / rpp / rpp_mrmain.tlc
1 %% Copyright (C) 2013-2015 Czech Technical University in Prague
2 %%
3 %% Authors:
4 %%     - Carlos Jenkins <carlos@jenkins.co.cr>
5 %%     - Michal Sojka <sojkam1@fel.cvut.cz>
6 %%     - Michal Horn <hornmich@fel.cvut.cz>
7 %%
8 %% This document contains proprietary information belonging to Czech
9 %% Technical University in Prague. Passing on and copying of this
10 %% document, and communication of its contents is not permitted
11 %% without prior written authorization.
12 %%
13 %% File : rpp_mrmain.tlc
14 %% Abstract:
15 %%     Custom TLC file to generate an RPP "main" file.
16 %%
17 %%     This file generates the "main" file for the RPP target on top of the RPP
18 %%     library and the FreeRTOS operating system.
19 %%
20 %%     The mr prefix is standard to mark Multi Tasking main, which is the case. See
21 %%     rpp_file_process.m description above for more information about this.
22 %%
23 %% References:
24 %%     Example in <matlabroot>/rtw/c/tlc/mw/bareboard_mrmain.tlc
25
26
27 %selectfile NULL_FILE
28
29 %function FcnMultiTaskingMain() void
30
31     %if GenerateSampleERTMain
32         %assign CompiledModel.GenerateSampleERTMain = TLC_FALSE
33     %endif
34
35
36     %assign cFile = LibCreateSourceFile("Source", "Custom", "ert_main")
37
38
39     %%%%%%%%
40     %openfile tmpBuf
41
42     /* Model includes */
43     #include "%<LibGetMdlPubHdrBaseName()>.h"
44
45     /* RPP runtime includes */
46     #include "rpp_simulink_runtime.h"
47
48     %if extMode == 1
49       /* External mode header file */
50       #include "ext_work.h"
51       #include <drv/sci.h>
52     %endif
53
54     %closefile tmpBuf
55     %<LibSetSourceFileSection(cFile, "Includes", tmpBuf)>
56     %%%%%%%%
57
58
59     %%%%%%%%
60     %openfile tmpBuf
61
62     /* Definitions */
63     #define STEP_SIZE_MILLIS (%<CompiledModel.FundamentalStepSize>*1000.0)
64     #define NUM_SAMPLE_TIMES    %<numSampleTimes>
65     #define CONTROL_PRIORITY (configMAX_PRIORITIES - 1)
66
67     %% Worker task priority assignment - rate transition block
68     %% requires rate monotonic priority assignment
69     %foreach i = numSampleTimes - tid01Eq
70         #define WORKING%<i + tid01Eq>_PRIORITY    (configMAX_PRIORITIES - %<2 + i>)
71     %endforeach
72
73     %if extMode == 1
74       #define EXTMODE_PRIORITY 1
75     %else
76       #define IDLE_PRIORITY 0
77       #define EXTMODE_PRIORITY IDLE_PRIORITY /* Extmode not used */
78     %endif
79
80     %foreach i = numSampleTimes - tid01Eq
81         %assign j = i + tid01Eq
82         #if (WORKING%<j>_PRIORITY <= EXTMODE_PRIORITY) || (WORKING%<j>_PRIORITY >= CONTROL_PRIORITY)
83         #error Too many tasks. Increase configMAX_PRIORITIES.
84         #endif
85     %endforeach
86
87     %closefile tmpBuf
88     %<LibSetSourceFileSection(cFile, "Defines", tmpBuf)>
89     %%%%%%%%
90
91
92     %%%%%%%%
93     %openfile tmpBuf
94     typedef struct sub_rate_st {
95         xTaskHandle      thread;
96         xSemaphoreHandle sem;
97     } sub_rate_t;
98
99     %if extMode == 1
100       static xSemaphoreHandle ext_mode_ready = NULL;
101     %endif
102     static uint32_t steps_control = 0;
103     static uint32_t steps_working[NUM_SAMPLE_TIMES];
104     boolean_t overrun_flag = FALSE;
105     static sub_rate_t sub_rate[NUM_SAMPLE_TIMES];
106     static boolean_t simulationFinished = 0;
107
108     %closefile tmpBuf
109     %<LibSetSourceFileSection(cFile, "Declarations", tmpBuf)>
110     %%%%%%%%
111
112
113     %%%%%%%%
114     %openfile tmpBuf
115
116     /**
117      * Model step control and overrun detection task.
118      */
119     void control_task(void* p)
120     {
121         uint32_t i;
122
123         %% Variables used by LibCallSetEventForThisBaseStep (static => zero initialized)
124         static uint32_t taskCounter[NUM_SAMPLE_TIMES];
125         static boolean_t eventFlags[NUM_SAMPLE_TIMES];
126         static boolean_t OverrunFlags[NUM_SAMPLE_TIMES];
127
128         (void)OverrunFlags; /* Not used in multitasking mode, but required by TLC macro */
129
130         steps_control = 0;
131       %if extMode == 1
132         xSemaphoreTake(ext_mode_ready, portMAX_DELAY);
133       %endif
134
135       static const portTickType freq_ticks = STEP_SIZE_MILLIS / portTICK_RATE_MS;
136       portTickType last_wake_time = xTaskGetTickCount();
137
138     %% This condition has been added because of the warning:
139     %% "ert_main.c", line 46: warning #238-D: controlling expression is constant
140     %% caused by the expression (void*) 0 passed to the while statement. The rtmGetStopRequested
141     %% macro is defined to this constant if and only if the GenerateSampleERTMain is not set. So
142     %% The condition is not needed in this case as well.
143     %%
144     %% See <MATLAB_ROOT>/rtw/c/tlc/mw/rtmspecmacs.tlc at line 198.
145
146     %if !GenerateSampleERTMain
147         while (rtmGetErrorStatus(%<modelName>_M) == NULL) {
148     %else
149         while (rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
150     %endif
151             /* Wait until next step */
152             vTaskDelayUntil(&last_wake_time, freq_ticks);
153
154             /* Check subrate overrun, set rates that need to run this time step*/
155             %<LibCallSetEventForThisBaseStep("eventFlags")>\
156
157             /* Trigger sub-rate threads */
158             %foreach j = numSampleTimes - tid01Eq
159                 %assign i = j + tid01Eq
160                 %assign s = CompiledModel.SampleTime[i].PeriodAndOffset[0]
161                 %assign o = CompiledModel.SampleTime[i].PeriodAndOffset[1]
162                 /* Sampling rate %<i>, sample time = %<s>, offset = %<o> */
163             %endforeach
164
165               for (i = %<tid01Eq>; i < NUM_SAMPLE_TIMES; i++) {
166                 if (i == 0 || eventFlags[i]) {
167                     eventFlags[i] = FALSE;
168                     uint32_t step_sem_value = uxQueueMessagesWaiting(sub_rate[i].sem);
169                     if (step_sem_value) {
170                         rtmSetErrorStatus(%<modelName>_M, "Overrun");
171                         overrun_flag = TRUE;
172                         break;
173                     }
174                     else {
175                         overrun_flag = FALSE;
176                     }
177                     if (xSemaphoreGive(sub_rate[i].sem) == pdFALSE) {
178                         rpp_sci_printk("ERROR: Task %d semaphore 1 give.\n", i);
179                         while (1) ;
180                     }
181                     if (xSemaphoreGive(sub_rate[i].sem) == pdFALSE) {
182                         rpp_sci_printk("ERROR: Task %d semaphore 2 give.\n", i);
183                         while (1) ;
184                     }
185                 }
186               }
187
188             steps_control++;
189
190             %if extMode == 1
191               rtExtModeCheckEndTrigger();
192             %endif
193
194         }
195         simulationFinished = 1;
196
197         /* Final step */
198         for (i = %<tid01Eq>; i < NUM_SAMPLE_TIMES; i++) {
199             xSemaphoreGive(sub_rate[i].sem);
200             xSemaphoreGive(sub_rate[i].sem);
201         }
202
203         /* In case of shutdown, delete this task */
204         vTaskDelete(NULL);
205     }
206
207     %foreach j = numSampleTimes - tid01Eq
208         %assign i = j + tid01Eq
209         /**
210          * Model step logic execution task for sample time %<CompiledModel.SampleTime[i].ClockTickStepSize>.
211          */
212         void working_task%<i>(void *p)
213         {
214             steps_working[%<i>] = 0;
215
216             while(!simulationFinished) {
217                 xSemaphoreTake(sub_rate[%<i>].sem, portMAX_DELAY); /* Sem_val = 1 */
218                 %<LibCallModelStep(i)>\
219                 steps_working[%<i>]++;
220                 xSemaphoreTake(sub_rate[%<i>].sem, portMAX_DELAY);  /* Sem_val = 0 */
221             }
222
223             %% /* In case of shutdown, delete this task */
224             vTaskDelete(NULL);
225         }
226     %endforeach
227
228     %if extMode == 1
229         void ext_mode_comm_task(void* p)
230         {
231             drv_sci_set_crlf_conv_en(FALSE); /* Disable CR->CRLF conversion */
232
233             %<SLibGenERTExtModeInit()>
234             xSemaphoreGive(ext_mode_ready);
235
236             while (rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
237                 rtExtModeOneStep(rtmGetRTWExtModeInfo(%<modelName>_M), %<numSampleTimes>, (boolean_T *)&rtmGetStopRequested(%<modelName>_M));
238             }
239             rtExtModeShutdown(%<numSampleTimes>);
240             /* In case of shutdown, delete this task */
241             vTaskDelete(NULL);
242         }
243     %endif
244
245     /**
246      * Hardware initialization, task spawning and OS scheduler start.
247      */
248     void main(void)
249     {
250         /* Initialize RPP board */
251          /* Initialize RPP board */
252         %if EXISTS(::rpp_ain_present)
253             rpp_adc_init();
254         %endif
255         %if EXISTS(::rpp_aout_present)
256             rpp_dac_init();
257         %endif
258         %if EXISTS(::rpp_din_present)
259             rpp_din_init();
260         %endif
261         %if EXISTS(::rpp_hbr_present)
262             rpp_hbr_init();
263         %endif
264         %if EXISTS(::rpp_irc_present)
265             rpp_irc_init();
266         %endif
267         %if EXISTS(::rpp_lout_present)
268             rpp_lout_init();
269         %endif
270         %if EXISTS(::rpp_mout_present)
271             rpp_mout_init();
272         %endif
273         %if EXISTS(::rpp_sdr_present)
274             rpp_sdr_init();
275         %endif
276         %if EXISTS(::rpp_gio_in_present) || EXISTS(::rpp_gio_out_present)
277             rpp_gio_init(RPP_GIO_PORT_ALL);
278         %endif
279         rpp_sci_init();
280
281         // Speed up the SCI
282         rpp_sci_setup(115200);
283
284         /* Initialize model */
285         %<LibCallModelInitialize()>\
286
287         %if rppPrintMeta
288             %assign model_info = SPRINTF("'%s' - %s (TLC %s)\\r\\n", LibGetMdlPubHdrBaseName(), TLC_TIME, TLC_VERSION)
289             rpp_sci_printk("%<model_info>");
290         %endif
291
292         %if extMode == 1
293           vSemaphoreCreateBinary(ext_mode_ready);
294           xSemaphoreTake(ext_mode_ready, 0);
295         %endif
296
297         %foreach j = numSampleTimes - tid01Eq
298             %assign i = j + tid01Eq
299             %assign s = CompiledModel.SampleTime[i].PeriodAndOffset[0]
300             %assign o = CompiledModel.SampleTime[i].PeriodAndOffset[1]
301
302             /* Initializing the step semaphore of the loop %<i> */
303             sub_rate[%<i>].sem = xSemaphoreCreateCounting(2, 0);
304             if (sub_rate[%<i>].sem == NULL) {
305                 rpp_sci_printk("ERROR: Can not create semaphore for task %<i>.\r\n");
306                 while (1) ;
307             }
308
309             /* Starting loop %<i> thread for sample time = %<s>s, offset = %<o>s. */
310             if (xTaskCreate(working_task%<i>,
311                             "working_task%<i>",
312                             %<rppModelTaskStack>,
313                             NULL,
314                             WORKING%<i>_PRIORITY,
315                             &sub_rate[%<i>].thread ) != pdPASS) {
316                 rpp_sci_printk("ERROR: Cannot spawn working task %<i>.\r\n");
317                 while (1);
318             }
319         %endforeach
320
321         /* Create tasks to step model and model task */
322
323         if (xTaskCreate(control_task,
324                         "control_task",
325                         %<rppModelTaskStack>,
326                         NULL,
327                         CONTROL_PRIORITY,
328                         NULL) != pdPASS) {
329             rpp_sci_printk("ERROR: Cannot spawn control task.\r\n");
330             while (1);
331         }
332
333         %if extMode == 1
334           /* External mode */
335           rtParseArgsForExtMode(0, NULL);
336
337           if (xTaskCreate(ext_mode_comm_task, "ext_mode_comm_task", 1024, NULL, EXTMODE_PRIORITY, NULL) != pdPASS) {
338             rpp_sci_printk("ERROR: Cannot spawn model task.\r\n");
339             while (1);
340           }
341         %endif
342
343         /* Start FreeRTOS Scheduler */
344         vTaskStartScheduler();
345
346         /* We should never get here */
347         %<LibCallModelTerminate()>\
348         rpp_sci_printk("ERROR: Problem allocating memory for idle task.\r\n");
349         while (1);
350     }
351
352
353     #if configUSE_MALLOC_FAILED_HOOK == 1
354     /**
355      * FreeRTOS malloc() failed hook.
356      */
357      void vApplicationMallocFailedHook(void) {
358        rpp_sci_printk("ERROR: Memory allocation failed.\r\n");
359        while (1);
360      }
361     #endif
362
363
364     #if configCHECK_FOR_STACK_OVERFLOW > 0
365     /**
366      * FreeRTOS stack overflow hook.
367      */
368     void vApplicationStackOverflowHook(xTaskHandle xTask, signed portCHAR *pcTaskName)
369     {
370       rpp_sci_printk("ERROR: Stack overflow : \"%s\".\r\n", pcTaskName);
371       while (1);
372     }
373     #endif
374
375     %closefile tmpBuf
376     %<LibSetSourceFileSection(cFile, "Functions", tmpBuf)>
377     %%%%%%%%
378
379 %endfunction