STM32G0xx基于串口(UART)Ymodem协议实现OTA升级包括Bootloader、上位机、应用程序

STM32G0xx基于串口Ymodem协议实现OTA升级包括Bootloader、上位机、应用程序

  • 例程说明
  • 一、串口相关的底层配置
  • 二、OTA相关的应用层
  • 三、Flash相关的操作
  • 四、Flash存储参数相关
  • 五、核心部分Ymodem相关
  • 六、其他宏配置
  • 七、主函数
  • 八、使用Python合并文件
  • 九、测试结果
  • 有疑问欢迎加交流

例程说明

  • STM32G0xx基于串口(UART)方式以Ymodem协议实现OTA升级,本例程包括Bootloader、上位机、应用程序
  • Bootloader通过串口(UART)接收Ymodem协议数据,将数据写Flash,并跳转到应用程序
  • 宏XSUPER_DEV_SPACE_APP_ONLY_ENABLE,为1表示只有Bootloader和应用程序
  • 宏XSUPER_DEV_SPACE_APP_OTA_ENABLE,为1表示有Bootloader + 应用程序 + OTA升级区
  • 例程使用STM32G030C8T6芯片,Flash大小为64KB,分配如下:64KB = 16KB + 22KB + 22KB + 4KB
    • 16KB:Bootloader
    • 22KB:App应用程序
    • 22KB:OTA升级区
    • 4KB :Flash参数区


参考源码

一、串口相关的底层配置

  • 串口采用查询方式接手数据,采用阻塞的方式发送数据
  • 为减少Flash的使用,已实现简单的printf函数my_printf()
  • 串口接收数据时,采用DMA方式接收,接收数据时,采用查询方式接收,接收数据时,采用阻塞的方式发送数据


#define MCU_UART1_TXD_Pin                                           LL_GPIO_PIN_6
#define MCU_UART1_TXD_GPIO_Port                                     GPIOB
#define MCU_UART1_RXD_Pin                                           LL_GPIO_PIN_7
#define MCU_UART1_RXD_GPIO_Port                                     GPIOB#define SYS_PWR_EN_Pin                                              LL_GPIO_PIN_15
#define SYS_PWR_EN_GPIO_Port                                        GPIOAstruct fmt_info 
{int left_align; char pad_char;  int width;      
};static void vInit_UART(uint32_t baudRate)
{LL_USART_InitTypeDef USART_InitStruct = {0};LL_GPIO_InitTypeDef GPIO_InitStruct = {0};LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK1);LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_USART1);LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOB);GPIO_InitStruct.Pin        = MCU_UART1_TXD_Pin;GPIO_InitStruct.Mode       = LL_GPIO_MODE_ALTERNATE;GPIO_InitStruct.Speed      = LL_GPIO_SPEED_FREQ_HIGH;GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;GPIO_InitStruct.Pull       = LL_GPIO_PULL_NO;GPIO_InitStruct.Alternate  = LL_GPIO_AF_0;LL_GPIO_Init(MCU_UART1_TXD_GPIO_Port, &GPIO_InitStruct);GPIO_InitStruct.Pin        = MCU_UART1_RXD_Pin;GPIO_InitStruct.Mode       = LL_GPIO_MODE_ALTERNATE;GPIO_InitStruct.Speed      = LL_GPIO_SPEED_FREQ_HIGH;GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;GPIO_InitStruct.Pull       = LL_GPIO_PULL_NO;GPIO_InitStruct.Alternate  = LL_GPIO_AF_0;LL_GPIO_Init(MCU_UART1_RXD_GPIO_Port, &GPIO_InitStruct);USART_InitStruct.PrescalerValue      = LL_USART_PRESCALER_DIV1;USART_InitStruct.BaudRate            = baudRate;USART_InitStruct.DataWidth           = LL_USART_DATAWIDTH_8B;USART_InitStruct.StopBits            = LL_USART_STOPBITS_1;USART_InitStruct.Parity              = LL_USART_PARITY_NONE;USART_InitStruct.TransferDirection   = LL_USART_DIRECTION_TX_RX;USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;USART_InitStruct.OverSampling        = LL_USART_OVERSAMPLING_16;LL_USART_Init(USART1, &USART_InitStruct);LL_USART_SetTXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_8);LL_USART_SetRXFIFOThreshold(USART1, LL_USART_FIFOTHRESHOLD_1_8);LL_USART_DisableFIFO(USART1);LL_USART_ConfigAsyncMode(USART1);LL_USART_Enable(USART1);LL_USART_Enable(USART1);while((!(LL_USART_IsActiveFlag_TEACK(USART1))) || (!(LL_USART_IsActiveFlag_REACK(USART1)))){}LL_USART_ClearFlag_FE(USART1);LL_USART_ClearFlag_NE(USART1);LL_USART_ClearFlag_ORE(USART1);
}static void vInit_GPIO(void)
{LL_GPIO_InitTypeDef GPIO_InitStruct = {0};LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);LL_GPIO_SetOutputPin(SYS_PWR_EN_GPIO_Port, SYS_PWR_EN_Pin);GPIO_InitStruct.Pin        = SYS_PWR_EN_Pin;GPIO_InitStruct.Mode       = LL_GPIO_MODE_OUTPUT;GPIO_InitStruct.Speed      = LL_GPIO_SPEED_FREQ_LOW;GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;GPIO_InitStruct.Pull       = LL_GPIO_PULL_UP;LL_GPIO_Init(SYS_PWR_EN_GPIO_Port, &GPIO_InitStruct);
}static void vDeInit_UART(void)
{LL_USART_DeInit(USART1);
}void vTxByte(uint8_t byte)
{USART1->TDR = byte;while(!(USART1->ISR & USART_ISR_TC));// USART1->TDR = byte;// while(!(LL_USART_IsActiveFlag_TC(USART1)));
}uint8_t xReceive_Byte_Wait(uint8_t * pDat, uint32_t timeout)
{volatile uint32_t timeOut = timeout;while (timeOut-- > 10){if (USART1->ISR & USART_ISR_RXNE_RXFNE){*pDat = (USART1->RDR & 0xFFU);return 0;}if (USART1->ISR & LL_USART_ISR_ORE){USART1->ISR = USART_ICR_ORECF;}}return 1;// if (LL_USART_IsActiveFlag_RXNE(USART1)) *pDat = LL_USART_ReceiveData8(USART1);// if (LL_USART_IsActiveFlag_FE(USART1))  LL_USART_ClearFlag_FE(USART1);// if (LL_USART_IsActiveFlag_NE(USART1))  LL_USART_ClearFlag_NE(USART1);// if (LL_USART_IsActiveFlag_ORE(USART1)) LL_USART_ClearFlag_ORE(USART1);
}void vDeInit_Board(void)
{vDeInit_UART();
}void vInit_Board_Drive(void)
{vInit_GPIO();vInit_UART(921600);FLASH->SR |= FLASH_SR_OPTVERR;my_printf("\r\nSystem Power On......\r\n");
}/***************************************************************************************************************************************************************/
/***************************************************************************************************************************************************************/
/***************************************************************************************************************************************************************/
static void reverse(char *buf, int len) 
{int i = 0, j = len - 1;while (i < j) {char tmp = buf[i];buf[i] = buf[j];buf[j] = tmp;i++;j--;}
}static int num_to_str(unsigned int num, char *buf, int base) 
{const char digits[] = "0123456789ABCDEF";int i = 0;if (num == 0) {buf[i++] = '0';} else {while (num > 0) {buf[i++] = digits[num % base];num /= base;}}reverse(buf, i);return i;
}static void print_padding(char c, int count) 
{while (count-- > 0) {vTxByte(c);}
}static void print_str(const char *s, int len) 
{while (len-- > 0) {vTxByte(*s++);}
}void my_printf(const char * fmt, ...) 
{va_list args;va_start(args, fmt);while (*fmt) {if (*fmt != '%') {vTxByte(*fmt++);continue;}fmt++;struct fmt_info info = {0};info.pad_char = ' ';if (*fmt == '-') {info.left_align = 1;fmt++;} else if (*fmt == '0') {info.pad_char = '0';fmt++;}while (*fmt >= '0' && *fmt <= '9') {info.width = info.width * 10 + (*fmt - '0');fmt++;}switch (*fmt) {case 'd': {int num = va_arg(args, int);int is_negative = num < 0;unsigned int abs_num = is_negative ? -num : num;char buffer[12];int len = num_to_str(abs_num, buffer, 10);char num_buffer[12];int num_len;if (is_negative) {num_buffer[0] = '-';for (int i = 0; i < len; i++) {num_buffer[i + 1] = buffer[i];}num_len = len + 1;} else {for (int i = 0; i < len; i++) {num_buffer[i] = buffer[i];}num_len = len;}int padding = info.width - num_len;if (padding < 0) padding = 0;if (info.left_align) {print_str(num_buffer, num_len);print_padding(' ', padding);} else {print_padding(info.pad_char, padding);print_str(num_buffer, num_len);}break;}case 'x':case 'X': {unsigned int x_num = va_arg(args, unsigned int);char buffer[8];int len = num_to_str(x_num, buffer, 16);int padding = info.width - len;if (padding < 0) padding = 0;if (info.pad_char == '0' && !info.left_align) {print_padding('0', padding);print_str(buffer, len);} else {print_padding(' ', padding);print_str(buffer, len);}break;}case 's': {char *s = va_arg(args, char*);int s_len = 0;while (s[s_len]) s_len++;int padding = info.width - s_len;if (padding < 0) padding = 0;if (info.left_align) {print_str(s, s_len);print_padding(' ', padding);} else {print_padding(' ', padding);print_str(s, s_len);}break;}case 'c': {char c = va_arg(args, int);int padding = info.width - 1;if (padding < 0) padding = 0;if (info.left_align) {vTxByte(c);print_padding(' ', padding);} else {print_padding(' ', padding);vTxByte(c);}break;}case 'u': {unsigned int num = va_arg(args, unsigned int); char buffer[11];int len = num_to_str(num, buffer, 10);int padding = info.width - len;if (padding < 0) padding = 0;if (info.left_align) {print_str(buffer, len);print_padding(' ', padding);  } else {if (info.pad_char == '0') {print_padding('0', padding);print_str(buffer, len);}else {print_padding(' ', padding);print_str(buffer, len);}}}break;default: vTxByte(*fmt); break;}fmt++;}va_end(args);
}



二、OTA相关的应用层

  • 主要实现了固件升级、Flash的擦除、固件读取、跳转到应用程序等功能
  • 当XSUPER_DEV_SPACE_APP_OTA_ENABLE为1时,需要进行固件比较,Flash擦除,固件写入,固件比较,最后跳转到应用程序
  • 匹配上位机发送过来的命令,并进行相应的操作,最后保存标志位



#define IAP_OTA_CMD_UPDATE                                                              "iap:update"
#define IAP_OTA_CMD_UPLOAD                                                              "iap:upload"
#define IAP_OTA_CMD_ERASE                                                               "iap:erase"
#define IAP_OTA_CMD_MENU                                                                "iap:menu"
#define IAP_OTA_CMD_RUN_APP                                                             "iap:runapp"#define IAP_OTA_FLG_UPDATE                                                              (0xEEEE)
#define IAP_OTA_FLG_UPLOAD                                                              (0xDDDD)
#define IAP_OTA_FLG_ERASE                                                               (0xCCCC)
#define IAP_OTA_FLG_MENU                                                                (0xFFFF)
#define IAP_OTA_FLG_RUN_APP                                                             (0x5A5A)#define IAP_OAT_CMD_MEM_SIZE                                                            (128)typedef struct
{const uint8_t * cmd;uint16_t        flg;
}IAP_CMD_Typedef;typedef  void (*pFunction)(void);
static uint32_t JumpAddress = 0;
static pFunction Jump_To_Application;const IAP_CMD_Typedef IAP_CMD_TAB[] = 
{{ .cmd = (const uint8_t *)IAP_OTA_CMD_UPDATE,  .flg = (uint16_t)IAP_OTA_FLG_UPDATE  },{ .cmd = (const uint8_t *)IAP_OTA_CMD_UPLOAD,  .flg = (uint16_t)IAP_OTA_FLG_UPLOAD  },{ .cmd = (const uint8_t *)IAP_OTA_CMD_ERASE,   .flg = (uint16_t)IAP_OTA_FLG_ERASE   },{ .cmd = (const uint8_t *)IAP_OTA_CMD_MENU,    .flg = (uint16_t)IAP_OTA_FLG_MENU    },{ .cmd = (const uint8_t *)IAP_OTA_CMD_RUN_APP, .flg = (uint16_t)IAP_OTA_FLG_RUN_APP },
};static void vJump_Application(void)
{vSave_IapStore_Parameter();if (((*(volatile uint32_t*)XSUPER_APP_BASE_ADDR) & 0x2FFE0000) == 0x20000000){   my_printf("\r\n");my_printf("Running To Application......\r\n");my_printf("App Base Addr  :0x%08X\r\n", XSUPER_APP_BASE_ADDR);my_printf("App True Size  :%dByte\r\n", xGet_FirmwareTrueSize());my_printf("App Space Size :0x%08X\r\n\r\n", XSUPER_APP_FLASH_SIZE);JumpAddress = *(volatile uint32_t*) (XSUPER_APP_BASE_ADDR + 4);Jump_To_Application = (pFunction) JumpAddress;__disable_irq();vDeInit_Board();__set_MSP(*(volatile uint32_t*) XSUPER_APP_BASE_ADDR);Jump_To_Application();}vSet_IapFlag(IAP_OTA_FLG_MENU);my_printf("Running Application Error......\r\n");}static uint16_t xSearchCmd(const uint8_t * pCmd)
{uint8_t i = 0, num = sizeof(IAP_CMD_TAB)/sizeof(IAP_CMD_Typedef);for(i = 0; i < num; i++){if(strstr((const char *)pCmd, (const char *)IAP_CMD_TAB[i].cmd) != NULL){return IAP_CMD_TAB[i].flg;}}return 0;
}static void vRxDataCmd(uint8_t * pDat)
{uint8_t  chr   = 0;uint16_t index = 0;while (1){if (xReceive_Byte_Wait(&chr, 0xF00000)) continue;if (((chr >= 0x20) && (chr <= 0x7E)) || (chr == '\r') || (chr == '\n') || (chr == '\b')){if (index >= IAP_OAT_CMD_MEM_SIZE){my_printf("Cmd Size Over......\r\n");index = 0;}pDat[index++] = chr;if ((chr == '\n') && (index > 5) && (pDat[index - 2] == '\r')){break;}if ((chr == '\b') && index){index--;}}}pDat[index] = '\0';
}static void vMain_Menu_Handler(void)
{uint16_t iapFlg = 0;uint8_t  rxDat[IAP_OAT_CMD_MEM_SIZE] = {0};while (1){my_printf("\r\n\r\n\r\n");my_printf("******************* Bootloader Main Menu ******************\r\n");my_printf("Software Version: %s\r\n", DEV_INFO_SOFT_VER_STR);my_printf("Compiler Date   : %s %s\r\n", __DATE__, __TIME__);my_printf("***********************************************************\r\n");vRxDataCmd(rxDat);iapFlg = xSearchCmd((const uint8_t *)rxDat);if (iapFlg){vSet_IapFlag(iapFlg); break;}else{my_printf("Unknown Command......\r\n");}}
}static uint8_t xFirmware_Update_State(int32_t res)
{if (res > 0)        { my_printf("Firmware Update Succeed...\r\n"); res = 0; }else if (res == -1) { my_printf("Firmware Too Big...\r\n");        res = 1; }else if (res == -2) { my_printf("Firmware Update Failed...\r\n");  res = 2; }else if (res == -3) { my_printf("Aborted Update By User...\r\n");  res = 3; }else                { my_printf("Receive Data Filed...\r\n");      res = 4; }my_printf("\r\n");return (uint8_t)res;
}void vFirmware_Show(uint32_t startAddr, uint32_t len)
{uint32_t i = 0;my_printf("-------------------------------------------------------------\r\n");my_printf("            00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  \r\n");my_printf("-------------------------------------------------------------\r\n");for (i = 0; i < len; ++i){if (i && (i % 16 == 0)) my_printf("\r\n");if (i % 16 == 0)        my_printf("0x%08X  ", (startAddr + i));my_printf("%02X ", *(volatile uint8_t *)(startAddr + i));}my_printf("\r\n");my_printf("-------------------------------------------------------------\r\n");my_printf("\r\n\r\n");
}#if defined(XSUPER_DEV_SPACE_APP_OTA_ENABLE) && (XSUPER_DEV_SPACE_APP_OTA_ENABLE == 1)
static uint8_t vFirmware_Compare(uint8_t * pSrcDat, uint8_t * pDstDat, uint32_t len)
{uint32_t i = 0;for (i = 0; i < len; i++){if (*(uint8_t *)(pSrcDat + i) != *(uint8_t *)(pDstDat + i)){return 1;}}return 0;
}static uint8_t vFirmware_Compare_Move(void)
{uint8_t res = 1;res = vFirmware_Compare((uint8_t *)XSUPER_APP_BASE_ADDR, (uint8_t *)XSUPER_OTA_BASE_ADDR, XSUPER_APP_FLASH_SIZE);if (!res) {my_printf("APP OTA Firmware Same......\r\n");return 0;}res = xFlash_ErasePage_Continue(XSUPER_APP_BASE_ADDR, xFlash_GetPageNumber(XSUPER_APP_FLASH_SIZE), 0);if (res){my_printf("Erase Page Failed......%d\r\n", res);return 1;}res = xFlash_Program_DoubleWord_Continue(XSUPER_APP_BASE_ADDR, (uint8_t *)XSUPER_OTA_BASE_ADDR, XSUPER_APP_FLASH_SIZE);if (res){my_printf("Continue Program Failed......%d\r\n", res);return 2;}res = vFirmware_Compare((uint8_t *)XSUPER_APP_BASE_ADDR, (uint8_t *)XSUPER_OTA_BASE_ADDR, XSUPER_APP_FLASH_SIZE);if (res) {my_printf("Firmware Compare Failed......\r\n");return 3;}return 0;
}
#endifstatic void vFirmware_Update(void)
{uint16_t flag = IAP_OTA_FLG_RUN_APP;int32_t  res = -1;res = xYmodem_Receive_Data(YMODEM_REC_TYPE_DFU);my_printf("\r\nFirmware Update......%d\r\n", res);if (xFirmware_Update_State(res)) {flag = IAP_OTA_FLG_MENU;}#if defined(XSUPER_DEV_SPACE_APP_OTA_ENABLE) && (XSUPER_DEV_SPACE_APP_OTA_ENABLE == 1)else{res = vFirmware_Compare_Move();if (res){my_printf("Firmware Compare Move Error......%d\r\n", res);flag = IAP_OTA_FLG_MENU;}}#endifvSet_IapFlag(flag);
}static void vFirmware_Read(void)
{uint32_t index = 0, firmSize = 0; uint8_t res = 0;vSet_IapFlag(IAP_OTA_FLG_MENU);if (xGet_FirmwareTrueSize() < 3000) res = 1;else if (((*(volatile uint32_t *)(XSUPER_APP_BASE_ADDR + 0)) & 0x2FFE0000) != 0x20000000) res = 2;else if (((*(volatile uint32_t *)(XSUPER_APP_BASE_ADDR + 4)) & 0x0800FFFF) <= XSUPER_APP_BASE_ADDR) res = 3;if (res) {my_printf("Firmware Exception Error......Res:%u\r\n", res);return;}firmSize = xGet_FirmwareTrueSize();my_printf("----------------------- App Firmware Show ------------------\r\n");my_printf("            00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  \r\n");my_printf("-------------------------------------------------------------\r\n");for (index = 0; index < firmSize + 80; ++index){if (index && (index % 16 == 0)) my_printf("\r\n");if (index % 16 == 0) my_printf("0x%08X  ", (XSUPER_APP_BASE_ADDR + index));my_printf("%02X ", *(volatile uint8_t *)(XSUPER_APP_BASE_ADDR + index));}my_printf("\r\n");my_printf("-------------------------------------------------------------\r\n");my_printf("\r\n\r\n");
}void vShow_Info_Erase_Flash(uint32_t pageIndex)
{uint32_t startPage = xFlash_GetPageIndex(XSUPER_APP_BASE_ADDR);uint32_t pageCount = xFlash_GetPageNumber(XSUPER_APP_FLASH_SIZE);uint32_t start     = pageIndex * FLASH_PAGE_SIZE_BYTE + FLASH_BASE_ADDR;uint32_t end       = start + FLASH_PAGE_SIZE_BYTE - 1;my_printf("Erase Flash Page:%02u/%02u  Addr:0x%08X~0x%08X Success......\r\n", pageIndex, (startPage + pageCount - 1), start, end);
}static void vErase_Flash(void)
{uint8_t res = 1, usrFlg = 0;uint32_t i = 0;vSet_FirmwareTrueSize(0);vSet_IapFlag(IAP_OTA_FLG_MENU);for (i = 0; i < XSUPER_APP_FLASH_SIZE; i++){res = *(volatile uint8_t *)(XSUPER_APP_BASE_ADDR + i);if (res != 0xFF) { usrFlg = 1; break; }}if (usrFlg){res = xFlash_ErasePage_Continue(XSUPER_APP_BASE_ADDR, xFlash_GetPageNumber(XSUPER_APP_FLASH_SIZE), 1);my_printf("Erase Flash %s......Res:%u \n\r", (res ? "Error" : "Success"), res);}else{my_printf("Flash Has Been Erase Befor......\n\r");}
}void vIAP_Running_Handler(void)
{switch (xGet_IapFlag()){case IAP_OTA_FLG_RUN_APP: vJump_Application();  break;case IAP_OTA_FLG_MENU:    vMain_Menu_Handler(); break;case IAP_OTA_FLG_ERASE:   vErase_Flash();       break;case IAP_OTA_FLG_UPDATE:  vFirmware_Update();   break;case IAP_OTA_FLG_UPLOAD:  vFirmware_Read();     break;default: vMain_Menu_Handler(); break;}
}



三、Flash相关的操作

  • 主要实现Flash的解锁,枷锁,擦除,写入,读取等操作


#define FLASH_KEY1                                                  (0x45670123U) /*!< Flash key1 */
#define FLASH_KEY2                                                  (0xCDEF89ABU) /*!< Flash key2: used with FLASH_KEY1*/
#define CLOCK_PLL                                                   (72000000)        //or 54000000    
#define FLASH_TRY_COUNT                                             (5)#define FLASH_SR_ERRORS                                             (FLASH_SR_OPERR  | FLASH_SR_PROGERR | FLASH_SR_WRPERR | \FLASH_SR_PGAERR | FLASH_SR_SIZERR  | FLASH_SR_PGSERR |  \FLASH_SR_MISERR | FLASH_SR_FASTERR | FLASH_SR_OPTVERR) /*!< All SR error flags */
#define FLASH_SR_CLEAR                                              (FLASH_SR_ERRORS | FLASH_SR_EOP)
#define GET_PAGE_NUMBER(PAGETYPE)                                   (FLASH_SIZE/PAGE_SIZE-1-(uint8_t)PAGETYPE)
#define GET_PAGE_START_ADDRESS(PAGETYPE)                            ((uint32_t)(FLASH_BASE + FLASH_SIZE - (PAGETYPE+1)*PAGE_SIZE))static uint8_t xFlashUnlock(void)
{uint8_t status = 0;if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00U){/* Authorize the FLASH Registers access */WRITE_REG(FLASH->KEYR, FLASH_KEY1);WRITE_REG(FLASH->KEYR, FLASH_KEY2);/* verify Flash is unlock */if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00U){status = 1;}}return status;
}uint8_t xFlashLock(void)
{uint8_t status = 1;/* Set the LOCK Bit to lock the FLASH Registers access */SET_BIT(FLASH->CR, FLASH_CR_LOCK);/* verify Flash is locked */if (READ_BIT(FLASH->CR, FLASH_CR_LOCK) != 0x00u){status = 0;}return status;
}static uint8_t xFlash_WaitForLast_Operation(uint32_t overTime)
{uint32_t error = 0;volatile int timeout = overTime * (CLOCK_PLL / 1000000) / 6; // 6 Instruction cycle, 2000us timeout/* Wait for a Flash operation to complete or a TIMEOUT to occur */while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U){if (timeout-- == 0x00){return 1;}}/* check flash errors */error = (FLASH->SR & FLASH_SR_ERRORS);/* Clear SR register */FLASH->SR = FLASH_SR_CLEAR;if (error != 0x00U){return 2;}/* Wait for control register to be written */timeout = overTime * (CLOCK_PLL / 1000000) / 6;while ((FLASH->SR & FLASH_SR_CFGBSY) != 0x00U){if (timeout-- == 0x00){return 3;}}/* Return the operation status */return 0;
}static uint8_t xFlash_Unlock(void)
{uint8_t i = 0;for (i = 0; i < FLASH_TRY_COUNT; i++){if (xFlashUnlock()) xFlash_WaitForLast_Operation(2000);else                return 0;}return 1;
}static uint8_t xFlash_Lock(void)
{uint8_t i = 0;for (i = 0; i < FLASH_TRY_COUNT; i++){if (xFlashLock()) xFlash_WaitForLast_Operation(2000);else              return 0;}return 1;
}static void vFlashErasePage(uint32_t page)
{uint32_t tmp = 0;/* Get configuration register, then clear page number */tmp = (FLASH->CR & ~FLASH_CR_PNB);/* Set page number, Page Erase bit & Start bit */FLASH->CR = (tmp | (FLASH_CR_STRT | (page << FLASH_CR_PNB_Pos) | FLASH_CR_PER));
}void vFlash_Program_DoubleWord(uint32_t address, uint64_t data)
{if(data == 0xFFFFFFFFFFFFFFFF){return;}/* Set PG bit */SET_BIT(FLASH->CR, FLASH_CR_PG);FLASH->ECCR |= FLASH_ECCR_ECCC|FLASH_ECCR_ECCD;FLASH->SR = FLASH_SR_CLEAR;/* Program first word */*(uint32_t *)address = (uint32_t)(data & 0xFFFFFFFF);/* Barrier to ensure programming is performed in 2 steps, in right order(independently of compiler optimization behavior) */__ISB();FLASH->ECCR |= FLASH_ECCR_ECCC|FLASH_ECCR_ECCD;FLASH->SR = FLASH_SR_CLEAR;/* Program second word */*(uint32_t *)(address + 4U) = (uint32_t)(data >> 32U);
}uint32_t xFlash_GetPageIndex(uint32_t flashAddr)
{return ((flashAddr - FLASH_BASE_ADDR) / FLASH_PAGE_SIZE_BYTE);
}uint32_t xFlash_GetPageNumber(uint32_t fileSize)
{return ((fileSize + FLASH_PAGE_SIZE_BYTE - 1) / FLASH_PAGE_SIZE_BYTE);// return ((fileSize / FLASH_PAGE_SIZE_BYTE) + ((fileSize % FLASH_PAGE_SIZE_BYTE) ? 1 : 0));
}uint8_t xFlash_ErasePage_Single(uint32_t page)
{uint32_t i = 0, overTime = 0xFF000;if (xFlash_Unlock()) return 1;if (xFlash_WaitForLast_Operation(2000)) {xFlash_Lock(); return 2;}for (i = 0; i < FLASH_TRY_COUNT; i++){vFlashErasePage(page);/* wait for BSY1 in order to be sure that flash operation is ended beforeallowing prefetch in flash.  */while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U){if (overTime-- < 10){break;}}/* If operation is completed or interrupted, disable the Page Erase Bit */CLEAR_BIT(FLASH->CR, FLASH_CR_PER);    }if (i == FLASH_TRY_COUNT) {xFlash_Lock();return 3;}if (xFlash_Lock()) {return 4;}return 0;
}uint8_t xFlash_ErasePage_Continue(uint32_t baseAdrr, uint32_t pageCount, uint8_t mode)
{uint32_t start = xFlash_GetPageIndex(baseAdrr);uint32_t end   = start + pageCount - 1;uint32_t overTime = 0, i = 0, n = 0;if (xFlash_Unlock()) return 1;if (xFlash_WaitForLast_Operation(2000)) {xFlash_Lock(); return 2;}for (i = start; i <= end; i++){for (n = 0; n < FLASH_TRY_COUNT; n++){overTime = 0xFF000;vFlashErasePage(i);/* wait for BSY1 in order to be sure that flash operation is ended beforeallowing prefetch in flash.  */while ((FLASH->SR & FLASH_SR_BSY1) != 0x00U){if (overTime-- < 10){xFlash_Lock();return 3;}}/* If operation is completed or interrupted, disable the Page Erase Bit */CLEAR_BIT(FLASH->CR, FLASH_CR_PER);if (mode){extern void vShow_Info_Erase_Flash(uint32_t pageIndex);vShow_Info_Erase_Flash(i);}break;}if (n == FLASH_TRY_COUNT) {xFlash_Lock();return 4;}xFlash_WaitForLast_Operation(2000);}if (xFlash_Lock()) {return 5;}return 0;
}uint8_t xFlash_Program_DoubleWord_Continue(uint32_t startAddr, uint8_t * pSrcDat, uint32_t len)
{uint32_t i = 0, n = 0, max = 0;if (xFlash_Unlock()) return 1;if (xFlash_WaitForLast_Operation(2000)) {xFlash_Lock(); return 2;}max = len >> 3;for (i = 0; i < max; i++){for (n = 0; n < FLASH_TRY_COUNT; n++){vFlash_Program_DoubleWord(startAddr, (uint64_t)(*(uint64_t *)pSrcDat));xFlash_WaitForLast_Operation(2000);CLEAR_BIT(FLASH->CR, FLASH_CR_PG);if (*(uint64_t *)startAddr == *(uint64_t *)(pSrcDat)){break;}}if (n == FLASH_TRY_COUNT){xFlash_Lock();return 3;}startAddr += 8;pSrcDat   += 8;}if (xFlash_Unlock()) {return 4;}return 0;
}void vFlash_ReadData_Continue(uint32_t baseAdrr, uint8_t * pDstDat, uint32_t len)
{uint32_t i = 0;for(i = 0; i < len; ++i){*pDstDat++ = *(volatile uint8_t *)(baseAdrr + i);}
}uint8_t xFlash_Program_EreasePage_Continue(uint32_t startAddr, uint8_t * pSrcDat, uint32_t len, uint8_t mode)
{if (mode && xFlash_ErasePage_Single(xFlash_GetPageIndex(startAddr))){return 5;}return xFlash_Program_DoubleWord_Continue(startAddr, pSrcDat, len);
}

四、Flash存储参数相关

  • Flash存储参数读取和写入,使用页分块的方式,实现一次擦除多次写入,提高Flash的寿命。
  • 向外提供存储相关的操作接口,TrueSize为固件的真实大小,IapFlag为IAP标志,根据次标志来实现不同的操作


#define XOFS(t , m)                                                         ((u32)(&(((t *)0)->m)))#pragma pack(1)
typedef struct
{uint16_t HeaderTag;uint16_t StoreIndex;
}FlashStoreHeader, * FlashStoreHeader_t;typedef struct
{FlashStoreHeader Header;uint32_t TrueSize;uint16_t IapFlag;uint8_t Res[5];uint8_t CRC8; 
}IAP_ParamStore_TypeDef, * IAP_ParamStore_TypeDef_t;
#pragma pack()static IAP_ParamStore_TypeDef IapStoreParam = {0};static uint8_t ubCheckSum_CRC8(void * pData, uint32_t len)
{uint8_t * pBuf = (uint8_t *)pData;uint32_t i = 0, sum = 0;for (i = 0; i < len; ++i){sum += *(pBuf + i);}return (uint8_t)sum;
}static uint16_t usGet_Flash_Read_Index(uint16_t page)
{uint32_t startAddr  = IAP_BOOT_STORE_PARM_BASE_ADDR;uint16_t blackSize  = IAP_BOOT_STORE_PARM_BLOCK_SIZE;uint16_t headerTag  = IAP_BOOT_STORE_PARM_HEADER_TAG;uint8_t  blackCount = IAP_BOOT_STORE_PARM_BLOCK_COUNT;uint8_t  len = XOFS(IAP_ParamStore_TypeDef , CRC8);uint16_t dat = 0, i = 0;uint8_t  crc = 0;// my_printf("R-startAddr:%X blackSize:%u headerTag:%X  blackCount:%u  len:%u\r\n", startAddr, blackSize, headerTag, blackCount, len);for (i = 0; i < blackCount; ++i){dat = *(volatile uint16_t *)(startAddr + ((blackCount - 1 - i) * blackSize));if (dat == headerTag){crc = ubCheckSum_CRC8((void *)(startAddr + ((blackCount - 1 - i) * blackSize)), len);dat = *(volatile uint8_t *)(startAddr + ((blackCount - 1 - i) * blackSize) + (blackSize - 1));if (dat == crc){return (blackCount - 1 - i);}}}return IAP_BOOT_STORE_PARM_BLOCK_COUNT;
}static uint16_t usGet_Flash_Write_Index(uint16_t page)
{uint32_t startAddr  = IAP_BOOT_STORE_PARM_BASE_ADDR;uint16_t blackSize  = IAP_BOOT_STORE_PARM_BLOCK_SIZE;uint8_t  blackCount = IAP_BOOT_STORE_PARM_BLOCK_COUNT;uint16_t dat = 0, i = 0, x = 0;uint8_t  tmp = 0, uFlg = 0;// my_printf("W-startAddr:%X blackSize:%u blackCount:%u\r\n", startAddr, blackSize, blackCount);for (i = 0; i < blackCount; ++i){dat = *(volatile uint16_t *)(startAddr + (blackSize * i));if (dat == 0xFFFFU){uFlg = 0;for (x = 0; x < blackSize; ++x){tmp = *(volatile uint8_t *)(startAddr + (blackSize * i) + x);if (tmp != 0xFFU){uFlg = 1;break;}}if (!uFlg) {return i;}}}return IAP_BOOT_STORE_PARM_BLOCK_COUNT;
}static void vFixed_Iap_Value(void)
{IapStoreParam.Header.HeaderTag = IAP_BOOT_STORE_PARM_HEADER_TAG;
}static void vRestore_IapStore_Parameter(void)
{memset((void *)(&IapStoreParam), 0, sizeof(IAP_ParamStore_TypeDef));vFixed_Iap_Value();
}static void vRead_IapStore_Parameter(void)
{uint16_t index = usGet_Flash_Read_Index(0);if (index < IAP_BOOT_STORE_PARM_BLOCK_COUNT){vFlash_ReadData_Continue(IAP_BOOT_STORE_PARM_BASE_ADDR + (IAP_BOOT_STORE_PARM_BLOCK_SIZE * index), (uint8_t *)(&IapStoreParam), IAP_BOOT_STORE_PARM_BLOCK_SIZE);vFixed_Iap_Value();}else{vRestore_IapStore_Parameter();}my_printf("%s IAP Param OK......Index:%u\r\n", (index < IAP_BOOT_STORE_PARM_BLOCK_COUNT) ? "Read" : "Restore", IapStoreParam.Header.StoreIndex);#if 1my_printf("----------------------- IAP Param Info ---------------------\r\n");my_printf("            00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  \r\n");my_printf("-------------------------------------------------------------\r\n");for (index = 0; index < IAP_BOOT_STORE_PARM_BLOCK_SIZE; ++index){if (index && (index % 16 == 0)) my_printf("\r\n");if (index % 16 == 0) my_printf("0x%08X  ", (IAP_BOOT_STORE_PARM_BASE_ADDR + (IAP_BOOT_STORE_PARM_BLOCK_SIZE * IapStoreParam.Header.StoreIndex) + index));my_printf("%02X ", *(volatile uint8_t *)(IAP_BOOT_STORE_PARM_BASE_ADDR + (IAP_BOOT_STORE_PARM_BLOCK_SIZE * IapStoreParam.Header.StoreIndex) + index));}my_printf("\r\n");my_printf("-------------------------------------------------------------\r\n");my_printf("\r\n\r\n");#endif}static void vSave_System_Parameter(uint16_t page)
{uint32_t startAddr   = IAP_BOOT_STORE_PARM_BASE_ADDR;uint16_t blackSize   = IAP_BOOT_STORE_PARM_BLOCK_SIZE;uint8_t  blackCount  = IAP_BOOT_STORE_PARM_BLOCK_COUNT;uint16_t StoreIndex  = IapStoreParam.Header.StoreIndex;uint8_t  * pSrc      = (uint8_t *)(&IapStoreParam);uint8_t   mode = 0, dat = 0;uint16_t  index = 0;for (index = 0; index < blackSize; ++index){dat = *(volatile uint8_t *)(startAddr + (blackSize * StoreIndex) + index);if (dat != *pSrc++){mode = 1;break;}}if (!mode){my_printf("Save Iap Pram Same......Index:%02u\r\n", StoreIndex);return;}mode  = 0;index = usGet_Flash_Write_Index(page);if (index >= blackCount){index = 0; mode  = 1;}IapStoreParam.Header.StoreIndex = index;IapStoreParam.CRC8 = ubCheckSum_CRC8((void *)(&IapStoreParam),  XOFS(IAP_ParamStore_TypeDef , CRC8));dat = xFlash_Program_EreasePage_Continue((startAddr + (blackSize * index)), (uint8_t *)(&IapStoreParam), blackSize, mode);my_printf("Save Pram %s......Res:%u Index:%u CRC:%X\r\n", (dat?"Error":"Succeed"), dat, index, IapStoreParam.CRC8);
}static void vShow_System_Parameter(void)
{#if 1my_printf("---------------------- System Param Info --------------------\r\n");my_printf("Firmware Size: %uByte\r\n", xGet_FirmwareTrueSize());my_printf("IAP Flag     : %04X\r\n", xGet_IapFlag());my_printf("-------------------------------------------------------------\r\n");my_printf("\r\n\r\n");#endif
}static void vRead_GlobalSystem_Parameter(void)
{vRead_IapStore_Parameter();vShow_System_Parameter();
}void vRead_System_Parameter(void)
{#if 0my_printf("IAP_ParamStore_TypeDef Size: %u\r\n", sizeof(IAP_ParamStore_TypeDef));if (sizeof(IAP_ParamStore_TypeDef) != IAP_BOOT_STORE_PARM_BLOCK_SIZE){my_printf("Iap Param Size Error......\r\n");while (1);}#endifvRead_GlobalSystem_Parameter();
}void vSave_IapStore_Parameter(void)
{vSave_System_Parameter(0);
}/***************************************************************************************************************************************************************/
/***************************************************************************************************************************************************************/
/***************************************************************************************************************************************************************/
uint32_t xGet_FirmwareTrueSize(void)
{return IapStoreParam.TrueSize;
}void vSet_FirmwareTrueSize(uint32_t size)
{IapStoreParam.TrueSize = size;
}uint16_t xGet_IapFlag(void)
{return IapStoreParam.IapFlag;
}void vSet_IapFlag(uint16_t flag)
{IapStoreParam.IapFlag = flag;
}

五、核心部分Ymodem相关

  • 主要实现Ymodem协议的发送和接收功能
  • 从串口接收Ymodem协议数据,进行校验,并保存到Flash中,最后设置IapFlag标志位



#define YMODEM_CMD_SOH                                                          (0x01)  /* start of header 128-byte data packet */
#define YMODEM_CMD_STX                                                          (0x02)  /* start of text 1024-byte data packet */
#define YMODEM_CMD_EOT                                                          (0x04)  /* end of transmission */
#define YMODEM_CMD_ACK                                                          (0x06)  /* acknowledge */
#define YMODEM_CMD_NAK                                                          (0x15)  /* negative acknowledge */
#define YMODEM_CMD_CAN                                                          (0x18)  /* cancel */
#define YMODEM_CMD_C                                                            (0x43)  /* C = 'C' - receive CRC */#define YMODEM_UCMD_ABORT1                                                      (0x41)  /* 'A' == 0x41, abort by user */
#define YMODEM_UCMD_ABORT2                                                      (0x61)  /* 'a' == 0x61, abort by user */ #define YMODEM_UCMD_STX_8BYTE                                                    (0xA1) 
#define YMODEM_UCMD_STX_16BYTE                                                   (0xA2) 
#define YMODEM_UCMD_STX_32BYTE                                                   (0xA3) 
#define YMODEM_UCMD_STX_64BYTE                                                   (0xA4) 
#define YMODEM_UCMD_STX_128BYTE                                                  (0xA5) 
#define YMODEM_UCMD_STX_256BYTE                                                  (0xA6) 
#define YMODEM_UCMD_STX_512BYTE                                                  (0xA7) 
#define YMODEM_UCMD_STX_1KBYTE                                                   (0xA8) 
#define YMODEM_UCMD_STX_2KBYTE                                                   (0xA9) #define YMODEM_PACKET_SIZE_8BYTE                                                 (8) 
#define YMODEM_PACKET_SIZE_16BYTE                                                (16) 
#define YMODEM_PACKET_SIZE_32BYTE                                                (32) 
#define YMODEM_PACKET_SIZE_64BYTE                                                (64) 
#define YMODEM_PACKET_SIZE_128BYTE                                               (128) 
#define YMODEM_PACKET_SIZE_256BYTE                                               (256) 
#define YMODEM_PACKET_SIZE_512BYTE                                               (512) 
#define YMODEM_PACKET_SIZE_1KBYTE                                                (1024) 
#define YMODEM_PACKET_SIZE_2KBYTE                                                (2048) #define YMODEM_PACKET_HEADER_SIZE                                                (3)
#define YMODEM_PACKET_CHECKSUM_SIZE                                              (2)
#define YMODEM_PACKET_OVERHEAD_SIZE                                              (YMODEM_PACKET_HEADER_SIZE + YMODEM_PACKET_CHECKSUM_SIZE)
#define YMODEM_PACKET_MAX_SIZE                                                   YMODEM_PACKET_SIZE_1KBYTE#define YMODEM_PACKET_INDEX0                                                    (0)
#define YMODEM_PACKET_INDEX1                                                    (1)
#define YMODEM_PACKET_INDEX2                                                    (2)#define YMODEM_DAT_TIME_OVER                                                    (0x300000)
#define YMODEM_DAT_ERROR_MAX                                                    (5)#define YMODEM_REC_TYPE_DFU                                                     (0x01)
#define YMODEM_REC_TYPE_BIN                                                     (0x02)
#define YMODEM_REC_TYPE_MAX                                                     YMODEM_REC_TYPE_BINstatic uint16_t xUpdateCRC16(uint16_t inDat, uint8_t data)
{uint32_t crc = inDat;uint32_t in  = data | 0x100;do{crc <<= 1;in  <<= 1;if (in & 0x100) ++crc;if (crc & 0x10000) crc ^= 0x1021;} while (!(in & 0x10000));return crc & 0xFFFF;
}static uint16_t xCRC16(const uint8_t * pDat, uint32_t len)
{uint32_t crc = 0;const uint8_t * dataEnd = pDat + len;while (pDat < dataEnd) {crc = xUpdateCRC16(crc, *pDat++);}crc = xUpdateCRC16(crc, 0);crc = xUpdateCRC16(crc, 0);return (crc & 0xFFFF);
}#pragma optimize=none
static uint8_t xYmodem_Verify_Data(uint8_t * pDat, uint16_t packetSize, uint16_t curIndex)
{uint16_t crc = 0;if (pDat[1] != (curIndex & 0xFF)) return 1;if (pDat[1] != (pDat[2] ^ 0xFF))  return 2;crc = xCRC16(&pDat[3], (packetSize - 5));if (pDat[packetSize - 1] != (uint8_t)(crc & 0x00FF)) return 3;if (pDat[packetSize - 2] != (uint8_t)(crc >> 8))     return 4;return 0;
}#pragma optimize=none
static uint32_t StrToNum(const uint8_t * pStr)
{uint32_t res = 0;while (*pStr != '\0'){res = res * 10 + (*pStr - '0');pStr++;}return res;
}#pragma optimize=none
static int32_t xYmodem_Receive_Packet(uint8_t * pDat, int32_t * len, uint32_t timeout)
{uint16_t i   = 0, packetSize = 0;uint8_t  chr = 0;*len = 0;if (xReceive_Byte_Wait(&chr, timeout)) return -1;switch (chr){case YMODEM_UCMD_STX_8BYTE:   packetSize = YMODEM_PACKET_SIZE_8BYTE;   break;case YMODEM_UCMD_STX_16BYTE:  packetSize = YMODEM_PACKET_SIZE_16BYTE;  break;case YMODEM_UCMD_STX_32BYTE:  packetSize = YMODEM_PACKET_SIZE_32BYTE;  break;case YMODEM_UCMD_STX_64BYTE:  packetSize = YMODEM_PACKET_SIZE_64BYTE;  break;case YMODEM_UCMD_STX_256BYTE: packetSize = YMODEM_PACKET_SIZE_256BYTE; break;case YMODEM_UCMD_STX_512BYTE: packetSize = YMODEM_PACKET_SIZE_512BYTE; break;case YMODEM_UCMD_STX_2KBYTE:  packetSize = YMODEM_PACKET_SIZE_2KBYTE;  break;case YMODEM_CMD_SOH:case YMODEM_UCMD_STX_128BYTE: packetSize = YMODEM_PACKET_SIZE_128BYTE; break;case YMODEM_CMD_STX: case YMODEM_UCMD_STX_1KBYTE:  packetSize = YMODEM_PACKET_SIZE_1KBYTE;  break;case YMODEM_UCMD_ABORT1:case YMODEM_UCMD_ABORT2: return 1;case YMODEM_CMD_EOT:     return 0;case YMODEM_CMD_CAN:{if ((!xReceive_Byte_Wait(&chr, timeout)) && (chr == YMODEM_CMD_CAN)){*len = -1;return 0;}else{return -1;}}break;default: return -1;}*pDat = chr;for (i = 1; i < (packetSize + YMODEM_PACKET_OVERHEAD_SIZE); i++){if (xReceive_Byte_Wait(pDat + i, timeout)){return -1;}}*len = packetSize;return 0;
}#pragma optimize=none
static uint8_t xYmodem_Get_HeaderInfo(uint8_t * pSrcDat, uint16_t srcLen, uint32_t * pOutFileSize)
{uint8_t  fileName[60] = {0};uint8_t  fileSize[7]  = {0, 0, 0, 0, 0, 0, 0};uint8_t * pFileName = fileName, nameLen = 60;uint8_t * pFileSize = fileSize, sizeLen = 6;uint8_t * pDat = pSrcDat;uint16_t i = 0, n = 0;uint8_t  dat = 0;for (i = 0; (i < srcLen) && (*pDat != 0); i++){dat = *pDat++;if ((dat >= 0x20) && (dat <= 0x7E)){if (i <= nameLen) *pFileName++ = dat;}else{return 1;}}if (i < 5)       return 2;if (i > nameLen) return 3;for (n = i, pDat++; (i < srcLen) && (*pDat != 0); i++){dat = *pDat++;if ((dat >= 0x30) && (dat <= 0x39)){if ((i - n) <= sizeLen) pFileSize[i - n] = dat;else                    return 4;}else {return 5;}}if ((i - n) < 3) return 6;*pOutFileSize = StrToNum(fileSize);// my_printf("File Name: %s\r\n", fileName);// my_printf("File Size: %s\r\n", fileSize);// my_printf("File Size: %dByte\r\n", StrToNum(fileSize));return 0;
}#pragma optimize=none
static uint8_t xYmodem_HeaderInfo_Verify(uint8_t typeOpt, uint32_t fileSize)
{uint32_t maxSpace = XSUPER_APP_FLASH_SIZE;if (typeOpt == YMODEM_REC_TYPE_DFU){#if defined(XSUPER_DEV_SPACE_APP_ONLY_ENABLE) && (XSUPER_DEV_SPACE_APP_ONLY_ENABLE == 1)maxSpace = XSUPER_APP_FLASH_SIZE;#endif#if defined(XSUPER_DEV_SPACE_APP_OTA_ENABLE) && (XSUPER_DEV_SPACE_APP_OTA_ENABLE == 1)maxSpace = XSUPER_OTA_FLASH_SIZE;#endifif (fileSize > maxSpace) return 1;}else if (typeOpt == YMODEM_REC_TYPE_BIN){return 2;}else{return 3;}return 0;
}#pragma optimize=none
static uint8_t xYmodem_Erase_Handler(uint8_t typeOpt, uint32_t fileSize)
{uint32_t baseAddr = XSUPER_APP_BASE_ADDR;if (typeOpt == YMODEM_REC_TYPE_DFU){#if defined(XSUPER_DEV_SPACE_APP_ONLY_ENABLE) && (XSUPER_DEV_SPACE_APP_ONLY_ENABLE == 1)baseAddr = XSUPER_APP_BASE_ADDR;#endif#if defined(XSUPER_DEV_SPACE_APP_OTA_ENABLE) && (XSUPER_DEV_SPACE_APP_OTA_ENABLE == 1)baseAddr = XSUPER_OTA_BASE_ADDR;#endifreturn xFlash_ErasePage_Continue(baseAddr, xFlash_GetPageNumber(fileSize), 0);}else if (typeOpt == YMODEM_REC_TYPE_BIN){}else{return 6;}return 7;
}#pragma optimize=none
static uint8_t xYmodem_DataSave_Handler(uint8_t typeOpt, uint32_t startAddr, uint8_t * pSrcDat, uint32_t len)
{if (typeOpt == YMODEM_REC_TYPE_DFU){return xFlash_Program_DoubleWord_Continue(startAddr, pSrcDat, len);}else if (typeOpt == YMODEM_REC_TYPE_BIN){}else{return 5;}return 6;
}#pragma optimize=none
int32_t xYmodem_Receive_Data(uint8_t typeOpt)
{#define YMODEM_COMPLETE_FLG_DAT_PACKET (0x01)#define YMODEM_COMPLETE_FLG_ABORT_CMD  (0x02)#define YMODEM_COMPLETE_FLG_END_PACKET (0x04)#define YMODEM_COMPLETE_FLG_ALL        (YMODEM_COMPLETE_FLG_DAT_PACKET | YMODEM_COMPLETE_FLG_ABORT_CMD | YMODEM_COMPLETE_FLG_END_PACKET)uint8_t  packetDat[YMODEM_PACKET_MAX_SIZE + YMODEM_PACKET_OVERHEAD_SIZE] __attribute__((aligned(4)));uint8_t  errCount = 0, errFlag = 0, completeFlg = 0, * pSrcDat = packetDat, value = 1;uint32_t fileSize = 0, startBaseAdrr = XSUPER_APP_BASE_ADDR;uint16_t curRxPacketCount = 0, maxPacketCount = 0;int32_t  packetSize = 0, res = -2;#if defined(XSUPER_DEV_SPACE_APP_ONLY_ENABLE) && (XSUPER_DEV_SPACE_APP_ONLY_ENABLE == 1)startBaseAdrr = XSUPER_APP_BASE_ADDR;#endif#if defined(XSUPER_DEV_SPACE_APP_OTA_ENABLE) && (XSUPER_DEV_SPACE_APP_OTA_ENABLE == 1)startBaseAdrr = XSUPER_OTA_BASE_ADDR;#endifvTxByte(YMODEM_CMD_C);while (1){res = xYmodem_Receive_Packet(packetDat, &packetSize, YMODEM_DAT_TIME_OVER);switch (res){case 0:{errCount = 0;switch (packetSize){case -1:{/* abort transmit */vTxByte(YMODEM_CMD_ACK); return 0;}break;case 0:{/* transmit end */vTxByte(YMODEM_CMD_ACK);if (completeFlg & YMODEM_COMPLETE_FLG_DAT_PACKET){curRxPacketCount = 0;completeFlg     |= YMODEM_COMPLETE_FLG_ABORT_CMD;}}break;default:{/* data check */if (xYmodem_Verify_Data(packetDat, (packetSize + 5), curRxPacketCount)){vTxByte(YMODEM_CMD_NAK);}else{/* packet index */if (!curRxPacketCount){/* first packet data */if (packetDat[YMODEM_PACKET_HEADER_SIZE]){value = xYmodem_Get_HeaderInfo(&packetDat[3], (packetSize + 2), &fileSize);if (value){vTxByte(YMODEM_CMD_NAK);my_printf("Get Header Error...%d\r\n", value);break;}value = xYmodem_HeaderInfo_Verify(typeOpt, fileSize);if (value){vTxByte(YMODEM_CMD_CAN); vTxByte(YMODEM_CMD_CAN);my_printf("Header Verify Error...%d\r\n", value);return -1;}value = xYmodem_Erase_Handler(typeOpt, fileSize);if (value){vTxByte(YMODEM_CMD_CAN); vTxByte(YMODEM_CMD_CAN);my_printf("Erase Error......%d\r\n", value);return -1;}maxPacketCount = ((fileSize + packetSize - 1) / packetSize);vSet_FirmwareTrueSize(fileSize);vTxByte(YMODEM_CMD_ACK); vTxByte(YMODEM_CMD_C);}else{/* end packet data */if (completeFlg & YMODEM_COMPLETE_FLG_ABORT_CMD){completeFlg |= YMODEM_COMPLETE_FLG_END_PACKET;}vTxByte(YMODEM_CMD_ACK);break;}}else {/* true data */memcpy(packetDat, packetDat + YMODEM_PACKET_HEADER_SIZE, packetSize);pSrcDat = packetDat;value = xYmodem_DataSave_Handler(typeOpt, startBaseAdrr, pSrcDat, packetSize);if (value){my_printf("Data Save Error...%d\r\n", value);vTxByte(YMODEM_CMD_ACK); vTxByte(YMODEM_CMD_C);return -2;}startBaseAdrr += packetSize;vTxByte(YMODEM_CMD_ACK);}curRxPacketCount++;if (!errFlag) errFlag = 1;if (curRxPacketCount >= maxPacketCount){completeFlg |= YMODEM_COMPLETE_FLG_DAT_PACKET;}}}break;}}break;case 1:{/* user abort transmit */vTxByte(YMODEM_CMD_CAN);  vTxByte(YMODEM_CMD_CAN); return -3;}break;default:{if (errFlag && (errCount++ > YMODEM_DAT_ERROR_MAX)){/* abort transmit */vTxByte(YMODEM_CMD_CAN); vTxByte(YMODEM_CMD_CAN);return 0;}vTxByte(YMODEM_CMD_C);}break;}if (completeFlg == YMODEM_COMPLETE_FLG_ALL){break;}}return (int32_t)fileSize;
}

六、其他宏配置

#define DEV_INFO_SOFT_MAJOR_VER                                                                     2   
#define DEV_INFO_SOFT_MINOR_VER                                                                     6   
#define DEV_INFO_SOFT_REVISE_VER                                                                    37#define DEV_INFO_HARD_MAJOR_VER                                                                     2   
#define DEV_INFO_HARD_MINOR_VER                                                                     0   
#define DEV_INFO_HARD_REVISE_VER                                                                    0   #define STR(s)                                                                                      #s
#define DEV_INFO_VER_STR_ARG(major , minor , revise)                                                STR(major) "." STR(minor) "." STR(revise)   #define DEV_INFO_SOFT_VER_STR                                                                       DEV_INFO_VER_STR_ARG(DEV_INFO_SOFT_MAJOR_VER , DEV_INFO_SOFT_MINOR_VER , DEV_INFO_SOFT_REVISE_VER)  
#define DEV_INFO_HARD_VER_STR                                                                       DEV_INFO_VER_STR_ARG(DEV_INFO_HARD_MAJOR_VER , DEV_INFO_HARD_MINOR_VER , DEV_INFO_HARD_REVISE_VER)  #define DEV_INFO_SOFT_VER_INT                                                                       ((DEV_INFO_SOFT_MAJOR_VER << 16) | (DEV_INFO_SOFT_MINOR_VER << 8) | DEV_INFO_SOFT_REVISE_VER) 
#define DEV_INFO_HARD_VER_INT                                                                       ((DEV_INFO_HARD_MAJOR_VER << 16) | (DEV_INFO_HARD_MINOR_VER << 8) | DEV_INFO_HARD_REVISE_VER) #define XSUPER_DEV_SPACE_APP_ONLY_ENABLE                                                             (0)
#define XSUPER_DEV_SPACE_APP_OTA_ENABLE                                                              (1)/* 64KB = 16KB + 22KB + 22KB + 4KB */
#define IAP_BOOT_FLASH_SIZE                                                                         (0x4000)
#define FLASH_PAGE_SIZE_BYTE                                                                        (0x800)
#define FLASH_BASE_ADDR                                                                             FLASH_BASE#define IAP_BOOT_STORE_PARM_BASE_ADDR                                                               (FLASH_BASE_ADDR + IAP_BOOT_FLASH_SIZE - FLASH_PAGE_SIZE_BYTE)
#define IAP_BOOT_STORE_PARM_HEADER_TAG                                                              (0x2D36)
#define IAP_BOOT_STORE_PARM_BLOCK_SIZE                                                              (16)
#define IAP_BOOT_STORE_PARM_BLOCK_COUNT                                                             (uint16_t)(FLASH_PAGE_SIZE_BYTE / IAP_BOOT_STORE_PARM_BLOCK_SIZE) #define XSUPER_APP_BASE_ADDR                                                                        (FLASH_BASE_ADDR + IAP_BOOT_FLASH_SIZE)
#define XSUPER_APP_FLASH_SIZE                                                                       (0x5800)#define XSUPER_OTA_BASE_ADDR                                                                        (FLASH_BASE_ADDR + IAP_BOOT_FLASH_SIZE + XSUPER_APP_FLASH_SIZE)
#define XSUPER_OTA_FLASH_SIZE                                                                       (0x5800)

七、主函数


int main(void)
{/* Reset of all peripherals, Initializes the Flash interface and the Systick. */LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);/* Disable the internal Pull-Up in Dead Battery pins of UCPD peripheral */LL_SYSCFG_DisableDBATT(LL_SYSCFG_UCPD1_STROBE | LL_SYSCFG_UCPD2_STROBE);SystemClock_Config();vInit_Board_Drive();vRead_System_Parameter();while (1){vIAP_Running_Handler();}
}void SystemClock_Config(void)
{LL_FLASH_SetLatency(LL_FLASH_LATENCY_2);while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2);LL_FLASH_EnablePrefetch();/* HSE configuration and activation */LL_RCC_HSE_Enable();while(LL_RCC_HSE_IsReady() != 1);/* Main PLL configuration and activation */LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_3, 16, LL_RCC_PLLR_DIV_2);LL_RCC_PLL_Enable();LL_RCC_PLL_EnableDomain_SYS();while(LL_RCC_PLL_IsReady() != 1);/* Set AHB prescaler*/LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);/* Sysclk activation on the main PLL */LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL);/* Set APB1 prescaler*/LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);//LL_Init1msTick(72000000); //63000000/* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function) */LL_SetSystemCoreClock(72000000); //63000000LL_RCC_ConfigMCO(LL_RCC_MCO1SOURCE_HSE, LL_RCC_MCO1_DIV_1);LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK1);LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_SYSCLK);
}

八、使用Python合并文件

  • 合并方式Bootloader + App
  • 合并后的文件test.bin, boot.bin为Bootloader文件, app.bin为App文件
  • Bootloader后需要保存IapFlag相关疏忽, 保证烧录后直接运行,也可以通过Bootloader实现



def main():fix  = bytes([0x36, 0x2D, 0x00, 0x00, 0xAA, 0x11, 0x00, 0x00, 0x5A, 0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2])data = bytes([0xFF])with open('test.bin', 'wb') as outFile: with open('boot.bin', 'rb') as bootFile:rDat = bootFile.read()outFile.write(rDat)size = len(rDat)max  = 16 * 1024tem  = max - sizeprint('boot.bin size: %d Byte' % size)for i in range(size, max):if i >= 0x3800 and i < 0x3800 + 16:fixDat = fix[i - 0x3800] dat = bytes([fixDat])outFile.write(dat)else:outFile.write(data)with open('app.bin', 'rb') as appFile:rDat = appFile.read()outFile.write(rDat)print('app.bin size : %d Byte' % len(rDat))remainByte   = 0with open('test.bin', 'rb') as outFile: lenght = len(outFile.read()) remainByte = 512 - (lenght % 512)print('test.bin size: %d Byte  %u  %u' % (lenght, lenght % 512, remainByte))if remainByte > 0:with open('test.bin', 'ab') as outFile: for i in range(remainByte):data = bytes([0])outFile.write(data)if __name__ == '__main__':main()

九、测试结果

  • 烧录Bootloader的情况
System Power On......
Restore IAP Param OK......Index:0
----------------------- IAP Param Info ---------------------00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  
-------------------------------------------------------------
0x08003800  FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF 
----------------------------------------------------------------------------------- System Param Info --------------------
Firmware Size: 0Byte
IAP Flag     : 0000
-------------------------------------------------------------******************* Bootloader Main Menu ******************
Software Version: 2.6.37
Compiler Date   : May 26 2025 14:29:44
***********************************************************

在这里插入图片描述

  • 烧录应用程序
******************* Bootloader Main Menu ******************
Software Version: 2.6.37
Compiler Date   : May 26 2025 14:29:44
***********************************************************
文件大小: 6950Firmware Update......6950
Firmware Update Succeed...Save Pram Succeed......Res:0 Index:0 CRC:58Running To Application......
App Base Addr  :0x08004000
App True Size  :6950Byte
App Space Size :0x00005800Read IAP Param OK......Index:0
----------------------- App Param Info ---------------------00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  
-------------------------------------------------------------
0x08003800  36 2D 00 00 26 1B 00 00 5A 5A 00 00 00 00 00 58 
----------------------------------------------------------------------------------- System Param Info --------------------
Firmware Size: 6950Byte
IAP Flag     : 5A5A
-------------------------------------------------------------HHHHHHH

在这里插入图片描述

  • 读取应用程序
HHHHHHHHHHHHW-startAddr:8003800 blackSize:16 blackCount:128
Save Pram Succeed......Res:0 Index:1 CRC:5FSystem Power On......
Read IAP Param OK......Index:1
----------------------- IAP Param Info ---------------------00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  
-------------------------------------------------------------
0x08003810  36 2D 01 00 26 1B 00 00 DD DD 00 00 00 00 00 5F 
----------------------------------------------------------------------------------- System Param Info --------------------
Firmware Size: 6950Byte
IAP Flag     : DDDD
------------------------------------------------------------------------------------ App Firmware Show ------------------00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F  
-------------------------------------------------------------
0x08004000  A0 08 00 20 A5 5A 00 08 8D 5A 00 08 8F 5A 00 08 
0x08004010  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x08004020  00 00 00 00 00 00 00 00 00 00 00 00 91 5A 00 08 
0x08004030  00 00 00 00 00 00 00 00 93 5A 00 08 95 5A 00 08 
0x08004040  DF 46 00 08 00 00 00 00 DF 47 00 08 33 4B 00 08 
0x08004050  5B 4D 00 08 8F 50 00 08 A3 50 00 08 1B 57 00 08 
0x08004060  00 00 00 00 6B 5A 00 08 77 5A 00 08 01 5B 00 08 
0x08004070  03 5B 00 08 05 5B 00 08 07 5B 00 08 00 00 00 00 
0x08004080  09 5B 00 08 0B 5B 00 08 0D 5B 00 08 0F 5B 00 08 
0x08004090  11 5B 00 08 13 5B 00 08 15 5B 00 08 17 5B 00 08 
0x080040A0  19 5B 00 08 1B 5B 00 08 1D 5B 00 08 FD 42 00 08 
0x080040B0  1F 5B 00 08 21 5B 00 08 01 00 05 D4 01 21 C0 06 
0x080040C0  C0 0E 81 40 AB 48 01 60 70 47 10 B4 C2 00 18 23 
0x080040D0  13 40 FF 24 9C 40 E2 43 89 01 C9 B2 99 40 03 00 
0x080040E0  08 D4 A5 48 9B 08 9B 00 C0 18 03 68 1A 40 11 43 
0x080040F0  01 60 0A E0 A1 4B 00 07 00 0F 08 38 80 08 80 00 
0x08004100  18 18 03 68 1A 40 11 43 01 60 10 BC 70 47 9C 49 
0x08004110  0A 68 03 0C 9A 43 80 B2 10 43 08 60 70 47 81 B0 
0x08004120  98 49 0A 68 02 43 0A 60 09 68 08 40 00 90 00 98 
0x08004130  01 B0 70 47 81 B0 94 49 0A 68 02 43 0A 60 09 68 
0x08004140  08 40 00 90 00 98 01 B0 70 47 01 68 01 22 0A 43 
0x08004150  02 60 70 47 01 68 80 22 92 05 0A 43 02 60 70 47 
0x08004160  EF F3 10 82 01 23 83 F3 10 88 83 68 DB 00 DB 08 
0x08004170  49 07 19 43 81 60 82 F3 10 88 70 47 10 B4 EF F3 
0x08004180  10 82 01 23 83 F3 10 88 83 68 80 4C 1C 40 49 06 
0x08004190  21 43 81 60 82 F3 10 88 10 BC 70 47 41 68 7C 4A 
0x080041A0  0A 40 42 60 81 68 2A 22 91 43 81 60 70 47 C0 69 
0x080041B0  41 09 08 00 C0 07 C0 0F 70 47 C0 69 41 0D 08 00 
0x080041C0  C0 07 C0 0F 70 47 C0 69 81 0D 08 00 C0 07 C0 0F 
0x080041D0  70 47 08 21 01 62 70 47 10 21 01 62 70 47 80 21 
0x080041E0  09 01 01 62 70 47 EF F3 10 81 01 22 82 F3 10 88 
0x080041F0  02 68 20 23 13 43 03 60 81 F3 10 88 70 47 00 68 
0x08004200  41 09 08 00 C0 07 C0 0F 70 47 40 6A C0 B2 70 47 
0x08004210  F8 B5 8E B0 00 22 20 21 06 A8 00 F0 43 FA 00 22 
0x08004220  18 21 68 46 00 F0 3E FA C0 20 80 02 FF F7 6F FF 
0x08004230  80 20 C0 01 FF F7 73 FF 01 20 FF F7 7B FF 80 20 
0x08004240  80 00 00 90 02 26 01 96 00 24 02 94 03 94 04 94 
0x08004250  01 25 05 95 A0 27 FF 05 69 46 38 00 00 F0 87 FA 
0x08004260  A8 02 00 90 01 96 02 94 03 94 04 94 05 95 69 46 
0x08004270  38 00 00 F0 7C FA 47 4D 28 00 FF F7 AA FF 28 00 
0x08004280  FF F7 AA FF 28 00 FF F7 AA FF 28 00 FF F7 AB FF 
0x08004290  03 21 1B 20 FF F7 19 FF 1B 20 FF F7 0D FF 06 94 
0x080042A0  E1 20 00 03 07 90 08 94 09 94 0A 94 0C 20 0B 90 
0x080042B0  0C 94 0D 94 06 A9 28 00 00 F0 1C FB 21 46 28 00 
0x080042C0  FF F7 4E FF 21 46 28 00 FF F7 58 FF 28 00 FF F7 
0x080042D0  41 FF 28 00 FF F7 62 FF 28 00 FF F7 36 FF 28 00 
0x080042E0  FF F7 6B FF 00 28 FA D0 28 00 FF F7 6C FF 00 28 
0x080042F0  F5 D0 28 00 FF F7 6D FF 0F B0 F0 BD 10 B5 25 4C 
0x08004300  20 00 FF F7 54 FF 00 28 2B D0 20 00 FF F7 77 FF 
0x08004310  00 28 26 D0 20 00 FF F7 78 FF 1F 49 0A 78 80 23 
0x08004320  1A 42 1E D1 40 24 22 42 0A D0 0A 28 02 D0 00 20 
0x08004330  08 70 10 BD 13 43 0B 70 08 1D 00 F0 63 FB 10 BD 
0x08004340  0D 28 02 D1 14 43 0C 70 10 BD 0B 1D 14 00 A4 06 
0x08004350  A4 0E 18 55 52 1C 0A 70 D2 B2 3F 2A 01 DD 00 20 
0x08004360  08 70 10 BD 0D 49 C8 60 08 68 40 06 FC D5 70 47 
0x08004370  00 00 00 00 00 E1 00 E0 00 E4 00 E0 1C ED 00 E0 
0x08004380  54 10 02 40 40 10 02 40 34 10 02 40 FF FF FF F1 
0x08004390  FF B7 FF FF 00 38 01 40 04 00 00 20 1C 38 01 40 
0x080043A0  10 B4 00 22 49 1E 05 E0 83 5C 44 5C 84 54 43 54 
0x080043B0  52 1C 49 1E 8A 42 F7 DB 10 BC 70 47 F8 B5 86 B0 
0x080043C0  04 00 0D 00 16 00 01 A8 A9 A1 14 22 00 F0 40 FB 
0x080043D0  00 27 00 2C 12 D1 30 20 28 70 01 27 10 E0 01 A8 
0x080043E0  00 90 20 00 31 00 00 F0 4D FB 00 98 40 5C E8 55 
0x080043F0  7F 1C 20 00 31 00 00 F0 45 FB 04 00 00 2C EE D1 
0x08004400  39 00 28 00 FF F7 CC FF 38 00 07 B0 F0 BD 38 B5 
0x08004410  05 00 0C 00 02 E0 28 00 FF F7 A4 FF 20 00 44 1E 
0x08004420  F9 DA 31 BD 38 B5 05 00 0C 00 03 E0 28 78 FF F7 
0x08004430  99 FF 6D 1C 20 00 44 1E F8 DA 31 BD 0E B4 F0 B5 
0x08004440  8A B0 04 00 0F AE 02 E0 FF F7 8C FF 64 1C 20 78 
0x08004450  00 28 00 D1 07 E1 25 28 F6 D1 64 1C 00 22 0C 21 
0x08004460  68 46 00 F0 1F F9 20 20 69 46 08 71 20 78 2D 28 
0x08004470  03 D1 01 20 00 90 64 1C 0D E0 30 28 0B D1 30 20 
0x08004480  08 71 64 1C 07 E0 02 99 8A 00 51 18 49 00 08 18 
0x08004490  30 38 02 90 64 1C 20 78 01 00 0A 00 30 3A 0A 2A 
0x080044A0  F1 D3 09 94 58 29 4D D0 63 29 00 D1 8E E0 64 29 
0x080044B0  07 D0 73 29 68 D0 75 29 00 D1 A2 E0 78 29 41 D0 
0x080044C0  CC E0 33 68 36 1D 1C 00 E4 0F 01 D0 58 42 03 00 
0x080044D0  0A 22 06 A9 18 00 FF F7 71 FF 05 00 00 20 00 2C 
0x080044E0  0D D0 03 A9 2D 22 0A 70 02 00 4C 1C 03 E0 06 AB 
0x080044F0  9B 5C A3 54 52 1C AA 42 F9 DB 6D 1C 08 E0 01 00 
0x08004500  03 AB 03 E0 06 AA 52 5C 5A 54 49 1C A9 42 F9 DB 
0x08004510  02 99 4C 1B 00 D5 04 00 00 98 00 28 08 D0 29 00 
0x08004520  03 A8 FF F7 7F FF 21 00 20 20 FF F7 70 FF 97 E0 
0x08004530  21 00 68 46 00 79 FF F7 6A FF 29 00 03 A8 FF F7 
0x08004540  71 FF 8D E0 30 68 36 1D 10 22 03 A9 FF F7 36 FF 
0x08004550  04 00 02 98 01 1B 00 D5 00 21 68 46 00 79 30 28 
0x08004560  0A D1 00 98 00 28 07 D1 30 20 FF F7 50 FF 21 00 
0x08004570  03 A8 FF F7 57 FF 73 E0 20 20 FF F7 48 FF 21 00 
0x08004580  03 A8 FF F7 4F FF 6B E0 34 68 36 1D 00 20 05 00 
0x08004590  00 E0 6D 1C 61 5D 00 29 FB D1 02 99 4F 1B 00 D5 
0x080045A0  07 00 00 98 00 28 08 D0 29 00 20 00 FF F7 3A FF 
0x080045B0  39 00 20 20 FF F7 2B FF 52 E0 39 00 20 20 FF F7 
0x080045C0  26 FF 29 00 20 00 FF F7 2D FF 49 E0 34 68 36 1D 
0x080045D0  02 9D 6D 1E 00 D5 00 25 00 98 00 28 08 D0 20 00 
0x080045E0  C0 B2 FF F7 BF FE 29 00 20 20 FF F7 10 FF 37 E0 
0x080045F0  29 00 20 20 FF F7 0B FF 20 00 C0 B2 FF F7 B2 FE 
0x08004600  2E E0 30 68 36 1D 0A 22 03 A9 FF F7 D7 FE 05 00 
0x08004610  02 98 44 1B 00 D5 00 24 00 98 00 28 08 D0 29 00 
0x08004620  03 A8 FF F7 FF FE 21 00 20 20 FF F7 F0 FE 17 E0 
0x08004630  68 46 00 79 30 28 08 D1 21 00 30 20 FF F7 E7 FE 
0x08004640  29 00 03 A8 FF F7 EE FE 0A E0 21 00 20 20 FF F7 
0x08004650  DE FE 29 00 03 A8 FF F7 E5 FE 01 E0 FF F7 82 FE 
0x08004660  09 98 44 1C F3 E6 0A B0 04 98 F0 BC 04 B0 00 47 
0x08004670  30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46 
0x08004680  00 00 00 00 12 06 13 0A 1A 43 13 0C 1A 43 00 BF 
0x08004690  09 42 05 D0 83 07 0B D0 02 70 40 1C 49 1E F9 D1 
0x080046A0  70 47 00 00 12 06 13 0A 1A 43 13 0C 1A 43 00 BF 
0x080046B0  13 00 10 39 06 D3 30 B4 14 00 15 00 10 39 3C C0 
0x080046C0  FC D2 30 BC 49 07 00 D3 0C C0 00 D5 04 C0 89 00 
0x080046D0  02 D3 02 80 80 1C 00 29 00 D5 02 70 70 47 FE E7 
0x080046E0  10 B4 0B 00 4B 43 01 68 5C 00 E4 18 A1 43 53 43 
0x080046F0  0B 43 03 60 10 BC 70 47 43 68 8B 43 51 43 19 43 
0x08004700  41 60 70 47 10 B4 0B 00 4B 43 81 68 5C 00 E4 18 
0x08004710  A1 43 53 43 0B 43 83 60 10 BC 70 47 10 B4 0B 00 
0x08004720  4B 43 C1 68 5C 00 E4 18 A1 43 53 43 0B 43 C3 60 
0x08004730  10 BC 70 47 10 B4 0B 00 4B 43 4B 43 4B 43 01 6A 
0x08004740  1C 01 E4 1A A1 43 53 43 0B 43 03 62 10 BC 70 47 
0x08004750  10 B4 09 0A 0B 00 4B 43 4B 43 4B 43 41 6A 1C 01 
0x08004760  E4 1A A1 43 53 43 0B 43 43 62 10 BC 70 47 F8 B5 
0x08004770  00 25 07 00 0E 00 2C E0 21 00 38 00 FF F7 E8 FF 
0x08004780  21 E0 01 24 AC 40 04 40 22 D0 70 68 01 28 01 D0 
0x08004790  02 28 09 D1 B2 68 21 00 38 00 FF F7 B3 FF F2 68 
0x080047A0  21 00 38 00 FF F7 A8 FF 32 69 21 00 38 00 FF F7 
0x080047B0  B5 FF 70 68 02 28 06 D1 72 69 FF 2C DC D8 21 00 
0x080047C0  38 00 FF F7 B7 FF 72 68 21 00 38 00 FF F7 88 FF 
0x080047D0  6D 1C 30 68 01 00 E9 40 D3 D1 00 20 F2 BD FE E7 
0x080047E0  01 68 08 00 C0 07 C0 0F 70 47 C2 6A 0F 23 9A 43 
0x080047F0  89 B2 0A 43 C2 62 70 47 42 68 64 4B 13 40 19 43 
0x08004800  41 60 70 47 82 68 62 4B 13 40 19 43 81 60 70 47 
0x08004810  70 B5 04 00 08 00 0C 2A 22 D2 04 9D 00 2D 1F D0 
0x08004820  1E 00 5C 49 D2 B2 92 00 89 58 00 F0 2B F9 69 08 
0x08004830  80 22 12 02 96 42 0D D1 40 00 40 18 29 00 00 F0 
0x08004840  21 F9 80 B2 54 49 01 40 40 08 40 07 40 0F 01 43 
0x08004850  E1 60 70 BD 40 18 29 00 00 F0 14 F9 80 B2 E0 60 
0x08004860  70 BD 4E 49 0A 68 10 43 08 60 70 47 4B 49 0A 68 
0x08004870  82 43 0A 60 70 47 4A 49 0A 68 10 43 08 60 70 47 
0x08004880  47 49 0A 68 82 43 0A 60 70 47 38 B5 00 24 45 49 
0x08004890  88 42 08 D1 80 25 ED 01 28 00 FF F7 EC FF 28 00 
0x080048A0  FF F7 EE FF 24 E0 40 49 88 42 08 D1 80 25 AD 02 
0x080048B0  28 00 FF F7 D6 FF 28 00 FF F7 D8 FF 18 E0 3B 49 
0x080048C0  88 42 08 D1 80 25 ED 02 28 00 FF F7 CA FF 28 00 
0x080048D0  FF F7 CC FF 0C E0 36 49 88 42 08 D1 80 25 2D 03 
0x080048E0  28 00 FF F7 BE FF 28 00 FF F7 C0 FF 00 E0 01 24 
0x080048F0  20 00 32 BD F8 B5 84 B0 05 00 0E 00 01 27 00 24 
0x08004900  FF F7 6E FF 00 28 3E D1 28 68 2A 49 01 40 B0 68 
0x08004910  08 43 31 69 01 43 70 69 08 43 F1 69 01 43 29 60 
0x08004920  F1 68 28 00 FF F7 68 FF B1 69 28 00 FF F7 6A FF 
0x08004930  1C 48 85 42 04 D1 03 20 00 F0 42 F9 04 00 11 E0 
0x08004940  19 48 85 42 04 D1 0C 20 00 F0 3A F9 04 00 09 E0 
0x08004950  16 48 85 42 02 D0 16 48 85 42 03 D1 01 A8 00 F0 
0x08004960  23 F9 03 9C 00 2C 0A D0 70 68 00 28 07 D0 00 27 
0x08004970  00 90 F3 69 32 68 21 00 28 00 FF F7 49 FF 31 68 
0x08004980  28 00 FF F7 32 FF 38 00 05 B0 F0 BD FF CF FF FF 
0x08004990  FF FC FF FF 20 59 00 08 F0 FF 00 00 2C 10 02 40 
0x080049A0  30 10 02 40 00 38 01 40 00 44 00 40 00 48 00 40 
0x080049B0  00 4C 00 40 F3 69 FF EF BF F3 4F 8F 0E 48 0F 49 
0x080049C0  08 60 BF F3 4F 8F 00 BF FD E7 00 00 70 B5 00 24 
0x080049D0  06 00 00 E0 64 1C 20 00 C0 B2 04 28 0A DC 08 49 
0x080049E0  C0 00 0D 18 29 68 30 00 00 F0 A0 F9 00 28 F1 D0 
0x080049F0  A8 88 70 BD 00 20 70 BD 04 00 FA 05 0C ED 00 E0 
0x08004A00  AC 59 00 08 80 B5 FF F7 E1 FF 01 00 0C D0 00 F0 
0x08004A10  DC FA 72 B6 00 F0 CE FA 05 48 FF F7 36 FF 00 20 
0x08004A20  04 49 08 60 FF F7 C8 FF 03 A0 FF F7 07 FD 01 BD 
0x08004A30  00 38 01 40 10 E0 00 E0 55 6E 6B 6E 6F 77 6E 20 
0x08004A40  43 6F 6D 6D 61 6E 64 2E 2E 2E 2E 2E 2E 0D 0A 00 
0x08004A50  70 B4 10 3A 03 D3 78 C9 10 3A 78 C0 FB D2 53 07 
0x08004A60  01 D3 18 C9 18 C0 01 D5 08 C9 08 C0 D2 07 04 D3 
0x08004A70  0B 88 03 80 89 1C 80 1C 00 2A 01 D5 0B 78 03 70 
0x08004A80  70 BC 70 47 00 22 03 0A 8B 42 0B D2 03 09 8B 42 
0x08004A90  19 D2 43 08 8B 42 2E D2 41 1A 00 D2 01 46 52 41 
0x08004AA0  10 46 70 47 FF 22 09 02 3F D0 12 06 8B 42 05 D3 
0x08004AB0  12 12 09 02 8B 42 01 D3 12 12 09 02 03 09 8B 42 
0x08004AC0  19 D3 00 E0 09 0A C3 09 8B 42 01 D3 CB 01 C0 1A 
0x08004AD0  52 41 83 09 8B 42 01 D3 8B 01 C0 1A 52 41 43 09 
0x08004AE0  8B 42 01 D3 4B 01 C0 1A 52 41 03 09 8B 42 01 D3 
0x08004AF0  0B 01 C0 1A 52 41 C3 08 8B 42 01 D3 CB 00 C0 1A 
0x08004B00  52 41 83 08 8B 42 01 D3 8B 00 C0 1A 52 41 43 08 
0x08004B10  8B 42 01 D3 4B 00 C0 1A 52 41 88 42 00 D3 40 1A 
0x08004B20  52 41 CF D2 01 46 10 46 70 47 08 B5 00 F0 AE FA 
0x08004B30  08 BD FE E7 48 48 00 68 81 0A 08 00 C0 07 C0 0F 
0x08004B40  70 47 46 48 00 68 41 08 08 00 C0 07 C0 0F 70 47 
0x08004B50  43 48 01 68 38 20 08 40 70 47 41 48 01 68 F0 20 
0x08004B60  00 01 08 40 70 47 3E 48 01 68 E0 20 C0 01 08 40 
0x08004B70  70 47 3C 49 09 68 01 40 00 04 08 43 70 47 47 48 
0x08004B80  00 68 00 0A 40 06 40 0E 70 47 44 48 00 68 40 0F 
0x08004B90  40 07 70 47 41 48 00 68 80 07 80 0F 70 47 3F 48 
0x08004BA0  01 68 70 20 08 40 70 47 10 B5 04 00 00 F0 5C F8 
0x08004BB0  20 60 00 F0 75 F8 60 60 00 F0 81 F8 A0 60 10 BD 
0x08004BC0  10 B5 00 24 03 28 1F D1 03 20 FF F7 D2 FF 50 49 
0x08004BD0  40 1A 26 D0 40 1E 02 D0 40 1E 06 D0 0C E0 FF F7 
0x08004BE0  A9 FF 01 28 35 D1 4B 4C 33 E0 FF F7 AA FF 01 28 
0x08004BF0  2F D1 80 24 24 02 2C E0 00 F0 36 F8 00 F0 50 F8 
0x08004C00  00 F0 5D F8 04 00 24 E0 0C 28 22 D1 0C 20 FF F7 
0x08004C10  B0 FF 41 49 40 1A 04 D0 00 1F 06 D0 00 1F 0A D0 
0x08004C20  10 E0 00 F0 21 F8 04 00 13 E0 FF F7 83 FF 01 28 
0x08004C30  0F D1 38 4C 0D E0 FF F7 84 FF 01 28 09 D1 80 24 
0x08004C40  24 02 06 E0 00 F0 10 F8 00 F0 2A F8 00 F0 37 F8 
0x08004C50  04 00 20 00 10 BD 00 00 00 10 02 40 5C 10 02 40 
0x08004C60  08 10 02 40 54 10 02 40 80 B5 FF F7 71 FF 08 28 
0x08004C70  02 D0 10 28 02 D0 04 E0 28 48 02 BD 00 F0 2C F8 
0x08004C80  02 BD 01 21 26 48 00 68 C0 0A 40 07 40 0F 81 40 
0x08004C90  20 48 FF F7 F7 FE 02 BD 00 00 00 00 0C 10 02 40 
0x08004CA0  10 B5 04 00 FF F7 59 FF 1E 49 00 0A 00 07 00 0F 
0x08004CB0  80 00 08 5C C0 06 C0 0E C4 40 20 00 10 BD 10 B5 
0x08004CC0  04 00 FF F7 50 FF 18 49 00 0B 80 00 08 5C C0 06 
0x08004CD0  C0 0E C4 40 20 00 10 BD 10 B5 FF F7 5B FF 03 28 
0x08004CE0  01 D1 0E 4C 00 E0 0B 4C FF F7 49 FF 44 43 FF F7 
0x08004CF0  56 FF 01 00 20 00 09 09 49 1C FF F7 C3 FE 04 00 
0x08004D00  FF F7 43 FF 41 0F 49 1C 20 00 FF F7 BB FE 10 BD 
0x08004D10  01 00 03 00 00 24 F4 00 04 00 0C 00 C0 FC 9B 01 
0x08004D20  00 10 02 40 A4 58 00 08 20 5A 00 08 70 B5 0D 78 
0x08004D30  00 2D 11 D0 0C 00 04 E0 49 1C 0E 78 96 42 07 D0 
0x08004D40  40 1C 29 00 00 F0 A4 F9 00 28 05 D0 01 00 23 00 
0x08004D50  5B 1C 1A 78 00 2A EF D1 70 BD FE E7 10 B4 02 00 
0x08004D60  00 23 18 00 02 E0 D4 5C 00 19 5B 1C 8B 42 FA D3 
0x08004D70  C0 B2 10 BC 70 47 38 B5 00 25 01 E0 6D 1C AD B2 
0x08004D80  80 2D 13 DA 68 42 04 01 92 48 20 18 01 88 92 4A 
0x08004D90  91 42 F3 D1 0F 21 FF F7 E1 FF 90 49 61 18 09 78 
0x08004DA0  81 42 EB D1 7F 20 40 1B 80 B2 32 BD 80 20 32 BD 
0x08004DB0  70 B5 8B 4C 80 23 10 22 21 00 8A 48 FF F7 3E FB 
0x08004DC0  00 21 08 00 01 E0 40 1C 80 B2 80 28 18 DA 02 01 
0x08004DD0  13 19 1B 88 84 4D AB 42 F5 D1 0B 00 0D 00 00 E0 
0x08004DE0  6D 1C 2E 00 B6 B2 10 2E 07 DA 2E 00 B6 B2 96 19 
0x08004DF0  36 19 36 78 FF 2E F3 D0 01 23 00 2B E3 D1 70 BD 
0x08004E00  80 20 70 BD 74 48 79 49 08 80 70 47 80 B5 00 22 
0x08004E10  10 21 76 48 FF F7 46 FC FF F7 F4 FF 01 BD 00 00 
0x08004E20  F8 B5 00 20 FF F7 A7 FF 04 00 80 2C 09 DA 10 22 
0x08004E30  6E 49 20 01 6A 4B C0 18 00 F0 64 FA FF F7 E2 FF 
0x08004E40  01 E0 FF F7 E3 FF 80 2C 02 DA 00 BF 74 A1 00 E0 
0x08004E50  75 A1 66 48 00 90 42 88 69 A0 FF F7 EF FA 64 4F 
0x08004E60  38 00 FF F7 EB FA 38 00 40 30 FF F7 E7 FA 38 00 
0x08004E70  80 30 FF F7 E3 FA 00 24 59 4D 21 E0 E0 10 00 0F 
0x08004E80  00 19 00 11 00 01 26 1A 00 2C 04 D0 00 2E 02 D1 
0x08004E90  58 A0 FF F7 D3 FA 00 2E 07 D1 00 98 40 88 00 01 
0x08004EA0  00 19 41 19 62 A0 FF F7 C9 FA 00 98 40 88 00 01 
0x08004EB0  00 19 40 19 01 78 00 BF 60 A0 FF F7 BF FA 64 1C 
0x08004EC0  10 2C DB DB 4B A0 FF F7 B9 FA 38 00 80 30 FF F7 
0x08004ED0  B5 FA 00 BF 5B A0 FF F7 B1 FA F1 BD F1 B5 82 B0 
0x08004EE0  42 4F 79 88 3A 00 00 26 33 00 34 00 00 E0 64 1C 
0x08004EF0  20 00 80 B2 0F 28 0C DC 08 01 25 00 AD B2 40 19 
0x08004F00  37 4D 40 19 00 78 15 00 6A 1C 2D 78 A8 42 EE D0 
0x08004F10  01 23 00 2B 03 D1 38 48 FF F7 90 FA F7 BD 68 46 
0x08004F20  00 89 34 00 FF F7 44 FF 05 00 80 28 01 D3 35 00 
0x08004F30  01 24 7D 80 0F 21 38 00 FF F7 10 FF F8 73 23 00 
0x08004F40  10 22 39 00 28 01 26 4C 00 19 00 F0 E7 F9 02 00 
0x08004F50  02 D0 00 BF 3D A1 00 E0 3E A1 F8 7B 00 90 2B 00 
0x08004F60  26 48 FF F7 6B FA F7 BD 10 B5 21 4C 20 00 C0 30 
0x08004F70  FF F7 64 FA 00 F0 23 F8 01 00 00 BF 37 A0 FF F7 
0x08004F80  5D FA 00 F0 1F F8 01 00 3A A0 FF F7 57 FA 20 00 
0x08004F90  80 30 FF F7 53 FA 00 BF 2A A0 FF F7 4F FA 10 BD 
0x08004FA0  80 B5 FF F7 3D FF FF F7 DF FF 01 BD 80 B5 FF F7 
0x08004FB0  F7 FF 01 BD 80 B5 00 20 FF F7 90 FF 01 BD 0B 48 
0x08004FC0  40 68 70 47 09 48 00 89 70 47 08 49 08 81 70 47 
0x08004FD0  00 00 00 00 F0 3F 00 08 36 2D 00 00 FF 3F 00 08 
0x08004FE0  00 38 00 08 80 59 00 08 FF FF 00 00 8C 00 00 20 
0x08004FF0  50 57 00 08 0D 0A 00 00 50 58 00 08 78 58 00 08 
0x08005000  25 73 20 49 41 50 20 50 61 72 61 6D 20 4F 4B 2E 
0x08005010  2E 2E 2E 2E 2E 49 6E 64 65 78 3A 25 75 0D 0A 00 
0x08005020  52 65 61 64 00 00 00 00 52 65 73 74 6F 72 65 00 
0x08005030  30 78 25 30 38 58 20 20 00 00 00 00 25 30 32 58 
0x08005040  20 00 00 00 0D 0A 0D 0A 00 00 00 00 45 72 72 6F 
0x08005050  72 00 00 00 53 75 63 63 65 65 64 00 46 69 72 6D 
0x08005060  77 61 72 65 20 53 69 7A 65 3A 20 25 75 42 79 74 
0x08005070  65 0D 0A 00 49 41 50 20 46 6C 61 67 20 20 20 20 
0x08005080  20 3A 20 25 30 34 58 0D 0A 00 00 00 70 47 FE E7 
0x08005090  C9 B2 02 78 8A 42 03 D0 40 1C 00 2A F9 D1 00 20 
0x080050A0  70 47 FE E7 00 20 66 49 CA 68 00 2A 07 D5 65 4A 
0x080050B0  0A 60 91 4A 0A 60 C9 68 00 29 00 D5 01 20 70 47 
0x080050C0  01 20 89 49 0A 68 80 23 1B 06 13 43 0B 60 09 68 
0x080050D0  00 29 00 D5 00 20 70 47 80 B5 C1 00 08 18 C0 00 
0x080050E0  06 21 FF F7 CF FC 01 00 00 91 7D 48 02 68 D2 03 
0x080050F0  06 D5 00 98 42 1E 00 92 00 28 F6 D1 01 20 02 BD 
0x08005100  03 68 78 4A 1A 40 7D 4B 03 60 00 2A 01 D0 02 20 
0x08005110  02 BD 00 91 01 68 49 03 06 D5 00 99 4A 1E 00 92 
0x08005120  00 29 F7 D1 03 20 02 BD 00 20 02 BD 10 B5 00 24 
0x08005130  04 E0 FA 20 C0 00 FF F7 CF FF 64 1C 20 00 C0 B2 
0x08005140  05 28 05 DA FF F7 AE FF 00 28 F2 D1 00 20 10 BD 
0x08005150  01 20 10 BD 10 B5 00 24 04 E0 FA 20 C0 00 FF F7 
0x08005160  BB FF 64 1C 20 00 C0 B2 05 28 05 DA FF F7 A8 FF 
0x08005170  00 28 F2 D1 00 20 10 BD 01 20 10 BD 5A 49 0B 68 
0x08005180  5A 4A 1A 40 C0 00 10 43 5D 4A 02 43 0A 60 70 47 
0x08005190  70 B4 57 A4 30 CC AB 42 01 D1 A2 42 14 D0 50 49 
0x080051A0  4C 68 01 25 25 43 4D 60 C0 24 24 06 8D 68 25 43 
0x080051B0  8D 60 52 4D 0D 60 02 60 BF F3 6F 8F 8E 68 34 43 
0x080051C0  8C 60 0D 60 00 1D 03 60 70 BC 70 47 F8 21 09 06 
0x080051D0  40 18 C0 0A 70 47 70 B5 04 00 00 25 FF 26 36 03 
0x080051E0  FF F7 A4 FF 00 28 01 D0 01 20 70 BD FA 20 C0 00 
0x080051F0  FF F7 72 FF 00 28 13 D0 FF F7 AC FF 02 20 70 BD 
0x08005200  20 00 FF F7 BB FF 36 48 01 68 C9 03 03 D5 31 00 
0x08005210  4E 1E 0A 29 F8 D2 41 68 02 22 91 43 41 60 6D 1C 
0x08005220  05 2D ED D3 03 D1 FF F7 95 FF 03 20 70 BD FF F7 
0x08005230  91 FF 00 28 01 D0 04 20 70 BD 00 20 70 BD 00 00 
0x08005240  08 20 02 40 23 01 67 45 F8 B5 04 00 0E 00 15 00 
0x08005250  00 27 FF F7 6B FF 00 28 01 D0 01 20 F2 BD FA 20 
0x08005260  C0 00 FF F7 39 FF 00 28 03 D0 FF F7 73 FF 02 20 
0x08005270  F2 BD E8 08 00 90 20 00 35 00 02 E0 08 30 08 35 
0x08005280  7F 1C 00 99 8F 42 22 D2 00 24 06 00 00 E0 64 1C 
0x08005290  05 2C 15 D2 0C CD 08 3D 30 00 FF F7 79 FF FA 20 
0x080052A0  C0 00 FF F7 19 FF 10 48 01 68 01 22 91 43 01 60 
0x080052B0  0C CE 08 3E 03 CD 08 3D 8B 42 E8 D1 82 42 E6 D1 
0x080052C0  30 00 05 2C DA D1 FF F7 45 FF 03 20 F2 BD FF F7 
0x080052D0  2D FF 00 28 01 D0 04 20 F2 BD 00 20 F2 BD 00 00 
0x080052E0  10 20 02 40 FA 83 00 00 14 20 02 40 07 E0 FF FF 
0x080052F0  FF FF FF FF FF FF FF FF AB 89 EF CD FB 83 00 00 
0x08005300  02 00 01 00 10 B4 00 23 04 E0 C4 18 24 78 0C 70 
0x08005310  49 1C 5B 1C 93 42 F8 D3 10 BC 70 47 70 B5 06 00 
0x08005320  0C 00 15 00 00 2B 07 D0 FF F7 50 FF FF F7 53 FF 
0x08005330  00 28 01 D0 05 20 70 BD 2A 00 21 00 30 00 FF F7 
0x08005340  83 FF 70 BD 10 B4 C2 00 18 23 13 40 FF 24 9C 40 
0x08005350  E2 43 89 01 C9 B2 99 40 03 00 08 D4 87 48 9B 08 
0x08005360  9B 00 C0 18 03 68 1A 40 11 43 01 60 0A E0 A1 4B 
0x08005370  00 07 00 0F 08 38 80 08 80 00 18 18 03 68 1A 40 
0x08005380  11 43 01 60 10 BC 70 47 9C 48 01 68 80 22 52 02 
0x08005390  0A 43 02 60 70 47 99 48 00 68 41 0C 08 00 C0 07 
0x080053A0  C0 0F 70 47 96 49 0A 68 07 23 9A 43 10 43 08 60 
0x080053B0  70 47 93 48 01 68 38 20 08 40 70 47 90 49 0A 68 
0x080053C0  90 4B 13 40 18 43 08 60 70 47 8D 49 0A 68 8E 4B 
0x080053D0  13 40 18 43 08 60 70 47 10 B4 89 4A 13 68 8B 4C 
0x080053E0  1C 40 20 43 01 43 11 60 10 BC 70 47 88 49 0A 68 
0x080053F0  03 0C 9A 43 80 B2 10 43 08 60 70 47 7F 48 01 68 
0x08005400  80 22 52 04 0A 43 02 60 70 47 7C 48 00 68 41 0E 
0x08005410  08 00 C0 07 C0 0F 70 47 70 B4 7E 4C 25 68 7E 4E 
0x08005420  2E 40 30 43 01 43 10 02 08 43 03 43 23 60 70 BC 
0x08005430  70 47 78 48 01 68 80 22 52 05 0A 43 02 60 70 47 
0x08005440  81 B0 76 49 0A 68 02 43 0A 60 09 68 08 40 00 90 
0x08005450  00 98 01 B0 70 47 81 B0 71 49 0A 68 02 43 0A 60 
0x08005460  09 68 08 40 00 90 00 98 01 B0 70 47 81 B0 6D 49 
0x08005470  0A 68 02 43 0A 60 09 68 08 40 00 90 00 98 01 B0 
0x08005480  70 47 69 49 0A 68 10 43 08 60 70 47 67 49 0A 68 
0x08005490  07 23 9A 43 10 43 08 60 70 47 64 48 00 68 40 07 
0x080054A0  40 0F 70 47 61 48 01 68 82 0D 0A 43 02 60 70 47 
0x080054B0  81 62 70 47 81 61 70 47 10 B5 4F 4C 5C 48 60 60 
0x080054C0  03 21 00 20 C0 43 FF F7 3D FF 00 20 A0 60 03 20 
0x080054D0  20 60 10 BD 38 B5 86 B0 18 22 00 21 68 46 00 F0 
0x080054E0  AF F8 01 20 FF F7 C2 FF A0 25 ED 05 80 24 24 02 
0x080054F0  21 00 28 00 FF F7 DE FF 00 94 01 20 01 90 00 21 
0x08005500  02 91 03 91 04 90 69 46 28 00 FF F7 30 F9 07 B0 
0x08005510  30 BD 80 B5 48 21 47 48 FF F7 CA FF FA 21 49 00 
0x08005520  45 48 00 F0 B6 F8 01 BD 80 B5 40 48 01 68 82 0D 
0x08005530  0A 43 02 60 00 F0 EA F8 A0 20 C0 00 00 F0 EE F8 
0x08005540  01 20 FF F7 88 FF 80 20 40 05 FF F7 79 FF C0 20 
0x08005550  C0 00 FF F7 96 FF 00 F0 13 F8 FF F7 AD FF FF F7 
0x08005560  B9 FF FE F7 55 FE 62 B6 FA 21 C9 00 32 48 00 F0 
0x08005570  90 F8 FF F7 1B FD 00 F0 6D F8 FC E7 00 E4 00 E0 
0x08005580  80 B5 02 20 FF F7 82 FF FF F7 87 FF 02 28 FB D1 
0x08005590  FF F7 88 FF FF F7 F8 FE FF F7 FD FE 01 28 FB D1 
0x080055A0  80 23 9B 05 10 22 20 21 03 20 FF F7 35 FF FF F7 
0x080055B0  25 FF FF F7 3E FF FF F7 28 FF 01 28 FB D1 00 20 
0x080055C0  FF F7 FC FE 02 20 FF F7 ED FE FF F7 F2 FE 10 28 
0x080055D0  FB D1 00 20 FF F7 F9 FE 18 48 00 F0 B3 F8 00 21 
0x080055E0  80 20 C0 04 FF F7 F8 FE C0 20 80 02 FF F7 FE FE 
0x080055F0  01 BD 00 00 1C ED 00 E0 10 E0 00 E0 00 10 02 40 
0x08005600  08 10 02 40 FF F0 FF FF FF 8F FF FF FF FF FF 88 
0x08005610  54 10 02 40 0C 10 02 40 8C 80 FF 1F 3C 10 02 40 
0x08005620  40 10 02 40 34 10 02 40 00 00 01 40 00 20 02 40 
0x08005630  27 23 00 00 00 38 01 40 13 55 00 08 00 A2 4A 04 
0x08005640  10 B5 04 00 08 00 11 00 02 00 20 00 FF F7 1A F8 
0x08005650  20 00 10 BD F8 B5 2C 4F 38 78 00 28 18 D0 18 20 
0x08005660  3D 5E 00 24 26 00 11 E0 B0 00 38 18 C1 69 00 29 
0x08005670  0B D0 2A 00 73 00 FB 18 9B 88 D2 1A 12 04 04 D4 
0x08005680  C4 61 38 78 40 1E 38 70 88 47 76 1C 0A 2E EB DB 
0x08005690  F1 BD F8 B4 00 29 02 D1 00 20 C0 43 31 E0 1A 4C 
0x080056A0  23 78 1A 00 0A 2A 00 DB FE E7 22 8B 51 18 00 22 
0x080056B0  D2 43 00 92 00 25 04 E0 00 9E B2 42 00 D1 2A 00 
0x080056C0  6D 1C 0A 2D 0D DA 26 00 1C 36 AF 00 F6 59 00 2E 
0x080056D0  F2 D0 07 00 BE 42 F3 D1 20 1D 6A 00 81 52 00 20 
0x080056E0  0F E0 00 25 ED 43 AA 42 01 D1 28 00 09 E0 25 00 
0x080056F0  1C 35 96 00 A8 51 20 1D 52 00 81 52 5B 1C 23 70 
0x08005700  01 20 F2 BC 70 47 00 00 48 00 00 20 80 B5 80 21 
0x08005710  C9 01 48 03 00 F0 07 F8 01 BD FE E7 05 49 01 43 
0x08005720  05 48 01 60 70 47 05 4A 0A 40 02 43 04 48 02 60 
0x08005730  70 47 00 00 00 00 FA 05 0C ED 00 E0 80 FF FF 1F 
0x08005740  08 ED 00 E0 01 49 08 60 70 47 00 00 00 00 00 20 
0x08005750  2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 
0x08005760  2D 2D 2D 2D 2D 2D 2D 20 41 70 70 20 50 61 72 61 
0x08005770  6D 20 49 6E 66 6F 20 2D 2D 2D 2D 2D 2D 2D 2D 2D 
0x08005780  2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 0D 0A 00 00 
0x08005790  20 20 20 20 20 20 20 20 20 20 20 20 30 30 20 30 
0x080057A0  31 20 30 32 20 30 33 20 30 34 20 30 35 20 30 36 
0x080057B0  20 30 37 20 30 38 20 30 39 20 30 41 20 30 42 20 
0x080057C0  30 43 20 30 44 20 30 45 20 30 46 20 20 0D 0A 00 
0x080057D0  2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 
0x080057E0  2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 
0x080057F0  2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 
0x08005800  2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 0D 0A 00 
0x08005810  2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 
0x08005820  2D 2D 2D 2D 2D 2D 20 53 79 73 74 65 6D 20 50 61 
0x08005830  72 61 6D 20 49 6E 66 6F 20 2D 2D 2D 2D 2D 2D 2D 
0x08005840  2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 0D 0A 00 
0x08005850  53 61 76 65 20 49 61 70 20 50 72 61 6D 20 53 61 
0x08005860  6D 65 2E 2E 2E 2E 2E 2E 49 6E 64 65 78 3A 25 30 
0x08005870  32 75 0D 0A 00 00 00 00 53 61 76 65 20 50 72 61 
0x08005880  6D 20 25 73 2E 2E 2E 2E 2E 2E 52 65 73 3A 25 75 
0x08005890  20 49 6E 64 65 78 3A 25 75 20 43 52 43 3A 25 58 
0x080058A0  0D 0A 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x080058B0  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x080058C0  00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00 
0x080058D0  04 00 00 00 06 00 00 00 07 00 00 00 08 00 00 00 
0x080058E0  09 00 00 00 70 B4 01 23 00 24 13 E0 01 68 00 1D 
0x080058F0  19 42 02 D0 4D 46 6D 1E 49 19 0C 60 09 1D 12 1F 
0x08005900  04 2A FA D2 0D 00 96 07 01 D5 0C 80 AD 1C 1A 40 
0x08005910  00 D0 2C 70 02 68 00 1D 00 2A E7 D1 70 BC 70 47 
0x08005920  01 00 00 00 02 00 00 00 04 00 00 00 06 00 00 00 
0x08005930  08 00 00 00 0A 00 00 00 0C 00 00 00 10 00 00 00 
0x08005940  20 00 00 00 40 00 00 00 80 00 00 00 00 01 00 00 
0x08005950  30 B4 01 22 0E E0 03 68 C3 18 44 68 08 30 14 42 
0x08005960  02 D0 4D 46 6D 1E 64 19 1D 68 25 60 1B 1D 24 1D 
0x08005970  09 1F F9 D1 01 68 00 1D 00 29 EC D1 30 BC 70 47 
0x08005980  57 2D 73 74 61 72 74 41 64 64 72 3A 25 58 20 62 
0x08005990  6C 61 63 6B 53 69 7A 65 3A 25 75 20 62 6C 61 63 
0x080059A0  6B 43 6F 75 6E 74 3A 25 75 0D 0A 00 B4 5A 00 08 
0x080059B0  EE EE 00 00 C0 5A 00 08 DD DD 00 00 CC 5A 00 08 
0x080059C0  CC CC 00 00 D8 5A 00 08 FF FF 00 00 E4 5A 00 08 
0x080059D0  5A 5A 00 00 10 B5 07 49 79 44 18 31 06 4C 7C 44 
0x080059E0  16 34 04 E0 08 1D 0A 68 89 18 88 47 01 00 A1 42 
0x080059F0  F8 D1 10 BD 08 00 00 00 28 00 00 00 E9 FE FF FF 
0x08005A00  98 00 00 00 04 00 00 20 00 00 00 00 45 FF FF FF 
0x08005A10  04 00 00 00 E8 00 00 00 00 00 00 20 00 00 00 00 
0x08005A20  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x08005A30  01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 
0x08005A40  00 F0 0D F8 00 28 01 D0 FF F7 C4 FF 00 BF 00 BF 
0x08005A50  00 20 00 BF 00 BF FF F7 67 FD 00 F0 02 F8 01 20 
0x08005A60  70 47 80 B5 00 F0 02 F8 01 BD FE E7 07 46 38 46 
0x08005A70  00 F0 02 F8 FB E7 FE E7 80 B5 00 BF 00 BF 02 4A 
0x08005A80  11 00 18 20 AB BE FB E7 26 00 02 00 70 47 70 47 
0x08005A90  70 47 70 47 02 48 01 88 49 1C 01 80 70 47 00 00 
0x08005AA0  60 00 00 20 01 48 80 47 01 48 00 47 25 5B 00 08 
0x08005AB0  F1 5A 00 08 69 61 70 3A 75 70 64 61 74 65 00 00 
0x08005AC0  69 61 70 3A 75 70 6C 6F 61 64 00 00 69 61 70 3A 
0x08005AD0  65 72 61 73 65 00 00 00 69 61 70 3A 6D 65 6E 75 
0x08005AE0  00 00 00 00 69 61 70 3A 72 75 6E 61 70 70 00 00 
0x08005AF0  00 BF 00 BF 00 BF 00 BF FF F7 A2 FF 00 24 F4 00 
0x08005B00  FE E7 FE E7 FE E7 FE E7 FE E7 FE E7 FE E7 FE E7 
0x08005B10  FE E7 FE E7 FE E7 FE E7 FE E7 FE E7 FE E7 FE E7 
0x08005B20  FE E7 00 00 70 47 00 00 00 00 00 00 00 00 00 00 
0x08005B30  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x08005B40  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x08005B50  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x08005B60  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 
0x08005B70  00 00 00 00 00 00 
-------------------------------------------------------------******************* Bootloader Main Menu ******************
Software Version: 2.6.37
Compiler Date   : May 26 2025 14:29:44
***********************************************************

在这里插入图片描述

  • 擦除应用程序
Erase Flash Page:08/18  Addr:0x08004000~0x080047FF Success......
Erase Flash Page:09/18  Addr:0x08004800~0x08004FFF Success......
Erase Flash Page:10/18  Addr:0x08005000~0x080057FF Success......
Erase Flash Page:11/18  Addr:0x08005800~0x08005FFF Success......
Erase Flash Page:12/18  Addr:0x08006000~0x080067FF Success......
Erase Flash Page:13/18  Addr:0x08006800~0x08006FFF Success......
Erase Flash Page:14/18  Addr:0x08007000~0x080077FF Success......
Erase Flash Page:15/18  Addr:0x08007800~0x08007FFF Success......
Erase Flash Page:16/18  Addr:0x08008000~0x080087FF Success......
Erase Flash Page:17/18  Addr:0x08008800~0x08008FFF Success......
Erase Flash Page:18/18  Addr:0x08009000~0x080097FF Success......
Erase Flash Success......Res:0 ******************* Bootloader Main Menu ******************
Software Version: 2.6.37
Compiler Date   : May 26 2025 14:29:44
***********************************************************

在这里插入图片描述

有疑问欢迎加交流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/907076.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins实践(6):配置“构建历史的显示名称,加上包名等信息“

Jenkins实践(6):配置“构建历史的显示名称,加上包名等信息“ 版本:Jenkins 4.262.2 需求:想要在构建历史中展示,本次运行的是哪个版本或哪个包 操作步骤: 1、先安装插件Build Name and Description Setter 2、Set Build Name 3、构建历史处查看展示 插件特性说明 安装依赖…

快速解决azure aks aad身份和权限问题

现状分析 AKS cluster 1.31.8启用aad 身份验证和kubernetes RBAC 当尝试执行kubectl get node命令时&#xff0c;系统返回以下错误信息&#xff1a; Error from server (Forbidden): nodes is forbidden: User "357517e8-4df5-4daa-88b4-94a84d763ec5" cannot list…

【玩转腾讯混元大模型】腾讯混元大模型AIGC系列产品深度体验

【玩转腾讯混元大模型】腾讯混元大模型AIGC系列产品深度体验 腾讯推出的系列AI产品&#xff1a;混元大模型、大模型图像创作引擎、大模型视频创作引擎、腾讯元宝&#xff0c;共同构成了一个强大的AI生态系统&#xff1b;凭借腾讯自研的大规模预训练技术和先进的自然语言处理、计…

(自用)Java学习-5.13(Redis,OSS)

核心功能实现 1. 类别导航动态加载 前端实现&#xff1a; // 加载一级分类 $.ajax({url: /category/showFirstMenu?pid0,success: function(resp) {resp.forEach(item > {$(".index-menu").append(<li onmouseover"showSecondMenu(${item.id})">…

2025电工杯A题电工杯数学建模思路代码文章教学:光伏电站发电功率日前预测问题

完整内容请看文章最下面的推广群 已更新数据、思路和模型 问题1&#xff1a;基于历史功率的光伏电站发电特性分析 建模与求解思路&#xff1a; 首先&#xff0c;需要收集光伏电站的历史发电功率数据、地理位置信息&#xff08;经纬度、海拔、倾角等&#xff09;以及太阳辐照…

Visual Studio 调试中 PDB 与图像不匹配

Visual Studio 调试中 PDB 与图像不匹配 在使用 Visual Studio 进行本地或远程调试时&#xff0c;很多开发者会遇到 PDB 加载失败、符号不匹配的问题&#xff0c;甚至程序进程未退出&#xff0c;导致 .exe 文件无法成功覆盖。本文详细解析了从后台进程清理、构建产物验证、模块…

WebRTC:实时通信的未来之路

WebRTC&#xff1a;实时通信的未来之路 目录 WebRTC&#xff1a;实时通信的未来之路一、背景介绍二、使用方式三、前途展望 一、背景介绍 随着互联网的飞速发展&#xff0c;实时音视频通信需求日益增长。传统的音视频通信多依赖于专有协议和插件&#xff08;如Flash、ActiveX等…

华为OD机试真题——猴子吃桃/爱吃蟠桃的孙悟空(2025B卷:200分)Java/python/JavaScript/C++/C语言/GO六种最佳实现

2025 B卷 200分 题型 本文涵盖详细的问题分析、解题思路、代码实现、代码详解、测试用例以及综合分析; 并提供Java、python、JavaScript、C++、C语言、GO六种语言的最佳实现方式! 本文收录于专栏:《2025华为OD真题目录+全流程解析/备考攻略/经验分享》 华为OD机试真题《猴子…

【Java学习笔记】单例设计模式

单例设计模式 单例模式介绍 1. 所谓类的单例设计模式&#xff0c;就是采取一定的方法保证在整个的软件系统中 &#xff08;1&#xff09;对某个类只能存在一个对象实例 &#xff08;2&#xff09;并且该类只提供一个取得对象实例的方法 2. 分类&#xff08;两种方式&#xf…

vue实例 与组件实例

vue实例 与组件实例流程图 &#x1f9e9; 基本解释 ✅ Vue 实例 Vue 实例是通过 new Vue({…}) 创建的对象&#xff0c;是整个应用的根节点。 const vm new Vue({el: #app,data: { msg: Hello Vue } });是整个应用的起点。只有一个根 Vue 实例&#xff08;通常&#xff09;…

Hive 分桶(Bucketing)深度解析:原理、实战与核心概念对比

一、分桶的意义&#xff1a;比分区更细的粒度管理 1.1 解决分区数据不均匀问题 分区的局限性&#xff1a;分区基于表外字段&#xff08;如时间字段&#xff09;划分数据&#xff0c;但可能导致部分分区数据量过大&#xff0c;部分过小&#xff0c;无法进一步细化。 分桶的定…

pytest+allure+allure-pytest 报告输出遇到的问题汇总

文章目录 前言问题一&#xff1a;module allure has no attribute severity_level问题二&#xff1a;ERROR:file or directory not found: ‐vs问题三&#xff1a;生成的 html 报告是空的&#xff0c;明明有测试用例执行完成&#xff0c;但报告没有显示数据 前言 pytestallure…

升级node@22后运行npm install报错 distutils not found

从node20升级到node22后&#xff0c;在运行 npm install 的时候报了很多 gyp 错误&#xff0c;其中包括 npm error npm error ModuleNotFoundError: No module named distutils。 问题原因是我在使用 brew install node22 的过程中自动把 python 升级到了 3.13。而 distutils …

IPD流程落地:项目任务书Charter开发

目录 简介 第一个方面&#xff0c;回答的是Why的问题。 第二点&#xff0c;要回答做什么的问题&#xff0c;也就是产品定义What的问题。 第三点就是要回答执行策略与计划的问题&#xff0c;也就是How、When、Who的问题。 第四点是对上述这些分析的总结分析&#xff0c;要为…

Qt popup窗口半透明背景

半透明弹窗需要paintEvent()接口支持 方法一&#xff1a;使用setStyleSheet设置半透明样式&#xff0c;如果是子窗口&#xff0c;则可注释构建函数内属性设置 class TranslucentWidget : public QWidget { public: explicit TranslucentWidget(QWidget *parent nullptr)…

Excel快捷键大全

Excel快捷键 工作表操作快速选择区域快速跳转/视图操作单元格公式批量填充与编辑功能键打开/关闭工作簿 工作表操作 快捷键功能ShiftF11(或Alt→H→I→S)默认插入新工作表到当前工作表左侧的左侧Alt→E→L→Enter删除当前工作表&#xff0c;删除后不可销&#xff0c;须谨慎操作…

SQLMesh 用户定义变量详解:从全局到局部的全方位配置指南

SQLMesh 提供了灵活的多层级变量系统&#xff0c;支持从全局配置到模型局部作用域的变量定义。本文将详细介绍 SQLMesh 的四类用户定义变量&#xff08;global、gateway、blueprint 和 local&#xff09;以及宏函数的使用方法。 一、变量类型概述 SQLMesh 支持四种用户定义变量…

爬虫学习-Scrape Center spa6 超简单 JS 逆向

关卡 spa6 电影数据网站&#xff0c;无反爬&#xff0c;数据通过 Ajax 加载&#xff0c;数据接口参数加密且有时间限制&#xff0c;适合动态页面渲染爬取或 JavaScript 逆向分析。 首先抓包发现get请求的参数token有加密。 offset表示翻页&#xff0c;limit表示每一页有多少…

webtrees——在线协作家谱

webtrees——在线协作家谱 内容 执照编码风格和标准介绍系统要求互联网浏览器兼容性安装升级建设与发展Gedcom&#xff08;家谱&#xff09;文件安全备份从备份还原 执照 webtrees&#xff1a;在线家谱版权所有 2022 webtrees 开发团队 该程序是免费软件&#xff1a;您可以根据…

day 37

模型的保存和加载 仅保存模型参数 - 原理&#xff1a;保存模型的权重参数&#xff0c;不保存模型结构代码。加载时需提前定义与训练时一致的模型类。 - 优点&#xff1a;文件体积小&#xff08;仅含参数&#xff09;&#xff0c;跨框架兼容性强&#xff08;需自行定义模型结…