/******************************************************************************** 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-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= (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+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= 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= 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 } }