📄 xyzmodem.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 <redboot.h>#include <xyzModem.h>// Assumption - run xyzModem protocol over the console port// Values magic to the protocol#define SOH 0x01#define STX 0x02#define EOT 0x04#define ACK 0x06#define BSP 0x08#define NAK 0x15#define CAN 0x18#define EOF 0x1A // ^Z for DOS officionados#define nUSE_YMODEM_LENGTH// Data & state local to the protocolstatic struct { hal_virtual_comm_table_t* __chan; unsigned char pkt[1024], *bufp; unsigned char blk,cblk,crc1,crc2; unsigned char next_blk; // Expected block int len, mode, total_retries; int total_SOH, total_STX, total_CAN; bool crc_mode, at_eof, tx_ack;#ifdef USE_YMODEM_LENGTH unsigned long file_length, read_length;#endif} xyz;#define xyzModem_CHAR_TIMEOUT 2000 // 2 seconds#define xyzModem_MAX_RETRIES 20#define xyzModem_MAX_RETRIES_WITH_CRC 10#define xyzModem_CAN_COUNT 3 // Wait for 3 CAN before quitting#ifdef DEBUG#ifndef USE_SPRINTF//// Note: this debug setup only works if the target platform has two serial ports// available so that the other one (currently only port 1) can be used for debug// messages.//static intzm_dprintf(char *fmt, ...){ int cur_console; va_list args; va_start(args, fmt); cur_console = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); CYGACC_CALL_IF_SET_CONSOLE_COMM(1); diag_vprintf(fmt, args); CYGACC_CALL_IF_SET_CONSOLE_COMM(cur_console);}static voidzm_flush(void){}#else//// Note: this debug setup works by storing the strings in a fixed buffer//static char *zm_out = (char *)0x00380000;static char *zm_out_start = (char *)0x00380000;static intzm_dprintf(char *fmt, ...){ int len; va_list args; va_start(args, fmt); len = diag_vsprintf(zm_out, fmt, args); zm_out += len; return len;}static voidzm_flush(void){ char *p = zm_out_start; while (*p) mon_write_char(*p++); zm_out = zm_out_start;}#endifstatic voidzm_dump_buf(void *buf, int len){ diag_vdump_buf_with_offset(zm_dprintf, buf, len, 0);}static unsigned char zm_buf[2048];static unsigned char *zm_bp;static voidzm_new(void){ zm_bp = zm_buf;}static voidzm_save(unsigned char c){ *zm_bp++ = c;}static voidzm_dump(int line){ zm_dprintf("Packet at line: %d\n", line); zm_dump_buf(zm_buf, zm_bp-zm_buf);}#define ZM_DEBUG(x) x#else#define ZM_DEBUG(x)#endif// Wait for the line to go idlestatic voidxyzModem_flush(void){ int res; char c; while (true) { res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &c); if (!res) return; }}static intxyzModem_get_hdr(void){ char c; int res; bool hdr_found = false; int i, can_total, hdr_chars; unsigned short cksum; ZM_DEBUG(zm_new()); // Find the start of a header can_total = 0; hdr_chars = 0; if (xyz.tx_ack) { CYGACC_COMM_IF_PUTC(*xyz.__chan, ACK); xyz.tx_ack = false; } while (!hdr_found) { res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &c); ZM_DEBUG(zm_save(c)); if (res) { hdr_chars++; switch (c) { case SOH: xyz.total_SOH++; case STX: if (c == STX) xyz.total_STX++; hdr_found = true; break; case CAN: xyz.total_CAN++; ZM_DEBUG(zm_dump(__LINE__)); if (++can_total == xyzModem_CAN_COUNT) { return xyzModem_cancel; } else { // Wait for multiple CAN to avoid early quits break; } case EOT: // EOT only supported if no noise if (hdr_chars == 1) { CYGACC_COMM_IF_PUTC(*xyz.__chan, ACK); ZM_DEBUG(zm_dprintf("ACK on EOT #%d\n", __LINE__)); ZM_DEBUG(zm_dump(__LINE__)); return xyzModem_eof; } default: // Ignore, waiting for start of header ; } } else { // Data stream timed out xyzModem_flush(); // Toss any current input ZM_DEBUG(zm_dump(__LINE__)); CYGACC_CALL_IF_DELAY_US((cyg_int32)250000); return xyzModem_timeout; } } // Header found, now read the data res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.blk); ZM_DEBUG(zm_save(xyz.blk)); if (!res) { ZM_DEBUG(zm_dump(__LINE__)); return xyzModem_timeout; } res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.cblk); ZM_DEBUG(zm_save(xyz.cblk)); if (!res) { ZM_DEBUG(zm_dump(__LINE__)); return xyzModem_timeout; } xyz.len = (c == SOH) ? 128 : 1024; xyz.bufp = xyz.pkt; for (i = 0; i < xyz.len; i++) { res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &c); ZM_DEBUG(zm_save(c)); if (res) { xyz.pkt[i] = c; } else { ZM_DEBUG(zm_dump(__LINE__)); return xyzModem_timeout; } } res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.crc1); ZM_DEBUG(zm_save(xyz.crc1)); if (!res) { ZM_DEBUG(zm_dump(__LINE__)); return xyzModem_timeout; } if (xyz.crc_mode) { res = CYGACC_COMM_IF_GETC_TIMEOUT(*xyz.__chan, &xyz.crc2); ZM_DEBUG(zm_save(xyz.crc2)); if (!res) { ZM_DEBUG(zm_dump(__LINE__)); return xyzModem_timeout; } } ZM_DEBUG(zm_dump(__LINE__)); // Validate the message if ((xyz.blk ^ xyz.cblk) != (unsigned char)0xFF) { ZM_DEBUG(zm_dprintf("Framing error - blk: %x/%x/%x\n", xyz.blk, xyz.cblk, (xyz.blk ^ xyz.cblk))); ZM_DEBUG(zm_dump_buf(xyz.pkt, xyz.len)); xyzModem_flush(); return xyzModem_frame;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -