⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 linux_xmload.c

📁 在uclinux/linux下通过串口以XMLOAD协议与PC终端通讯
💻 C
字号:
/* xmloac.c for down soft to uclinux*		Copyright (C) 2007/3/27  wangwudong  <w..d@163.com>,	255k libmit	1000ms	timeout	use:		xmload [filename]	*/#include <errno.h>#include <stdio.h>#include <sys/ioctl.h>#include <asm/termbits.h>#define TIMEOUT 		1000#define	MAX_DOWNLOAD_SIZE	1024*128#define MAXERRORS		10	//10#define SOH 0x01#define STX 0x02#define EOT 0x04#define ACK 0x06#define NAK 0x15#define CAN 0x18#define BS  0x08typedef	int	BOOL;#define	FALSE	((BOOL) 0)#define	TRUE	((BOOL) 1)#define 	STDIN 		0 /*标准输入文件描述符*/#define	STDOUT		1/*错误日志,调试用*/char msg[1024] = "erro is ";/*向终端写一个字节*/static __inline void WriteByte(char cc) { 	//write(STDOUT, cc, 1);/*不知道为什么发不了数,有时间再看看*/		//sprintf(&msg[strlen(msg)],"\n?\n");/*调试显示用*/		/*向终端发送一个字符*/	fputc(cc, stdout);	/*必需要的,否则不能立即显示*/	fflush(stdout);	}/*从终端等待一个字节*/int  ReadByteWithTimeout(unsigned int msecs) {		/*nfds为select函数的返回值	result暂存结果*/	int nfds,result;		/*读操作文件描述集*/		fd_set readset;		/*时间变量,超时参数*/	struct timeval timeout;		/*秒和微秒分别计算*/	timeout.tv_sec = msecs / 1000;	timeout.tv_usec = (msecs % 1000) * 1000;			/*下面第一种是采用循环查迅法,附带超时处理,效率不高,影响传输速度*/	/*result = 0;		for(i = 0 ; i < 20 && result <= 0 ; i++)	{				ioctl(STDIN, FIONREAD, &result);				usleep(1);			}	if ( result >0)	{		sprintf(&msg[strlen(msg)]," (%d)",result);		result = fgetc(stdin) & 0xff;			sprintf(&msg[strlen(msg)],"%x ",result);		}	else 	{			result = -1;	}	*/		/*select有很强大的功能,对阻塞通道可以多个同时监控并可以超时返回*/	for( ; ; )	{		FD_ZERO(&readset);			FD_SET(STDIN, &readset);			//遇到ctrl+c继续注意:STDIN 和 stdin的区别		if (((nfds = select( STDIN +1, &readset, NULL, NULL, &timeout)) == -1) && 			(errno == EINTR))		{			/*如果因信号中断退出,则继续,但实际上终端以不是行输入,则不会出现组合键的中断信号*/			//sprintf(&msg[strlen(msg)],"errno == EINTRr!\n");			continue;			}				if (nfds == -1)		{			result = -1;			//sprintf(&msg[strlen(msg)],"\nerr!\n ");				break;		}		/*检测是否是该通道的事件*/		if (FD_ISSET(STDIN, &readset))	 	{				/*第一种方法读有影响,可揣摩*/			//result = read(stdin, &cc, 1) & 0xff;						/*安全起见,还是与调前面的未知数*/			result = fgetc(stdin) & 0xff;				//sprintf(&msg[strlen(msg)],"%x ",result);			break;			}		else 		{			/*超时事件或其它事件都做超时处理*/			errno = EINVAL;			result = -1;			//sprintf(&msg[strlen(msg)],"... ");				break;					}	}			return result ;	}/*读空终端的输入字节存储区*/static void ReadFlush() {	while(ReadByteWithTimeout(1000) >= 0);	}int XModemReceive(char *name){	FILE	*fp;	int bufLen = MAX_DOWNLOAD_SIZE;		unsigned int errors = 0;	unsigned int wantBlockNo = 1;	unsigned int length = 0;	int crc = 1;		//use crc by send 'C', use checksum by send NAK	char nak = 'C';	int crc_val;	unsigned char expectedCksum;		static char *blockBuf, *bufBase;					/*分配文件临时缓冲空间*/	if(!(bufBase = malloc(bufLen)))	{		sprintf(stderr, "no memory\n");		  return(0);	}		blockBuf = bufBase;	//("start xmodem!\n");	fflush(stdout);	ReadFlush();		/* Ask for CRC; if we get errors, we will go with checksum */	WriteByte(nak);			//("WriteByte(nak)\n");			for (;;) 	{		int blockBegin;		int blockNo, blockNoOnesCompl;		int blockLength;		int cksum = 0;		int crcHi = 0;		int crcLo = 0;		blockBegin = ReadByteWithTimeout(TIMEOUT);		if (blockBegin < 0)		{						sprintf(&msg[strlen(msg)],"Read blockBegin timeout!\n");					goto timeout;		}		nak = NAK;		switch (blockBegin) 		{		case SOH:		case STX:			break;		case EOT:			WriteByte(ACK);			//("WriteByte(ACK): done\n");						goto done;		default:			//("blockBegin error!\n");				sprintf(&msg[strlen(msg)],"blockBegin error!!\n");				errors--;			goto error;		}		/* block no */		blockNo = ReadByteWithTimeout(TIMEOUT);		if (blockNo < 0)		{						sprintf(&msg[strlen(msg)],"blockNo timeout!\n");						goto timeout;		}		/* block no one's compliment */		blockNoOnesCompl = ReadByteWithTimeout(TIMEOUT);		if (blockNoOnesCompl < 0)		{						sprintf(&msg[strlen(msg)],"blockNoOnesCompl timeout!\n");						goto timeout;		}		if (( blockNo + blockNoOnesCompl ) != 255 ) 		{						sprintf(&msg[strlen(msg)],				"bad block ones compl(blockNo is %x,blockNoOnesCompl is %x)\n",				blockNo, blockNoOnesCompl);						goto error;		}		blockLength = (blockBegin == SOH) ? 128 : 1024;		{			int i, j;						crc_val = 0;						expectedCksum = 0;			for (i = 0; i < blockLength; i++) 			{				int cc = ReadByteWithTimeout(TIMEOUT);				if (cc < 0)				{										sprintf(&msg[strlen(msg)]," read block byte timeout!(i is %d)\n", i);										goto timeout;				}								blockBuf[i] = cc;						//crc 或 checksum 计算加在读数据后				if (crc) 				{					crc_val = crc_val ^ cc << 8;					for (j = 0; j < 8; j++)						if (crc_val & 0x8000)							crc_val = crc_val << 1 ^ 0x1021;						else							crc_val = crc_val << 1;				} 				else 				{					expectedCksum += cc;				}			}		}		if (crc) 		{			crcHi = ReadByteWithTimeout(TIMEOUT);			if (crcHi < 0) 			{								sprintf(&msg[strlen(msg)]," read crcHi timeout!\n");				goto timeout;			}			crcLo = ReadByteWithTimeout(TIMEOUT);			if (crcLo < 0) 			{								sprintf(&msg[strlen(msg)]," read crcLo timeout!\n");				goto timeout;			}									if ((crcHi != ((crc_val>>8) & 0xff)) ||			    (crcLo != (crc_val & 0xff))) 			{								sprintf(&msg[strlen(msg)],"crc error!\n");				goto error;			}					} 		else 		{			cksum = ReadByteWithTimeout(TIMEOUT);			if (cksum < 0)			{								sprintf(&msg[strlen(msg)]," read chksum timeout!\n");				goto timeout;			}						if (cksum != expectedCksum) 			{								sprintf(&msg[strlen(msg)],"checksum error! \n");				goto error;			}		}		if (blockNo == ((wantBlockNo - 1) & 0xff)) 		{			/* a repeat of the last block is ok, just ignore it. */			/* this also ignores the initial block 0 which is */			/* meta data. */			goto next;		} 		else if (blockNo != (wantBlockNo & 0xff)) 		{						sprintf(&msg[strlen(msg)],"unexpected block no! \n");			goto error;		}		wantBlockNo++;		length += blockLength;		if (length > bufLen) 		{						sprintf(&msg[strlen(msg)],"out of space(length is %d)\n",length);			goto error;		}		blockBuf += blockLength;	//接收成功,指针加上收到字节数next:		errors = 0;		WriteByte(ACK);		//("Receive one block OK!\n");		continue;error:		timeout:		//("Timeout.\n");		errors++;		if (errors == MAXERRORS) 		{			/* Abort */			int i;			// if using crc, try again w/o crc			if (nak == 'C') 			{								nak = NAK;				errors = 0;				crc = 0;		//use checksum				goto timeout;			}						for (i = 0; i < 5; i ++)				WriteByte(CAN);			for (i = 0; i < 5; i ++)				WriteByte(BS);			puts(" too many errors; giving up\n");						free(bufBase);						return -1;		}		ReadFlush();								WriteByte(nak);						//("WriteByte(nak)\n");	}done:	//("\nxmodem done.\n");	ReadFlush();		if( length > 0)	{		fp = fopen(name, "w");		fwrite(bufBase,1,length,fp);		fclose(fp);		chmod(name, 777);	}	free(bufBase);	return length;}int main(int argc, char * argv[]){	/*argv[0] argv[1]*/	/*xmload mytest*/	char *name;	int tmp;		struct termios  newterm ;		int saveflag ;		name = argv[1];	if(argc==2 && name[0] == '?')	{		printf("Default download name : xmload \n");		printf("Set new download name : xmload destination_address \n");			return 0;	}		if(argc<2)	{		name = "/tmp/tt";	}			//printf("Now download file by xmodem to %s...\n", name);	 						/*错误日志初始化*/		sprintf(msg,"\n erro is \n");		/**/			/*设置终端为非行输入,去掉终端回显*/		tcgetattr( STDIN, &newterm );		newterm.c_iflag = 0;	newterm.c_oflag &= ~OPOST;	newterm.c_lflag &= ~ ( ECHO | ISIG | ICANON );		newterm.c_cc[VMIN] = 1;	newterm.c_cc[VTIME] = 0;			tcsetattr(STDIN, TCSANOW, &newterm);				//system("stty raw");				/*必需设置终端输入无缓冲,否则getc一次后数据都读进来了,影响select的事件触发*/	setbuf(stdin,NULL);	/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/		/*输出不必要设置,但必需每次putc后,fflush()一次*/	//setbuf(stdout,NULL);	/*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/		tmp = XModemReceive( name );		/*恢复终端为行输入,回显*/	//system("stty cooked echo");		newterm.c_iflag |= BRKINT | IGNPAR | ISTRIP | ICRNL | IXON;				newterm.c_oflag |= OPOST;				newterm.c_lflag |= ECHO | ISIG | ICANON;				tcsetattr( STDIN, TCSANOW, &newterm);		fflush(stdout);		if ( tmp <0 )	{		printf("%s",msg);		}	printf("\nfile[%s] length is %d...\n",name, tmp);			return 0;}  

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -