📄 ext_svr_transport.c
字号:
/*
* Copyright 1994-2002 The MathWorks, Inc.
*
* File: ext_svr_transport.c $Revision: 1.11 $
*
* Abstract:
* Target-side, transport-dependent external mode functions and defs. This
* example file implements host/target communication using TCPIP. To
* implement other transport mechanisms, modify the functions in the
* 'Visible Functions' section of this file.
*
* Functionality supplied by this module includes:
*
* o definition of user data
* o is host message pending
* o get bytes from host message line
* o set bytes on host message line
* o set bytes on data upload line
* o create user data
* o destroy user data
* o initialize external mode
*
* The files relating to target-side external mode are:
* xx_main.c
* The main program harness for the generated code. There is a different
* main.c for each target (i.e., grt_main.c for grt, rt_main.c for
* VXWORKS, etc). This program controls the execution of the model.
* When compiled for external mode, this program contains the
* external mode "instrumentation" (i.e., function calls) into External
* Mode to enable data uploading and downloading).
*
* [THIS FILE SHOULD NOT NEED TO BE MODIFIED FOR DIFFERENT TRANSPORT
* MECHANISMS]
*
* ext_svr.c
* The server for external mode. This file is the interface between the
* model and external mode and essentially contains the boilerplate
* code for external mode. It generally contains:
* o transport-independent functions (wrappers) for external
* communication
* o function dispatch for some of the more involved external mode
* tasks (i.e., dispatch for setting params, etc).
* The code is transport-independent (i.e., should not have to change
* whether using sockets, shared memory, etc). Note that updown.c
* is the module that takes care of most of the detailed, dirty work
* such as decoding the set param message and installing the new
* parameter values into the parameter struct (rtP).
*
* [THIS FILE SHOULD NOT NEED TO BE MODIFIED FOR DIFFERENT TRANSPORT
* MECHANISMS]
*
* ext_svr_transport.c
* Transport-dependent external mode code (e.g., set bytes on host, get
* bytes from host, etc).
*
* [THIS FILE NEEDS TO BE MODIFIED TO IMPLEMENT VARIOUS DATA TRANSPORT
* MECHANISMS]
*
* ext_ext_transport_share.h
* Definitions that are specific to the implemented transport mechanism
* and that are required on both he host and the target.
*
* [THIS FILE NEEDS TO BE MODIFIED TO IMPLEMENT VARIOUS DATA TRANSPORT
* MECHANISMS]
*
* updown.c
* Transport-independent guts of external mode. Most direct interaction
* with target memory occurs in this file. For example:
* o decode set param message & install new param values into
* parameter array
* o Add data to upload buffers.
* o Monitor triggers and change trigger state.
* o and on, and on, and on....
*
* [THIS FILE SHOULD NOT NEED TO BE MODIFIED FOR DIFFERENT TRANSPORT
* MECHANISMS]
*/
/*
* Explanation of the EXT_BLOCKING:
*
* Depending on the implementation of the main program (e.g., grt_main.c,
* rt_main.c), the EXT_BLOCKING flag must be set to either 0 or 1. Let's
* look at two examples:
*
* grt_main.c (grt):
* grt_main is a real time template that essentially runs a simulation - in
* non-real-time - in a single thread. As seen in grt, the calls to the
* upload & msg servers are "in the loop". If any function related to
* external mode were to block, the real time code, would be prevented from
* running. In this case, we prevent blocking, and poll instead.
*
* rt_main.c (tornado/vxworks)
* rt_main.c is a full blown, real-time, multi-tasking target. The
* upload and msg servers are called via background (low priority) tasks.
* In this case, it is o.k. for the transport function to block as the blocked
* tasks will simply be pre-empted in order to enable the model to run. It
* is desirable to block instead of to poll to free up the cpu for any other
* potential work.
*/
/* modifications: (FW-02-03)
*
* (1) added header file <math.h> (needed in ExtInit())
* (2) added target specific header files
* (3) added header files simstruc_types.h and updown.h, needed to access 'ExtBufMemList'
* (4) removed definition of the structure ExtUserData -> now in ext_svr_transport.h
* (5) deleted unused conditional code sections (VXWORKS, UNIX, IBM_RS, GLNX86, SUN4, BLOCKING)
* (6) added header file "updown.h" (declaration of ExtBufMemList, used in put_data_buf() )
* (7) modified definition of structure ExtUserData
* (8) added section DEFINES
* (9) added section GLOBAL VARIABLES
* (10) removed PRIVATE function PassiveSocketShutdown() and replaced it with
* the handler serial_RX_irq() as well as the low-level access functions
* get_data_sp() and put_data_sp()
* (11) added VISIBLE functions init_ringBuf() and put_data_buffer()
* (12) replaced VISIBLE function ExtInit()
* (13) removed unused VISIBLE functions: ExtOpenConnection(), ExtCloseConnection(),
* ExtShutDown(), ExtProcessArgs() and ExtUserDataSetPort()
* (14) replaced VISIBLE functions ExtGetHostMsg(), ExtSetHostMsg() and ExtSetHostData()
* (15) added new VISIBLE function ExtSetHostUserData()
* (16) removed contents of (now non-functional) VISIBLE function ExtModeSleep()
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h> /* ceil */
/* System macros (EXT_MODE, etc.) -- generated by 'gen_cpp_req_defines_h.tlc' */
#include "cpp_req_defines.h"
#include <mc9s12dp256.h> /* port definitions etc. */
#include "buffer.h" /* (ring)buffer macros */
#include "mc_signal.h" /* blinky, SCIx_Init(), etc. */
#include "tmwtypes.h"
#include "updown_util.h"
#include "ext_share.h"
#include "ext_svr_transport.h" /* ExtUserData */
#include "simstruc_types.h" /* RTWExtModeInfo, needed in updown.h */
#include "updown.h" /* ExtBufMemList */
/*=============*
* Global data *
*=============*/
/* size of the reception ring buffer */
#define RBUFSIZE 1024 // increase this value for block diagrams with many parameters!!
// e. g.: f14.c -> 980 bytes, shower.c -> 6604
//#define RBUFSIZE 8192 // e. g.: shower.c
/* serial communication ring buffer (reception) -- this buffer can be static */
static struct BufferTyp *RecBufPtr = NULL;
/* RTW ring buffer */
ringBuf_tag ringBuf;
/* controls the buffering of data, defined in ext_svr.c */
extern boolean_T volatile bufenable;
/***************** PRIVATE FUNCTIONS ******************************************
* *
* THE FOLLOWING FUNCTIONS ARE SPECIFIC TO THE TCPIP EXAMPLE OF HOST- *
* TARGET COMMUNICATION. SEE THE 'VISIBLE FUNCTIONS' SECTION FOR THE *
* GENERIC SET OF FUNCTIONS THAT ARE CALLED BY EXTERNAL MODE. TO IMPLEMENT *
* A CUSTOM VERSION OF EXTERNAL MODE (E.G. SHARED MEMORY, SERIAL CABLE, ETC)*
* THE BODIES OF THE FUNCTIONS IN THE 'VISIBLE FUNCTIONS' SECTION MUST BE *
* REPLACED. *
* *
******************************************************************************/
/* ==============================================================================
* Function: SCI[0/1]_RX_ isr ===================================================
* Abstract:
* This is the Interrupt Serial Routine for SCI[0/1] - services with reception,
* data is stored in the reception ring buffer
============================================================================== */
/* make sure we're using the right port... */
#if SCI0_COMMS == 1
#pragma CODE_SEG __NEAR_SEG NON_BANKED /* Interrupt section for this module. Placement will be in NON_BANKED area. */
/* MATLAB communication ISR */
__interrupt void SCI0_RX_isr(void) {
char_T inVal;
// set sertime_pin high (timing -> scope)
#ifdef TIMING
setSerTiPin;
#endif
/* determine cause of interrupt */
if((SCI0SR1 & RDRF_mask) != 0) {
/* Receive Data Register Full -> fetch character and store */
inVal = SCI0DRL; /* get value from register SCI0DRL */
InBuffer(inVal, RecBufPtr); /* write character to the (ring) buffer */
}
// reset sertime_pin (timing -> scope)
#ifdef TIMING
clrSerTiPin;
#endif
} /* SCI0_RX_isr */
#else /* SCI0_COMMS != 1 -> SCI1_COMMS == 1 (must be, otherwise this file would not have been included) */
#pragma CODE_SEG __NEAR_SEG NON_BANKED /* Interrupt section for this module. Placement will be in NON_BANKED area. */
/* MATLAB communication ISR */
__interrupt void SCI1_RX_isr(void) {
char_T inVal;
// set sertime_pin high (timing -> scope)
#ifdef TIMING
setSerTiPin;
#endif
/* determine cause of interrupt */
if((SCI1SR1 & RDRF_mask) != 0) {
/* Receive Data Register Full -> fetch character and store */
inVal = SCI1DRL; /* get value from register SCI1DRL */
InBuffer(inVal, RecBufPtr); /* write character to the (ring) buffer */
}
// reset sertime_pin (timing -> scope)
#ifdef TIMING
clrSerTiPin;
#endif
} /* SCI1_RX_isr */
#endif /* SCI1_COMMS == 1 */
#pragma CODE_SEG DEFAULT
/* Function: get_data_sp ====================================================
* Abstract:
* Gets data from the reception buffer. Data in this buffer has been put by
* by the ISR of the serial port. Therefore this function never acceses the
* RS232 serial port.
*/
static int_T get_data_sp(
const int_T nBytesToGet,
int_T *nBytesGot, /* out */
char_T *dst) /* out */
{
char_T *bufPtr = dst;
uint_T i = 0;
uint_T attempts = 0;
uint_T nBuf;
/* determine the amount of data currently stored in the reception buffer */
nBuf = Buffercounter(RecBufPtr);
if(nBuf > 0) {
/* something in the buffer */
/* start timeout timer (RTI) */
//RTI_counter = 0; /* reset RTI counter */
//CRGFLG = 0x80; /* clear RTIF flag (used as timeout flag) */
//RTICTL = 0x3F; /* start RTI, period = 262.14 ms (max) */
while (nBuf < nBytesToGet) {
/* on timeout -> exit from the while loop */
//if(RTI_counter == TIMEOUT) break;
/* check if the buffer counter has increased */
if(Buffercounter(RecBufPtr) > nBuf) {
/* new data has arrived -> update variable 'nBuf' and reset timer */
nBuf = Buffercounter(RecBufPtr);
//RTI_counter = 0; /* reset RTI_counter */
//CRGFLG = 0x80; /* clear RTIF flag (used as timeout flag) */
//RTICTL = 0x3F; /* (re-)start RTI, period = 262.14 ms (max) */
}
}
/* only return data if no timeout has occurred */
//if(RTI_counter != TIMEOUT) {
/* 'nBytesToGet' of data can now be read from the reception ring buffer */
for (i=0; i<nBytesToGet; i++) {
OutBuffer(RecBufPtr, *bufPtr++, char_T);
}
/* correct the information on the number of bytes currently stored in RecBuf */
nBuf -= nBytesToGet;
//}
/* stop timer */
//RTICTL = 0;
} /* nBuf > 0 */
/* return actual number of bytes which have been read from the reception buffer (0 or nBytesToGet) */
*nBytesGot = i;
/* also return the actual number of bytes in the buffer */
return nBuf;
} /* End of get_data_sp */
/* Function: put_data_sp ====================================================
* Abstract:
* Sends nbyte via the serial port ('S0')
*/
static void put_data_sp(
const uint_T nBytesToSet,
const char_T *src,
int_T *nBytesSet)
{
uint_T i;
for (i = 0; i < nBytesToSet; i++) {
/* make sure we're using the right port... */
#if SCI0_COMMS == 1
while((SCI0SR1 & TDRE_mask) == 0){}; // wait until the end of a possibly ongoing transmission
SCI0DRL = src[i]; // send character
#else /* SCI1_COMMS == 1 */
while((SCI1SR1 & TDRE_mask) == 0){}; // wait until the end of a possibly ongoing transmission
SCI1DRL = src[i]; // send character
#endif
}
*nBytesSet = i;
} /* end of put_data_sp */
/***************** VISIBLE FUNCTIONS ******************************************
* *
* YOU MUST REPLACE EACH OF THE FOLLOWING FUNCTIONS TO IMPLEMENT A CUSTOM *
* VERSION OF EXTERNAL MODE. *
* *
* ALSO SEE <MATLABROOT>/RTW/C/SRC/EXT_TRANSPORT_SHARE.H FOR ADDING DEFS FOR *
* YOUR CUSTOM IMPLEMENTATION THAT ARE REQUIRED BY BOTH THE HOST AND THE *
* TARGET. *
* *
******************************************************************************/
/* Function: init_ringBuf ==================================================
* Abstract:
* Initialises the ring buffer.
*/
PUBLIC void init_ringBuf(void) {
ringBuf.head = 0;
ringBuf.tail = 0;
ringBuf.size = RB_SIZE;
ringBuf.nRecords = 0;
(void)memset(&ringBuf.buf, 0, (uint16_T)ringBuf.size);
} /* init_ringBuf */
/* Function: put_data_buffer ===============================================
* Abstract:
* Put model signals into general buffer
*/
PUBLIC void put_data_buffer(void) {
int_T i;
ExtBufMemList upList;
/* only allow data logging if 'bufenable' (formerly called 'connected') is TRUE */
if (!bufenable) return;
UploadBufGetData(&upList);
while(upList.nActiveBufs > 0) {
//PORTB |= 0x02; /* LED2 on */
for (i=0; i<upList.nActiveBufs; i++) {
const BufMem *bufMem = &upList.bufs[i];
/* Check whether head has reached the end of the buffer. If so mark the byte with '0' so *
* that ext_svr knows which was the last packet sent, and set the head to offset zero. */
if ((ringBuf.head + bufMem->nBytes1 + bufMem->nBytes2 + 3) > ringBuf.size) {
//*(ringBuf.buf + ringBuf.head) = 0;
*(ringBuf.buf + ringBuf.head + 3) = 0; /* '+3' to account for byte inversion... fw-03-05 */
ringBuf.head = 0;
/* If tail = 0 the buffer is full. This case is not detected in the condiction below */
if (ringBuf.tail == 0) {
//abort_LED(43);
//UploadCancelLogging();
//break;
}
}
/* Check whether the buffer is full.*/
/* 9 comes from 8 + 1, where 8 are the bytes for the TRIGGER_TERMINATING message */
if ((((signed) (ringBuf.head - ringBuf.tail)) < 0) && \
((ringBuf.head + bufMem->nBytes1 + bufMem->nBytes2 + 3 + 9) > ringBuf.tail )) {
/* buffer wrapped (head < tail) and not enough space to store next telegram */
/* -> do nothing... tail's going to move, then there should be enough space... */
/* fw-03-05 */
//abort_LED(77);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -