]> rtime.felk.cvut.cz Git - jenkicar/rpp-simulink.git/blob - rpp/rpp/rpp_srmain.tlc
Add support for multirate singlethread models
[jenkicar/rpp-simulink.git] / rpp / rpp / rpp_srmain.tlc
1 %% Copyright (C) 2013-2014 Czech Technical University in Prague
2 %%
3 %% Authors:
4 %%     - Carlos Jenkins <carlos@jenkins.co.cr>
5 %%     - Michal Sojka <sojkam1@fel.cvut.cz>
6 %%
7 %% This document contains proprietary information belonging to Czech
8 %% Technical University in Prague. Passing on and copying of this
9 %% document, and communication of its contents is not permitted
10 %% without prior written authorization.
11 %%
12 %% File : rpp_srmain.tlc
13 %% Abstract:
14 %%     Custom TLC file to generate an RPP "main" file.
15 %%
16 %%     This file generates the "main" file for the RPP target on top of the RPP
17 %%     library and the FreeRTOS operating system.
18 %%
19 %%     The sr prefix is standard to mark Single Tasking main, which is the case. See 
20 %%     rpp_file_process.m description above for more information about this.
21 %%
22 %% References:
23 %%     Example in <matlabroot>/rtw/c/tlc/mw/bareboard_srmain.tlc
24
25
26 %selectfile NULL_FILE
27
28 %function FcnSingleTaskingMain() void
29
30     %if GenerateSampleERTMain
31         %assign CompiledModel.GenerateSampleERTMain = TLC_FALSE
32     %endif
33
34
35     %assign cFile = LibCreateSourceFile("Source", "Custom", "ert_main")
36
37
38     %%%%%%%%
39     %openfile tmpBuf
40
41     /* Model includes */
42     #include "%<LibGetMdlPubHdrBaseName()>.h"
43
44     /* RPP runtime includes */
45     #include "rpp_simulink_runtime.h"
46
47     %if extMode == 1
48       /* External mode header file */
49       #include "ext_work.h"
50       #include <drv/sci.h>
51     %endif
52
53     %closefile tmpBuf
54     %<LibSetSourceFileSection(cFile, "Includes", tmpBuf)>
55     %%%%%%%%
56
57
58     %%%%%%%%
59     %openfile tmpBuf
60
61     /* Definitions */
62     #define STEP_SIZE_MILLIS %<CompiledModel.FundamentalStepSize>*1000.0
63     #define CONTROL_PRIORITY 3
64     #define WORKING_PRIORITY 2
65     #define EXTMODE_PRIORITY 1
66
67     %closefile tmpBuf
68     %<LibSetSourceFileSection(cFile, "Defines", tmpBuf)>
69     %%%%%%%%
70
71
72     %%%%%%%%
73     %openfile tmpBuf
74
75     static boolean_t working = FALSE;
76     static xSemaphoreHandle step_signal = NULL;
77     static xSemaphoreHandle initialized_signal = NULL;
78     %if extMode == 1
79       static xSemaphoreHandle ext_mode_ready = NULL;
80     %endif
81     static uint32_t steps_control = 0;
82     static uint32_t steps_working = 0;
83     boolean_t overrun_flag = FALSE;
84
85     %closefile tmpBuf
86     %<LibSetSourceFileSection(cFile, "Declarations", tmpBuf)>
87     %%%%%%%%
88
89
90     %%%%%%%%
91     %openfile tmpBuf
92
93     /**
94      * Model step control and overrun detection task.
95      */
96     void control_task(void* p)
97     {
98
99       xSemaphoreTake(initialized_signal, portMAX_DELAY);
100       %if extMode == 1
101         xSemaphoreTake(ext_mode_ready, portMAX_DELAY);
102       %endif
103
104         static const portTickType freq_ticks = STEP_SIZE_MILLIS / portTICK_RATE_MS;
105         portTickType last_wake_time = xTaskGetTickCount();
106
107     %% This condition has been added because of the warning:
108     %% "ert_main.c", line 46: warning #238-D: controlling expression is constant
109     %% caused by the expression (void*) 0 passed to the while statement. The rtmGetStopRequested
110     %% macro is defined to this constant if and only if the GenerateSampleERTMain is not set. So
111     %% The condition is not needed in this case as well.
112     %%
113     %% See <MATLAB_ROOT>/rtw/c/tlc/mw/rtmspecmacs.tlc at line 198.
114
115     %if !GenerateSampleERTMain
116         while (rtmGetErrorStatus(%<modelName>_M) == NULL) {
117     %else
118         while (rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
119     %endif
120             /* Wait until next step */
121             vTaskDelayUntil(&last_wake_time, freq_ticks);
122
123             if (working) {
124                 /* Overrun detected */
125                 overrun_flag = TRUE;
126             } else {
127                 overrun_flag = FALSE;
128                 /* Release semaphore */
129                 xSemaphoreGive(step_signal);
130             }
131             steps_control++;
132
133             %if extMode == 1
134               rtExtModeCheckEndTrigger();
135             %endif
136
137         }
138
139         /* In case of shutdown, delete this task */
140         vTaskDelete(NULL);
141     }
142
143     /**
144      * Model step logic execution task.
145      */
146     void working_task(void* p)
147     {
148         /* Initialize model */
149         %<LibCallModelInitialize()>\
150         /* Step the model for any subrate */
151         xSemaphoreGive(initialized_signal);
152         %foreach idx = LibGetNumSyncPeriodicTasks()
153         %assign tid = idx + tid01Eq
154         %assign sampleTime = LibGetSampleTimePeriodAndOffset(tid,0)
155         %assign steps = FEVAL("round", sampleTime / CompiledModel.FundamentalStepSize)
156         #define STEPS_FOR_TID%<tid>   ((int)%<steps>)
157         %endforeach
158
159         while (1) {
160
161             /* Lock semaphore */
162             if (xSemaphoreTake(step_signal, portMAX_DELAY)) {
163                 working = TRUE;
164                 %if LibNumSynchronousSampleTimes() > 1
165                                 int i;
166                         for (i = %<tid01Eq>; i < %<LibNumSynchronousSampleTimes()>; i++) {
167                             switch(i) {
168                                 %foreach idx = LibGetNumSyncPeriodicTasks()
169                                 %assign tid = idx + tid01Eq
170                                         case %<tid> :
171                                     %assign sampleTime = LibGetSampleTimePeriodAndOffset(tid,0)
172                                                         if ((steps_working % STEPS_FOR_TID%<tid>) == 0) {
173                                         %<LibCallModelStep(tid)>\
174                             }
175                                             break;
176                                 %endforeach
177                                 default : 
178                                     break;
179                                 }
180                         }
181                 %else
182                     %<LibCallModelStep(0)>\
183                 %endif
184                         steps_working++;
185                         working = FALSE;
186                         }
187         }
188
189         %% /* In case of shutdown, delete this task */
190         %% vTaskDelete(NULL);
191     }
192
193     %if extMode == 1
194       void ext_mode_comm_task(void* p)
195       {
196         drv_sci_set_crlf_conv_en(FALSE); /* Disable CR->CRLF conversion */
197
198         %<SLibGenERTExtModeInit()>
199         xSemaphoreGive(ext_mode_ready);
200
201         while (rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
202           rtExtModeOneStep(rtmGetRTWExtModeInfo(%<modelName>_M), %<numSampleTimes>, (boolean_T *)&rtmGetStopRequested(%<modelName>_M));
203         }
204         rtExtModeShutdown(%<numSampleTimes>);
205         /* In case of shutdown, delete this task */
206         vTaskDelete(NULL);
207       }
208     %endif
209
210     /**
211      * Hardware initialization, task spawning and OS scheduler start.
212      */
213     void main(void)
214     {
215         /* Initialize RPP board */
216         %if EXISTS(::rpp_ain_present)
217             rpp_adc_init();
218         %endif
219         %if EXISTS(::rpp_din_present) || EXISTS(::rpp_dout_present)
220             rpp_gio_init(RPP_GIO_PORT_ALL);
221         %endif
222         rpp_sci_init();
223
224         // Speed up the SCI
225         rpp_sci_setup(115200);
226
227         %if rppPrintMeta
228         %assign model_info = SPRINTF("'%s' - %s (TLC %s)\\r\\n", LibGetMdlPubHdrBaseName(), TLC_TIME, TLC_VERSION)
229         rpp_sci_printk("%<model_info>");
230         %endif
231
232         /* Create and lock semaphore */
233         vSemaphoreCreateBinary(step_signal);
234         xSemaphoreTake(step_signal, 0);
235         vSemaphoreCreateBinary(initialized_signal);
236         xSemaphoreTake(initialized_signal, 0);
237         %if extMode == 1
238           vSemaphoreCreateBinary(ext_mode_ready);
239           xSemaphoreTake(ext_mode_ready, 0);
240         %endif
241
242         /* Create tasks to step model and model task */
243         if (xTaskCreate(control_task, "control_task",
244             configMINIMAL_STACK_SIZE, NULL, CONTROL_PRIORITY, NULL) != pdPASS) {
245             rpp_sci_printk("ERROR: Cannot spawn control task.\r\n");
246             return;
247         }
248         if (xTaskCreate(working_task, "working_task",
249             %<rppModelTaskStack>, NULL, WORKING_PRIORITY, NULL) != pdPASS) {
250             rpp_sci_printk("ERROR: Cannot spawn model task.\r\n"
251             );
252             return;
253         }
254         %if extMode == 1
255           /* External mode */
256           rtParseArgsForExtMode(0, NULL);
257
258           if (xTaskCreate(ext_mode_comm_task, "ext_mode_comm_task", 1024, NULL, EXTMODE_PRIORITY, NULL) != pdPASS) {
259             rpp_sci_printk("ERROR: Cannot spawn model task.\r\n");
260             return;
261           }
262         %endif
263
264         /* Start FreeRTOS Scheduler */
265         vTaskStartScheduler();
266
267         /* We should never get here */
268         %<LibCallModelTerminate()>
269         rpp_sci_printk("ERROR: Problem allocating memory for idle task.\r\n");
270     }
271
272
273     #if configUSE_MALLOC_FAILED_HOOK == 1
274     /**
275      * FreeRTOS malloc() failed hook.
276      */
277      void vApplicationMallocFailedHook(void) {
278        rpp_sci_printk("ERROR: Memory allocation failed.\r\n");
279      }
280     #endif
281
282
283     #if configCHECK_FOR_STACK_OVERFLOW > 0
284     /**
285      * FreeRTOS stack overflow hook.
286      */
287     void vApplicationStackOverflowHook(xTaskHandle xTask, signed portCHAR *pcTaskName)
288     {
289       rpp_sci_printk("ERROR: Stack overflow : \"%s\".\r\n", pcTaskName);
290     }
291     #endif
292
293     %closefile tmpBuf
294     %<LibSetSourceFileSection(cFile, "Functions", tmpBuf)>
295     %%%%%%%%
296
297 %endfunction