]> rtime.felk.cvut.cz Git - jenkicar/rpp-simulink.git/blobdiff - rpp/rpp/rpp_srmain.tlc
demo: Uncheck "Download to RPP"
[jenkicar/rpp-simulink.git] / rpp / rpp / rpp_srmain.tlc
index 48e66c34adf76c2558ac3ec965470ca23c33abeb..5491f846af1ad57bc18411a192769acf17d61de2 100644 (file)
-%% Copyright (C) 2013 Czech Technical University in Prague
+%% Copyright (C) 2013-2015 Czech Technical University in Prague
 %%
 %% Authors:
-%%      - Carlos Jenkins <carlos@jenkins.co.cr>
+%%     - Carlos Jenkins <carlos@jenkins.co.cr>
+%%     - Michal Sojka <sojkam1@fel.cvut.cz>
 %%
-%% This program is free software; you can redistribute it and/or modify
-%% it under the terms of the GNU General Public License as published by
-%% the Free Software Foundation; either version 2 of the License, or
-%% (at your option) any later version.
-%%
-%% This program is distributed in the hope that it will be useful,
-%% but WITHOUT ANY WARRANTY; without even the implied warranty of
-%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-%% GNU General Public License for more details.
-%%
-%% You should have received a copy of the GNU General Public License
-%% along with this program.  If not, see <http://www.gnu.org/licenses/>.
+%% This document contains proprietary information belonging to Czech
+%% Technical University in Prague. Passing on and copying of this
+%% document, and communication of its contents is not permitted
+%% without prior written authorization.
 %%
 %% File : rpp_srmain.tlc
 %% Abstract:
-%%       Custom file processing to generate a "main" file.
-%%       Reference: ???
+%%     Custom TLC file to generate an RPP "main" file.
+%%
+%%     This file generates the "main" file for the RPP target on top of the RPP
+%%     library and the FreeRTOS operating system.
+%%
+%%     The sr prefix is standard to mark Single Tasking main, which is the case. See 
+%%     rpp_file_process.m description above for more information about this.
+%%
+%% References:
+%%     Example in <matlabroot>/rtw/c/tlc/mw/bareboard_srmain.tlc
 
 
 %selectfile NULL_FILE
 
 %function FcnSingleTaskingMain() void
 
-  %if GenerateSampleERTMain
-    %assign CompiledModel.GenerateSampleERTMain = TLC_FALSE
-  %endif
-
-  %assign cFile = LibCreateSourceFile("Source", "Custom", "ert_main")
-  %openfile tmpBuf
-  %closefile tmpBuf
-
-  %<LibSetSourceFileSection(cFile, "Includes", tmpBuf)>
-  %openfile tmpBuf
-  /* OS includes */
-  #include "FreeRTOS.h"
-  #include "os_task.h"
-
-  /* Common includes */
-  #include "sys_common.h"
-  #include "system.h"
-
-  /* Library includes */
-  // FIXME: Implement conditional #include's
-  %% IF GIO (General Input/Outputs)
-  %% IF HOUT (PWM outputs)
-  %% IF MOUT (Motor outputs)
-  %% IF ADC (Analog to Digital Converter)
-  %% IF SCI (Serial Communication Interface)
-  %% IF CAN (CAN Bus)
-  %% IF SDRAM
-
-  /* Model includes */
-  #include "%<LibGetMdlPubHdrBaseName()>.h"
-  %closefile tmpBuf
-
-  %<LibSetSourceFileSection(cFile, "Declarations", tmpBuf)>
-  %openfile tmpBuf
+    %if GenerateSampleERTMain
+        %assign CompiledModel.GenerateSampleERTMain = TLC_FALSE
+    %endif
 
-    void main(void)
+
+    %assign cFile = LibCreateSourceFile("Source", "Custom", "ert_main")
+
+
+    %%%%%%%%
+    %openfile tmpBuf
+
+    /* Model includes */
+    #include "%<LibGetMdlPubHdrBaseName()>.h"
+
+    /* RPP runtime includes */
+    #include "rpp_simulink_runtime.h"
+
+    %if extMode == 1
+      /* External mode header file */
+      #include "ext_work.h"
+      #include <drv/sci.h>
+    %endif
+
+    %closefile tmpBuf
+    %<LibSetSourceFileSection(cFile, "Includes", tmpBuf)>
+    %%%%%%%%
+
+
+    %%%%%%%%
+    %openfile tmpBuf
+
+    /* Definitions */
+    #define STEP_SIZE_MILLIS (%<CompiledModel.FundamentalStepSize>*1000.0)
+    #define CONTROL_PRIORITY 3
+    #define WORKING_PRIORITY 2
+    #define EXTMODE_PRIORITY 1
+
+    %closefile tmpBuf
+    %<LibSetSourceFileSection(cFile, "Defines", tmpBuf)>
+    %%%%%%%%
+
+
+    %%%%%%%%
+    %openfile tmpBuf
+
+    static boolean_t working = FALSE;
+    static xSemaphoreHandle step_signal = NULL;
+    static xSemaphoreHandle initialized_signal = NULL;
+    %if extMode == 1
+      static xSemaphoreHandle ext_mode_ready = NULL;
+    %endif
+    static uint32_t steps_control = 0;
+    static uint32_t steps_working = 0;
+    boolean_t overrun_flag = FALSE;
+
+    %closefile tmpBuf
+    %<LibSetSourceFileSection(cFile, "Declarations", tmpBuf)>
+    %%%%%%%%
+
+
+    %%%%%%%%
+    %openfile tmpBuf
+
+    /**
+     * Model step control and overrun detection task.
+     */
+    void control_task(void* p)
     {
 
-        /* Initialize peripherals */
-        // FIXME: Implement conditional init()'s
-        _enable_IRQ();
+      xSemaphoreTake(initialized_signal, portMAX_DELAY);
+      %if extMode == 1
+        xSemaphoreTake(ext_mode_ready, portMAX_DELAY);
+      %endif
+
+        static const portTickType freq_ticks = STEP_SIZE_MILLIS / portTICK_RATE_MS;
+        portTickType last_wake_time = xTaskGetTickCount();
+
+    %% This condition has been added because of the warning:
+    %% "ert_main.c", line 46: warning #238-D: controlling expression is constant
+    %% caused by the expression (void*) 0 passed to the while statement. The rtmGetStopRequested
+    %% macro is defined to this constant if and only if the GenerateSampleERTMain is not set. So
+    %% The condition is not needed in this case as well.
+    %%
+    %% See <MATLAB_ROOT>/rtw/c/tlc/mw/rtmspecmacs.tlc at line 198.
+
+    %if !GenerateSampleERTMain
+        while (rtmGetErrorStatus(%<modelName>_M) == NULL) {
+    %else
+        while (rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
+    %endif
+            /* Wait until next step */
+            vTaskDelayUntil(&last_wake_time, freq_ticks);
 
+            if (working) {
+                /* Overrun detected */
+                overrun_flag = TRUE;
+            } else {
+                /* Release semaphore */
+                xSemaphoreGive(step_signal);
+            }
+            steps_control++;
+
+            %if extMode == 1
+              rtExtModeCheckEndTrigger();
+            %endif
+
+        }
+
+        /* In case of shutdown, delete this task */
+        vTaskDelete(NULL);
+    }
+
+    /**
+     * Model step logic execution task.
+     */
+    void working_task(void* p)
+    {
         /* Initialize model */
         %<LibCallModelInitialize()>\
+        /* Step the model for any subrate */
+        xSemaphoreGive(initialized_signal);
 
-        /* Create task to step model and start scheduler */
-        // FIXME: Implement OS task for model step
-        vTaskStartScheduler();
+        while (1) {
+            if (xSemaphoreTake(step_signal, portMAX_DELAY)) {
+                working = TRUE;
+                %<LibCallModelStep(0)>\
+                steps_working++;
+                working = FALSE;
+            }
+        }
+
+       %% /* In case of shutdown, delete this task */
+       %% vTaskDelete(NULL);
+    }
 
-        // We should never get here
-        %<LibCallModelTerminate()>\
-        while(1){
+    %if extMode == 1
+      void ext_mode_comm_task(void* p)
+      {
+        drv_sci_set_crlf_conv_en(FALSE); /* Disable CR->CRLF conversion */
+
+        %<SLibGenERTExtModeInit()>
+        xSemaphoreGive(ext_mode_ready);
+
+        while (rtmGetErrorStatus(%<modelName>_M) == NULL && !rtmGetStopRequested(%<modelName>_M)) {
+          rtExtModeOneStep(rtmGetRTWExtModeInfo(%<modelName>_M), %<numSampleTimes>, (boolean_T *)&rtmGetStopRequested(%<modelName>_M));
         }
+        rtExtModeShutdown(%<numSampleTimes>);
+        /* In case of shutdown, delete this task */
+        vTaskDelete(NULL);
+      }
+    %endif
+
+    /**
+     * Hardware initialization, task spawning and OS scheduler start.
+     */
+    void main(void)
+    {
+        /* Initialize RPP board */
+        %if EXISTS(::rpp_ain_present)
+            rpp_adc_init();
+        %endif
+        %if EXISTS(::rpp_aout_present)
+            rpp_dac_init();
+        %endif
+        %if EXISTS(::rpp_din_present)
+            rpp_din_init();
+        %endif
+        %if EXISTS(::rpp_hbr_present)
+            rpp_hbr_init();
+        %endif
+        %if EXISTS(::rpp_irc_present)
+            rpp_irc_init();
+        %endif
+        %if EXISTS(::rpp_lout_present)
+            rpp_lout_init();
+        %endif
+        %if EXISTS(::rpp_mout_present)
+            rpp_mout_init();
+        %endif
+        %if EXISTS(::rpp_sdr_present)
+            rpp_sdr_init();
+        %endif
+        %if EXISTS(::rpp_gio_in_present) || EXISTS(::rpp_gio_out_present)
+            rpp_gio_init(RPP_GIO_PORT_ALL);
+        %endif
+        rpp_sci_init();
+
+        // Speed up the SCI
+        rpp_sci_setup(115200);
+
+        %if rppPrintMeta
+        %assign model_info = SPRINTF("'%s' - %s (TLC %s)\\r\\n", LibGetMdlPubHdrBaseName(), TLC_TIME, TLC_VERSION)
+        rpp_sci_printk("%<model_info>");
+        %endif
+
+        /* Create and lock semaphore */
+        vSemaphoreCreateBinary(step_signal);
+        xSemaphoreTake(step_signal, 0);
+        vSemaphoreCreateBinary(initialized_signal);
+        xSemaphoreTake(initialized_signal, 0);
+        %if extMode == 1
+          vSemaphoreCreateBinary(ext_mode_ready);
+          xSemaphoreTake(ext_mode_ready, 0);
+        %endif
+
+        /* Create tasks to step model and model task */
+        if (xTaskCreate(control_task, "control_task",
+            configMINIMAL_STACK_SIZE, NULL, CONTROL_PRIORITY, NULL) != pdPASS) {
+            rpp_sci_printk("ERROR: Cannot spawn control task.\r\n");
+            return;
+        }
+        if (xTaskCreate(working_task, "working_task",
+            %<rppModelTaskStack>, NULL, WORKING_PRIORITY, NULL) != pdPASS) {
+            rpp_sci_printk("ERROR: Cannot spawn model task.\r\n"
+            );
+            return;
+        }
+        %if extMode == 1
+          /* External mode */
+          rtParseArgsForExtMode(0, NULL);
+
+          if (xTaskCreate(ext_mode_comm_task, "ext_mode_comm_task", 1024, NULL, EXTMODE_PRIORITY, NULL) != pdPASS) {
+            rpp_sci_printk("ERROR: Cannot spawn model task.\r\n");
+            return;
+          }
+        %endif
+
+        /* Start FreeRTOS Scheduler */
+        vTaskStartScheduler();
+
+        /* We should never get here */
+        %<LibCallModelTerminate()>
+        rpp_sci_printk("ERROR: Problem allocating memory for idle task.\r\n");
+    }
+
+
+    #if configUSE_MALLOC_FAILED_HOOK == 1
+    /**
+     * FreeRTOS malloc() failed hook.
+     */
+     void vApplicationMallocFailedHook(void) {
+       rpp_sci_printk("ERROR: Memory allocation failed.\r\n");
+     }
+    #endif
+
+
+    #if configCHECK_FOR_STACK_OVERFLOW > 0
+    /**
+     * FreeRTOS stack overflow hook.
+     */
+    void vApplicationStackOverflowHook(xTaskHandle xTask, signed portCHAR *pcTaskName)
+    {
+      rpp_sci_printk("ERROR: Stack overflow : \"%s\".\r\n", pcTaskName);
     }
-  %closefile tmpBuf
+    #endif
 
-  %<LibSetSourceFileSection(cFile, "Functions", tmpBuf)>
+    %closefile tmpBuf
+    %<LibSetSourceFileSection(cFile, "Functions", tmpBuf)>
+    %%%%%%%%
 
 %endfunction