Subversion Repositories shark

Compare Revisions

Regard whitespace Rev 1341 → Rev 1342

/demos/trunk/rtw/initfile.c
0,0 → 1,120
/*
* Project: S.Ha.R.K.
*
* Coordinators:
* Giorgio Buttazzo <giorgio@sssup.it>
* Paolo Gai <pj@gandalf.sssup.it>
*
* Authors :
* Paolo Gai <pj@gandalf.sssup.it>
* (see the web pages for full authors list)
*
* ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
*
* http://www.sssup.it
* http://retis.sssup.it
* http://shark.sssup.it
*/
 
/*
------------
CVS : $Id: initfile.c,v 1.1 2004-03-13 14:50:57 giacomo Exp $
 
File: $File$
Revision: $Revision: 1.1 $
Last update: $Date: 2004-03-13 14:50:57 $
------------
 
System initialization file
 
This file contains the 2 functions needed to initialize the system.
 
These functions register the following levels:
 
an EDF (Earliest Deadline First) level
a RR (Round Robin) level
a CBS (Costant Bandwidth Server) level
a Dummy level
 
It can accept these task models:
 
HARD_TASK_MODEL (wcet+mit) at level 0
SOFT_TASK_MODEL (met, period) at level 1
NRT_TASK_MODEL at level 2
 
This file is similar to the configuration of kernel/init/hartik3.c
 
TICK is set to 0 (one-shot timer is used)
*/
 
/*
* Copyright (C) 2000 Paolo Gai
*
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
 
#include "kernel/kern.h"
#include "modules/edf.h"
#include "modules/cbs.h"
#include "modules/rr.h"
#include "modules/dummy.h"
 
#include "modules/sem.h"
#include "modules/hartport.h"
#include "modules/cabs.h"
 
#include "drivers/keyb.h"
 
 
/*+ sysyem tick in us +*/
#define TICK 0
 
/*+ RR tick in us +*/
#define RRTICK 10000
 
TIME __kernel_register_levels__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
EDF_register_level(EDF_ENABLE_ALL);
CBS_register_level(CBS_ENABLE_ALL, 0);
RR_register_level(RRTICK, RR_MAIN_YES, mb);
dummy_register_level();
 
SEM_register_module();
 
CABS_register_module();
 
return TICK;
}
 
TASK __init__(void *arg)
{
struct multiboot_info *mb = (struct multiboot_info *)arg;
 
KEYB_PARMS kparms = BASE_KEYB;
 
HARTPORT_init();
 
keyb_def_ctrlC(kparms, NULL);
keyb_def_map(kparms,itaMap);
KEYB_init(&kparms);
 
__call_main__(mb);
 
return (void *)0;
}
 
/demos/trunk/rtw/rt_sim_shark.c
0,0 → 1,383
#include <math.h>
 
#include "tmwtypes.h"
#ifdef USE_RTMODEL
# include "simstruc_types.h"
#else
# include "simstruc.h"
#endif
#include "rt_sim.h"
 
#ifndef RT_MALLOC /* statically declare data */
 
/*==========*
* Struct's *
*==========*/
 
/*
* TimingData
*/
typedef struct TimingData_Tag {
real_T period[NUMST]; /* Task periods in seconds */
real_T offset[NUMST]; /* Task offsets in seconds */
real_T clockTick[NUMST]; /* Flint task time tick counter */
int_T taskTick[NUMST]; /* Counter for determining task hits */
int_T nTaskTicks[NUMST]; /* Number base rate ticks for a task hit */
int_T firstDiscIdx; /* First discrete task index */
} TimingData;
 
/*=========================*
* Data local to this file *
*=========================*/
 
static TimingData td;
 
/*==================*
* Visible routines *
*==================*/
 
/* Function: rt_SimInitTimingEngine ============================================
* Abstract:
* This function is for use with single tasking or multitasking
* real-time systems.
*
* Initializes the timing engine for a fixed-step real-time system.
* It is assumed that start time is 0.0.
*
* Returns:
* NULL - success
* non-NULL - error string
*/
const char *rt_SimInitTimingEngine(int_T rtmNumSampTimes,
real_T rtmStepSize,
real_T *rtmSampleTimePtr,
real_T *rtmOffsetTimePtr,
int_T *rtmSampleHitPtr,
int_T *rtmSampleTimeTaskIDPtr,
real_T rtmTStart,
SimTimeStep *rtmSimTimeStepPtr,
void **rtmTimingDataPtr)
{
int_T i;
int *tsMap = rtmSampleTimeTaskIDPtr;
real_T *period = rtmSampleTimePtr;
real_T *offset = rtmOffsetTimePtr;
int_T *sampleHit = rtmSampleHitPtr;
real_T stepSize = rtmStepSize;
 
if (rtmTStart != 0.0) {
return("Start time must be zero for real-time systems");
}
 
*rtmSimTimeStepPtr = MAJOR_TIME_STEP;
 
*rtmTimingDataPtr = (void*)&td;
 
for (i = 0; i < NUMST; i++) {
tsMap[i] = i;
td.period[i] = period[i];
td.offset[i] = offset[i];
td.nTaskTicks[i] = (int_T)floor(period[i]/stepSize + 0.5);
if (td.period[i] == CONTINUOUS_SAMPLE_TIME ||
td.offset[i] == 0.0) {
td.taskTick[i] = 0;
td.clockTick[i] = 0.0;
sampleHit[i] = 1;
} else {
td.taskTick[i] = (int_T)floor((td.period[i]-td.offset[i]) /
stepSize+0.5);
td.clockTick[i] = -1.0;
sampleHit[i] = 0;
}
}
 
/* Correct first sample time if continuous task */
td.period[0] = stepSize;
td.nTaskTicks[0] = 1;
 
/* Set first discrete task index */
#if NUMST == 1
td.firstDiscIdx = (int_T)(period[0] == CONTINUOUS_SAMPLE_TIME);
#else
td.firstDiscIdx = ((int_T)(period[0] == CONTINUOUS_SAMPLE_TIME) +
(int_T)(period[1] == CONTINUOUS_SAMPLE_TIME));
#endif
 
return(NULL); /* success */
 
} /* end rt_SimInitTimingEngine */
 
 
#if !defined(MULTITASKING)
 
/*###########################################################################*/
/*########################### SINGLE TASKING ################################*/
/*###########################################################################*/
 
/* Function: rt_SimGetNextSampleHit ============================================
* Abstract:
* For a single tasking real-time system, return time of next sample hit.
*/
time_T rt_SimGetNextSampleHit(void)
{
time_T timeOfNextHit;
td.clockTick[0] += 1;
timeOfNextHit = td.clockTick[0] * td.period[0];
 
# if NUMST > 1
{
int i;
for (i = 1; i < NUMST; i++) {
if (++td.taskTick[i] == td.nTaskTicks[i]) {
td.taskTick[i] = 0;
td.clockTick[i]++;
}
}
}
# endif
 
return(timeOfNextHit);
 
} /* end rt_SimGetNextSampleHit */
 
 
 
/* Function: rt_SimUpdateDiscreteTaskSampleHits ================================
* Abstract:
* This function is for use with single tasking real-time systems.
*
* If the number of sample times is greater than one, then we need to
* update the discrete task sample hits for the next time step. Note,
* task 0 always has a hit since it's sample time is the fundamental
* sample time.
*/
void rt_SimUpdateDiscreteTaskSampleHits(int_T rtmNumSampTimes,
void *rtmTimingData,
int_T *rtmSampleHitPtr,
real_T *rtmTPtr)
{
int_T *sampleHit = rtmSampleHitPtr;
int i;
UNUSED_PARAMETER(rtmTimingData);
UNUSED_PARAMETER(rtmNumSampTimes);
for (i = td.firstDiscIdx; i < NUMST; i++) {
int_T hit = (td.taskTick[i] == 0);
if (hit) {
rttiSetTaskTime(rtmTPtr, i,
td.clockTick[i]*td.period[i] + td.offset[i]);
}
sampleHit[i] = hit;
}
} /* rt_SimUpdateDiscreteTaskSampleHits */
 
 
 
#else /* defined(MULTITASKING) */
 
/*###########################################################################*/
/*############################## MULTITASKING ###############################*/
/*###########################################################################*/
 
 
/* Function: rt_SimUpdateDiscreteEvents ========================================
* Abstract:
* This function is for use with multitasking real-time systems.
*
* This function updates the status of the RT_MODEL sampleHits
* flags and the perTaskSampleHits matrix which is used to determine
* when special sample hits occur.
*
* The RT_MODEL contains a matrix, called perTaskSampleHits.
* This matrix is used by the ssIsSpecialSampleHit macro. The row and
* column indices are both task id's (equivalent to the root RT_MODEL
* sample time indices). This is a upper triangle matrix. This routine
* only updates the slower task hits (kept in column j) for row
* i if we have a sample hit in row i.
*
* column j
* tid 0 1 2 3 4 5
* -------------------------
* 0 | | X | X | X | X | X |
* r -------------------------
* o 1 | | | X | X | X | X | This matrix(i,j) answers:
* w ------------------------- If we are in task i, does
* 2 | | | | X | X | X | slower task j have a hit now?
* i -------------------------
* 3 | | | | | X | X |
* -------------------------
* 4 | | | | | | X | X = 0 or 1
* -------------------------
* 5 | | | | | | |
* -------------------------
*
* How macros index this matrix:
*
* ssSetSampleHitInTask(S, j, i, X) => matrix(i,j) = X
*
* ssIsSpecialSampleHit(S, my_sti, promoted_sti, tid) =>
* (tid_for(promoted_sti) == tid && !minor_time_step &&
* matrix(tid,tid_for(my_sti))
* )
*
* my_sti = My (the block's) original sample time index.
* promoted_sti = The block's promoted sample time index resulting
* from a transition via a ZOH from a fast to a
* slow block or a transition via a unit delay from
* a slow to a fast block.
*
* The perTaskSampleHits array, of dimension n*n, is accessed using
* perTaskSampleHits[j + i*n] where n is the total number of sample
* times, 0 <= i < n, and 0 <= j < n. The C language stores arrays in
* row-major order, that is, row 0 followed by row 1, etc.
*
*/
time_T rt_SimUpdateDiscreteEvents(int_T rtmNumSampTimes,
void *rtmTimingData,
int_T *rtmSampleHitPtr,
int_T *rtmPerTaskSampleHits)
{
int i, j;
int_T *sampleHit = rtmSampleHitPtr;
UNUSED_PARAMETER(rtmTimingData);
/*
* Run this loop in reverse so that we do lower priority events first.
*/
i = NUMST;
while (--i >= 0) {
if (td.taskTick[i] == 0) {
/*
* Got a sample hit, reset the counter, and update the clock
* tick counter.
*/
sampleHit[i] = 1;
td.clockTick[i]++;
 
/*
* Record the state of all "slower" events
*/
for (j = i + 1; j < NUMST; j++) {
rttiSetSampleHitInTask(rtmPerTaskSampleHits, rtmNumSampTimes,
j, i, sampleHit[j]);
}
} else {
/*
* no sample hit, increment the counter
*/
sampleHit[i] = 0;
}
 
if (++td.taskTick[i] == td.nTaskTicks[i]) { /* update for next time */
td.taskTick[i] = 0;
}
}
 
return(td.clockTick[0]*td.period[0]);
} /* rt_SimUpdateDiscreteEvents */
 
 
 
/* Function: rt_SimUpdateDiscreteTaskTime ======================================
* Abstract:
* This function is for use with multitasking systems.
*
* After a discrete task output and update has been performed, this
* function must be called to update the discrete task time for next
* time around.
*/
void rt_SimUpdateDiscreteTaskTime(real_T *rtmTPtr,
void *rtmTimingData,
int tid)
{
UNUSED_PARAMETER(rtmTimingData);
rttiSetTaskTime(rtmTPtr, tid,
td.clockTick[tid]*td.period[tid] + td.offset[tid]);
}
 
#endif /* MULTITASKING */
 
#else
 
#include "mrt_sim.c" /* dynamically allocate data */
 
#endif /* RT_MALLOC */
 
/*
*******************************************************************************
* FUNCTIONS MAINTAINED FOR BACKWARDS COMPATIBILITY WITH THE SimStruct
*******************************************************************************
*/
#ifndef USE_RTMODEL
const char *rt_InitTimingEngine(SimStruct *S)
{
const char_T *retVal = rt_SimInitTimingEngine(
ssGetNumSampleTimes(S),
ssGetStepSize(S),
ssGetSampleTimePtr(S),
ssGetOffsetTimePtr(S),
ssGetSampleHitPtr(S),
ssGetSampleTimeTaskIDPtr(S),
ssGetTStart(S),
&ssGetSimTimeStep(S),
&ssGetTimingData(S));
return(retVal);
}
 
# ifdef RT_MALLOC
void rt_DestroyTimingEngine(SimStruct *S)
{
rt_SimDestroyTimingEngine(ssGetTimingData(S));
}
# endif
 
# if !defined(MULTITASKING)
void rt_UpdateDiscreteTaskSampleHits(SimStruct *S)
{
rt_SimUpdateDiscreteTaskSampleHits(
ssGetNumSampleTimes(S),
ssGetTimingData(S),
ssGetSampleHitPtr(S),
ssGetTPtr(S));
}
 
# ifndef RT_MALLOC
 
time_T rt_GetNextSampleHit(void)
{
return(rt_SimGetNextSampleHit());
}
 
# else /* !RT_MALLOC */
 
time_T rt_GetNextSampleHit(SimStruct *S)
{
return(rt_SimGetNextSampleHit(ssGetTimingData(S),
ssGetNumSampleTimes(S)));
}
 
# endif
 
# else /* MULTITASKING */
 
time_T rt_UpdateDiscreteEvents(SimStruct *S)
{
return(rt_SimUpdateDiscreteEvents(
ssGetNumSampleTimes(S),
ssGetTimingData(S),
ssGetSampleHitPtr(S),
ssGetPerTaskSampleHitsPtr(S)));
}
 
void rt_UpdateDiscreteTaskTime(SimStruct *S, int tid)
{
rt_SimUpdateDiscreteTaskTime(ssGetTPtr(S), ssGetTimingData(S), tid);
}
 
#endif
#endif
 
/* EOF: rt_sim.c */
/demos/trunk/rtw/makefile
0,0 → 1,26
#
#
#
 
ifndef BASE
BASE=../..
endif
include $(BASE)/config/config.mk
 
MATLAB_ROOT = /matlab
MATLAB_RTW_DEMO_DIR = /home/mckrak/test_grt_rtw/
 
DEFINE_MODEL = test
DEFINE_NUMST = 1
 
PROGS = rtw
 
RTW_CFG = "-I$(MATLAB_ROOT)/simulink/include -I$(MATLAB_ROOT)/extern/include -I$(MATLAB_ROOT)/rtw/c/src -I$(MATLAB_ROOT)/rtw/c/libsrc -I$(MATLAB_RTW_DEMO_DIR) -DUSE_RTMODEL -DRT -DMODEL=$(DEFINE_MODEL) -DNUMST=$(DEFINE_NUMST)"
 
RTW_OBJS = $(MATLAB_RTW_DEMO_DIR)/$(DEFINE_MODEL).o $(MATLAB_RTW_DEMO_DIR)/$(DEFINE_MODEL)_data.o
 
include $(BASE)/config/example.mk
 
rtw:
make -f $(SUBMAKE) OTHERINCL=$(RTW_CFG) APP=rtw INIT= OTHEROBJS="initfile.o $(RTW_OBJS)" SHARKOPT="__OLDCHAR__"
 
/demos/trunk/rtw/rtw.c
0,0 → 1,347
#include "tmwtypes.h"
#include "rtmodel.h"
#include "rt_sim.h"
#include "rt_logging.h"
#include "rt_nonfinite.h"
 
#include "ext_work.h"
#include "rt_nonfinite.h"
 
#include "kernel/kern.h"
 
/*=========*
* Defines *
*=========*/
 
#ifndef TRUE
#define FALSE (0)
#define TRUE (1)
#endif
 
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
 
#define QUOTE1(name) #name
#define QUOTE(name) QUOTE1(name) /* need to expand name */
 
#define RUN_FOREVER -1.0
 
#define EXPAND_CONCAT(name1,name2) name1 ## name2
#define CONCAT(name1,name2) EXPAND_CONCAT(name1,name2)
#define RT_MODEL CONCAT(MODEL,_rtModel)
 
extern RT_MODEL *MODEL(void);
extern void MdlInitializeSizes(void);
extern void MdlInitializeSampleTimes(void);
extern void MdlStart(void);
extern void MdlOutputs(int_T tid);
extern void MdlUpdate(int_T tid);
extern void MdlTerminate(void);
 
real_T rtInf;
real_T rtMinusInf;
real_T rtNaN;
 
# define rt_CreateIntegrationData(S) \
rtsiSetSolverName(rtmGetRTWSolverInfo(S),"FixedStepDiscrete");
# define rt_UpdateContinuousStates(S) \
rtmSetT(S, rtsiGetSolverStopTime(rtmGetRTWSolverInfo(S)));
 
/*==================================*
* Global data local to this module *
*==================================*/
static struct {
int_T stopExecutionFlag;
int_T isrOverrun;
int_T overrunFlags[NUMST];
const char_T *errmsg;
} GBLbuf;
 
/* Function: rt_InitInfAndNaN ==================================================
* Abstract:
* Initialize the rtInf, rtMinusInf, and rtNaN needed by the
* generated code. NaN is initialized as non-signaling. Assumes IEEE.
*/
void rt_InitInfAndNaN(int_T realSize)
{
short one = 1;
enum {
LittleEndian,
BigEndian
} machByteOrder = (*((char *) &one) == 1) ? LittleEndian : BigEndian;
 
switch (realSize) {
case 4:
switch (machByteOrder) {
case LittleEndian: {
typedef struct {
uint32_T fraction : 23;
uint32_T exponent : 8;
uint32_T sign : 1;
} LittleEndianIEEEDouble;
(*(LittleEndianIEEEDouble*)&rtInf).sign = 0;
(*(LittleEndianIEEEDouble*)&rtInf).exponent = 0xFF;
(*(LittleEndianIEEEDouble*)&rtInf).fraction = 0;
rtMinusInf = rtInf;
rtNaN = rtInf;
(*(LittleEndianIEEEDouble*)&rtMinusInf).sign = 1;
(*(LittleEndianIEEEDouble*)&rtNaN).fraction = 0x7FFFFF;
}
break;
case BigEndian: {
typedef struct {
uint32_T sign : 1;
uint32_T exponent : 8;
uint32_T fraction : 23;
} BigEndianIEEEDouble;
(*(BigEndianIEEEDouble*)&rtInf).sign = 0;
(*(BigEndianIEEEDouble*)&rtInf).exponent = 0xFF;
(*(BigEndianIEEEDouble*)&rtInf).fraction = 0;
rtMinusInf = rtInf;
rtNaN = rtInf;
(*(BigEndianIEEEDouble*)&rtMinusInf).sign = 1;
(*(BigEndianIEEEDouble*)&rtNaN).fraction = 0x7FFFFF;
}
break;
}
break;
case 8:
switch (machByteOrder) {
case LittleEndian: {
typedef struct {
struct {
uint32_T fraction2;
} wordH;
struct {
uint32_T fraction1 : 20;
uint32_T exponent : 11;
uint32_T sign : 1;
} wordL;
} LittleEndianIEEEDouble;
(*(LittleEndianIEEEDouble*)&rtInf).wordL.sign = 0;
(*(LittleEndianIEEEDouble*)&rtInf).wordL.exponent = 0x7FF;
(*(LittleEndianIEEEDouble*)&rtInf).wordL.fraction1 = 0;
(*(LittleEndianIEEEDouble*)&rtInf).wordH.fraction2 = 0;
rtMinusInf = rtInf;
(*(LittleEndianIEEEDouble*)&rtMinusInf).wordL.sign = 1;
(*(LittleEndianIEEEDouble*)&rtNaN).wordL.sign = 0;
(*(LittleEndianIEEEDouble*)&rtNaN).wordL.exponent = 0x7FF;
(*(LittleEndianIEEEDouble*)&rtNaN).wordL.fraction1 = 0xFFFFF;
(*(LittleEndianIEEEDouble*)&rtNaN).wordH.fraction2 = 0xFFFFFFFF;
}
break;
case BigEndian: {
typedef struct {
struct {
uint32_T sign : 1;
uint32_T exponent : 11;
uint32_T fraction1 : 20;
} wordL;
struct {
uint32_T fraction2;
} wordH;
} BigEndianIEEEDouble;
(*(BigEndianIEEEDouble*)&rtInf).wordL.sign = 0;
(*(BigEndianIEEEDouble*)&rtInf).wordL.exponent = 0x7FF;
(*(BigEndianIEEEDouble*)&rtInf).wordL.fraction1 = 0;
(*(BigEndianIEEEDouble*)&rtInf).wordH.fraction2 = 0;
rtMinusInf = rtInf;
(*(BigEndianIEEEDouble*)&rtMinusInf).wordL.sign = 1;
(*(BigEndianIEEEDouble*)&rtNaN).wordL.sign = 0;
(*(BigEndianIEEEDouble*)&rtNaN).wordL.exponent = 0x7FF;
(*(BigEndianIEEEDouble*)&rtNaN).wordL.fraction1 = 0xFFFFF;
(*(BigEndianIEEEDouble*)&rtNaN).wordH.fraction2 = 0xFFFFFFFF;
}
break;
}
break;
default:
cprintf("Unable to initialize rtInf, rtMinusInf and rtNaN\n");
sys_end();
break;
}
 
} /* end rt_InitInfAndNaN */
 
/* Function: rtOneStep ========================================================
*
* Abstract:
* Perform one step of the model. This function is modeled such that
* it could be called from an interrupt service routine (ISR) with minor
* modifications.
*/
static void rt_OneStep(RT_MODEL *S)
{
real_T tnext;
 
/***********************************************
* Check and see if base step time is too fast *
***********************************************/
 
if (GBLbuf.isrOverrun++) {
GBLbuf.stopExecutionFlag = 1;
return;
}
 
/***********************************************
* Check and see if error status has been set *
***********************************************/
 
if (rtmGetErrorStatus(S) != NULL) {
GBLbuf.stopExecutionFlag = 1;
return;
}
 
/* enable interrupts here */
 
rtExtModeOneStep(rtmGetRTWExtModeInfo(S),
(boolean_T *)&rtmGetStopRequested(S));
 
tnext = rt_SimGetNextSampleHit();
rtsiSetSolverStopTime(rtmGetRTWSolverInfo(S),tnext);
 
MdlOutputs(0);
 
GBLbuf.errmsg = rt_UpdateTXYLogVars(rtmGetRTWLogInfo(S),
rtmGetTPtr(S));
if (GBLbuf.errmsg != NULL) {
GBLbuf.stopExecutionFlag = 1;
return;
}
 
MdlUpdate(0);
rt_SimUpdateDiscreteTaskSampleHits(rtmGetNumSampleTimes(S),
rtmGetTimingData(S),
rtmGetSampleHitPtr(S),
rtmGetTPtr(S));
 
if (rtmGetSampleTime(S,0) == CONTINUOUS_SAMPLE_TIME) {
rt_UpdateContinuousStates(S);
}
 
GBLbuf.isrOverrun--;
 
rtExtModeCheckEndTrigger();
 
} /* end rtOneStep */
 
int main() {
 
RT_MODEL *S;
const char *status;
real_T finaltime = -2.0;
/****************************
* Initialize global memory *
****************************/
(void)memset(&GBLbuf, 0, sizeof(GBLbuf));
 
/************************
* Initialize the model *
************************/
rt_InitInfAndNaN(sizeof(real_T));
 
S = MODEL();
if (rtmGetErrorStatus(S) != NULL) {
cprintf("Error during model registration: %s\n",
rtmGetErrorStatus(S));
sys_end();
}
if (finaltime >= 0.0 || finaltime == RUN_FOREVER) rtmSetTFinal(S,finaltime);
 
MdlInitializeSizes();
MdlInitializeSampleTimes();
status = rt_SimInitTimingEngine(rtmGetNumSampleTimes(S),
rtmGetStepSize(S),
rtmGetSampleTimePtr(S),
rtmGetOffsetTimePtr(S),
rtmGetSampleHitPtr(S),
rtmGetSampleTimeTaskIDPtr(S),
rtmGetTStart(S),
&rtmGetSimTimeStep(S),
&rtmGetTimingData(S));
 
if (status != NULL) {
cprintf("Failed to initialize sample time engine: %s\n", status);
sys_end();
}
rt_CreateIntegrationData(S);
 
rtExtModeCheckInit();
rtExtModeWaitForStartMsg(rtmGetRTWExtModeInfo(S),
(boolean_T *)&rtmGetStopRequested(S));
 
cprintf("\n** starting the model **\n");
 
MdlStart();
if (rtmGetErrorStatus(S) != NULL) {
GBLbuf.stopExecutionFlag = 1;
}
 
/*************************************************************************
* Execute the model. You may attach rtOneStep to an ISR, if so replace *
* the call to rtOneStep (below) with a call to a background task *
* application. *
*************************************************************************/
 
if (rtmGetTFinal(S) == RUN_FOREVER) {
cprintf("\n**May run forever. Model stop time set to infinity.**\n");
}
while (!GBLbuf.stopExecutionFlag &&
(rtmGetTFinal(S) == RUN_FOREVER ||
rtmGetTFinal(S)-rtmGetT(S) > rtmGetT(S)*DBL_EPSILON)) {
 
rtExtModePauseIfNeeded(rtmGetRTWExtModeInfo(S),
(boolean_T *)&rtmGetStopRequested(S));
 
cprintf(".");
 
if (rtmGetStopRequested(S)) break;
rt_OneStep(S);
}
 
if (!GBLbuf.stopExecutionFlag && !rtmGetStopRequested(S)) {
/* Execute model last time step */
rt_OneStep(S);
}
 
/********************
* Cleanup and exit *
********************/
 
rtExtModeShutdown();
 
if (GBLbuf.errmsg) {
cprintf("%s\n",GBLbuf.errmsg);
sys_end();
}
 
if (GBLbuf.isrOverrun) {
cprintf("%s: ISR overrun - base sampling rate is too fast\n",QUOTE(MODEL));
sys_end();
}
 
if (rtmGetErrorStatus(S) != NULL) {
cprintf("%s\n", rtmGetErrorStatus(S));
sys_end();
}
 
MdlTerminate();
return 0;
 
} /* end main */