/** * @Author: 李建 * @Date: 2024/9/7 13:06 * Description: * Copyright: Copyright (©) 2024 永续绿建. All rights reserved. */ #include "ymodem_update.h" #include "port.h" #include "mb.h" #include "flash.h" #include static enum UPDATE_STATE Update_State = TO_START; /* 设置升级的步骤 */ static inline void Set_State(enum UPDATE_STATE state) { Update_State = state; } /* 查询升级的步骤 */ static inline uint8_t Get_State(void) { return Update_State; } #define POLY 0x1021 /** * @brief CRC-16 校验 * @param addr 开始地址 * @param num 长度 * @param crc CRC * @return crc 返回CRC的值 */ static uint16_t CRC16(uint8_t *addr, int num, uint16_t crc) { int i; for (; num > 0; num--) /* Step through bytes in memory */ { crc = crc ^ (*addr++ << 8); /* Fetch byte from memory, XOR into CRC top byte*/ for (i = 0; i < 8; i++) /* Prepare to rotate 8 bits */ { if (crc & 0x8000) /* b15 is set... */ crc = (crc << 1) ^ POLY; /* rotate and XOR with polynomic */ else /* b15 is clear... */ crc <<= 1; /* just rotate */ } /* Loop for 8 bits */ crc &= 0xFFFF; /* Ensure CRC remains 16-bit value */ } /* Loop until num=0 */ return(crc); /* Return updated CRC */ } /** * @brief 获取数据包的类型, 顺便进行校验 * @param buf 开始地址 * @param len 长度 * @return 1 通过校验 0 没通过校验 */ uint8_t Check_CRC(uint8_t* buf, int len) { uint16_t crc = 0; /* 进行CRC校验 */ crc = CRC16(buf+3, len - 5, crc); if(crc != (buf[131]<<8|buf[132])) { return 0; /* 没通过校验 */ }else{ return 1; /* 通过校验 */ } } void Code_Storage_Done(void) { uint32_t update_flag = Startup_Update; // 对应bootloader的启动步骤 flash_write((Application_2_Addr + Application_Size - 4), &update_flag,4 ); //在APP2中添加标记 0x801DFFC } /** * 串口写文件回调,内容为ymodem协议报文 * @param header * @param pucRegBuffer * @return */ eMBErrorCode eMBWriteFileCB(UCHAR * header, UCHAR * pucRegBuffer, USHORT * usLen) { switch (*header) { case SOH:{ static uint8_t Data_State = 0; static uint16_t pack_offset = 0; if(Check_CRC(pucRegBuffer, *usLen - 1)) { // 如果是起始帧 if(Get_State() == TO_START && pucRegBuffer[1] == 0&&(pucRegBuffer[2] == (uint8_t)(~pucRegBuffer[1]))) { Set_State(TO_RECEIVE_DATA); Data_State = 0x01; pack_offset = 1; pucRegBuffer[0] = ACK; flash_erase(Application_2_Addr, (Application_2_Addr + Application_Size) / FLASH_PAGE_SIZE); DEBUG_PRINTF("flash_erase\r\n"); } else if((Get_State()==TO_RECEIVE_END)&&(pucRegBuffer[1] == 0x00)&&(pucRegBuffer[2] == (uint8_t)(~pucRegBuffer[1]))) { Code_Storage_Done(); //APP2区代码存放完成 DEBUG_PRINTF("Code_Storage_Done\r\n"); Set_State(TO_START); //标记可以继续接收Ymodem数据 pucRegBuffer[0] = ACK; pack_offset = 0; HAL_NVIC_SystemReset(); //重启系统 } else if((Get_State()==TO_RECEIVE_DATA)&&(pucRegBuffer[1] == Data_State)&&(pucRegBuffer[2] == (uint8_t)(~pucRegBuffer[1]))) { /* 烧录程序 */ flash_write((Application_2_Addr + (pack_offset -1) * 128), pucRegBuffer+3, 128); pack_offset++; if(Data_State++ == 0xFF) { Data_State = 0x01; } pucRegBuffer[0] = ACK; DEBUG_PRINTF("flash_write:%d\r\n", Data_State); } } else { pucRegBuffer[0] = NACK; DEBUG_PRINTF("crc error:%d\r\n", Data_State); } } break; case EOT: { if(Get_State()==TO_RECEIVE_DATA) { Set_State(TO_RECEIVE_EOT2); pucRegBuffer[0] = NACK; } else if(Get_State()==TO_RECEIVE_EOT2) { Set_State(TO_RECEIVE_END); pucRegBuffer[0] = ACK; } else { //Receive EOT, But error... } } break; } return MB_ENOERR; }