/********************************************************************************
Copyright (C), Sinowealth Electronic. Ltd.
Author: 	Sino
Version: 	V0.0
Date: 		2020/04/26
History:
	V2.0	2020/04/26		 Preliminary
********************************************************************************/
#include "MCURegister.h"
#include "C51_TYPE.H"
#include "Flash.h"
#include "IapIsp.h"

BOOL bIapIspFlg;            //0：表示当前执行IAP操作；1：表示当前执行ISP操作
BOOL bHandsheakOkFlg;
BOOL bUartSndOverFlg;
U16 uiUartRcvChkSum;
U8	ucUartErrCode;
U8	ucUartBufPT;
U32	ulIapDataPtr;
U32	ulIapChksum;
U32	ulIapRecDataLen;
U8	ucIapIndexBk;
U8	ucIapRestCommand;
U8	xdata ucUartBuf[150];
U8	xdata ucIapBuf[MCU_CODE_SECTOR_SIZE];

extern void UARTInit(void);
/*************************************************************************************************
* 函数名: UartSendAck
* 参  数: 无
* 返回值: 无
* 描  述: 当Slave接收完数据并处理完成后，开始返回数据
*************************************************************************************************/
void UartSendAck(void)
{
    U8 i, DataBak;
    U16 CheckSum = 0;

    ucUartBuf[LENGTH] = 0x00;
    ucUartBuf[COMMAND] = 0x0B;
    
    DataBak = ucUartBuf[SOURCE];                                            //交换源ID和目标ID
	ucUartBuf[SOURCE] = ucUartBuf[TARGET];
	ucUartBuf[TARGET] = DataBak;
	
	for(i=2; i<(ucUartBuf[LENGTH]+7); i++)
	{
		CheckSum += ucUartBuf[i];
	}
	
	ucUartBuf[7+ucUartBuf[LENGTH]] = (U8)CheckSum;
	ucUartBuf[8+ucUartBuf[LENGTH]] = (U8)(CheckSum>>8);
	
	bUartSndOverFlg = 0;
	UartTxEn(ucUartBuf[ucUartBufPT]);
}


/*************************************************************************************************
* 函数名: IapHandShake
* 参  数: 无
* 返回值: 无
* 描  述: 握手协议，进入IAP或者ISP烧写流程
          bIapIspFlg: 0--IAP操作；1--ISP操作
*************************************************************************************************/
void IapHandShake(void)
{
	ucUartBuf[INDEXES] = 0;
	if(ucUartBuf[DATA]=='I' && ucUartBuf[DATA+1]=='A' && ucUartBuf[DATA+2]=='P')
	{
		bIapIspFlg = IAP_MODE;
        bHandsheakOkFlg = 1;
	}
	else if(ucUartBuf[DATA]=='I' && ucUartBuf[DATA+1]=='S' && ucUartBuf[DATA+2]=='P')
	{
		bIapIspFlg = ISP_MODE;
        bHandsheakOkFlg = 1;
	}
	else
	{
		ucUartBuf[INDEXES] = IAPERROR_HANDSHAKE;                            //握手失败
        bHandsheakOkFlg = 0;
	}
}


/*************************************************************************************************
* 函数名: IapBeginAck
* 参  数: 无
* 返回值: 无
* 描  述: IAP或ISP开始操作，擦除CODE的备份区30K
*************************************************************************************************/
void IapBeginAck(void)
{
    U8 i, SectorNum, McuFlashType;
	U32 McuFlashAddr;
    
	ulIapDataPtr = 0;
	ulIapChksum = 0;
	ulIapRecDataLen = 0;
	ulIapRecDataLen = ((U32)ucUartBuf[DATA+3]<<24)                          //数据长度
					| ((U32)ucUartBuf[DATA+2]<<16)
					| ((U32)ucUartBuf[DATA+1]<<8)
					| (U32)ucUartBuf[DATA];

    if(!bHandsheakOkFlg)
    {
        ucUartBuf[INDEXES] = IAPERROR_HANDSHAKE;                            //握手失败
    }
    
    if((ulIapRecDataLen > IAP_BK_CODE_SIZE) && (bIapIspFlg == IAP_MODE))
	{
		ucUartBuf[INDEXES] = IAPERROR_SIZE;                                 //如果数据长度不等于IAP和ISP长度，则默认为长度异常
	}
    else if((ulIapRecDataLen > ISP_CODE_SIZE) && (bIapIspFlg == ISP_MODE))
	{
		ucUartBuf[INDEXES] = IAPERROR_SIZE;                                 //如果数据长度不等于IAP和ISP长度，则默认为长度异常
	}
	else
	{
		ucUartBuf[INDEXES] = 0;                                             //先预设回复成功
		ucIapIndexBk = 0;
        
//1. 如果当前操作是ISP，则先擦除BOOT区的标志，然后在BOOT_FLG_ISP_ADD中写ISP_FLG标志0xA5
        ucMcuFlashWrValid = 0x55;                                           //设置MCU Code区可操作标志，防止误写
        McuFlashEraseSector(BOOT_FLG_START_ADDR, MCU_TYPE_CODE);
        if(McuFlashBlankCheck(BOOT_FLG_START_ADDR, MCU_TYPE_CODE))          //擦除结束后，需要查空
        {
            if(bIapIspFlg == ISP_MODE)
            {
                McuFlashWrOneByte(BOOT_FLG_ISP_ADDR, ISP_FLG, MCU_TYPE_CODE);
                if(McuFlashRdOneByte(BOOT_FLG_ISP_ADDR, MCU_TYPE_CODE) != ISP_FLG)
                {
                    ucUartBuf[INDEXES] = IAPERROR_WR;                       //Write失败
                }
            }
        }
        else
        {
            ucUartBuf[INDEXES] = IAPERROR_ERASE;                            //Erase失败
        }
        ucMcuFlashWrValid = 0;
		
//2. 不管是IAP还是ISP，都先擦除程序的所有Sector，如果是ISP，则还需要擦除EEPROM区
		if(ucUartBuf[INDEXES] == 0)							                //检查ucUartBuf[INDEXES]
		{
			SectorNum = ulIapRecDataLen/MCU_CODE_SECTOR_SIZE;
            for(i=0; i<SectorNum; i++)						                //先擦除CODE备份区的Sector
			{
                McuFlashType = MCU_TYPE_CODE;                               //先默认擦除flash
				if(bIapIspFlg == ISP_MODE)
				{
                    McuFlashAddr = ISP_CODE_START_ADDR;                     //ISP起始地址
				}
				else
				{
					McuFlashAddr = IAP_BK_CODE_START_ADDR;                  //IAP起始地址
				}
                McuFlashAddr += (U16)i*512;                                 //确定被擦除页起始地址
                
				if(bIapIspFlg == ISP_MODE)									//ISP模式下直接擦除EEPROM
				{
					if(i>=(SectorNum-APP_PARA_SIZE/MCU_CODE_SECTOR_SIZE))	//EEPROM按sector擦除
					{
						McuFlashType = MCU_TYPE_E2P;
						McuFlashAddr = (U16)(i+APP_PARA_SIZE/MCU_CODE_SECTOR_SIZE-SectorNum)*512;
					}
				}
				
				ucMcuFlashWrValid = 0x55;					                //设置MCU Code区可操作标志，防止误写
				McuFlashEraseSector(McuFlashAddr, McuFlashType);
				if(!McuFlashBlankCheck(McuFlashAddr, McuFlashType))	        //擦除结束后，需要查空
				{
					ucUartBuf[INDEXES] = IAPERROR_ERASE;                    //Erase失败
				}
				ucMcuFlashWrValid = 0;
			}
		}
        else
        {
            ucUartBuf[INDEXES] = IAPERROR_INDEX;
        }
	}
}


/*************************************************************************************************
* 函数名: IapWrSector
* 参  数: 无
* 返回值: 无
* 描  述: 写入1个Sector数据
*************************************************************************************************/
BOOL IapWrSector(void)
{
	BOOL Result = 1;
	U16 i;
	U32 McuFlashAddr;
	U8 McuFlashType;
	
	for(i=0; i<MCU_CODE_SECTOR_SIZE; i++)                                   //连续写1个sector
	{
		McuFlashType = MCU_TYPE_CODE;
		if(bIapIspFlg == ISP_MODE)                                          //ISP
		{
			McuFlashAddr = ISP_CODE_START_ADDR + ulIapDataPtr;
			if(McuFlashAddr >= (ulIapRecDataLen+BOOT_CODE_SIZE-APP_PARA_SIZE))
			{
				McuFlashAddr = McuFlashAddr - (ulIapRecDataLen+BOOT_CODE_SIZE-APP_PARA_SIZE);
				McuFlashType = MCU_TYPE_E2P;                                //ISP更新EEPROM区
			}
		}
		else
		{
			McuFlashAddr = IAP_BK_CODE_START_ADDR + ulIapDataPtr;
		}
		McuFlashWrOneByte(McuFlashAddr, ucIapBuf[i], McuFlashType);
		if(ucIapBuf[i] != McuFlashRdOneByte(McuFlashAddr, McuFlashType))
		{
			Result = 0;
			break;
		}
		ulIapDataPtr++;
	}
	
	return Result;
}


/*************************************************************************************************
* 函数名: IapReceiveData
* 参  数: 无
* 返回值: 无
* 描  述: 接收数据，同时将数据写入的MCU CODE区
*************************************************************************************************/
void IapReceiveData(void)
{
	U16 i;
	U8 j;
	U32 McuFlashAddr;
	U8 McuFlashType;
	
    bHandsheakOkFlg = 0;
    
    if( ((ucUartBuf[INDEXES]<ucIapIndexBk) || (ucUartBuf[INDEXES]>(ucIapIndexBk+4))) && (ucUartBuf[INDEXES] != 0) )    //yangweilei
	{
		ucUartBuf[INDEXES] = IAPERROR_INDEX;                                //数据索引错误，首先判断是否连续，其次判断是否超出范围
	}
	else
	{
		ucIapIndexBk = ucUartBuf[INDEXES];
        ucUartBuf[INDEXES] = 0;
		if(ucUartBuf[LENGTH] == 0)
		{
			ulIapDataPtr += 512;                                            //如果传递的长度为0，表示当前128个字节为0，指针加，但不写(增加150mS/1K)
		}
		else
		{
			j = ucIapIndexBk % 4;                                           //目前暂定sector长度为512bytes，每次传输128bytes，所以定义为4
            for(i=0; i<ucUartBuf[LENGTH]; i++)
			{
				ucIapBuf[i+(U16)j*ucUartBuf[LENGTH]] = ucUartBuf[DATA+i];
			}
			if(j == 3)                                                      //连续接收满1个sector，才进行写入操作
			{
                ucMcuFlashWrValid = 0x55;                                   //设置MCU Code区可操作标志，防止误写
				if(!IapWrSector())                                          //第一次写sector错误，则擦除后再写一次
				{
                    if(ulIapDataPtr >= MCU_CODE_SECTOR_SIZE)
                    {
                        ulIapDataPtr -= MCU_CODE_SECTOR_SIZE;               //指针返回到该Sector起始
					}
                    else
                    {
                        ulIapDataPtr = 0;
                    }
                    
                    McuFlashType = MCU_TYPE_CODE;                           //默认是CODE区
					if(bIapIspFlg == ISP_MODE)                              //ISP
					{
						McuFlashAddr = ISP_CODE_START_ADDR + ulIapDataPtr;
						if(McuFlashAddr >= (ulIapRecDataLen+BOOT_CODE_SIZE-APP_PARA_SIZE))
						{
							McuFlashAddr = McuFlashAddr - (ulIapRecDataLen+BOOT_CODE_SIZE-APP_PARA_SIZE);
							McuFlashType = MCU_TYPE_E2P;                    //ISP更新EEPROM区
						}
					}
					else
					{
                        McuFlashAddr = IAP_BK_CODE_START_ADDR + ulIapDataPtr;
					}
                    ucMcuFlashWrValid = 0x55;
					McuFlashEraseSector(McuFlashAddr, McuFlashType);
					if(McuFlashBlankCheck(McuFlashAddr, McuFlashType))      //擦除结束后，需要查空
					{
						if(!IapWrSector())                                  //如果连续写两次错误，则返回给上位机异常
						{
							ucUartBuf[INDEXES] = IAPERROR_WR;               //写入错误
						}
						else
						{
							goto UpdateChksum;
						}
					}
					else
					{
						ucUartBuf[INDEXES] = IAPERROR_ERASE;                //擦除错误
					}
				}
				else                                                        //512Bytes写入正确，才更新checksum值
				{
UpdateChksum:
					for(j=0; j<MCU_CODE_SECTOR_SIZE/4; j++)                 //计算checksum需要按照32bit，尽量兼容STM32
					{
						ulIapChksum += (((U32)ucIapBuf[j*4+3]<<24)
									  | ((U32)ucIapBuf[j*4+2]<<16)
									  | ((U32)ucIapBuf[j*4+1]<<8)
									  | ((U32)ucIapBuf[j*4+0]));
					}
				}
                
                ucMcuFlashWrValid = 0;
			}
		}
	}
}


/*************************************************************************************************
* 函数名: IapRDataVerify
* 参  数: 无
* 返回值: 无
* 描  述: 验证CheckSum是否正确
*************************************************************************************************/
void IapRDataVerify(void)
{
	U32 CheckSum = 0;
	
	CheckSum =	  ((U32)ucUartBuf[DATA+3]<<24)                              //获取上位机下发的校验和
				| ((U32)ucUartBuf[DATA+2]<<16)
				| ((U32)ucUartBuf[DATA+1]<<8)
				| ((U32)ucUartBuf[DATA+0]);
	
	if(ulIapChksum != CheckSum)                                             //数据校验失败
	{
		ucUartBuf[INDEXES] = IAPERROR_CRC;
	}
	else
	{
		ucUartBuf[INDEXES] = 0;                                             //数据校验成功
	}
}


/*************************************************************************************************
* 函数名: IapCmdReset
* 参  数: 无
* 返回值: 无
* 描  述: 当IAP和ISP正常Program结束之后，上位机发送复位指令，程序会跳转到0x0000地址
          ISP，程序会擦除BOOT区的标志区，ISP结束
          IAP，程序会擦除BOOT区的标志区，同时将标志区的最后一个字节写0x5A，APP会自动升级
*************************************************************************************************/
void IapCmdReset(void)
{
	ucUartBuf[INDEXES] = 0;
	ucIapRestCommand = IAP_CMD_RESET;
	
	ucMcuFlashWrValid = 0x55;                                               //设置MCU Code区可操作标志，防止误写
	McuFlashEraseSector(BOOT_FLG_START_ADDR, MCU_TYPE_CODE);
	if(McuFlashBlankCheck(BOOT_FLG_START_ADDR, MCU_TYPE_CODE))              //擦除结束后，需要查空
	{
		if(bIapIspFlg == IAP_MODE)                                          //IAP升级结束后，需要将BOOT区的标志区最后一个字节写0x5A
		{
			McuFlashWrOneByte(BOOT_FLG_IAP_ADDR, IAP_FLG, MCU_TYPE_CODE);
			if(McuFlashRdOneByte(BOOT_FLG_IAP_ADDR, MCU_TYPE_CODE) != IAP_FLG)
			{
				ucUartBuf[INDEXES] = IAPERROR_WR;                           //Write失败
				ucIapRestCommand = 0;
			}
		}
	}
	else
	{
		ucUartBuf[INDEXES] = IAPERROR_ERASE;                                //擦除失败
		ucIapRestCommand = 0;
	}
	ucMcuFlashWrValid = 0;
}


/*************************************************************************************************
* 函数名: UartCmdProcess
* 参  数: 无
* 返回值: 无
* 描  述: 处理IAP和ISP的四条命令
*************************************************************************************************/
void UartCmdProcess(void)
{
	ucUartBufPT = 0;
	if(uiUartRcvChkSum != ((ucUartBuf[ucUartBuf[LENGTH]+8]<<8) + ucUartBuf[ucUartBuf[LENGTH]+7]))
	{
		ucUartErrCode |= IAPERROR_CHECKSUM;
	}
	
	if(ucUartErrCode != 0)                                                  //如果有错误代码则不执行命令处理
	{
		ucUartBuf[INDEXES] = ucUartErrCode;
	}
	else
	{
		if(ucUartBuf[COMMAND] == IAP_CMD_HANDSHAKE)                         //IAP和ISP握手协议，上位机连续发两次
		{
			IapHandShake();
		}
		else if(ucUartBuf[COMMAND] == IAP_CMD_BEGIN)                        //开始IAP或ISP，并将CODE区/EEP区全部擦除
		{
			IapBeginAck();
		}
		else if(ucUartBuf[COMMAND] == IAP_CMD_TRANS)                        //接收数据、写入、校验
		{
			IapReceiveData();
		}
		else if(ucUartBuf[COMMAND] == IAP_CMD_VERIFY)                       //
		{
			IapRDataVerify();
		}
		else if(ucUartBuf[COMMAND] == IAP_CMD_RESET)
		{
			IapCmdReset();
		}
	}
	
	UartSendAck();
}


/*************************************************************************************************
* 函数名: BootIapIsp
* 参  数: 无
* 返回值: 无
* 描  述: IAP和ISP函数处理
*************************************************************************************************/
void BootIapIsp(void)
{
	ulIapDataPtr = 0;
	ulIapChksum = 0;
	ucIapRestCommand = 0;
	UARTInit();
	while(1)
	{
		#if ((UART_DEFINE >= 1)&&(UART_DEFINE<= 30))
		{
			if(RI)
			{
				//BootMcuWdtClear();                                              //在该程序循环中，未接收到UART通讯，则判定通讯异常，触发看门狗
				ucUartBuf[ucUartBufPT] = SBUF;
				ucUartBufPT++;
				if(ucUartBufPT >= 140)                                          //该指针不会超过140
				{
					ucUartBufPT = 0;
				}
				if(ucUartBufPT == 1)
				{
					if(ucUartBuf[HEARD1] != 0x5A)                               //检查帧头是否Wie0x5AA5
					{
						ucUartBufPT = 0;
					}
	
				}
				else if(ucUartBufPT == 2)
				{
	
					if(ucUartBuf[HEARD2] != 0xA5)
					{
						ucUartBufPT = 0;
					}
					else
					{
						uiUartRcvChkSum = 0;                                    //帧头判断正确
						ucUartErrCode = 0;
					}
				}
				else
				{
	
					if(ucUartBufPT < (ucUartBuf[LENGTH]+9))
					{
						if(ucUartBufPT <= (ucUartBuf[LENGTH]+7))
						{
							uiUartRcvChkSum += ucUartBuf[ucUartBufPT-1];
						}
						
						if(ucUartBufPT == (TARGET+1))                           //检查ID
						{
							
							if(ucUartBuf[TARGET] != IAP_BMSID)
							{
								ucUartBufPT = 0;
							}
						}
						else if(ucUartBufPT == (COMMAND+1))                     //检测COMMAND
						{						
							if((ucUartBuf[COMMAND] != IAP_CMD_HANDSHAKE)
							&& (ucUartBuf[COMMAND] != IAP_CMD_BEGIN)
							&& (ucUartBuf[COMMAND] != IAP_CMD_TRANS)
							&& (ucUartBuf[COMMAND] != IAP_CMD_VERIFY)
							&& (ucUartBuf[COMMAND] != IAP_CMD_RESET))
							{
								ucUartErrCode |= IAPERROR_CMD;
							}
						}
					}
					else
					{
						BootMcuWdtClear();
						UartCmdProcess();
					}
				}
				RI = 0;
			}
			
			if(TI)
			{
				BootMcuWdtClear();                                              //在该程序循环中，未接收到UART通讯，则判定通讯异常，触发看门狗
				
				if(ucUartBufPT >= (ucUartBuf[LENGTH]+8))
				{
					UartRxEn();                                                 //Allow UART receive data
					ucUartBufPT = 0;
					ucUartBuf[0] = 0;
					ucUartBuf[1] = 0;
					ucUartBuf[2] = 0;
					bUartSndOverFlg = 1;
				}
				else
				{
					ucUartBufPT++;
					UartTxEn(ucUartBuf[ucUartBufPT]);
				}
	
				TI = 0;
			}
			
			if(ucIapRestCommand == IAP_CMD_RESET)
			{
				BootMcuWdtClear();
				if(bUartSndOverFlg)                                             //Reset帧回复结束
				{
					bUartSndOverFlg = 0;
					ucIapRestCommand = 0;
					((void(code*)(void))0x0000)();
				}
			}
		}
		#elif ((UART_DEFINE >= 31)&&(UART_DEFINE<= 60))
		{
			INSCON = 0x40;
			if(RI1)
			{
				//BootMcuWdtClear();                                              //在该程序循环中，未接收到UART通讯，则判定通讯异常，触发看门狗
				ucUartBuf[ucUartBufPT] = SBUF1;
				INSCON = 0x00;
				ucUartBufPT++;
				if(ucUartBufPT >= 140)                                          //该指针不会超过140
				{
					ucUartBufPT = 0;
				}
				if(ucUartBufPT == 1)
				{
					if(ucUartBuf[HEARD1] != 0x5A)                               //检查帧头是否Wie0x5AA5
					{
						ucUartBufPT = 0;
					}
	
				}
				else if(ucUartBufPT == 2)
				{
	
					if(ucUartBuf[HEARD2] != 0xA5)
					{
						ucUartBufPT = 0;
					}
					else
					{
						uiUartRcvChkSum = 0;                                    //帧头判断正确
						ucUartErrCode = 0;
					}
				}
				else
				{
	
					if(ucUartBufPT < (ucUartBuf[LENGTH]+9))
					{
						if(ucUartBufPT <= (ucUartBuf[LENGTH]+7))
						{
							uiUartRcvChkSum += ucUartBuf[ucUartBufPT-1];
						}
						
						if(ucUartBufPT == (TARGET+1))                           //检查ID
						{
							
							if(ucUartBuf[TARGET] != IAP_BMSID)
							{
								ucUartBufPT = 0;
							}
						}
						else if(ucUartBufPT == (COMMAND+1))                     //检测COMMAND
						{						
							if((ucUartBuf[COMMAND] != IAP_CMD_HANDSHAKE)
							&& (ucUartBuf[COMMAND] != IAP_CMD_BEGIN)
							&& (ucUartBuf[COMMAND] != IAP_CMD_TRANS)
							&& (ucUartBuf[COMMAND] != IAP_CMD_VERIFY)
							&& (ucUartBuf[COMMAND] != IAP_CMD_RESET))
							{
								ucUartErrCode |= IAPERROR_CMD;
							}
						}
					}
					else
					{
						BootMcuWdtClear();
						UartCmdProcess();
					}
				}
				INSCON = 0x40;
				RI1 = 0;
				INSCON = 0x00;
			}
			INSCON = 0x40;
			
			if(TI1)
			{
				INSCON = 0x00;
				BootMcuWdtClear();                                              //在该程序循环中，未接收到UART通讯，则判定通讯异常，触发看门狗
				
				if(ucUartBufPT >= (ucUartBuf[LENGTH]+8))
				{
					UartRxEn();                                                 //Allow UART receive data
					ucUartBufPT = 0;
					ucUartBuf[0] = 0;
					ucUartBuf[1] = 0;
					ucUartBuf[2] = 0;
					bUartSndOverFlg = 1;
				}
				else
				{
					ucUartBufPT++;
					UartTxEn(ucUartBuf[ucUartBufPT]);
				}
				INSCON = 0x40;
	
				TI1 = 0;
				INSCON = 0x00;
			}
			
			if(ucIapRestCommand == IAP_CMD_RESET)
			{
				BootMcuWdtClear();
				if(bUartSndOverFlg)                                             //Reset帧回复结束
				{
					bUartSndOverFlg = 0;
					ucIapRestCommand = 0;
					((void(code*)(void))0x0000)();
				}
			}
		}
		#elif ( UART_DEFINE == 61)
		{
			INSCON = 0x40;
			if(RI2)
			{
				//BootMcuWdtClear();                                              //在该程序循环中，未接收到UART通讯，则判定通讯异常，触发看门狗
				ucUartBuf[ucUartBufPT] = SBUF2;
				INSCON = 0x00;
				ucUartBufPT++;
				if(ucUartBufPT >= 140)                                          //该指针不会超过140
				{
					ucUartBufPT = 0;
				}
				if(ucUartBufPT == 1)
				{
					if(ucUartBuf[HEARD1] != 0x5A)                               //检查帧头是否Wie0x5AA5
					{
						ucUartBufPT = 0;
					}
	
				}
				else if(ucUartBufPT == 2)
				{
	
					if(ucUartBuf[HEARD2] != 0xA5)
					{
						ucUartBufPT = 0;
					}
					else
					{
						uiUartRcvChkSum = 0;                                    //帧头判断正确
						ucUartErrCode = 0;
					}
				}
				else
				{
	
					if(ucUartBufPT < (ucUartBuf[LENGTH]+9))
					{
			if(ucUartBufPT <= (ucUartBuf[LENGTH]+7))
			{
				uiUartRcvChkSum += ucUartBuf[ucUartBufPT-1];
			}
						
						if(ucUartBufPT == (TARGET+1))                           //检查ID
						{
							
							if(ucUartBuf[TARGET] != IAP_BMSID)
							{
								ucUartBufPT = 0;
							}
						}
						else if(ucUartBufPT == (COMMAND+1))                     //检测COMMAND
						{						
							if((ucUartBuf[COMMAND] != IAP_CMD_HANDSHAKE)
							&& (ucUartBuf[COMMAND] != IAP_CMD_BEGIN)
							&& (ucUartBuf[COMMAND] != IAP_CMD_TRANS)
							&& (ucUartBuf[COMMAND] != IAP_CMD_VERIFY)
							&& (ucUartBuf[COMMAND] != IAP_CMD_RESET))
							{
								ucUartErrCode |= IAPERROR_CMD;
							}
						}
					}
					else
					{
						BootMcuWdtClear();
						UartCmdProcess();
					}
				}
				INSCON = 0x40;
				RI2 = 0;
				INSCON = 0x00;
			}
			INSCON = 0x40;
			
			if(TI2)
			{
				INSCON = 0x00;
				BootMcuWdtClear();                                              //在该程序循环中，未接收到UART通讯，则判定通讯异常，触发看门狗
				
				if(ucUartBufPT >= (ucUartBuf[LENGTH]+8))
				{
					UartRxEn();                                                 //Allow UART receive data
					ucUartBufPT = 0;
					ucUartBuf[0] = 0;
					ucUartBuf[1] = 0;
					ucUartBuf[2] = 0;
					bUartSndOverFlg = 1;
				}
				else
				{
					ucUartBufPT++;
					UartTxEn(ucUartBuf[ucUartBufPT]);
				}
				INSCON = 0x40;
	
				TI2 = 0;
				INSCON = 0x00;
			}
			
			if(ucIapRestCommand == IAP_CMD_RESET)
			{
				BootMcuWdtClear();
				if(bUartSndOverFlg)                                             //Reset帧回复结束
				{
					bUartSndOverFlg = 0;
					ucIapRestCommand = 0;
					((void(code*)(void))0x0000)();
				}
			}
		}
		#endif
	}
}







