📄 bus232.cpp
字号:
/****************************************************************************
* Program/file: BUS232.CPP
*
* Copyright (C) by RTX TELECOM A/S, Denmark.
* These computer program listings and specifications, are the property of
* RTX TELECOM A/S, Denmark and shall not be reproduced or copied or used in
* whole or in part without written permission from RTX TELECOM A/S, Denmark.
*
* Programmer: LHJ
*
* MODULE: WIN32SIM
* CONTROLLING DOCUMENT:
* SYSTEM DEPENDENCIES:
*
*
* DESCRIPTION: RS232 driver
*
*
*
*
*
****************************************************************************/
/****************************************************************************
* PVCS info
*****************************************************************************
$Author: SS $
$Date: 17 Jul 2003 11:27:14 $
$Revision: 1.5 $
$Modtime: 16 Jul 2003 12:43:54 $
*/
#include <conio.h>
#include <process.h>
#include <stdlib.h>
#include <time.h>
#include <stdio.h>
#include <windows.h>
#include <process.h>
#ifdef CVMCON
#include <std-def.h>
#include <dbg_mail.h>
#include <clrsx.h>
#include <cmclient.h>
#else
#include <win32sim\common\std-def.h>
#include <win32sim\rsx\dbg_mail.h>
#include <win32sim\rsx\clrsx.h>
#include <win32sim\cm\cmclient.h>
#endif
#ifdef RSX
#include <win32sim\debug\dbg_intf.h>
#endif
#ifndef RSX
extern void sendmail_ReceivePacket(uint16 Length, uint8 *bDataPtr);
#endif
extern clRsxType clRsx; // RSX vindow.
extern void internal_SendPacketToTask(int iTaskId, int iLength, unsigned char *bInputDataPtr);
//extern int32 debug_ProgramId;
//extern long debug_ProgramId;
#ifdef RSX
extern "C" void PrintfInt(char *format, ...);
#endif
HANDLE hComPortHandle = NULL;
OVERLAPPED ovlRd,ovlWr;
HANDLE Rx232Id, Tx232Id, RtsTaskId; // Thread handles
void InitRs232(int Port, int BaudRate);
// Used to stop the tasks.
bool StopTxTask, StopRxTask, StopRtsTask;
HANDLE semTestbusFrameQueueSem; // mutex semaphore to protect TestbusFrameQueue
int RtsTimeout = 0;
uint32 iTxDelay = 0;
#define MAX_PACKET_LENGTH 350
#ifdef BUSM_HDLC // Sliding window protocol
#define MIN_PACKET_LENGTH 1 // Control frames have length 1
#else
#define MIN_PACKET_LENGTH 4
#endif
#ifdef SIM_RS232_ERRORS
uint8 BUSM_SimulateRxError = 0;
uint8 BUSM_SimulateTxError = 0;
#endif
#ifdef BUSM_HDLC // CVM HDLC
#define BUSM_FLOW_FINAL 0x08
#define BUSM_FLOW_RX_SEQ_MASK 0x07
#define BUSM_FLOW_TX_SEQ_MASK 0x70
#define BUSM_FLOW_CONTROL_FRAME 0x80
#define BUSM_FLOW_CONTROL_MASK 0x70
#define BUSM_FLOW_CONTROL_SHIFT 4
/****************************************************************************
* Enumerations/Type definitions/Structs
****************************************************************************/
typedef enum
{
BUSM_UNLOCKED,
BUSM_LOCK_PENDING,
BUSM_LOCKED
}ENUM8(eBusmState);
typedef enum
{
INFORMATION_FRAME,
SUPERVISORY_FRAME,
UNNUMBERED_FRAME,
MAX_FRAME
} ENUM8(eFrameTypeEnum);
typedef enum
{
BUSM_FLOW_CTRL_RR = 0 ,
BUSM_FLOW_CTRL_REJ = 1 ,
BUSM_FLOW_CTRL_RNR = 2 ,
} ENUM8(BusmCtrlSpecType);
typedef enum
{
BUSM_FLOW_UNNMB_SABM = 0, // Set Asynchronous Balanced Mode, i.e. ask peer to reset counters
} ENUM8(BusmUnNmbSpecType);
typedef struct
{
uint8 RxSeq : 3; // Next sequence expected from peer
uint8 PollFinal : 1; // If set -> peer must be answered
uint8 TxSeq : 3; // Sequence of this frame
uint8 InfoControl : 1; // Must be 0
} BUSM_InfoFrameType;
typedef struct
{
uint8 RxSeq : 3; // Next sequence expected from peer
uint8 PollFinal : 1; // If set -> peer must be answered -
BusmCtrlSpecType CtrlSpec : 2;
uint8 Supervisory : 1; // Must be 0
uint8 InfoControl : 1; // Must be 1
} BUSM_SuperVisoryControlFrameType;
typedef struct
{
uint8 Modifier : 3; // Not used
uint8 PollFinal : 1; // If set -> peer must be answered -
BusmUnNmbSpecType UnNmbSpec : 2;
uint8 Unnumbered : 1; // Must be 1
uint8 InfoControl : 1; // Must be 1
} BUSM_UnnumberedControlFrameType;
// Types for length and sequence fields in buffer
typedef uint16 BUSM_PacketLengthType;
typedef uint8 BUSM_SequenceNrType;
typedef uint8 BUSM_DleType;
// Type for paylaod header
typedef struct
{
uint8 uProgId;
uint8 uTaskId;
} BUSM_PayloadHeaderType;
// Buffer header, a mail in the buffer is organized as: BUSM_BufferHeaderType - Mail - BUSM_TailMarkerType
typedef struct
{
//BUSM_PacketLengthType length; // length filtered out in RSX
BUSM_SequenceNrType uControl;
BUSM_PayloadHeaderType payloadHead;
} BUSM_BufferHeaderType;
typedef struct
{
BUSM_DleType Dle;
uint8 uLengthMSB;
uint8 uLengthLSB;
BUSM_InfoFrameType uControl;
BUSM_PayloadHeaderType payloadHead;
uint8 payloadTail[1]; // Equals zero length package with 1 CRC byte
} BUSM_FrameType;
#define BUSM_HDLC_SEQ_MOD 0x07
#define BUSM_MAX_OUTSTANDING_FRAMES 0x06
#define BUSM_MAX_FRAMES_BEFORE_FINAL_FLAG 0x03
typedef struct
{
uint8 bExpectedRxSeq;
uint8 bNextTxSeq;
uint8 bTxNoAckCnt;
uint8 bExpectedAck;
clock_t tNoAckNowledge;
eBusmState eHdlcState;
} sHdlcControlType;
sHdlcControlType sHdlcControl;
static bool RsxSwpCheckReceivedFrame(uint8 *RxFrame);
#define NO_ACKNOWLEDGE_TIMEOUT 0.2 //200 ms
extern void bus232_ResetHDLCprotocol(void);
extern void bus232_SendPacketToUnit(int iTaskId, int iLength, unsigned char *bInputDataPtr);
//static void bus232_RetransmitFrame(BUSM_FrameType *bInputDataPtr);
static void bus232_RetransmitFrame(BUSM_FrameType *bInputDataPtr, bool boolPollFinal);
static void bus232_SendUnnumberedFrame(int iTaskId, bool boolPollFinal);
static bool Between(unsigned char a, unsigned int b, unsigned int c);
uint8 WrongFrame;
BUSM_FrameType *NotAcknowledgeFramePtr[BUSM_HDLC_SEQ_MOD+1];
HANDLE semBusmHdlcSem; // mutex semaphore to protect hdlc data
FILE *Rs232HdlcLogFile;
bool Rs232LogToFile=FALSE;
typedef struct
{
int iTaskId;
int iLength;
void *Next;
uint8 Data[1]; // variable length
} sUnsentInfoframes;
sUnsentInfoframes *FirstUnsent=NULL;
sUnsentInfoframes *LastUnsent=NULL;
#endif //HDLC
// Queue stuff.
struct QueueStorage {
struct QueueStorage *Next;
void *Data;
};
typedef struct {
struct QueueStorage *First,*Last;
} QueueRecord;
typedef struct {
uint8 bLength;
uint8 bData[1];
} QueueElement;
QueueRecord TestbusFrameQueue;
void EnQueue(QueueRecord *rec,void *vdata)
{
struct QueueStorage *tmp;
tmp=(struct QueueStorage *) malloc(sizeof(struct QueueStorage));
tmp->Next=NULL;
tmp->Data=vdata;
if(rec->First==NULL) {
rec->First=tmp;
rec->Last=tmp;
} else {
rec->Last->Next=tmp;
rec->Last=tmp;
}
}
void *DeQueue(QueueRecord *rec)
{
void *tmp;
struct QueueStorage *tmpqe;
if(rec->First==NULL)
return NULL;
tmpqe=rec->First;
rec->First=tmpqe->Next;
tmp=tmpqe->Data;
free(tmpqe);
return tmp;
}
#ifdef __TURBOC__
#pragma argsused
#endif
VOID RtsProc(PVOID unused)
{
while(StopRtsTask == FALSE)
{
Sleep(500);
switch(RtsTimeout)
{
case 0:
break;
case 1:
EscapeCommFunction( hComPortHandle, CLRRTS );
default:
RtsTimeout--;
break;
}
}
StopRtsTask = FALSE; // To indicate that the task has stopped
ExitThread(0);
}
#ifdef __TURBOC__
#pragma argsused
#endif
VOID Tx232Proc(PVOID unused)
{
uint8 bTransmit232ElementArr[500];
uint8 *Rs232FrameQueuePtr;
uint16 bSenderSize;
unsigned long dwWritten;
while(StopTxTask == FALSE)
{
WaitForSingleObject(semTestbusFrameQueueSem, INFINITE);
if(TestbusFrameQueue.First != NULL)
{
Rs232FrameQueuePtr = (uint8*) DeQueue(&TestbusFrameQueue);
bSenderSize = (uint16) (256*Rs232FrameQueuePtr[1] + Rs232FrameQueuePtr[2] + 4);
memcpy(bTransmit232ElementArr, Rs232FrameQueuePtr, bSenderSize);
#ifdef BUSM_HDLC // Sliding window protocol
if (Rs232LogToFile)
{
if (bSenderSize > 0x100)
{
fprintf(Rs232HdlcLogFile, "\n bSenderSize fuck up!!! %x",bSenderSize);
#ifdef RSX
PrintfInt("bSenderSize fuck up!!!\n");
#endif
}
}
#endif
#ifdef SIM_RS232_ERRORS //
if (--BUSM_SimulateTxError == 0)
{
bTransmit232ElementArr[6]++; // Simulate transmit error, will be percieved as receive error in target
#ifdef RSX
if(clRsx.iPrintBytes)
{
clRsx.Printf("\n Sim Tx Error Checksum = %02X",bTransmit232ElementArr[6]);
}
#endif
BUSM_SimulateTxError = rand()&0x1F; // a littlebit random
if (BUSM_SimulateTxError == 0) BUSM_SimulateTxError = 1;
}
#endif
#ifdef RSX
if(clRsx.iPrintBytes)
{
int c1;
clRsx.Printf("\nO: ");
for(c1=0; c1<bSenderSize; c1++)
clRsx.Printf("%02X ",(int) bTransmit232ElementArr[c1]);
}
#else
#ifdef SENDMAIL_DEBUG
{
int c1;
printf("\nO: ");
for(c1=0; c1<bSenderSize; c1++)
printf("%02X ",(int) bTransmit232ElementArr[c1]);
}
#endif
#endif
EscapeCommFunction( hComPortHandle, SETRTS );
// Sleep(10); // To fix bug in target.
ovlWr.Offset = 0;
ovlWr.OffsetHigh = 0;
ResetEvent(ovlWr.hEvent);
if(iTxDelay == 0)
{
//DWORD lpEvtMask;
WriteFile(hComPortHandle, bTransmit232ElementArr, bSenderSize, &dwWritten, &ovlWr);
/* lpEvtMask = 0;
while (!(lpEvtMask&EV_TXEMPTY)) // Wait until finished transmitting buffer
{
WaitCommEvent(hComPortHandle, &lpEvtMask, &ovlWr);
};*/
}
else
{
int i;
for(i=0; i<bSenderSize; i++)
{
WriteFile(hComPortHandle, &bTransmit232ElementArr[i], 1, &dwWritten, &ovlWr);
Sleep(iTxDelay);
}
}
free(Rs232FrameQueuePtr);
ReleaseMutex(semTestbusFrameQueueSem);
RtsTimeout = 3;
}
else
{
ReleaseMutex(semTestbusFrameQueueSem);
#ifdef BUSM_HDLC // Sliding window protocol
Sleep(10); // OK to sleep 10 ms, corresponds to target kernel tick
#else
Sleep(100); //If staying in idle loop give other programs CPU time
#endif
}
#ifdef BUSM_HDLC // Sliding window protocol
WaitForSingleObject(semBusmHdlcSem, INFINITE);
if (sHdlcControl.tNoAckNowledge)
{
if ((clock()-sHdlcControl.tNoAckNowledge)>(CLOCKS_PER_SEC*NO_ACKNOWLEDGE_TIMEOUT)) // timer has run out
{
uint8 bFirstUnAcknowledged;
uint8 i;
bool boolFinal;
#ifdef RSX
PrintfInt("Retransmit\n");
#endif
if (Rs232LogToFile)
{
fprintf(Rs232HdlcLogFile, "\n Retransmit");
}
// Transmit all outstanding frames again.
bFirstUnAcknowledged = sHdlcControl.bExpectedAck;
for (i=0;i<sHdlcControl.bTxNoAckCnt;i++)
{
if ((i+1)== sHdlcControl.bTxNoAckCnt) // if last
{
boolFinal=TRUE;
}
else
{
boolFinal=FALSE;
}
bus232_RetransmitFrame(NotAcknowledgeFramePtr[bFirstUnAcknowledged],boolFinal);
bFirstUnAcknowledged=(bFirstUnAcknowledged+1)&BUSM_HDLC_SEQ_MOD;
}
sHdlcControl.tNoAckNowledge = clock();
}
}
ReleaseMutex(semBusmHdlcSem);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -