📄 ext_transport232.c
字号:
/*
* Copyright 1994-2001 The MathWorks, Inc.
*
* File: ext_transport.c $Revision: 1.7 $
*
* Abstract:
* Host-side, transport-dependent external mode functions and defs. This
* example file implements host/target communication using an RS232 serial
* connection (FW-09-02).Functionality supplied by this module includes:
*
*
* >>>>> modified: FW-01-03
*
*
* o definition of 'UserData'
* o is target message pending
* o is target upload data pending
* o get bytes from target message line
* o set bytes on target message line
* o get bytes from target data upload line
* o close connection with target
* o open connection with target
* o create user data
* o destroy user data
* o process command line arguments
*
* Note:
* This mex file specifies the signal, SIGPIPE, be ignored.
*
* The files relating to host-side external mode are:
* ext_main.c
* The mex file interface to Simulink. This gets/sets message flags
* and data from/to Simulink and dispatches as approriate to ext_comm.c.
*
* [THIS FILE SHOULD NOT NEED TO BE MODIFIED]
*
* ext_comm.c
* Transport-independent external mode functions. Handles external mode
* tasks and dispatches all transport-specific tasks (e.g., TCPIP) to
* this file (ext_custom.c).
*
* [THIS FILE SHOULD NOT NEED TO BE MODIFIED FOR DIFFERENT TRANSPORT
* MECHANISMS]
*
* ext_transport.c
* This file. Transport-dependent implementation of the mandatory
* support functions (e.g., set bytes, get bytes, open connection, etc).
*
* [THIS FILE NEEDS TO BE MODIFIED TO IMPLEMENT VARIOUS DATA TRANSPORT
* MECHANISMS]
*
* <matlabroot>/rtw/c/src/ext_transport_share.h
* Defininitions that are specific to the implemented transport mechanism
* and that are required on both the host and the target.
*
* [THIS FILE NEEDS TO BE MODIFIED TO IMPLEMENT VARIOUS DATA TRANSPORT
* MECHANISMS]
*
* ext_convert.c
* Conversion routines from host to target and vice versa. All conversion
* is done on the host. The target always sends and receives data in
* it's native format.
*
* [THIS FILE DOES NOT NEED TO BE CUSTOMIZED FOR VARIOUS TRANSPORT
* MECHANISMS, BUT DOES NEED TO BE CUSTOMIZED FOR THE INTENDED TARGET.
* FOR EXAMPLE, IF THE TARGET REPRESENTS FLOATS IN TI FORMAT, THEN
* EXT_CONVERT MUST BE MODIFIED TO PERFORM A TI TO IEEE CONVERSION.
* THE CONVERSION ROUTINES IN THIS FILE ARE CALLED BOTH FROM
* EXT_COMM AND DIRECTLY FROM SIMULINK (VIA FUNCTION POINTERS)]
*
* **** SUMMARY ****
* To implement a different transport mechanism you need to do the following
* on the host:
* o modify this file
* o modify ext_transport_share.h
*
* For the target, see <matlabroot>/rtw/c/src/ext_svr_transport.c.
*/
#include <windows.h> // BuildCommDCB, CloseHandle, CreateFile, EscapeCommFunction, GetCommState,
// GetLastError, ReadFile, SetCommState, SetCommTimeouts, WriteFile, FlushFileBuffers
// Sleep
#include <stdio.h> // sprintf
#include <stdlib.h> // malloc, calloc
#include <string.h> // memcpy
#include <math.h> // ceil
#include "tmwtypes.h"
#include "mex.h"
#include "extsim.h"
#include "extutil.h"
#include "ext_convert.h" // slCopyNBytes (added: fw-02-05)
#include "ext_share.h" // MsgHeader {(uint32_T)type, (uint32_T)size}, NUM_HDR_ELS (2)
#include "ext_transport232.h" // Definition of UserData_tag, etc.
/* set verbosity of debugging messages (0, 1, 2, 3 or 4 -> set this to 0 in the release version) */
#define DEBUG_MSG_LVL 0
/* communication bytes (FW-01-03) */
#define ACK_SUCCESS 31
#define ACK_NO_SUCCESS 32
#define USR 33 /* user data telegrams */
#define DAT 34 /* log data telegrams */
#define MES 35 /* message telegrams */
/***************** DEFINE USER DATA HERE **************************************
* *
* THE DEFINITION OF USER DATA IS SPECIFIC TO THE TRANSPORT IMPLEMENTATION. *
* IT IS EXPORTED AS AN 'OPAQUE' OR 'INCOMPLETE' TYPE IN EXT_TRANSORT.H. SEE *
* EXT_TRANSPORT.H FOR MORE INFO. *
* *
* NOTE THAT USERDATA MUST EXIST. IF NOT NEEDED, DEFINE IT TO HAVE ONE DUMMY *
* FIELD *
* *
******************************************************************************/
// typedef struct UserData_tag {} UserData ... moved to 'ext_transport.h'
/* local data buffer -- used to store intercepted data packages until Simulink gets'em */
static uint8_T interceptDatBuf[1024];
static uint8_T tempSendMsgBuf[1024]; /* used in conjunction with targets that need byte re-ordering -- fw-02-05 */
static uint8_T interceptMsgBuf[1024];
/* declare global admin variables of the communication buffers (defined in ext_comm.c) */
typedef struct myUsrBuf_tag {
int_T buffer_full;
uint_T access_count;
uint_T buf_size;
uint8_T *buf;
} myUsrBuf;
extern myUsrBuf *userTelBuf[]; /* pointer to the data buffers of outgoing user telegrams */
/***************** 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: checkCOMforData ===================================================
* check if there's data in the COM buffer (FW-09-02)
*/
static int checkCOMforData(HANDLE fd) {
COMSTAT cs;
DWORD error;
// reset error status (returns structure COMSTAT [winbase.h])
if(!ClearCommError(fd, (LPDWORD)&error, (LPCOMSTAT)&cs)) {
// error during call to ClearCommError
mexPrintf("checkCOM4data: Error during call to ClearCommError.\n");
// flag error to the calling function
return(-1);
}
else {
#if DEBUG_MSG_LVL >= 3
mexPrintf("ExtTagetTelPending: checkCOMforData detected %d data bytes in COM buffer\n", (int)cs.cbInQue);
#endif
// return number of bytes in the buffer
return((int)cs.cbInQue);
}
} /* end checkCOMforData */
/***************** 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: ExtTargetTelPending ===============================================
* Abstract:
* Returns true via the 'pending' arg, if a telegram is pending. The type of
* data received (MES, DAT, USR) is stored in userData->TelType
* Returns EXT_NO_ERROR on success (no timeouts etc.), EXT_ERROR otherwise.
*/
PUBLIC boolean_T ExtTargetTelPending(
ExternalSim *ES,
boolean_T *pending,
long int timeOutSecs,
long int timeOutUSecs)
{
UserData *userData = (UserData *)esGetUserData(ES);
uint_T nBytesGot;
int_T lookforACK;
char_T dst;
/* repeat this section a second time, in case a (trailing) acknowledgement is received */
lookforACK = 1;
while(lookforACK) {
/* nothing has been received yet; -> check if new data is waiting in the COM buffer */
if(checkCOMforData(userData->hCom) > 0) {
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtTagetTelPending: data available COM\n");
#endif
// there is... -> retrieve first byte to determine the telegram type [message / data / usr data]
if(ReadFile(userData->hCom, (LPSTR)&dst, 1, &nBytesGot, NULL)) {
if (nBytesGot == 1) {
// determine telegram type
switch((int_T)dst) {
case ACK_SUCCESS:
/* target is uploading a message (8 bytes) on the data channel -> remove trailing ACK_SUCCESS */
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtTagetTelPending: removing trailing ACK_SUCCESS signal.\n");
#endif
/* check if this is the trailing ACK_SUCCESS following ExtDisconnectConfirmed */
if(userData->ExtDisconnectConfirmed == TRUE) {
/* indeed... -> reset ExtDisconnectConfirmed flag */
userData->ExtDisconnectConfirmed = FALSE;
/* flag 'no telgram available' to the calling function and exit from the while loop */
*pending = FALSE;
lookforACK--;
}
/* else -> lookforACK remains '1' ... go 'round the while loop */
break; /* switch */
case MES:
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtTagetTelPending: message telegram detected.\n");
#endif
userData->TelType = MES; /* signal the receipt of an MES telegram */
/* flag 'telegram available' to the calling function and return */
*pending = TRUE;
lookforACK--;
break; /* switch */
case USR:
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtTagetTelPending: user telegram detected.\n");
#endif
userData->TelType = USR; /* signal the receipt of an USR telegram */
/* flag 'telegram available' to the calling function and return */
*pending = TRUE;
lookforACK--;
break; /* switch */
case DAT:
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtTagetTelPending: data telegram detected.\n");
#endif
userData->TelType = DAT; /* signal the receipt of an DAT telegram */
/* flag 'telegram available' to the calling function and return */
*pending = TRUE;
lookforACK--;
break; /* switch */
default:
/* communication error... unexpected telegram type */
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtTagetTelPending: unknown telegram detected (%d).\n", (int_T)dst);
#endif
#ifdef ERASE
// debug only
{
int_T i = 0;
int_T oneByteGot = 0;
while((int_T)dst != 8 && i++ < 10) {
if(ReadFile(userData->hCom, (LPSTR)&dst, 1, &oneByteGot, NULL)) {
mexPrintf("next byte (%d): %d\n", (uint_T)dst, i);
}
else {
mexPrintf("read error\n");
}
}
}
#endif
/* return with an error */
return EXT_ERROR;
} /* switch */
}
else {
/* nBytesGot != 1 -> TIMEOUT occurred during reception */
mexPrintf ("ExtTagetTelPending: Timeout occurred during reception of telegram type (ReadFile).\n");
{
DWORD err = GetLastError();
mexPrintf("Error code: %ld\n", err);
}
/* return with an error */
return EXT_ERROR;
}
}
else {
/* unspecified error during data reception (ReadFile) */
mexPrintf ("ExtTagetTelPending: Unspecified error during data reception (ReadFile).\n");
/* return with an error */
return EXT_ERROR;
}
} /* end of: check COM buffer if there is any data at all */
else {
/* nothing in COM -> return with 'FALSE' (currently nothing pending) */
*pending = FALSE;
lookforACK--;
}
} /* while(lookforACK) */
/* successful detection of telegram type byte (or nothing) */
return EXT_NO_ERROR;
} /* end ExtTagetTelPending */
/* Function: ExtGetTargetMsg ===================================================
* Abstract:
* Attempts to get the specified number of bytes from the msg buffer. The number
* of bytes read is returned via the 'nBytesGot' parameter. EXT_NO_ERROR is
* returned on success, EXT_ERROR is returned on failure.
*
* NOTES:
* o it is not an error for 'nBytesGot' to be returned as 0
* o it is o.k. for this function to block if no data is available
*/
PUBLIC boolean_T ExtGetTargetMsg(
ExternalSim *ES,
const int nBytesToGet,
int *nBytesGot, /* out */
char *dst) /* out */
{
UserData *userData = (UserData *)esGetUserData(ES);
/* check if the ENTIRE message is already available in interceptMsgBuf[1 ... 8] (-> intercepted MsgHdr) */
if(userData->MsgTelIntercepted == TRUE) {
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtGetTargetMsg: Previously intercepted message header available in interceptMsgBuf\n");
#endif
/* yep... -> fetch it from there */
memcpy(dst, interceptMsgBuf, 8);
/* adjust number of bytes received */
*nBytesGot = 8;
/* re-order bytes (ms9S12) -- fw-02-05 */
//slCopyNBytes(dst, dst, *nBytesGot, TRUE, 4);
{
int_T i;
char_T dat;
for(i=0; i<*nBytesGot; i +=4) {
dat = dst[i+3];
dst[i+3] = dst[i+0];
dst[i+0] = dat;
dat = dst[i+2];
dst[i+2] = dst[i+1];
dst[i+1] = dat;
}
}
/* reset TelType & MsgTelIntercepted */
userData->TelType = 0;
userData->MsgTelIntercepted = FALSE;
#if DEBUG_MSG_LVL >= 2
{
int_T i;
for(i=0; i<8; i++)
mexPrintf("ExtGetTargetMsg: previously intercepted message [%d/8]) %d\n", i+1, (uint_T)(dst[i]));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -