/* Copyright Statement: * * This software/firmware and related documentation ("AutoChips Software") are * protected under relevant copyright laws. The information contained herein is * confidential and proprietary to AutoChips Inc. and/or its licensors. Without * the prior written permission of AutoChips inc. and/or its licensors, any * reproduction, modification, use or disclosure of AutoChips Software, and * information contained herein, in whole or in part, shall be strictly * prohibited. * * AutoChips Inc. (C) 2016. All rights reserved. * * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("AUTOCHIPS SOFTWARE") * RECEIVED FROM AUTOCHIPS AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER * ON AN "AS-IS" BASIS ONLY. AUTOCHIPS EXPRESSLY DISCLAIMS ANY AND ALL * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR * NONINFRINGEMENT. NEITHER DOES AUTOCHIPS PROVIDE ANY WARRANTY WHATSOEVER WITH * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, * INCORPORATED IN, OR SUPPLIED WITH THE AUTOCHIPS SOFTWARE, AND RECEIVER AGREES * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN AUTOCHIPS * SOFTWARE. AUTOCHIPS SHALL ALSO NOT BE RESPONSIBLE FOR ANY AUTOCHIPS SOFTWARE * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND AUTOCHIPS'S * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE AUTOCHIPS SOFTWARE * RELEASED HEREUNDER WILL BE, AT AUTOCHIPS'S OPTION, TO REVISE OR REPLACE THE * AUTOCHIPS SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE * CHARGE PAID BY RECEIVER TO AUTOCHIPS FOR SUCH AUTOCHIPS SOFTWARE AT ISSUE. */ #include //#include "crc16.h" #include "IAP.h" #include "md5c.h" #include "flash.h" #include "WDG.h" static __align(4)uint8_t WriteDataBuff[2048]; static uint32_t s_writeAddress; static uint8_t s_iapStep; static uint32_t s_writeDataBuffSeek; //升级完成后, 重启标志 uint8_t iap_reboot = 0; ///< 升级包信息 static uint8_t s_flashType; static uint32_t s_version[4]; static uint32_t s_flashMemSize; static uint32_t s_recvByte=0; static uint16_t s_sequence=0; //回传数据buffer 指针、 及数据长度 static uint8_t* s_wData = NULL; static uint16_t s_wLen = 0; typedef void (*pFunction)(void); static pFunction s_jumpToApplication; /** * JumpTOApp * * @param[in] none * @return none * * @brief Jump to APP Code */ void JumpTOApp1(void) { uint32_t JumpAddress; //if ( (*(__IO uint32_t *)APP1_ADDRESS) <= 0x80000) if (((*(__IO uint32_t *)APP1_ADDRESS) >= 0x1FFF0000) && ((*(__IO uint32_t *)APP1_ADDRESS) <= 0x2000EFFF)) { DisableInterrupts /* 关全局中断 */ s_jumpToApplication = (pFunction)(*(__IO uint32_t *)(APP1_ADDRESS + 4)); /* 指向APP程序的Reset中断*/ __set_MSP(*(__IO uint32_t*)APP1_ADDRESS); s_jumpToApplication(); } else { //printf("top of stack pointer is unvalid! enter APP update!\r\n"); return; } while (1); } int App_MD5_Check(uint32_t addr,unsigned int all_len) { unsigned char digest[16]; // unsigned char *md5_ptr=(unsigned char *)(StartMode_Addr+72); unsigned int i,update_len; MD5_CTX md5c; all_len -= 16; MD5Init(&md5c); for(i=0;i(i+512)) update_len = 512; else update_len = all_len-i; //memcpy(WriteDataBuff,(const void *)(addr+i),update_len); FLASH_DRV_Read(&g_Flash_Config,(addr+i), (uint8_t*)WriteDataBuff, update_len); MD5Update (&md5c, WriteDataBuff, update_len); i += update_len; WDG_Feed(); } MD5Final(digest,&md5c); //memcpy(iapbuf,(const void *)(addr+all_len),16); for(i=0;i<16;++i) { if(digest[i]!=*(unsigned char *)(addr+all_len+i)) break; } if(i>=16) return 1; else return 0; } /* // appxaddr:应用程序的起始地址 // appbuf:应用程序CODE. // appsize:应用程序大小(字节). void IAP_write_appbin(uint32_t appxaddr, uint8_t *appbuf, uint32_t appsize) { uint32_t t; uint16_t i = 0; uint16_t temp; uint32_t fwaddr = appxaddr; //当前写入的地址 uint32_t *dfu = appbuf; for (t = 0; t < appsize; t += 2) { temp = (uint16_t)dfu[1] << 8; temp += (uint16_t)dfu[0]; dfu += 2; //偏移2个字节 iapbuf[i++] = temp; if (i == 1024) { i = 0; HAL_GPIO_TogglePin(WDI_sp706_kanmemgou_GPIO_Port, WDI_sp706_kanmemgou_Pin); STMFLASH_Write(fwaddr, iapbuf, 1024); fwaddr += 2048; //偏移2048 16=2*8.所以要乘以2. } } if (i) STMFLASH_Write(fwaddr, iapbuf, i); //将最后的一些内容字节写进去. } */ // int IAP_Init(void) { s_recvByte=0; s_sequence=0; s_version[0] = 0; s_version[1] = 0; s_version[2] = 0; s_version[3] = 0; s_flashType = 0; s_flashMemSize = 0; iap_reboot = 0; return 0; } void IAP_Start(void) { if (s_iapStep == 1) { return; /// 0) { if ((s_writeAddress < APP2_ADDRESS) || (s_writeAddress >= APP2_ADDRESS_END)) /// EFLASH_PAGE_SIZE_INIT) ///得到单次写入的长度 { MiniLength = EFLASH_PAGE_SIZE_INIT - s_writeDataBuffSeek; ///<长度超出buff } else { MiniLength = length; ///<全部写完, } memcpy(&WriteDataBuff[s_writeDataBuffSeek], pdata, MiniLength); pdata += MiniLength; s_writeDataBuffSeek += MiniLength; length -= MiniLength; if (s_writeDataBuffSeek == EFLASH_PAGE_SIZE_INIT) { FLASH_DRV_UnlockCtrl(); //ret = EFLASH_PageErase(s_writeAddress); ///= APP2_ADDRESS_END)) /// APP_SIZE) { s_wData[s_wLen++] = ResultExceedLimit; ///> 24) & 0xff); s_wData[s_wLen++] = (uint8_t)((MaxBlockSize >> 16) & 0xff); s_wData[s_wLen++] = (uint8_t)((MaxBlockSize >> 8) & 0xff); s_wData[s_wLen++] = (uint8_t)(MaxBlockSize & 0xff); //版本不一致 if(0 != memcmp(s_version, _version, 16)){ s_version[0] = _version[0]; s_version[1] = _version[1]; s_version[2] = _version[2]; s_version[3] = _version[3]; s_recvByte=0; s_sequence=0; } s_wData[s_wLen++] = (s_sequence>>8)&0xFF; s_wData[s_wLen++] = s_sequence&0xFF; } /** * TransferDataHandle * * @param[in] pdata:data point * @param[in] length:data length * * @return none * * @brief 上位机通信 传输数据处理 */ static void TransferDataHandle(uint8_t *pdata, uint16_t length) { uint16_t _sequence = pdata[2]; _sequence <<= 8; _sequence += pdata[3]; s_wData[s_wLen++] = DataTransferCmdHost; s_wData[s_wLen++] = DataTransferRequest; if (length-4 > MaxBlockSize) { s_wData[s_wLen++] = ResultExceedLimit; ///<长度超出限制 IAP_Stop(); } else if (_sequence != s_sequence) { s_wData[s_wLen++] = ResultSequenceErr; ///<序列号不正确 IAP_Stop(); } else { if (0 != IAP_Write(&pdata[4], length - 4)) { s_wData[s_wLen++] = ResultExecErr; ///<执行错误 IAP_Stop(); }else{ s_wData[s_wLen++] = ResultSuccess; ///>8)&0xFF; s_wData[s_wLen++] = s_sequence&0xFF; } /** * TransferExitHandle * * @param[in] pdata:data point * @param[in] length:data length * * @return none * * @brief 上位机通信 传输数据结束 */ static void TransferExitHandle(uint8_t *pdata, uint16_t length) { s_wData[s_wLen++] = DataTransferCmdHost; s_wData[s_wLen++] = DataTransferRequest; //crc = ((uint16_t)pdata[2] << 8) | pdata[3]; if (0 != IAP_Stop()) { s_wData[s_wLen++] = ResultExecErr; ///<执行错误 } else { if (s_recvByte != s_flashMemSize) { s_wData[s_wLen++] = ResultTotalLengthErr; ///<接收数据长度不正确 } else { s_wData[s_wLen++] = ResultSuccess; config->App2Size = s_flashMemSize; config->IapFlag = Startup_Update; SaveConfig(); //if (0 != SaveConfig()) //{ // data[index] = ResultExecErr; //} iap_reboot = 1; } } } /** * IAP_CmdHandle * * @param[in] pdata:recv data point * @param[in] length:data length * @param[in] pout:send data point * @return none * * @brief 上位机通信 数据接收处理函数 */ uint16_t IAP_CmdHandle(uint8_t* pdata, uint16_t length, uint8_t* pout) { s_wData = pout; s_wLen = 0; if(DataTransferCmd == pdata[0]){ switch (pdata[1]) { case DataTransferRequest: //0x00 DataTransferRequestHandle(pdata, length); break; case TransferData: //0x01 TransferDataHandle(pdata, length); break; case TransferExit: //0x02 TransferExitHandle(pdata, length); break; default : s_wData[0] = ResultCmdErr; s_wLen = 1; break; } }else{ s_wData[0] = ResultCmdErr; s_wLen = 1; } return s_wLen; } /** * @bieaf 进行BootLoader的启动 * * @param none * @return none */ void Start_BootLoader(void) { //uint16_t crcCheck; uint32_t writed_len; uint32_t will_write_len; status_t ret = STATUS_SUCCESS; switch (config->IapFlag) ///< 读取是否启动应用程序 */ { case Startup_Normal: ///< 正常启动 */ //在APP2中可以设定此标志位 使得下次重启之后进入APP1 { //printf("> Normal start......\r\n"); break; } case Startup_Update: /*启动最新的程序 */ //printf("> Startup_Update start......\r\n"); //crcCheck = crc16((const uint8_t *)APP2_ADDRESS, config->App2Size); if ((config->App2Size <= APP_SIZE) && App_MD5_Check(APP2_ADDRESS,config->App2Size)) { writed_len =0; will_write_len = config->App2Size; do{ WDG_Feed(); if(will_write_len >= EFLASH_PAGE_SIZE_INIT){ //memcpy(WriteDataBuff, (void *)(APP2_ADDRESS+writed_len), EFLASH_PAGE_SIZE_INIT); FLASH_DRV_Read(&g_Flash_Config,(APP2_ADDRESS+writed_len), (uint8_t*)WriteDataBuff, EFLASH_PAGE_SIZE_INIT); FLASH_DRV_UnlockCtrl(); //ret = EFLASH_PageErase(APP1_ADDRESS+writed_len); /// 0); if(STATUS_SUCCESS == ret){ config->App1Size = config->App2Size; } } config->IapFlag = Startup_APP1; SaveConfig(); case Startup_APP1: /*启动最新的程序 */ //printf("> Startup_APP1 start......\r\n"); //printf("> Startup_APP1 App1Size = [%d].\r\n", config->App1Size); //crcCheck = crc16((const uint8_t *)APP1_ADDRESS, config->App1Size); if((config->App1Size <= APP_SIZE) && App_MD5_Check(APP1_ADDRESS,config->App1Size)) { //printf("> Startup_APP1 JumpTOApp1 ......\r\n"); JumpTOApp1(); } break; default: ///< 启动失败 { return; } } }