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

📄 xmodem1k.c

📁 LPC1700在线升级方案V1.00
💻 C
字号:
/****************************************Copyright (c)****************************************************
**                            Guangzhou ZLGMCU Development Co., LTD
**
**                                 http://www.zlgmcu.com
**
**--------------File Info---------------------------------------------------------------------------------
** File name:           crc.c
** Last modified Date:  2011-12-23
** Last Version:        V1.0
** Descriptions:        The u16CRC_Calc16() function example template
**
**--------------------------------------------------------------------------------------------------------
** Created by:          Liu zhipeng
** Created date:        2011-12-23
** Version:             V1.00
** Descriptions:        整理应用程序
**
**--------------------------------------------------------------------------------------------------------
** Modified by:         
** Modified date:       
** Version:             
** Descriptions:        
**
**--------------------------------------------------------------------------------------------------------
** Modified by:        
** Modified date:      
** Version:            
** Descriptions:       
**
** Rechecked by:
*********************************************************************************************************/
#include <LPC17xx.h>
#include "../CRC/crc.h"
#include "../UART/uart.h"
#include "xmodem1k.h"

/* Protocol control ASCII characters */
#define SOH							0x01
#define STX							0x02
#define EOT							0x04
#define ACK							0x06
#define NAK							0x15
#define POLL						0x43

/* Internal state machine */
#define STATE_IDLE					0
#define STATE_CONNECTING			1
#define STATE_RECEIVING				2

/* Define the rate at which the server will be polled when starting a transfer */
#define POLL_PERIOD_ms				3000

/* Define packet timeout period (maximum time to receive a packet) */
#define PACKET_TIMEOUT_PERIOD_ms	7000

/* Baud rate to be used by UART interface */
//#define BAUD_RATE					9600

/* Size of packet payloads and header */
#define LONG_PACKET_PAYLOAD_LEN		1024
#define SHORT_PACKET_PAYLOAD_LEN	128
#define PACKET_HEADER_LEN			3

/* Buffer in which received data is stored, must be aligned on a word boundary
   as point to this array is going to be passed to IAP routines (which require
   word alignment). */
static uint8_t au8RxBuffer[LONG_PACKET_PAYLOAD_LEN] __attribute__ ((aligned(4)));

/* Local functions */
static void vTimerStart(uint32_t u32Periodms);

/*****************************************************************************
 ** Function name:
 **
 ** Descriptions:
 **
 ** Parameters:	    None
 **
 ** Returned value:  None
 **
 *****************************************************************************/
void vXmodem1k_Client(uint32_t (*pu32Xmodem1kRxPacketCallback)(uint8_t *pu8Data, uint16_t u16Len))
{
	uint32_t u32InProgress = 1;
	uint32_t u32State = STATE_IDLE;
	uint32_t u32ByteCount;
	uint32_t u32PktLen;
	uint16_t u16CRC;

	/* Prepare UART0 for RX/TX */
	vUARTInit(BAUD_RATE);

	while(u32InProgress)
	{
		switch (u32State)
		{
			case STATE_IDLE:
			{
				/* Send command to server indicating we are ready to receive */
				uint8_t u8Cmd = POLL;
				vUARTSend(&u8Cmd, 1);

				/* Start timeout to send another poll if we do not get a response */
				vTimerStart(POLL_PERIOD_ms);

				/* Wait for a response */
				u32State = STATE_CONNECTING;
			}
			break;

			case STATE_CONNECTING:
			{
				uint8_t u8Data;

				/* Check if a character has been received on the UART */
				if (u8UARTReceive(&u8Data))
				{
					/* Expecting a start of packet character */
					if ((u8Data == STX) || (u8Data == SOH))
					{
						if (u8Data == STX)
						{
							/* STX indicates long payload packet is being transmitted */
							u32PktLen = LONG_PACKET_PAYLOAD_LEN;
						}
						else
						{
							/* SOH indicates short payload packet is being transmitted */
							u32PktLen = SHORT_PACKET_PAYLOAD_LEN;
						}
						u32ByteCount = 1;

						/* Start packet timeout */
						vTimerStart(PACKET_TIMEOUT_PERIOD_ms);

						/* Wait for a further characters */
						u32State = STATE_RECEIVING;
					}
				}
				else /* No data received yet, check poll command timeout */
				{
					if ((LPC_TIM0->TCR & 0x01) == 0)
					{
						/* Timeout expired following poll command transmission so try again.. */
						uint8_t u8Cmd = POLL;
						vUARTSend(&u8Cmd, 1);

						/* Restart timeout to send another poll if we do not get a response */
						vTimerStart(POLL_PERIOD_ms);
					}
				}
			}
			break;

			case STATE_RECEIVING:
			{
				uint8_t u8Data;

				/* Check if a character has been received on the UART */
				if (u8UARTReceive(&u8Data))
				{
					/* Position of received byte determines action we take */
					if (u32ByteCount == 0)
					{
						/* Expecting a start of packet character */
						if ((u8Data == STX) || (u8Data == SOH))
						{
							if (u8Data == STX)
							{
								/* STX indicates long payload packet is being transmitted */
								u32PktLen = LONG_PACKET_PAYLOAD_LEN;
							}
							else
							{
								/* SOH indicates short payload packet is being transmitted */
								u32PktLen = SHORT_PACKET_PAYLOAD_LEN;
							}
							u32ByteCount = 1;

							/* Start packet timeout */
							vTimerStart(PACKET_TIMEOUT_PERIOD_ms);
						}
						else if (u8Data == EOT)
						{
							/* Server indicating transmission is complete */
							uint8_t u8Cmd = ACK;
							vUARTSend(&u8Cmd, 1);

							/* Close xmodem client */
							u32InProgress = 0;
						}
						else
						{
							/* TODO - Unexpected character, do what...? */
						}
					}
					else if (u32ByteCount == 1)
					{
						/* Byte 1 is the packet number - should be different from last one we received */
						u32ByteCount++;
					}
					else if (u32ByteCount == 2)
					{
						/* Byte 2 is the packet number inverted - check for error with last byte */
						u32ByteCount++;
					}
					else if (((u32ByteCount == 131 ) && (u32PktLen == SHORT_PACKET_PAYLOAD_LEN)) ||
							 ((u32ByteCount == 1027) && (u32PktLen == LONG_PACKET_PAYLOAD_LEN)))
					{
						/* If payload is short byte 131 is the MS byte of the packet CRC, if payload
						   is long byte 1027 is the MS byte of the packet CRC. */
						u16CRC = u8Data;
						u32ByteCount++;
					}
					else if (((u32ByteCount == 132)  && (u32PktLen == SHORT_PACKET_PAYLOAD_LEN)) ||
					         ((u32ByteCount == 1028) && (u32PktLen == LONG_PACKET_PAYLOAD_LEN)))
					{
						/* If payload is short byte 132 is the LS byte of the packet CRC, if payload
						   is long byte 1028 is the LS byte of the packet CRC. */
						u16CRC <<= 8;
						u16CRC  |= u8Data;

						/* Check the received CRC against the CRC we generate on the packet data */
						if (u16CRC_Calc16(&au8RxBuffer[0], u32PktLen) == u16CRC)
						{
							uint8_t u8Cmd;

							/* Have now received full packet, call handler BEFORE sending ACK to application
							   can process data before more is sent. */
							if (pu32Xmodem1kRxPacketCallback(&au8RxBuffer[0], u32PktLen) != 0)
							{
								/* Packet handled successfully, send ACK to server indicating we are ready for next packet */
								u8Cmd = ACK;
								vUARTSend(&u8Cmd, 1);
							}
							else
							{
								/* Something went wrong with packet handler, all we can do is send NAK causing the
								   packet to be retransmitted by the server.. */
								u8Cmd = NAK;
								vUARTSend(&u8Cmd, 1);
							}
						}
						else /* Error CRC calculated does not match that received */
						{
							/* Indicate problem to server - should result in packet being resent.. */
							uint8_t u8Cmd = NAK;
							vUARTSend(&u8Cmd, 1);
						}
						u32ByteCount = 0;
					}
					else
					{
						/* Must be payload data so store */
						au8RxBuffer[u32ByteCount - PACKET_HEADER_LEN] = u8Data;
						u32ByteCount++;
					}
				}
				else
				{
					/* TODO - Check packet timeout */
				}
			}
			break;

			default:
				break;
		}
	}
}

/*****************************************************************************
 ** Function name:
 **
 ** Descriptions:
 **
 ** Parameters:	     None
 **
 ** Returned value:  None
 **
 *****************************************************************************/
static void vTimerStart(uint32_t u32Periodms)
{
	/* Enable the timer clock */
//	LPC_SYSCON->SYSAHBCLKCTRL |= (1UL << 9);

	/* Configure the timer so that we can poll for a match */
	LPC_TIM0->TCR = 0x02;		/* reset timer */
	LPC_TIM0->PR  = 0x00;		/* set prescaler to zero */
	LPC_TIM0->MR0 = u32Periodms * ((SystemFrequency / (LPC_TIM0->PR + 1)) / 1000UL);
	LPC_TIM0->IR  = 0xFF;		/* reset all interrupts */
	LPC_TIM0->MCR = 0x04;		/* stop timer on match */
	LPC_TIM0->TCR = 0x01;		/* start timer */
}

/*****************************************************************************
 **                            End Of File
 *****************************************************************************/

⌨️ 快捷键说明

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