]> rtime.felk.cvut.cz Git - pes-rpp/rpp-simulink.git/blob - rpp/rpp/rpp_mrmain.tlc
Change license to MIT
[pes-rpp/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 %% 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
15 %% conditions:
16
17 %% The above copyright notice and this permission notice shall be
18 %% included in all copies or substantial portions of the Software.
19
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.
28 %%
29 %% File : rpp_mrmain.tlc
30 %% Abstract:
31 %%     Custom TLC file to generate an RPP "main" file.
32 %%
33 %%     This file generates the "main" file for the RPP target on top of the RPP
34 %%     library and the FreeRTOS operating system.
35 %%
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.
38 %%
39 %% References:
40 %%     Example in <matlabroot>/rtw/c/tlc/mw/bareboard_mrmain.tlc
41
42
43 %selectfile NULL_FILE
44
45 %function FcnMultiTaskingMain() void
46
47     %if GenerateSampleERTMain
48         %assign CompiledModel.GenerateSampleERTMain = TLC_FALSE
49     %endif
50
51     %assign cFile = LibCreateSourceFile("Source", "Custom", "ert_main")
52
53     %if LibIsSingleTasking()
54       %assign taskCount = 1
55       %assign firstTask = 0
56     %else
57       %assign taskCount = numSampleTimes - tid01Eq
58       %assign firstTask = tid01Eq
59     %endif
60
61
62     %%%%%%%%
63     %openfile tmpBuf
64
65     /* Model includes */
66     #include "%<LibGetMdlPubHdrBaseName()>.h"
67
68     /* RPP runtime includes */
69     #include "rpp_simulink_runtime.h"
70
71     %if extMode == 1
72       /* External mode header file */
73       #include "ext_work.h"
74       #include <drv/sci.h>
75       #include <drv/emac.h>
76     %endif
77
78     %closefile tmpBuf
79     %<LibSetSourceFileSection(cFile, "Includes", tmpBuf)>
80     %%%%%%%%
81
82
83     %%%%%%%%
84     %openfile tmpBuf
85
86     /* Definitions */
87     #define STEP_SIZE_MILLIS (%<CompiledModel.FundamentalStepSize>*1000.0)
88     #define NUM_TASKS    %<taskCount>
89     #define CONTROL_PRIORITY (configMAX_PRIORITIES - 1)
90
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>)
95     %endforeach
96
97     %if extMode == 1
98       #define EXTMODE_PRIORITY 1
99     %else
100       #define IDLE_PRIORITY 0
101       #define EXTMODE_PRIORITY IDLE_PRIORITY /* Extmode not used */
102     %endif
103
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.
108         #endif
109     %endforeach
110
111     %closefile tmpBuf
112     %<LibSetSourceFileSection(cFile, "Defines", tmpBuf)>
113     %%%%%%%%
114
115
116     %%%%%%%%
117     %openfile tmpBuf
118     typedef struct sub_rate_st {
119         xTaskHandle      thread;
120         xSemaphoreHandle sem;
121     } sub_rate_t;
122
123     %if extMode == 1
124       static xSemaphoreHandle ext_mode_ready = NULL;
125     %endif
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;
131
132     %closefile tmpBuf
133     %<LibSetSourceFileSection(cFile, "Declarations", tmpBuf)>
134     %%%%%%%%
135
136
137     %%%%%%%%
138     %openfile tmpBuf
139
140     /**
141      * Model step control and overrun detection task.
142      */
143     void control_task(void* p)
144     {
145
146         %if !LibIsSingleTasking()
147           uint32_t i = 0;
148
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];
153
154           (void)OverrunFlags; /* Not used in multitasking mode, but required by TLC macro */
155         %endif
156
157         steps_control = 0;
158       %if extMode == 1
159         xSemaphoreTake(ext_mode_ready, portMAX_DELAY);
160       %endif
161
162       /* Initialize model */
163       %<LibCallModelInitialize()>\
164
165       /* Start periodic execution */
166       static const portTickType freq_ticks = STEP_SIZE_MILLIS / portTICK_RATE_MS;
167       portTickType last_wake_time = xTaskGetTickCount();
168
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.
174     %%
175     %% See <MATLAB_ROOT>/rtw/c/tlc/mw/rtmspecmacs.tlc at line 198.
176
177     %if !GenerateSampleERTMain
178         while (rtmGetErrorStatus(%<modelName>_M) == NULL) {
179     %else
180         while (rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
181     %endif
182             /* Wait until next step */
183             vTaskDelayUntil(&last_wake_time, freq_ticks);
184
185             %if !LibIsSingleTasking()
186               /* Mark rates that need to run this time step */
187               %<LibCallSetEventForThisBaseStep("eventFlags")>\
188             %endif
189
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> */
196             %endforeach
197
198             %if LibIsSingleTasking()
199               %assign i = "0"
200             %else
201               %assign i = "i"
202               for (%<i> = %<firstTask>; %<i> < NUM_TASKS; %<i>++) {
203                   if (%<i> == 0 || eventFlags[%<i>]) {
204                     eventFlags[%<i>] = FALSE;
205                 %endif
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");
210                         overrun_flag = TRUE;
211                         continue;
212                     }
213                     xSemaphoreGive(sub_rate[%<i>].sem);
214                     xSemaphoreGive(sub_rate[%<i>].sem);
215                 %if !LibIsSingleTasking()
216                 }
217               }
218             %endif
219
220             steps_control++;
221
222             %if extMode == 1
223               rtExtModeCheckEndTrigger();
224             %endif
225
226         }
227         simulationFinished = 1;
228
229         /* Final step */
230         %if !LibIsSingleTasking()
231         for (%<i> = %<firstTask>; %<i> < NUM_TASKS; %<i>++) {
232         %endif
233             xSemaphoreGive(sub_rate[%<i>].sem);
234             xSemaphoreGive(sub_rate[%<i>].sem);
235         %if !LibIsSingleTasking()
236         }
237         %endif
238
239         /* In case of shutdown, delete this task */
240         vTaskDelete(NULL);
241     }
242
243     %foreach j = taskCount
244         %assign i = j + firstTask
245         /**
246          * Model step logic execution task for sample time %<CompiledModel.SampleTime[i].ClockTickStepSize>.
247          */
248         void working_task%<i>(void *p)
249         {
250             steps_working[%<i>] = 0;
251
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 */
257             }
258
259             %% /* In case of shutdown, delete this task */
260             vTaskDelete(NULL);
261         }
262     %endforeach
263
264     %if extMode == 1
265         void ext_mode_comm_task(void* p)
266         {
267             drv_sci_set_crlf_conv_en(FALSE); /* Disable CR->CRLF conversion */
268             rtParseArgsForExtMode(0, NULL);
269
270             %<SLibGenERTExtModeInit()>
271             xSemaphoreGive(ext_mode_ready);
272
273             while (rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
274                 rtExtModeOneStep(rtmGetRTWExtModeInfo(%<modelName>_M), %<numSampleTimes>, (boolean_T *)&rtmGetStopRequested(%<modelName>_M));
275             }
276             rtExtModeShutdown(%<numSampleTimes>);
277             /* In case of shutdown, delete this task */
278             vTaskDelete(NULL);
279         }
280     %endif
281
282     /**
283      * Hardware initialization, task spawning and OS scheduler start.
284      */
285     void main(void)
286     {
287         /* Initialize RPP board */
288          /* Initialize RPP board */
289         %if EXISTS(::rpp_ain_present)
290             rpp_adc_init();
291         %endif
292         %if EXISTS(::rpp_aout_present)
293             rpp_dac_init();
294         %endif
295         %if EXISTS(::rpp_din_present)
296             rpp_din_init();
297         %endif
298         %if EXISTS(::rpp_hbr_present)
299             rpp_hbr_init();
300         %endif
301         %if EXISTS(::rpp_irc_present)
302             rpp_irc_init();
303         %endif
304         %if EXISTS(::rpp_lout_present)
305             rpp_lout_init();
306         %endif
307         %if EXISTS(::rpp_mout_present)
308             rpp_mout_init();
309         %endif
310         %if EXISTS(::rpp_sdr_present)
311             rpp_sdr_init();
312         %endif
313         %if EXISTS(::rpp_gio_in_present) || EXISTS(::rpp_gio_out_present)
314             rpp_gio_init(RPP_GIO_PORT_ALL);
315         %endif
316         rpp_sci_init();
317
318         %if extMode == 1
319             rpp_eth_init();
320         %endif
321         
322         // Speed up the SCI
323         rpp_sci_setup(115200);
324
325         %if rppPrintMeta
326             %assign model_info = SPRINTF("'%s' - %s (TLC %s)\\r\\n", LibGetMdlPubHdrBaseName(), TLC_TIME, TLC_VERSION)
327             rpp_sci_printk("%<model_info>");
328         %endif
329  
330         %if extMode == 1
331           vSemaphoreCreateBinary(ext_mode_ready);
332           xSemaphoreTake(ext_mode_ready, 0);
333         %endif
334
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]
339
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");
344                 while (1) ;
345             }
346
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");
352                 while (1);
353             }
354         %endforeach
355
356         /* Create tasks to step model and model task */
357
358         if (xTaskCreate(control_task, "control_task",
359                         %<rppModelTaskStack>, NULL, CONTROL_PRIORITY,
360                         NULL) != pdPASS) {
361             rpp_sci_printk("ERROR: Cannot spawn control task.\r\n");
362             while (1);
363         }
364
365         %if extMode == 1
366           /* External mode */
367
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");
370             while (1);
371           }
372         %endif
373
374         /* Start FreeRTOS Scheduler */
375         vTaskStartScheduler();
376
377         /* We should never get here */
378         %<LibCallModelTerminate()>\
379         rpp_sci_printk("ERROR: Problem allocating memory for idle task.\r\n");
380         while (1);
381     }
382
383
384     #if configUSE_MALLOC_FAILED_HOOK == 1
385     /**
386      * FreeRTOS malloc() failed hook.
387      */
388      void vApplicationMallocFailedHook(void) {
389        rpp_sci_printk("ERROR: Memory allocation failed.\r\n");
390        while (1);
391      }
392     #endif
393
394
395     #if configCHECK_FOR_STACK_OVERFLOW > 0
396     /**
397      * FreeRTOS stack overflow hook.
398      */
399     void vApplicationStackOverflowHook(xTaskHandle xTask, signed portCHAR *pcTaskName)
400     {
401       rpp_sci_printk("ERROR: Stack overflow : \"%s\".\r\n", pcTaskName);
402       while (1);
403     }
404     #endif
405
406     %closefile tmpBuf
407     %<LibSetSourceFileSection(cFile, "Functions", tmpBuf)>
408     %%%%%%%%
409
410 %endfunction