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

📄 xmodem.c

📁 某个ARM9板子的实际bootloader 对裁剪
💻 C
字号:
//==========================================================================////      xyzModem.c////      RedBoot stream handler for xyzModem protocol////==========================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.// Copyright (C) 2002 Gary Thomas//// eCos is free software; you can redistribute it and/or modify it under// the terms of the GNU General Public License as published by the Free// Software Foundation; either version 2 or (at your option) any later version.//// eCos is distributed in the hope that it will be useful, but WITHOUT ANY// WARRANTY; without even the implied warranty of MERCHANTABILITY or// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License// for more details.//// You should have received a copy of the GNU General Public License along// with eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    gthomas// Contributors: gthomas, tsmith, Yoshinori Sato// Date:         2000-07-14// Purpose:      // Description:  //              // This code is part of RedBoot (tm).////####DESCRIPTIONEND####////==========================================================================#include <define.h>#include <board_config.h>#include "Xmodem.h"#define Xmodem_putc(x)					uart_putc(x)#define Xmodem_delay_us(x)				hal_delay_us(x)XMODEM_T	xmodem_info;/*----------------------------------------------------------------------* Xmodem_getc*	To get a character form console port*----------------------------------------------------------------------*/static int Xmodem_getc(char *c){	UINT64	delay_time;	UINT32	delay_ticks;		delay_ticks = (XMODEM_INPUT_TIMEOUT * BOARD_TPS) / 1000;	delay_time = sys_get_ticks() + delay_ticks;		while (sys_get_ticks() < delay_time)	{		if ((uart_scanc(c)))		{    		return(1);    	}	}	return(0);}/*----------------------------------------------------------------------* Xmodem_flush*	To kill all input characters form console port*----------------------------------------------------------------------*/static void Xmodem_flush(void){    char c;        while (true)     {        if (!Xmodem_getc(&c))        	return;    }}/*----------------------------------------------------------------------* Xmodem_get_header*	To get Xmodem header*----------------------------------------------------------------------*/static int Xmodem_get_header(XMODEM_T *xmodem){	char c;    int res;    int hdr_found = FALSE;    int i, can_total, hdr_chars;    unsigned short cksum;    can_total = 0;    hdr_chars = 0;    if (xmodem->tx_ack)     {        Xmodem_putc(XMODEM_ACK);        xmodem->tx_ack_cnt++;        xmodem->tx_ack = false;    }    while (!hdr_found)     {        res = Xmodem_getc(&c);        if (res) 		{            hdr_chars++;            switch (c)             {            	case XMODEM_SOH:                	xmodem->total_XMODEM_SOH++;            	case XMODEM_STX:                	if (c == XMODEM_STX) xmodem->total_XMODEM_STX++;                	hdr_found = true;                	break;            	case XMODEM_CAN:                	xmodem->total_XMODEM_CAN++;                	if (++can_total == XMODEM_CAN_COUNT)                 	{                    	return XMODEM_ERR_CANCEL;                	}                 	else                 	{                    	// Wait for multiple XMODEM_CAN to avoid early quits                    	break;                	}            	case XMODEM_EOT:                	// XMODEM_EOT only supported if no noise                	if (hdr_chars == 1)                 	{                    	Xmodem_putc(XMODEM_ACK);        				xmodem->tx_ack_cnt++;                    	return XMODEM_ERR_EOF;                	}            	default:                	// Ignore, waiting for start of header                	;            }        } else {            // Data timed out            Xmodem_flush();  // Toss any current input            // Xmodem_delay_us((LONG)10000);            return XMODEM_ERR_TIMEOUT;        }    }    // Header found, now read the data    if (!Xmodem_getc(&xmodem->blk))        return XMODEM_ERR_CHKSUM;    if (!Xmodem_getc(&xmodem->cblk))        return XMODEM_ERR_CHKSUM;    xmodem->len = (c == XMODEM_SOH) ? 128 : 1024;    xmodem->bufp = xmodem->pkt;    for (i = 0;  i < xmodem->len;  i++)     {        if (Xmodem_getc(&c))            xmodem->pkt[i] = c;        else             return XMODEM_ERR_TIMEOUT;    }    if (!Xmodem_getc(&xmodem->crc1))        return XMODEM_ERR_TIMEOUT;        if (xmodem->crc_mode)     {        if (!Xmodem_getc(&xmodem->crc2))            return XMODEM_ERR_TIMEOUT;    }        // Validate the message    if ((xmodem->blk ^ xmodem->cblk) != (unsigned char)0xFF)     {        Xmodem_flush();        return XMODEM_ERR_FRAME;    }    // Verify checksum/CRC    if (xmodem->crc_mode)     {        cksum = Xmodem_crc16(xmodem->pkt, xmodem->len);        if (cksum != ((xmodem->crc1 << 8) | xmodem->crc2))            return XMODEM_ERR_CHKSUM;    }     else     {        cksum = 0;        for (i = 0;  i < xmodem->len;  i++)            cksum += xmodem->pkt[i];                if (xmodem->crc1 != (cksum & 0xFF))            return XMODEM_ERR_CHKSUM;    }    // If we get here, the message passes [structural] muster    xmodem->good_cnt++;    return 0;}int Xmodem_open(int *err){    int console_chan, stat;    int retries = XMODEM_MAX_RETRIES;    int crc_retries = XMODEM_MAX_RETRIES_WITH_CRC;	XMODEM_T *xmodem;		xmodem = (XMODEM_T *)&xmodem_info;    memset((char *)xmodem, 0, sizeof(XMODEM_T));    xmodem->crc_mode = TRUE;    while (retries-- > 0)    {        stat = Xmodem_get_header(xmodem);        if (stat == 0)         {#if 0 // 2006/1/16 01:18PM            if (xmodem->blk == 0)             {                xmodem->tx_ack = true;            	xmodem->next_blk = 1;            	xmodem->len = 0;            }            else#endif                        {				xmodem->next_blk = xmodem->blk + 1;				xmodem->tx_ack = true;            }            return 0;        }         else if (stat == XMODEM_ERR_TIMEOUT)        {            if (--crc_retries <= 0)            	xmodem->crc_mode = false;            Xmodem_delay_us(2*100000);   // Extra delay for startup            Xmodem_putc(xmodem->crc_mode ? 'C' : XMODEM_NAK);            xmodem->total_retries++;        }        // if (stat == XMODEM_ERR_CANCEL)        else        {            break;        }    }    *err = stat;    return -1;}int Xmodem_read(char *buf, int size, int *err){    int stat, total, len;    int retries;	XMODEM_T *xmodem;		xmodem = (XMODEM_T *)&xmodem_info;    total = 0;    stat = XMODEM_ERR_CANCEL;    // Try and get 'size' bytes into the buffer    while (!xmodem->at_eof && (size > 0))    {        if (xmodem->len == 0)        {            retries = 5;	// XMODEM_MAX_RETRIES;            while (retries-- > 0)            {                stat = Xmodem_get_header(xmodem);                if (stat == 0)                {                    if (xmodem->blk == xmodem->next_blk)                    {                        xmodem->tx_ack = true;                        xmodem->next_blk = (xmodem->next_blk + 1) & 0xFF;                        // Data blocks can be padded with ^Z (XMODEM_EOF) characters                        // This code tries to detect and remove them                        if ((xmodem->bufp[xmodem->len-1] == XMODEM_EOF) &&                             (xmodem->bufp[xmodem->len-2] == XMODEM_EOF) &&                             (xmodem->bufp[xmodem->len-3] == XMODEM_EOF))                        {							while (xmodem->len && (xmodem->bufp[xmodem->len-1] == XMODEM_EOF))							{								xmodem->len--;							}                        }                        break;                    }                     else if (xmodem->blk == ((xmodem->next_blk - 1) & 0xFF))                    {                        // Just re-ACK this so sender will get on with it                        Xmodem_putc(XMODEM_ACK);						xmodem->tx_ack_cnt++;                        continue;  // Need new header                    } else {                        stat = XMODEM_ERR_SEQUENCE;                    }                }                else if (stat == XMODEM_ERR_EOF)                {                    Xmodem_putc(XMODEM_ACK);        			xmodem->tx_ack_cnt++;                    xmodem->at_eof = true;                    break;                }                else if (stat != XMODEM_ERR_TIMEOUT)                	break;                	                Xmodem_putc(xmodem->crc_mode ? 'C' : XMODEM_NAK);                xmodem->total_retries++;            }            if (stat < 0)            {                *err = stat;                xmodem->len = -1;                return total;            }        }        // Don't "read" data from the XMODEM_EOF protocol package        if (!xmodem->at_eof)        {            len = xmodem->len;            if (size < len) len = size;            memcpy(buf, xmodem->bufp, len);            size -= len;            buf += len;            total += len;            xmodem->len -= len;            xmodem->bufp += len;        }    }    return total;}voidXmodem_close(int *err){#if 0		XMODEM_T *xmodem;		xmodem = (XMODEM_T *)&xmodem_info;    printf("Xmodem - %s mode, %d(XMODEM_SOH)/%d(XMODEM_STX)/%d(XMODEM_CAN) packets, %d retries\n",                 xmodem->crc_mode ? "CRC" : "Cksum",                xmodem->total_XMODEM_SOH, xmodem->total_XMODEM_STX, xmodem->total_XMODEM_CAN,                xmodem->total_retries);#endif                }// Need to be able to clean out the input buffer, so have to take the// getcvoid Xmodem_terminate(int abort){	unsigned char c;	XMODEM_T *xmodem;		xmodem = (XMODEM_T *)&xmodem_info;	if (abort) 	{		Xmodem_putc(XMODEM_CAN);		Xmodem_putc(XMODEM_CAN);		Xmodem_putc(XMODEM_CAN);		Xmodem_putc(XMODEM_CAN);		Xmodem_putc(XMODEM_BSP);		Xmodem_putc(XMODEM_BSP);		Xmodem_putc(XMODEM_BSP);		Xmodem_putc(XMODEM_BSP);		Xmodem_flush();		xmodem->at_eof = true;	}	else	{				while (uart_scanc(&c) > 0) ;		Xmodem_delay_us((LONG)250000);	}}/*----------------------------------------------------------------------* Xmodem_get_error_msg*----------------------------------------------------------------------*/char *Xmodem_get_error_msg(int err){    switch (err) {    case XMODEM_ERR_TIMEOUT:        return "Timed out";        break;    case XMODEM_ERR_EOF:        return "End of file";        break;    case XMODEM_ERR_CANCEL:        return "Cancelled";        break;    case XMODEM_ERR_FRAME:        return "Invalid framing";        break;    case XMODEM_ERR_CHKSUM:        return "CRC/checksum error";        break;    case XMODEM_ERR_SEQUENCE:        return "Block sequence error";        break;    default:        return "Unknown error";        break;    }}

⌨️ 快捷键说明

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