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

📄 xmodem.c

📁 linux下ROMMONITOR,FLASH,MODEM等操作原代码,请需要的朋友下载
💻 C
字号:
/*******************************************************************************
 *
 * Filename: xmodem.c
 *
 * Instantiation of simple x-modem support using debug uart channel.
 *
 * Revision information:
 *
 * 22AUG2004	kb_admin	initial creation
 * 24AUG2004	kb_admin	optimize for space, not quite as elegant. . .
 *
 * BEGIN_KBDD_BLOCK
 * No warranty, expressed or implied, is included with this software.  It is
 * provided "AS IS" and no warranty of any kind including statutory or aspects
 * relating to merchantability or fitness for any purpose is provided.  All
 * intellectual property rights of others is maintained with the respective
 * owners.  This software is not copyrighted and is intended for reference
 * only.
 * END_BLOCK
 ******************************************************************************/

#include "at91rm9200_lowlevel.h"
#include "xmodem.h"

/* ****************************** GLOBALS *************************************/

/* ********************* PRIVATE FUNCTIONS/DATA/DEFINES ***********************/

#define PACKET_SIZE	128

/* Line control codes */
#define SOH			0x01	/* start of header */
#define ACK			0x06	/* Acknowledge */
#define NAK			0x15	/* Negative acknowledge */
#define CAN			0x18	/* Cancel */
#define EOT			0x04	/* end of text */

enum {
	INVALID_STATE = 0,
	WAITING_START,
	WAIT_SOH,
	RX_PACKET,
	RX_EOT,
	SEND_NAK
};

static char	packetNumber;
char		localBuffer[LOCAL_BUFFER_SIZE];
static int	lastTransferSize = 0;
static int	lastTransferSuccess = 0;
static int	lastTransferAddress = 0;

#define TransitionState(x, y) (x = y)


/*
 * .KB_C_FN_DEFINITION_START
 * int GetRecord(char , char *)
 *  This private function receives a x-modem record to the pointer and
 * returns non-zero on success.
 * .KB_C_FN_DEFINITION_END
 */
static int GetRecord(char blocknum, char *dest) {
	int		size;
	char		nextChar;
	unsigned	chk, j;

	chk = 0;

	if (!WaitForChar(&nextChar, 1)) {
		return (0);
	}

	if ((char)nextChar != (char)~blocknum) {
		return (0);
	}

	for (size = 0; size < PACKET_SIZE; ++size) {
		if (!WaitForChar(&nextChar, 1)) {
			return (0);
		}
		chk = chk ^(int)nextChar << 8;
		for (j = 0; j < 8; ++j) {
			if (chk & 0x8000)
				chk = chk << 1 ^ 0x1021;
			else
				chk = chk << 1;
		}
		*dest++ = nextChar;
	}

	chk &= 0xFFFF;

	if ((!WaitForChar(&nextChar, 1)) || (nextChar != ((chk >> 8) & 0xFF))) {
		return (0);
	}

	if ((!WaitForChar(&nextChar, 1)) || (nextChar != (chk & 0xFF))) {
		return (0);
	}

	DebugPutc(ACK);

	return (1);
}


/* ************************** GLOBAL FUNCTIONS ********************************/


/*
 * .KB_C_FN_DEFINITION_START
 * int xmodem_rx(char *)
 *  This global function receives a x-modem transmission consisting of
 * (potentially) several blocks.  Returns the number of bytes received or
 * -1 on error or if report info requested.
 * .KB_C_FN_DEFINITION_END
 */
int xmodem_rx(char *dest) {

	int		state;
	char		nextChar, *startAddress = dest;

	packetNumber = 1;
	state = WAITING_START;

	if (!dest) {
		// report on x-modem status
		DebugPrint(" Local buffer available of size: ");
		DebugPrintValue(LOCAL_BUFFER_SIZE);
		DebugPrint(" bytes (");
		DebugPrint(LOCAL_BUFFER_TEXT);
		DebugPrint(") at address: ");
		DebugPrintHex(8, (unsigned)localBuffer);
		DebugPrint("\n\r\n\r");
		DebugPrint(" Last x-modem transfer: ");

		if (lastTransferSuccess) {
			DebugPrint("PASS size: ");
			DebugPrintHex(8, lastTransferSize);
			DebugPrint(" at address: ");
			DebugPrintHex(8, lastTransferAddress);
			DebugPrint("\n\r");
		} else {
			DebugPrint("FAIL (or not initiated)\n\r");
		}

		return (0);
	}

	lastTransferSuccess = 0;
	lastTransferAddress = (int)dest;

	while (1) {

		if (state == WAITING_START) {
			DebugPutc('C');
			if (WaitForChar(&nextChar, 1)) {
				if (nextChar == SOH) {
					TransitionState(state, RX_PACKET);
				}
			}
		}

		if (state == WAIT_SOH) {
			if (!WaitForChar(&nextChar, 1)) {
				return (-1);
			}

			if (nextChar == SOH) {
				TransitionState(state, RX_PACKET);
			}

			if (nextChar == EOT) {
				// TransitionState(state, RX_EOT);
				DebugPutc(ACK);
				lastTransferSuccess = 1;
				lastTransferSize = (dest - startAddress);
				return (lastTransferSize);
			}
		}

		if (state == RX_PACKET) {
			if (!WaitForChar(&nextChar, 1)) {
				return (-1);
			}

			if (nextChar != packetNumber) {
				// TransitionState(state, SEND_NAK);
				DebugPutc(NAK);
				return (-1);
			}

			if (GetRecord(packetNumber, dest)) {
				dest += PACKET_SIZE;
				++packetNumber;
				TransitionState(state, WAIT_SOH);
			} else {
				return (-1);
			}
		}
	}

	// the loop above should return in all cases
	return (-1);
}

⌨️ 快捷键说明

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