#include "main.h" #include "string.h" #include "stdio.h" #include "usart.h" #include "iap.h" #include "dataHandling.h" #include "md5c.h" extern void __set_FAULTMASK(uint32_t faultMask); /* 采用汇编设置栈的值 */ __asm void MSR_MSP(unsigned int ulAddr) { MSR MSP, r0 // 设置主堆栈指针的值为r0寄存器的值 BX r14 // 返回到调用子程序并使用r14寄存器中的地址 } typedef void (*Jump_Fun)(void); void IAP_ExecuteApp(unsigned int App_Addr) { Jump_Fun JumpToApp; if (((*(__IO unsigned int *)App_Addr) & 0x2FFE0000) == 0x20000000) //检查栈顶地址是否合法. { JumpToApp = (Jump_Fun) * (__IO unsigned int *)(App_Addr + 4); //用户代码区第二个字为程序开始地址(复位地址) MSR_MSP(*(__IO unsigned int *)App_Addr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) JumpToApp(); //跳转到APP. } } uint8_t YmodemID; uint8_t startFrame[40] = {0}; uint16_t version[4]; uint16_t length[3]; uint8_t binName[32] = {0}; uint8_t binLength[10] = {0}; uint8_t binMd5[16] = {0}; uint16_t iapbinMd5[8] = {0}; uint16_t FileBuffArray[512]; uint16_t FileBuffArray1[512]; uint16_t start_addr = 0; uint16_t packIndex = 0; uint16_t packTotalNum = 0; uint16_t packIndexbak = 0; uint16_t crcIAP = 0; uint16_t crcTerminal = 0; uint32_t AddrToWrite = Application_Buffer_Addr; int FileLength_IAP; uint32_t update_flag = 0; //uint16_t iapbigbuf[20000]; int tag = 0; int lenindex=0; //int indexbuf=0; void Process_CMD_IAP_Update(void) { int lenRx1; int i; USART_IAP_FLAG = 0; packIndex = USART_IAP_RX[8] << 8 | USART_IAP_RX[9]; lenRx1 = USART_PUB_LENGTH; uint8_t ERR_Arr[8] = "error\r\n"; // uint8_t ACK_Arr[16] = "acknowlege=ok"; YmodemID = USART_IAP_RX[7]; memset(FileBuffArray, 0, sizeof(FileBuffArray)); memset(FileBuffArray1, 0, sizeof(FileBuffArray1)); switch (YmodemID) { case 0x01: //起始帧与结束帧解析 根据包序号判别该帧为起始帧还是结束帧 memcpy(startFrame, &USART_IAP_RX[10], 40); crcIAP = crc16_xmodem(&USART_IAP_RX[10], 128); crcTerminal = (USART_IAP_RX[lenRx1 - 4] << 8) | USART_IAP_RX[lenRx1 - 3]; if (crcIAP == crcTerminal) { /*升级起始帧标记0*/ for (i = 0; i < 88; ++i) { if (*(unsigned char *)(StartMode_Addr + i + 4) != USART_IAP_RX[10 + i]) break; } if (i < 50) { for (i = 0; i < 25; i++) { FileBuffArray[i] = (uint16_t)(USART_IAP_RX[i * 2 + 11] << 8 | USART_IAP_RX[i * 2 + 10]); } Flash_WriteBytes(FileBuffArray, StartMode_Addr + 4, 25); //从StartMode_Addr+4 ,开始写入数据 delay_sys_us(50); /*升级起始帧标记1*/ /*IAP总长度标记0*/ #if indexfl == 4 lenindex =0;//长度为4位数 #else lenindex =1;//长度为5位数 #endif readFlashToArr(binLength, StartMode_Addr+27); if(lenindex != 0) { FileLength_IAP = ((binLength[0]&0xF)*10000) + ((binLength[1]&0xF) *1000) +((binLength[2]&0xF) *100) +\ ((binLength[3]&0xF) *10) + ((binLength[4]&0xF) ); } else { FileLength_IAP = ((binLength[0]&0xF)*1000) + ((binLength[1]&0xF) *100) +((binLength[2]&0xF) *10) +\ ((binLength[3]&0xF) *1) ; } all_len = FileLength_IAP; erase_flash(LENGTH_ADDR); HAL_FLASH_Unlock(); // 解锁Flash HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, LENGTH_ADDR, all_len); HAL_FLASH_Lock(); // 上锁Flash /*IAP总长度标记1*/ /*IAP_MD5标记0*/ if(lenindex!=0) { Flash_ReadBytes(iapbinMd5, StartMode_Addr + 33, 16); Flash_WriteBytes(iapbinMd5, MD5_ADDR, 8); for (int i = 0; i < 8; i++) { iapbinMd5[i] = ((iapbinMd5[i] >> 8) & 0xFF) | ((iapbinMd5[i] << 8) & 0xFF00); } } else { Flash_ReadBytes(iapbinMd5, StartMode_Addr + 32, 16); Flash_WriteBytes(iapbinMd5, MD5_ADDR, 8); for (int i = 0; i < 8; i++) { iapbinMd5[i] = ((iapbinMd5[i] >> 8) & 0xFF) | ((iapbinMd5[i] << 8) & 0xFF00); } } /*IAP_MD5标记1*/ AddrToWrite = Application_Buffer_Addr; } memset(USART_IAP_RX, 0, sizeof(USART_IAP_RX)); delay_sys_us(80); receive_modbus_9_1(initial_address, USART_MODBUS_RX[1], ((uint16_t)USART_MODBUS_RX[2] << 8) | USART_MODBUS_RX[3], \ ((uint16_t)USART_MODBUS_RX[4] << 8) | USART_MODBUS_RX[5], USART_MODBUS_RX[6]); __NOP(); } else { memset(USART_IAP_RX, 0, sizeof(USART_IAP_RX)); HAL_UART_Transmit(&huart1, ERR_Arr, strlen((char *)ERR_Arr), 100); } memset(FileBuffArray, 0, sizeof(FileBuffArray)); memset(FileBuffArray1, 0, sizeof(FileBuffArray1)); break; /*** * 存储并迁移下载区 */ case 0x02: //有效载荷帧数据处理 crcIAP = crc16_xmodem(&USART_IAP_RX[10], 128); crcTerminal = (USART_IAP_RX[lenRx1 - 4] << 8) + USART_IAP_RX[lenRx1 - 3]; if (crcIAP == crcTerminal) { for (i = 0; i < 64; i++) { FileBuffArray[i] = (uint16_t)(USART_IAP_RX[i * 2 + 11] << 8 | USART_IAP_RX[i * 2 + 10]); } Flash_WriteBytes(FileBuffArray, AddrToWrite, 64); AddrToWrite += 128; // Flash_ReadBytes(&iapbigbuf[indexbuf], AddrToWrite, 128); // indexbuf+=128; HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET); if((AddrToWrite & 0xffff) != (USART_IAP_RX[2] << 8 | USART_IAP_RX[3])) { HAL_UART_Transmit(&huart1, ERR_Arr, strlen((char *)ERR_Arr), 100); break; } memset(USART_IAP_RX, 0, sizeof(USART_IAP_RX)); delay_sys_us(80); receive_modbus_9_1(initial_address, USART_MODBUS_RX[1], ((uint16_t)USART_MODBUS_RX[2] << 8) | USART_MODBUS_RX[3], \ ((uint16_t)USART_MODBUS_RX[4] << 8) | USART_MODBUS_RX[5], USART_MODBUS_RX[6]); } break; case 0x04: { crcIAP = crc16_xmodem(&USART_IAP_RX[10], 128); crcTerminal = (USART_IAP_RX[lenRx1 - 4] << 8) + USART_IAP_RX[lenRx1 - 3]; if (crcIAP == crcTerminal) { // int txLen; // txLen = sprintf((char *)USART_IAP_RX, "%s\r\n", ACK_Arr); // HAL_UART_Transmit_IT(&huart1,USART_IAP_RX,txLen); // while (huart1.gState == HAL_UART_STATE_BUSY_TX) // { // HAL_Delay(1); // } /*系统版本标记0*/ Flash_ReadBytes(version, StartMode_Addr + 14, 8); for (int i = 0; i < 4; i++) { version[i] = ((version[i] >> 8) & 0xFF) | ((version[i] << 8) & 0xFF00); } convertHexToAscii(version, &System_version); erase_flash(VERSION_ADDR); HAL_FLASH_Unlock(); // 解锁Flash HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, VERSION_ADDR, System_version); HAL_FLASH_Lock(); // 上锁Flash /*系统版本标记1*/ tag = App2_MD5_Check(Application_Buffer_Addr,all_len); if(tag) { Set_Update_Down(); //设定标志位 下次启动时进行程序拷贝 }else{ int txLen = sprintf((char *)USART_IAP_RX,"check=error\r\n"); delay_sys_us(80); HAL_UART_Transmit_IT(&huart1,USART_IAP_RX,txLen); while (huart1.gState == HAL_UART_STATE_BUSY_TX) { HAL_Delay(1); } } } else { delay_sys_us(80); HAL_UART_Transmit(&huart1, ERR_Arr, strlen((char *)ERR_Arr), 100); delay_sys_us(80); } } break; default: break; } } uint8_t buffer[BUFFER_SIZE_length]; uint8_t buffer_length[100]; unsigned int all_len; int i; unsigned int ModeStart; void Start_BootLoader(void) { uint16_t ModeStart1[2]; Flash_ReadBytes(ModeStart1, StartMode_Addr, 2); ModeStart = (ModeStart1[0] << 16) | ModeStart1[1]; all_len = FileLength_IAP; int tag; int txLen; memset(USART_IAP_RX, 0, sizeof(USART_IAP_RX)); uint16_t pagenum = (all_len+2048)/2048; switch (ModeStart) { case Startup_Normal: // 正常启动 在APP2中可以设定此标志位 使得下次重启之后进入APP1 { txLen = sprintf((char *)USART_IAP_RX, "normalStart"); HAL_UART_Transmit_IT(&huart1,USART_IAP_RX,txLen); break; } case Startup_Update: /*启动最新的程序 */ { FLASH_EraseInitTypeDef erase_init; erase_init.TypeErase = FLASH_TYPEERASE_PAGES; // 擦除类型为页擦除 erase_init.PageAddress = ADD_UPDATE_PROG; erase_init.NbPages = pagenum; // 擦除的页数 uint32_t page_error = 0; HAL_FLASH_Unlock(); // 解锁Flash HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase_init, &page_error); // 执行擦除操作 HAL_FLASH_Lock(); // 上锁Flash } all_len = FileLength_IAP; tag = App2_MD5_Check(Application_Buffer_Addr,all_len); if (tag) { iap_write_appbin(ADD_UPDATE_PROG,Application_Buffer_Addr,all_len); txLen = sprintf((char *)USART_IAP_RX, "update\r\n"); HAL_UART_Transmit_IT(&huart1,USART_IAP_RX,txLen); while (huart1.gState == HAL_UART_STATE_BUSY_TX) { HAL_Delay(1); } } else { txLen = sprintf((char *)USART_IAP_RX,"checkfail"); delay_sys_us(80); HAL_UART_Transmit_IT(&huart1,USART_IAP_RX,txLen); while (huart1.gState == HAL_UART_STATE_BUSY_TX) { HAL_Delay(1); } return ; } if (App2_MD5_Check(ADD_UPDATE_PROG,all_len)) { txLen = sprintf((char *)USART_IAP_RX, "updateok\r\n"); HAL_UART_Transmit_IT(&huart1,USART_IAP_RX,txLen); while (huart1.gState == HAL_UART_STATE_BUSY_TX) { HAL_Delay(1); } Set_App2_Flag(); } break; case Startup_APP2: /*启动最新的程序 */ txLen = sprintf((char *)USART_IAP_RX, "jump"); HAL_UART_Transmit_IT(&huart1,USART_IAP_RX,txLen); while (huart1.gState == HAL_UART_STATE_BUSY_TX) { HAL_Delay(1); } __set_FAULTMASK(0); // Set_normal_Flag(); IAP_ExecuteApp(ADD_UPDATE_PROG); //执行FLASH APP2代码 // Set_jump_Flag(); // // case Jump_app: //// Set_normal_Flag(); // IAP_ExecuteApp(0x8020000); //执行FLASH APP2代码 // break; default: // 启动失败 { return; } } }