📄 ext_comm.c
字号:
#if DEBUG_MSG_LVL >= 3
mexPrintf("ExtRecvIncomingMsg: checking for pending data\n");
#endif
/* no telegrams are currently pending... -> check COM */
error = ExtTargetTelPending(ES, &pending, 0, 0);
if (error) {
esSetError(ES, "ExtTagetTelPending() call failed while checking for message telegrams\n");
goto EXIT_POINT;
}
#if DEBUG_MSG_LVL >= 3
mexPrintf("ExtRecvIncomingMsg: pending = %d\n", (uint_T)pending);
#endif
}
else {
/* previously intercepted telegrams pending -> check if it was a message telegram */
if(userData->TelType == MSG) {
/* previously intercepted MSG telegram */
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtRecvIncomingMsg: previously detected MSG\n");
#endif
pending = TRUE;
}
else {
/* previously intercepted DAT/USR telegram */
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtRecvIncomingMsg: previously detected DAT/USR telegram\n");
#endif
goto EXIT_POINT;
}
}
if (!pending) {
#ifdef MODELSTUCK
if(ModelIsRunning) {
if(NoDataPending++ > 10000) {
//mexPrintf("Alarm\n");
NoDataPending = 0;
if(alarmCounter++ > 3) {
mexPrintf("Communication stuck\n");
alarmCounter = 0;
}
}
}
#endif
goto EXIT_POINT; /* nothing to read */
}
else {
/* check if the detected telegram is a message telegram */
if(userData->TelType != MSG) goto EXIT_POINT;
}
/*
* Process pending message.
*/
{
MsgHeader msgHdr;
/* assume that the entire message header can be read in one shot */
error = ExtGetTargetMsg(ES,sizeof(msgHdr),&nGot,(char_T *)&msgHdr);
if (error || (nGot != sizeof(msgHdr))) {
esSetError(ES, "ExtGetTargetMsg() call failed while checking target msg's\n");
goto EXIT_POINT;
}
#if DEBUG_MSG_LVL >= 1
printf("Message Received type %d size %d\n",msgHdr.type,msgHdr.size);
#endif
/* Convert the msg hdr to host format. */
Copy32BitsFromTarget(ES, (uint32_T *)&msgHdr, (char *)&msgHdr, NUM_HDR_ELS);
if (!esIsErrorClear(ES)) goto EXIT_POINT;
nBytesNeeded = msgHdr.size * esGetHostBytesPerTargetByte(ES);
assert(nBytesNeeded <= esGetIncomingMsgDataBufSize(ES));
/*
* We have a message pending. Set the flag and the type.
*/
esSetIncomingMsgPending(ES, TRUE);
esSetIncomingMsg(ES, (ExtModeAction)msgHdr.type);
}
}
/* we're done unless this is a message with data... */
if (nBytesNeeded == 0) goto EXIT_POINT;
/* message with data -> receive data */
bufPtr = buf + nBytes;
/* get message data (all in one shot) */
error = ExtGetTargetMsg(ES, nBytesNeeded, &nGot, bufPtr);
if(error) {
esSetError(ES, "recv() call failed while retrieving msg data\n");
goto EXIT_POINT;
}
#if DEBUG_MSG_LVL >= 2
{
int i;
if(nBytesNeeded > 0) {
mexPrintf("\nData Sent ... \n\t");
for(i=0;i<nBytesNeeded;i++)
mexPrintf("%d ",esGetCommBuf(ES)[i]);
mexPrintf("\n");
}
}
#endif
esSetIncomingMsgPending(ES, TRUE);
nBytesNeeded -= nGot;
nBytes += nGot;
bufPtr += nGot; //* unnecessary... re-initialized upon next entry of this function -- fw-03-05 */
assert(nBytesNeeded >= 0);
EXIT_POINT:
esSetIncomingMsgDataNBytesNeeded(ES, nBytesNeeded);
esSetIncomingMsgDataNBytesInBuf (ES, nBytes );
#if DEBUG_MSG_LVL >= 3
mexPrintf("ExtRecvIncomingMsg: OUT\n");
mexPrintf("-----------------------\n");
#endif
} /* end ExtRecvIncomingMsg */
/* Function: ExtRecvIncomingLogData ============================================
* Abstract:
* Check and get upload data for 1 time point from one target tid buffer.
* In order to prevent the Simulink GUI, from "locking up", this function
* should not block indefinately. As such, there is no guarantee that all
* of the data corresponding to this time point will be retrieved via one
* call to this function. In the case where only a partial buffer is
* available, Simulink will hold onto the partial data buffer (in the
* ES data structure) and pass the partially filled buffer back into this
* function on the next call.
*
* NOTES:
* o 'nBytes' will be 0 if the buffer is empty. Otherwise, it contains
* the number of bytes that are currently held in the buffer (i.e., the
* part of the current time step that has previously arrived).
* o 'nBytesNeeded' will be 0 when - and only when - 'data' contains all of
* the data for the current time point
*
* o the data that is being received from the target is of the form:
* [nbytes data...][nbytes data...][nbytes data...], where nbytes
* is the number of bytes:
* - including itself
* - representing the target interpretation of a byte (not necessarily
* 8 bits)
* - in target data format (e.g., may need to be converted to host
* format)
* data is:
* - one time step of upload data corresponding to a given tid
* - in target data format (will be converted by Simulink via calls
* to ext_convert.c).
*/
PRIVATE void ExtRecvIncomingLogData(
ExternalSim *ES,
int_T nrhs,
const mxArray *prhs[])
{
int_T nGot;
boolean_T pending;
boolean_T error = EXT_NO_ERROR;
char *buf = esGetIncomingLogDataBuf(ES);
int32_T nBytesNeeded = esGetIncomingLogDataNBytesNeeded(ES);
int nBytes = esGetIncomingLogDataNBytesInBuf(ES);
UserData *userData = (UserData *)esGetUserData(ES);
(void)nrhs; /* unused */
(void)prhs; /* unused */
#if DEBUG_MSG_LVL >= 3
mexPrintf("\n--------------------------\n");
mexPrintf("ExtRecvIncomingLogData: IN\n");
#endif
/* check for new data telegrams */
if (nBytesNeeded == UNKNOWN_BYTES_NEEDED) {
assert(nBytes == 0);
/*
* Check for pending upload data. If none, nothing to do.
*/
#if DEBUG_MSG_LVL >= 3
mexPrintf("ExtRecvIncomingLogData: userData->TelType = %d\n", (uint_T)userData->TelType);
#endif
if(userData->TelType == 0) {
/* no telegrams are currently pending... -> check COM */
error = ExtTargetTelPending(ES, &pending, 0, 0);
if (error) {
esSetError(ES, "ExtTagetTelPending() call failed while checking for data telegrams\n");
goto EXIT_POINT;
}
}
else {
/* previously intercepted telegrams pending -> check if it was a data telegram */
if(userData->TelType == MSG) {
/* previously intercepted MSG telegram */
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtRecvIncomingLogData: previously detected MSG\n");
#endif
goto EXIT_POINT;
}
else {
/* previously intercepted DAT/USR telegram */
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtRecvIncomingLogData: previously detected DAT/USR telegram\n");
#endif
pending = TRUE;
}
}
if (!pending) {
#ifdef ERASE
/* nothing to read - request data (every 10 idle loops) -- fw-03-05 */
if(noRequestDataCounter++ > 10) {
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtRecvIncomingLogData: 10th idle transmission loop -> request data transmission.\n");
#endif
noRequestDataCounter = 0;
RequestDataTelegram(ES);
}
#endif
goto EXIT_POINT;
}
else {
/* bypass remainder of this function if a message was detected */
if(userData->TelType == MSG) goto EXIT_POINT;
}
/* DAT or USR have been detected -> both treated as 'data', ExtGetTargetData filters out USR data */
/*
* Read the nBytes field. Assume that the entire integer
* is available.
*/
error = ExtGetTargetData(ES, sizeof(int32_T), &nGot, buf);
if (error || (nGot != sizeof(int32_T))) {
/* 'nGot == -1' signifies the receipt of a USR TEL >> no error! (FW-01-03) */
if(nGot != -1) {
esSetError(ES, "recv() call failed while checking target data\n");
}
else {
/* finished uploading the USR telegram -> return */
nBytesNeeded = UNKNOWN_BYTES_NEEDED; /* << possibly to be 0 */
nBytes = 0;
/* possibly need to request next data telegram */
//RequestDataTelegram(ES);
}
goto EXIT_POINT;
}
#if DEBUG_MSG_LVL >= 3
mexPrintf("\nData received...\n\t");
mexPrintf("%d %d %d %d \n",buf[0],buf[1],buf[2],buf[3]);
fflush(stdout);
#endif
Copy32BitsFromTarget(ES, &nBytesNeeded, buf, 1);
if (!esIsErrorClear(ES)) goto EXIT_POINT;
nBytesNeeded *= esGetHostBytesPerTargetByte(ES);
assert(nBytesNeeded <= esGetIncomingLogDataBufSize(ES));
nBytes = sizeof(int32_T); /* this is what we have so far */
nBytesNeeded -= sizeof(int32_T); /* this is what we still need... */
} /*if (nBytesNeeded == UNKNOWN_BYTES_NEEDED) */
/*
* Retrieve data (all in one shot)
*/
error = ExtGetTargetData(ES, nBytesNeeded, &nGot, (char *)(buf + nBytes));
if (error) {
esSetError(ES, "recv() call failed while uploading target data\n");
goto EXIT_POINT;
}
nBytesNeeded -= nGot; /* should be 0 now */
nBytes += nGot; /* should be the required size now */
assert(nBytesNeeded >= 0);
/* request next upload -- or not */
if(nBytesNeeded == 0) {
/* check if EXT_DISCONNECT_CONFIRMED has been received */
if(buf[0] == 8) {
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtRecvIncomingLogData: Got an 8-%d-message.\n", (int_T)buf[4]);
#endif
if(buf[4] == 5) {
/* received EXT_DISCONNECT_CONFIRMED -> don't request upload */
userData->ExtDisconnectConfirmed = TRUE;
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtRecvIncomingLogData: EXT_DISCONNECT_CONFIRMED -> not sending any further upload requests\n");
#endif
//Sleep(2000);
}
else {
/* request next data telegram (without acknowledgement) */
RequestDataTelegram(ES);
}
}
else {
/* request next data telegram (without acknowledgement) */
RequestDataTelegram(ES);
}
}
else {
#if DEBUG_MSG_LVL >= 2
mexPrintf("ExtRecvIncomingLogData: nBytesNeeded = %d, nGot = %d\n", nBytesNeeded, nGot);
#endif
if(nGot == 0) {
/* timeout occurred during reception -> discard data... */
#if DEBUG_MSG_LVL >= 1
mexPrintf("ExtRecvIncomingLogData: data telegram length '0' (discarded data or incoming user telegram)\n");
mexPrintf("ExtRecvIncomingLogData: Requesting next data telegram (TXactive)\n");
#endif
/* enable next target data upload */
RequestDataTelegram(ES);
#if DEBUG_MSG_LVL >= 1
mexPrintf("ExtRecvIncomingLogData: next telegram requested (RequestDataTelegram). Exiting...\n");
#endif
/* set data telegram length to zero ('esSetIncomingLogData...') */
nBytesNeeded = UNKNOWN_BYTES_NEEDED;
nBytes = 0;
}
} /* if(nBytesNeeded == 0) */
EXIT_POINT:
esSetIncomingLogDataNBytesNeeded(ES, nBytesNeeded);
esSetIncomingLogDataNBytesInBuf (ES, nBytes );
#if DEBUG_MSG_LVL >= 3
mexPrintf("ExtRecvIncomingLogData: OUT\n");
mexPrintf("---------------------------\n");
#endif
} /* end ExtRecvIncomingLogData */
/* Function: ExtConnect ========================================================
* Abstract:
* Establish communication with target.
*/
PRIVATE void ExtConnect(
ExternalSim *ES,
int_T nrhs,
const mxArray *prhs[])
{
int_T nGot;
int_T nSet;
MsgHeader msgHdr;
int16_T one = 1;
boolean_T error = EXT_NO_ERROR;
mexLock();
{
UserData *userData = ExtUserDataCreate();
if (userData == NULL) {
esSetError(ES, "Memory allocation error.");
goto EXIT_POINT;
}
esSetUserData(ES, (void*)userData);
}
/*
* Parse the arguments.
*/
assert(esIsErrorClear(ES));
ExtProcessArgs(ES,nrhs,prhs);
if (!esIsErrorClear(ES)) goto EXIT_POINT;
assert(esIsErrorClear(ES));
ExtOpenConnection(ES);
if (!esIsErrorClear(ES)) goto EXIT_POINT;
/*
* Send the EXT_CONNECT msg to the target. This message consists
* of the string 'ext-mode'. The purpose of this header is to serve
* as a flag to start the handshaking process.
*/
#if DEBUG_MSG_LVL >= 3
mexPrintf("ExtConnect: Sending 'ext-mode'\n");
#endif
(void)memcpy((void *)&msgHdr,"ext-mode",8);
error = ExtSetTargetMsg(ES,sizeof(msgHdr),(char *)&msgHdr,&nSet);
if (error || (nSet != sizeof(msgHdr))) {
esSetError(ES, "ExtSetTargetMsg() call failed on EXT_CONNECT.\n"
"Ensure target is still running\n");
goto EXIT_POINT;
}
/*
* Get the first of two EXT_CONNECT_RESPONSE messages. See the
* ext_conv.c/ProcessConnectResponse1() function for a description of
* the message.
*
* NOTE: Until both EXT_CONNECT_RESPONSE messages are read, messages
* received from the target consists solely of unsigned 32 bit
* integers.
*/
#if DEBUG_MSG_LVL >= 3
mexPrintf("ExtConnect: Receiving EXT_CONNECT_RESPONSE (1/2)\n");
#endif
error = ExtGetTargetMsg(ES,sizeof(msgHdr),&nGot,(char_T *)&msgHdr);
if (error || (nGot != sizeof(msgHdr))) {
esSetError(ES, "ExtGetTargetMsg() call failed on 1st EXT_CONNECT_RESPONSE 1.\n");
goto EXIT_POINT;
}
#if DEBUG_MSG_LVL >= 4
{
int_T i;
for(i=0; i<sizeof(msgHdr); i++)
mexPrintf("ExtConnect: ExtGetTargetMsg returned [%d/%d]) %d\n", i+1, sizeof(msgHdr), (uint_T)*((char_T *)&msgHdr + i));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -