📄 xmodem.c
字号:
/****************************************************************************** 文 件 名 : xmodem.c 功能描述 : xmodem协议的实现 创建日期 : 2008年6月28日 作 者 : gateWay 修改记录 : ******************************************************************************/#include "vxWorks.h"#include "stdio.h"#include "fioLib.h"#include "timers.h"#include "string.h"#include "taskLib.h"#include "sysLib.h"#include "tickLib.h"#include "ioLib.h"#include "config.h"#include "t_xmodem.h"extern void memcopy ( S8 *pcDest, const S8 *pcSource, U32 ulLength);/*xmodem协议的公共属性记录*/XMODEM_PROPERTY_STRUCT g_xmodemProperty;U32 g_linkState;/*连接状态记录*/U32 g_ulRetry; /*重试记录*/U32 g_ulOldTicks;/*ticks记录*/U32 g_ulFileMaxLen; /*加载的最大文件长度,从入参获取到*//* 发送一个字符*/void putChar(U8 *uchar){ write(STD_OUT,(U8 *)uchar,1);}/* 接收一个字符*/STATUS getChar(U8 *uchar){ int bytesRead; (void) ioctl( STD_IN, FIONREAD, (int) &bytesRead); if (bytesRead != 0) { (void)read(STD_IN, (char *)uchar,1); return XMODEM_OK; } else return XMODEM_ERROR;}/*清空缓冲区*/static void flushSerial(void){ (void) ioctl (STD_IN, FIOFLUSH, 0); (void) ioctl (STD_OUT, FIOFLUSH, 0);}/*CRC计算*/U16 CRC16_CCITT (U8 *ptr, S32 count){ U16 usCrc; U8 * pTmp; U16 i; usCrc = 0; pTmp = ptr; while (--count >= 0) { usCrc = usCrc ^ ((U16)( *pTmp++ ) << 8); for ( i = 0; i < 8; ++i) { if ( usCrc & 0x8000 ) usCrc = (U16)( usCrc << 1) ^ 0x1021 ; else usCrc = (U16)(usCrc << 1); } } return (usCrc & 0xFFFF);}/***************************************************************************** 函 数 名 : xModemDateCheck(void) 功能描述 : 检查xmodem数据是否正确 日 期 : 2008年6月26日 作 者 : gateWay 说 明 : 正确则返回0,否则返回0xff。*****************************************************************************/static S32 xModemDateCheck(void){ U32 ulDateLen; U16 usCrc,usTcrc; U8 ucCks = 0; U32 i; ulDateLen = g_xmodemProperty.ulProSize; if (g_xmodemProperty.ucCheckType) { usCrc = CRC16_CCITT(&(g_xmodemProperty.pPacketData[2]), ulDateLen); usTcrc = ((g_xmodemProperty.pPacketData[ulDateLen + 2])<<8) + (g_xmodemProperty.pPacketData[ulDateLen + 3]); if (usCrc == usTcrc) return XMODEM_OK; } else { for (i = 2; i < ulDateLen + 2; i++) { ucCks += (g_xmodemProperty.pPacketData[i]); } if (ucCks == g_xmodemProperty.pPacketData[ulDateLen + 2]) return XMODEM_OK; } return XMODEM_ERROR;}/***************************************************************************** 函 数 名 : xModemLink(void) 功能描述 : xmodem接收端发起连接 日 期 : 2008年6月26日 作 者 : gateWay 说 明 : 正确则返回0,否则返回0xff。*****************************************************************************/STATUS xModemLink(void){ U8 ucData; if(OK == getChar(&ucData)) { switch ( ucData ) { case SOH:/*收到SOH则为xmodem协议*/ g_xmodemProperty.ulProSize = XMODEM_DATA_LENGTH; g_linkState = RECEIVE_DATA; g_ulRetry = 0; g_ulOldTicks = tickGet() + (U32)sysClkRateGet(); return XMODEM_OK; case STX:/*收到STX则为1K xmodem协议*/ g_xmodemProperty.ulProSize = XMODEM_1K_LENGTH; g_linkState = RECEIVE_DATA; g_ulRetry = 0; g_ulOldTicks = tickGet() + (U32)sysClkRateGet(); return XMODEM_OK; case EOT:/*收到EOT文件传输结束*/ ucData = ACK ; putChar(&ucData); g_linkState = END_OF_LINK; return XMODEM_OK; case CAN:/*收到CAN文件传输取消*/ g_linkState = XMODEM_REMOTE_CANCELES; return XMODEM_ERROR; default: break; } } return XMODEM_OK;}/***************************************************************************** 函 数 名 : xModemGetPacket(void) 功能描述 : xmodem接收一个数据包(c除包头),并校验数据 日 期 : 2008年6月26日 作 者 : gateWay 说 明 : 正确则返回0,否则返回0xff。*****************************************************************************/ STATUS xModemGetPacket(void){ U8 ucData; U32 ulReceiveSize; U32 ulLenTemp; /*将数据放到包缓冲区中*/ if(XMODEM_OK == getChar(&ucData)) { g_xmodemProperty.pPacketData[g_xmodemProperty.ulLenTemps++] = ucData; g_ulRetry = 0; g_ulOldTicks = tickGet() + (U32)sysClkRateGet(); } ulReceiveSize = g_xmodemProperty.ulProSize + (g_xmodemProperty.ucCheckType ? 1:0 ) + 3; /*如果收到一包数据*/ if(g_xmodemProperty.ulLenTemps == ulReceiveSize) { /*包序列校验及数据校验*/ if (g_xmodemProperty.pPacketData[0] == (unsigned char)(~g_xmodemProperty.pPacketData[1]) && (g_xmodemProperty.pPacketData[0] == (g_xmodemProperty.ucPacketNo + 1) || (g_xmodemProperty.pPacketData[0] == 0 && (g_xmodemProperty.ucPacketNo == MAX_SEQNO ))) && (XMODEM_OK == xModemDateCheck( ))) { ulLenTemp = g_ulFileMaxLen - g_xmodemProperty.ulDataLength; if(ulLenTemp >= g_xmodemProperty.ulProSize) { ulLenTemp = g_xmodemProperty.ulProSize; } g_xmodemProperty.ulDataLength += ulLenTemp; memcopy ( g_xmodemProperty.pDataPtr, &g_xmodemProperty.pPacketData[2], ulLenTemp); g_xmodemProperty.pDataPtr += ulLenTemp; if(ulLenTemp < g_xmodemProperty.ulProSize) { /*如果文件大小超过传入的最大字节数则取消文件传输*/ /* 最大字节数由xmodemReceive函数的U32 *pLength参数决定*/ ucData = CAN ; putChar( &ucData ); ucData = CAN ; putChar( &ucData ); g_linkState = XMODEM_FILE_TOO_LONG; return XMODEM_OK; } else { /* 数据包正确则回应ACK*/ ucData = ACK ; putChar( &ucData ); g_xmodemProperty.ucPacketNo = g_xmodemProperty.pPacketData[0]; } } else { /* 数据包正确则回应NAK*/ ucData = NAK ; putChar ( &ucData ); } g_xmodemProperty.ulLenTemps = 0; g_linkState = START_OF_LINK; return XMODEM_OK; } return XMODEM_OK;}/***************************************************************************** 函 数 名 : STATUS xmodemReceive(unsigned char *pBuffer, U32 *pLength) 功能描述 : xmodem接收数据接口函数 日 期 : 2008年6月26日 作 者 : gateWay 说 明 : pLength必须将能接收的最大长度放入后再传下来。g_ulFileMaxLen = *pLength;*****************************************************************************/ STATUS xmodemReceive(unsigned char *pBuffer, U32 *pLength){ U8 ucData; BOOL ulWaitLink = TRUE; if(NULL == pBuffer) return XMODEM_ERROR; /*接收文件的最大长度从传入的参数pLength获取*/ g_ulFileMaxLen = *pLength; memset(&g_xmodemProperty,0,sizeof(XMODEM_PROPERTY_STRUCT)); g_xmodemProperty.pDataPtr = pBuffer; g_xmodemProperty.pPacketData = malloc(PACKET_MAX_LEM);/* 1024(XModem 1k数据) + 2(序列号空间) + 2 (crc 空间)+ NULL */ memset(g_xmodemProperty.pPacketData,0,PACKET_MAX_LEM); g_xmodemProperty.ucCheckType = CHECK_CRC; g_ulRetry = 0; g_ulOldTicks = tickGet () + (U32)sysClkRateGet () * WAIT_SOH_TIME ; flushSerial( ); ucData = C ; putChar(&ucData); g_linkState = START_OF_LINK; while(1) { switch (g_linkState) { case START_OF_LINK: xModemLink(); /*接收端发起连接后等待回应*/ break; case RECEIVE_DATA: ulWaitLink = FALSE; xModemGetPacket();/*接收数据包*/ break; case XMODEM_FILE_TOO_LONG: case END_OF_LINK: /*将接收到的实际长度赋给 pLength*/ *pLength = g_xmodemProperty.ulDataLength; free(g_xmodemProperty.pPacketData); return XMODEM_OK; default: *pLength = 0; printf("xModem Receive Data Error! Error State: %d\n\r",g_linkState); free(g_xmodemProperty.pPacketData); return XMODEM_ERROR; } /*超时计算代码*/ if ( tickGet() >= g_ulOldTicks ) { if ( g_ulRetry < MAX_RETRY ) { if((START_OF_LINK == g_linkState) && (TRUE == ulWaitLink)) { /*发送C字符超过4次未回应后改用checksum校验*/ if(g_ulRetry >= SEND_C_TIMES) { ucData = NAK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -