/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 */ |