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

📄 xmodem.c

📁 嵌入式系统的小作品
💻 C
字号:
/*
 * vivi/deriver/serialxmodem.c:
 *     - an implementation of the xmodem protocol from the spec.
 *
 * Based on bootldr/xmodem.c (C) 2000 Compaq Computer Coporation.
 *
 * Copyright (C) 2001 MIZI Research, Inc.
 *
 *
 * 1999-01-xx: Edwin Foo <efoo@crl.dec.com>
 *    - Initial code
 *
 * 2001-10-04: Janghoon Lyu <nandy@mizi.com>
 *    - Modified a little bit.
 *
 * 2002-07-04: Janghoon Lyu <nandy@mizi.com>
 *    - get_param_value() 

   2006-05: jkuang BUPT
     some bugs are killed & code optimized

   UART related are changed by jkuang. 2006-05

   Buffer copy is canceled by jkuang, so this program can works very good with fast speed
   Windows terminal. 2006-05
 */

#include "stdio.h"
#include "string.h"
#include "vxworks.h"
#include "tylib.h"
/*
#include "def.h"
#include "option.h"
#include "s3c2410.h"
#include "2410slib.h"
#include "xmodem.h"
#include "uart.h"
*/
/* XMODEM parameters */
#define BLOCK_SIZE_1	128	/* size of transmit blocks , SOH=0x01时的block大小*/
#define BLOCK_SIZE_2	1024	/* size of transmit blocks , SOH=0x02时的block大小*/
#define BLOCK_SIZE block_size
#define RETRIES		20	/* maximum number of RETRIES */
#define MAX_BUF   80000

static int block_size = BLOCK_SIZE_1;

typedef int __u32;

/* Line control codes */
#define SOH_1	0x01	/* start of header */
#define SOH_2	0x02	/* 1K xmodem start of header */
#define ACK		0x06	/* Acknowledge */
#define NAK		0x15	/* Negative acknowledge */
#define CAN		0x18	/* Cancel */
#define EOT		0x04	/* end of text */

#define GET_BYTE_TIMEOUT 250000  /* 1000000 */
/* #define GET_BYTE_TIMEOUT (1000 * 5)	//秒 */


/* global error variable */
char *xmodem_errtxt = NULL;

/* prototypes of helper functions */
static int get_record(char* bufptr);
static int do_getc( unsigned long timeout, char *cp);
static int get_byte(char * cp);

enum
{
	SAC_SEND_NAK = 0,
	SAC_SENT_NAK = 1,
	SAC_PAST_START_NAK = 2
};

static unsigned long xmodem_timeout = GET_BYTE_TIMEOUT;
static volatile int seen_a_char = SAC_SEND_NAK;
static int one_nak = 0;

#ifdef XMODEM_DEBUG
char debugbuf[DEBUGBUF_SIZE];
int db_idx = 0;

/*-------------------------------------------------------------------*/
void bufputs(char *s)
{
	size_t len = strlen(s) + 1;

	if (len + db_idx > sizeof(debugbuf))
		len = sizeof(debugbuf) - db_idx;

	if (len) {
		memcpy(&debugbuf[db_idx], s, len);
		db_idx += len;
	}
}

/*-------------------------------------------------------------------*/
void reset_debugbuf(void)
{
	memset(debugbuf, 0x0, sizeof(debugbuf));
	db_idx = 0;
}
#endif

/*-------------------------------------------------------------------*/
__u32 xmodem_receive(char *dldaddr)
{
	char ochr;
	int r, rx_block_num, error_count;
	__u32 foffset = 0;  /* The offset */
	
	serial_init();  /* Initialize the serial port I/O */
	
    do{
		taskDelay(60);
		if (!sio_ischar())
			Uart_SendKey(NAK);
    } while(!sio_ischar()); /* Wait for the Terminal to Send file,sending NAK*/ 

	xmodem_errtxt = NULL;  /* The error log */
	seen_a_char = 0;

	/* one_nak = get_param_value("xmodem_one_nak", &ret);*/
	one_nak = 0;
	
	xmodem_timeout = GET_BYTE_TIMEOUT/2;   /* The time out value */

	rx_block_num = 1;  /* The first packet number */
	error_count = RETRIES;  /* Retries times */

  do{
      if  (foffset < (MAX_BUF-BLOCK_SIZE))  /* Test whether it is out of offset */
      {
          if ((r = get_record((char*)(dldaddr+foffset))) == (rx_block_num & 255))   
            /* Get a packet and set test if it is in the rang of 1 - 255 */
          {
            /* printf("xmodem_receive: Get a packet... Block Num %d\n",r);*/
            error_count = RETRIES;
            /* xmodem_errtxt = "RX PACKET";*/
            rx_block_num++;  /* Increase the packet num */
            foffset += BLOCK_SIZE;  /* Add the offset */
            Uart_SendKey(ACK);   /* jkuang*/
            /* printf("xmodem_receive: An ACK Sent continue...\n");*/
            continue;  /* Go on with the packet getting */
          }
      }else {
            r = -1;      /* Offset deal: mark as TIME OUT */
            }    
      if((r == -4)||(r == -5)) /* EOT or CAN*/
      {
        /* printf("xmodem_receive: EOT or CAN... Block Num %d\n",r);*/
        /* xmodem_errtxt = "DONE";*/
        {
          /* some terminal prog send more chars after 'EOT'*/
          /* printf("xmodem_receive: An ACK Sent.\n");*/
          Uart_SendKey(ACK);         /*  Send 2 ACKs */
          Uart_SendKey(ACK);
        }
        break;    /*  Jump out of the loop */
      }

      switch (r) 
      {
        case -1: /* TIMEOUT */
            printf("xmodem_receive: TIMEOUT \n");
            xmodem_errtxt = "TIMEOUT";
            ochr = NAK;
            break;
        case -2: /* Bad block */
            printf("xmodem_receive: Bad block  \n"); 
            xmodem_errtxt = "BAD BLOCK#";
            /* eat teh rest of the block */
            while (get_byte(&ochr) != -1);
            ochr = NAK;
            break;
        case -3: /* Bad checksum */
            printf("xmodem_receive: Bad checksum \n");  
            xmodem_errtxt = "BAD CHKSUM";
            ochr = NAK;
            break;
        default: /* Block out of sequence */
            /* printf("xmodem_receive: Block out of sequence  \n");   */  
            xmodem_errtxt = "WRONG BLK";
            ochr = NAK;
      }
      error_count--;    /*  Decrease the retry time */
      Uart_SendKey(ochr);    /*  Send info */
    } while ((r > -3) && error_count);

	if  ((!error_count) || (r != -4))     /*  If out of retries or other errors */
    {
        printf("x-modem error: %s\n", xmodem_errtxt);   /*  Display the error log */        
        return 0;	/* indicate failure to caller */
		/*printk("x-modem error: %s\n", xmodem_errtxt); */
	}

	return foffset;
}

/*-------------------------------------------------------------------*/
/*
 * Read a record in the XMODEM protocol, return the block number
 * (0-255) if successful, or one of the following return codes:
 * 	-1 = Bad byte
 * 	-2 = Bad block number
 * 	-3 = Bad block checksum
 * 	-4 = End of file
 * 	-5 = Canceled by remote
 */

static int get_record(char* bufptr)
{
    char c;
	int block_num;
	int i;
	__u32 check_sum;

    if  (!get_byte(&c))  /* 1st byte */
    {
        printf("get_record: First byte Error.\n");
        return -1;
    }       

    switch (c)    /* Switch the first byte */
    {
      case SOH_1:	/* Receive packet */
        BLOCK_SIZE = BLOCK_SIZE_1;
        /* printf("get_record: Block Size 1 \n");*/
        break;
      case SOH_2:	/* Receive packet */
        BLOCK_SIZE = BLOCK_SIZE_2;
        printf("get_record: Block Size 2 \n");
        break;
      case EOT:	/* end of file encountered */
        printf("get_record: End of Transmit. \n");   
        return -4;
      case CAN:	/* cancel protocol */
      default:
              printf("get_record: Cancelled or error. \n");
        return -5;
	}

    if  (!get_byte(&c))     /* 2nd byte */      
    {
        printf("get_record: Second byte error.\n");
        return -1;
    }       
    block_num = c;

    if  (!get_byte(&c))    /* 3rd byte */ 
    {
        printf("get_record: Third block error.\n");
        return -1;
    }
           
    /* from 4th -> byte before last */
    /* printf("get_record: Start recieving data part.\n");*/
    check_sum = 0;
    for(i=0; i<BLOCK_SIZE; i++)    /* Get the data bytes */
    {
      if  (!get_byte(&c))	
      {
          printf("get_record: Data byte recieving error.\n");
          return -1;
      }
      /* printf("get_record: Get a data byte %c \n",c);*/
      /* get_byte(&c);*/
      *bufptr = c;
      check_sum += c;
      bufptr++;
    }

    get_byte(&c);    /* last byte :check sum */

    if  ((check_sum & 0xff) == c)     /* test the check sum */
    {
        /* printf("get_record: check is OK.Return the check_sum.\n");*/
        return block_num;
    }
    printf("get_record: Checksum error.\n");
    return -3;
}


/*-------------------------------------------------------------------*/
static int do_getc(unsigned long timeout, char * cp)
{
  int rxstat;

  while((rxstat = Uart_GetKey( cp )) == -1)
      /* Get a byte from Uart and test if it is -1 */
  {
    printf("do_getc: Get -1 waiting for timeout.\n");
    if  (!(timeout--))
    {
        printf("do_getc: Getting char timeout.\n");
        taskDelay(2);
        break;
    }
  }
  /* printf("do_getc: get char integer %d \n" ,rxstat);*/
  return rxstat;
}


/*-------------------------------------------------------------------*/
static int get_byte(char *cp)
{
  int rc;
  
again:
/*
 * Reads and returns a character from the serial port
 *   - Times out after delay iterations checking for presence of character
 *   - Sets *error_p to UART error bits or - on timeout
 *   - On timeout, sets *error_p to -1 and returns 0
 */
    rc = do_getc( xmodem_timeout, cp);    /* get a byte */
    /* printf("get_byte: get char integer %d  %c \n",rc,(char)rc);*/
    
	if (rc)    /* if the byte is meanful not zero */
	{
	  /* printf("get_byte: Return a char integer.\n"); */
      seen_a_char = SAC_PAST_START_NAK;
	  return rc;
	}
    else     /* zero byte handling */
	{
	  /* printf("get_byte: get a zero char  integer.\n"); */
      if (seen_a_char == SAC_SEND_NAK || !one_nak) 
	  {
		/* bufputs("timeout nak");*/
		Uart_SendKey(NAK);   /* jkuang*/
	  }

   	  if (seen_a_char < SAC_PAST_START_NAK) 
	  {
		seen_a_char = SAC_SENT_NAK;
		xmodem_timeout = GET_BYTE_TIMEOUT;
		goto again;
 	  }
	}
	return (rc);
}

void gt(void)
{

    char text[MAX_BUF];    /* Set the data buffer */
	int i;
	int st;

    printf ("Prepare your terminal emulator to receive data now...\n");
    
	st = xmodem_receive(text);
	
	for (i = strlen(text)-2; i> 0; i--)    /* if reach the end of the data,trunk it */
		if (text[i] == 26)
			text[i] = 0; 
	if (st <= 0) {
		printf ("Xmodem transmit error: status: %d\n", st);
	}
	else  {
		printf ("Xmodem successfully transmitted %d bytes\n", st);
	}
	printf("The context of the file is : \n\n");
	printf("%s\n",text);
	
	return 0;

}

⌨️ 快捷键说明

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