📄 ext_serial_utils.c
字号:
boolean_T error=EXT_NO_ERROR;
// local function name... debugging only
#if DEBUG_MSG_LVL > 0
const char *funct_name="ExtGetPktBlocking";
#endif
PRINT_DEBUG_MSG_LVL3("IN");
PRINT_DEBUG_MSG_NL3;
#ifndef MATLAB_MEX_FILE
#if DEBUG_MSG_LVL > 0
/* nBytesAvailable = MAX_SERIAL_PKT_SIZE -> display up to MAX_SERIAL_PKT_SIZE bytes... */
ExtSerialPortPeekRB(MAX_SERIAL_PKT_SIZE);
#endif
#endif /* MATLAB_MEX_FILE */
/* Block until a packet is available from the comm line. */
error=GetExtSerialPacket(InBuffer, portDev);
PRINT_DEBUG_MSG_LVL1_Raw(">");
PRINT_DEBUG_MSG_NL1;
#if DEBUG_MSG_LVL > 0
DisplayActualReceivedPacket(InBuffer);
#endif
if(error!=EXT_NO_ERROR) {
/* never happens, errors caught above -- fw-07-07 */
abort_LED(23); // just in case
PRINT_DEBUG_MSG_LVL3("Error in call to GetExtSerialPacket\n\r");
goto EXIT_POINT;
}
PRINT_DEBUG_MSG_LVL3("Received valid packet. Type: ");
PRINT_DEBUG_MSG_LVL3_UDec((uint16_T)(InBuffer->PacketType));
PRINT_DEBUG_MSG_NL3;
PRINT_DEBUG_MSG_LVL3(debugTelTypeStrings[(uint16_T)InBuffer->PacketType]);
PRINT_DEBUG_MSG_NL3;
#ifdef MATLAB_MEX_FILE
#if DEBUG_MSG_LVL > 0
if(InBuffer->PacketType==EXTMODE_PACKET&&InBuffer->BufferSize>=4) {
uint8_T myAction=InBuffer->Buffer[3]; // stored in reverse order, e.g. 0 0 0 27
PRINT_DEBUG_MSG_LVL3("Payload indicates data action (if it is an action at all...): 0x");
PRINT_DEBUG_MSG_LVL3_UHex(myAction);
if(myAction<numActionStrings) {
PRINT_DEBUG_MSG_LVL3_Raw(" (");
PRINT_DEBUG_MSG_LVL3_Raw(debugActionStrings[myAction]);
PRINT_DEBUG_MSG_LVL3_Raw(")");
if(InBuffer->PacketType==EXTMODE_PACKET&&InBuffer->BufferSize>=8) {
uint8_T mySize=InBuffer->Buffer[7]; // stored in reverse order, e.g. 0 0 0 size(<=255)
PRINT_DEBUG_MSG_LVL3_Raw(", data size: 0x");
PRINT_DEBUG_MSG_LVL3_UHex(mySize);
PRINT_DEBUG_MSG_LVL3_Raw(" (");
PRINT_DEBUG_MSG_LVL3_UDec(mySize);
PRINT_DEBUG_MSG_LVL3_Raw(" bytes)");
}
}
PRINT_DEBUG_MSG_NL3;
}
#endif /* DEBUG_MSG_LVL */
#endif /* MATLAB_MEX_FILE */
/* Process ACK packets, don't pass on to application. */
if(InBuffer->PacketType==ACK_PACKET) {
PRINT_DEBUG_MSG_LVL3("Received ACK_PACKET -> waitForAck = FALSE;");
PRINT_DEBUG_MSG_NL3;
waitForAck = FALSE;
#ifdef HOSTALIVECHECK
HostIsAlive = TRUE; /* automatic target data buffer control -- fw-07-07 */
#endif
goto EXIT_POINT;
}
PRINT_DEBUG_MSG_LVL3("Storing received EXTMODE_PACKET in FIFO buffer");
PRINT_DEBUG_MSG_NL3;
SavePkt(InBuffer->Buffer, (int_T)(InBuffer->size));
if(!isFIFOFreeEmpty()) {
int bytesWritten;
PRINT_DEBUG_MSG_LVL3("Sending ACK_PACKET to acknowledge the receipt of the received EXTMODE_PACKET");
PRINT_DEBUG_MSG_NL3;
error=ExtSetPkt(portDev, NULL, 0, &bytesWritten, ACK_PACKET);
if(error!=EXT_NO_ERROR) {
PRINT_DEBUG_MSG_LVL3("Error in call to ExtSetPkt (while sending ACK_PACKET)");
PRINT_DEBUG_MSG_NL3;
/* never happens, errors caught above -- fw-07-07 */
abort_LED(24); // just in case
goto EXIT_POINT;
}
}
EXIT_POINT:
PRINT_DEBUG_MSG_LVL3("OUT, error status: ");
PRINT_DEBUG_MSG_LVL3_UDec(error);
PRINT_DEBUG_MSG_NL3;
return error;
} /* end ExtGetPktBlocking */
/* Function: ExtSetPkt =========================================================
* Abstract:
* Sets (sends) the specified number of bytes on the comm line. As long as an
* error does not occur, this function is guaranteed to set the requested
* number of bytes. The number of bytes set is returned via the 'nBytesSet'
* parameter. If a previously sent packet has not yet received an ACK, then we
* block for the next packet which must be an ACK.
*
* EXT_NO_ERROR is returned on success, EXT_ERROR on failure.
*/
PRIVATE boolean_T ExtSetPkt(ExtSerialPort *portDev, char *pktData, int pktSize, int *bytesWritten, PacketTypeEnum pktType) {
int bytesToSend;
int deadlockCntr;
boolean_T error=EXT_NO_ERROR;
// local function name... debugging only
#if DEBUG_MSG_LVL > 0
const char *funct_name="ExtSetPkt";
#endif
bytesToSend=(pktSize>MAX_SERIAL_PKT_SIZE)?MAX_SERIAL_PKT_SIZE:pktSize;
*bytesWritten=bytesToSend;
PRINT_DEBUG_MSG_LVL3("IN");
PRINT_DEBUG_MSG_NL3;
#if COMMSTATE_ON_PTT == 1
/* display current state of 'waitForAck' on PTT.1 */
if(waitForAck) {
PTT|=0x01;
}
else {
PTT&=~0x01;
}
#endif
/* debug: display current 'waitForAck' state on SCI0 */
#if DEBUG_MSG_LVL > 0
if(pktType != ACK_PACKET) {
if(waitForAck) {
PRINT_DEBUG_MSG_LVL3("waitForAck = TRUE -> need to wait for ACK_PACKET");
PRINT_DEBUG_MSG_NL3;
}
/* else message is printed below... (otherwise the 'clear to send' appears twice... */
} else {
PRINT_DEBUG_MSG_LVL3("Sending (regular) ACK_PACKET... (always possible, regardless the state of the 'waitForAck' flag)");
PRINT_DEBUG_MSG_NL3;
}
#endif
/*
* Wait for an ACK packet if needed. Every packet sent must be ACKed before
* another can be sent (the only exceptions are ACK packets which are never
* ACKed).
*/
deadlockCntr=0;
while(waitForAck && (pktType!=ACK_PACKET)) {
int32_T numPending = 0;
error=ExtSerialPortDataPending(portDev, &numPending);
if(error!=EXT_NO_ERROR) {
/* never happens, errors caught above -- fw-07-07 */
abort_LED(25); // just in case
goto EXIT_POINT;
}
/* NOTE: check for '>0' because the host sided version of 'ExtSerialPortDataPending'
* returns the actual number of bytes on the target instead of the number
* packets (on the target numPending is returned '1' if there's a full packet
* in the ring buffer, '0' if not and '-1' in case of a target comms timeout)
*
* fw-07-07
*/
if(numPending > 0) {
PRINT_DEBUG_MSG_LVL1_Raw("<3");
PRINT_DEBUG_MSG_LVL3("Making blocking call to fetch the data from the comms line...");
PRINT_DEBUG_MSG_NL3;
error=ExtGetPktBlocking(portDev);
if(error!=EXT_NO_ERROR) {
/* never happens, errors caught above -- fw-07-07 */
abort_LED(26); // just in case
goto EXIT_POINT;
}
}
/* on the target only... */
#ifndef MATLAB_MEX_FILE
else {
if(numPending == -1) {
/* target timeout has been detected... */
/* incomplete ACK_PACKET (currently only an assumption! -> perform check) packet has been removed */
PRINT_DEBUG_MSG_LVL1("Target timeout, setting waitForAck = FALSE\n\r");
waitForAck = false;
break; /* exit from the while loop */
}
}
#endif /* MATLAB_MEX_FILE */
/*
* If we are in this loop, it means we are trying to send a pkt but
* have not received an ACK from the other side. If we don't get an
* ACK after some amount of time, we may be in a deadlock condition
* where both sides are waiting for an ACK. In this case, allocating
* some more free packets will break the deadlock condition.
*/
if((++deadlockCntr>=200) && isFIFOFreeEmpty()) {
int temp;
PRINT_DEBUG_MSG_LVL3("ACK deadlock situation detected (host & target might be waiting for ACK)\n\r");
deadlockCntr=0;
error=AddToFIFOFree();
if(error!=EXT_NO_ERROR) {
abort_LED(27);
goto EXIT_POINT;
}
PRINT_DEBUG_MSG_LVL3("Sending ACK_PACKET to target to (hopefully) unblock communication\n\r");
error=ExtSetPkt(portDev, NULL, 0, &temp, ACK_PACKET);
if(error!=EXT_NO_ERROR) {
/* never happens, errors caught above -- fw-07-07 */
abort_LED(28); // just in case
goto EXIT_POINT;
}
} /* if(++deadlockCntr...) */
/*
* THE FOLLOWING 'MESS' SEEMED NECESSARY WHEN THE TARGET GOT STUCK ON READING FROM THE
* SERIAL LINE - THIS TURNED OUT TO BE BECAUSE OF THE WAY FUNCTION 'ExtSerialPortDataPending'
* (EXT_SERIAL_9S12_PORT.C) USED TO WORK... THE MODIFIED 'ExtSerialPortDataPending' NOW ONLY
* INDICATES PENDING DATA WHEN AT LEAST ONE "FULL DATA PACKET" HAS BEEN RECEIVED. PREVIOUSLY,
* THE FUNCTION SIMPLY RETURNED THE NUMBER OF "BYTES"...
*
* WITH THE NEW 'ExtSerialPortDataPending' THE ARTIFICIAL BREAKING OF THE DEADLOCK ON THE
* TARGET HAS BECOME UNNECESSARY.
*
* fw-07-07
*/
/* do not define DEADLOCK_EMERGENCY_TARGET !!! -- fw-07-07 */
#ifdef DEADLOCK_EMERGENCY_TARGET
else {
#ifdef MATLAB_MEX_FILE
if(((HostStatus == HOST_STATUS_CONNECTING) ||
(HostStatus == HOST_STATUS_RUNNING)) &&
(deadlockCntr > 200)) {
//if(deadlockCntr > 200) {
#else
//if(startModel && deadlockCntr>200) {
if(deadlockCntr>200) {
#endif
int temp;
deadlockCntr=0;
/* FIFO buffer not empty but clearly there is a deadlock...
... forget about it and force host to send an ACK_PACKET -- fw-07-07 */
PRINT_DEBUG_MSG_LVL1("Forcing 'waitForAck = FALSE' (to break local deadlock)");
PRINT_DEBUG_MSG_NL1;
waitForAck=false;
#ifdef MATLAB_MEX_FILE
PRINT_DEBUG_MSG_LVL3("Sending an ACK_PACKET to the target to break the remote deadlock\n");
//#ifdef ERASE
error=ExtSetPkt(portDev, NULL, 0, &temp, ACK_PACKET);
if(error!=EXT_NO_ERROR) {
/* never happens, errors caught above -- fw-07-07 */
abort_LED(28); // just in case
goto EXIT_POINT;
}
//#endif
#endif
} /* deadlockCntr > 200 */
} /* else */
#endif /* DEADLOCK_EMERGENCY_TARGET */
} /* while */
/*
* Write the packet to the outgoing buffer. The output buffer is
* guaranteed to be big enough to hold the maximum size packet.
*/
OutBuffer->size=(uint32_T)bytesToSend;
OutBuffer->PacketType=(char)pktType;
memcpy(OutBuffer->Buffer, pktData, (uint_T)bytesToSend);
/*
#if DEBUG_MSG_LVL >= 3
{
int i;
for(i=0; i<bytesToSend; i++) {
PRINT_DEBUG_MSG_LVL3("ExtSetPkt: Data to be sent: 0x");
PRINT_DEBUG_MSG_LVL3_UHex((uint8_T)pktData[i]);
PRINT_DEBUG_MSG_NL3;
}
}
#endif
*/
/* Finally read to send the packet over the comm line... =================================*/
#if DEBUG_MSG_LVL > 0
if(pktType!=ACK_PACKET) {
PRINT_DEBUG_MSG_LVL3("waitForAck = FALSE -> clear to send");
PRINT_DEBUG_MSG_NL3;
}
#endif
PRINT_DEBUG_MSG_LVL3("Sending now...");
PRINT_DEBUG_MSG_NL3;
error=SetExtSerialPacket(OutBuffer, portDev);
if(error!=EXT_NO_ERROR) {
/* never happens, errors caught above -- fw-07-07 */
// temporarily disable to throw an error in the calling methods instead -- fw-07-07
//abort_LED(29); // just in case
goto EXIT_POINT;
}
EXIT_POINT:PRINT_DEBUG_MSG_LVL3("OUT, error status: ");
PRINT_DEBUG_MSG_LVL3_UDec(error);
PRINT_DEBUG_MSG_NL3;
return error;
} /* end ExtSetPkt */
/* Function: ExtSetPktWithACK ==================================================
* Abstract:
* Sets (sends) the specified number of bytes on the comm line and waits for a
* return packet. As long as an error does not occur, this function is
* guaranteed to set the requested number of bytes. The number of bytes set is
* returned via the 'nBytesSet' parameter.
*
* If the return packet is an ACK, the ACK is processed and thrown away. If
* the return packet is something other than an ACK, the packet is saved and
* processed and a global flag is set to indicate we are still waiting for an
* ACK packet. A typical scenario where the return packet is not an ACK is
* when both the host and target send a packet to each other simultaneously.
*
* EXT_NO_ERROR is returned on success, EXT_ERROR on failure.
*/
PRIVATE boolean_T ExtSetPktWithACK(ExtSerialPort *portDev, char *pktData, int pktSize, PacketTypeEnum pktType) {
int bytesWritten=0;
int totalBytesWritten=0;
boolean_T error=EXT_NO_ERROR;
// local function name... debugging only
#if DEBUG_MSG_LVL > 0
const char *funct_name="ExtSetPktWithACK";
#endif
PRINT_DEBUG_MSG_LVL3("IN");
PRINT_DEBUG_MSG_NL3;
/* NOTE: ExtSetPkt can only send up to MAX_SERIAL_PKT_SIZE (= FIFOBUFSIZE) at a time... this
* loop spreads larger packets (theoretically up to CIRCBUFSIZE over multiple calls
* to ExtSetPkt -- fw-07-07
*/
while(totalBytesWritten<pktSize) {
/* Send the packet. */
error=ExtSetPkt(portDev, pktData+totalBytesWritten, pktSize-totalBytesWritten, &bytesWritten, pktType);
if(error!=EXT_NO_ERROR) {
/* never happens, errors caught above -- fw-07-07 */
abort_LED(30); // just in case
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -