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