#include "bootloader.h" #include "board_config.h" #include "gd32e23x.h" #include "uart_ring_buffer.h" #include "systick.h" uint8_t ymodem_rx_buffer[YMODEM_RX_BUFFER_SIZE] = {0}; uint16_t ymodem_rx_count = 0; static uint8_t temp_buffer[PACKET_1K_SIZE]; // 临时缓冲区,用于接收数据包 /** * @brief 擦除Flash页面(适配同事的flash_earse函数) * @param page_address 要擦除的页面地址 * @return 擦除结果状态 */ uint8_t flash_erase_page(uint32_t page_address) { fmc_state_enum fmc_state = FMC_READY; // 清除Flash状态标志 fmc_flag_clear(FMC_FLAG_BUSY | FMC_FLAG_PGERR | FMC_FLAG_PGAERR | FMC_FLAG_WPERR | FMC_FLAG_END); // 解锁Flash fmc_unlock(); // 执行页面擦除 fmc_state = fmc_page_erase(page_address); // 返回结果(0=成功,1=失败) return (fmc_state == FMC_READY) ? 0 : 1; } /** * @brief 写入数据到Flash(适配同事的write_data函数) * @param flash_address Flash地址指针(会被更新) * @param data 要写入的数据指针 * @param data_length 数据长度(以32位字为单位) * @return 写入结果:0=成功,1=写入错误,2=验证错误 */ uint8_t flash_write_data(__IO uint32_t* flash_address, uint32_t* data, uint32_t data_length) { uint32_t i = 0; // 清除Flash状态标志(可选,根据需要启用) // fmc_flag_clear(FMC_FLAG_PGERR | FMC_FLAG_PGAERR | FMC_FLAG_WPERR | FMC_FLAG_END); // 逐字写入数据 for (i = 0; (i < data_length) && (*flash_address <= (APP_FLASH_END_ADDRESS - 4)); i++) { // 写入32位数据到Flash if (fmc_word_program(*flash_address, *(uint32_t*)(data + i)) == FMC_READY) { // 验证写入的数据 if (*(uint32_t*)*flash_address != *(uint32_t*)(data + i)) { // Flash内容与写入数据不匹配 return 2; } // 增加Flash地址指针(下一个32位字) *flash_address += 4; } else { // Flash写入过程中发生错误 return 1; } } // 写入成功 return 0; } /** * @brief Check flash flag and jump to application if valid * @param buf Pointer to flash memory location to check * @return uint8_t 1=stay in bootloader, 0=jumped to application (won't return) */ uint8_t check_flash_and_jump(uint8_t *buf) { uint32_t jump_address; pFunction jump_to_application; if (*buf == 0xFF) { // Flash为空,继续bootloader模式 return 1; } fmc_lock(); // 锁定FMC以防止意外修改 // 读取应用程序的栈指针和复位向量 jump_address = *(__IO uint32_t*)(APPLICATION_ADDRESS + 4); // 验证栈指针是否有效(应该在SRAM范围内) // if ((app_stack_pointer & 0xFFF00000) != 0x20000000) { // // 栈指针无效,继续bootloader模式 // return 1; // } // 验证跳转地址是否有效(应该在Flash应用程序区域内且为奇数-Thumb模式) // if ((jump_address < APPLICATION_ADDRESS) || // (jump_address > 0x08010000) || // 假设Flash大小为64KB // ((jump_address & 0x01) == 0)) { // Thumb模式地址应为奇数 // // 跳转地址无效,继续bootloader模式 // return 1; // } /* Ensure flash operations are complete */ /* Get application reset vector */ jump_address = *(__IO uint32_t*)(APPLICATION_ADDRESS + 4); /* Basic validity check - reset vector should be in flash and odd (Thumb mode) */ // if ((jump_address < APPLICATION_ADDRESS) || ((jump_address & 0x01) == 0)) { // /* Invalid jump address, stay in bootloader */ // return 1; // } /* Create function pointer */ jump_to_application = (pFunction)jump_address; /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t*)APPLICATION_ADDRESS); /* Disable interrupts for safe transition */ __disable_irq(); /* Jump to user application - this function will not return */ jump_to_application(); /* Should never reach here */ return 0; /* Should never reach here */ } /** * @brief Convert string to integer (supports hex, decimal, K, M suffixes) * @param input_str Input string to convert * @param int_num Pointer to store converted integer * @return 1 if successful, 0 if failed */ uint32_t str_to_int(uint8_t *input_str, int32_t *int_num) { uint32_t i = 0, res = 0; uint32_t val = 0; if (input_str[0] == '0' && (input_str[1] == 'x' || input_str[1] == 'X')) { // Hexadecimal input if (input_str[2] == '\0') { return 0; } for (i = 2; i < 11; i++) { if (input_str[i] == '\0') { *int_num = val; res = 1; break; } if (ISVALIDHEX(input_str[i])) { val = (val << 4) + CONVERTHEX(input_str[i]); } else { res = 0; break; } } if (i >= 11) { res = 0; // Over 8 digit hex - invalid } } else { // Decimal input (max 10-digit) for (i = 0; i < 11; i++) { if (input_str[i] == '\0') { *int_num = val; res = 1; break; } else if ((input_str[i] == 'k' || input_str[i] == 'K') && (i > 0)) { val = val << 10; // Multiply by 1024 *int_num = val; res = 1; break; } else if ((input_str[i] == 'm' || input_str[i] == 'M') && (i > 0)) { val = val << 20; // Multiply by 1024*1024 *int_num = val; res = 1; break; } else if (ISVALIDDEC(input_str[i])) { val = val * 10 + CONVERTDEC(input_str[i]); } else { res = 0; break; } } if (i >= 11) { res = 0; // Over 10 digit decimal - invalid } } return res; } /** * @brief Update CRC16 value with a single byte * @param crc_in Current CRC value * @param byte Byte to process * @return Updated CRC value */ uint16_t crc16_update(uint16_t crc_in, uint8_t byte) { uint32_t crc = crc_in; uint32_t in = byte | 0x100; do { crc <<= 1; in <<= 1; if (in & 0x100) { ++crc; } if (crc & 0x10000) { crc ^= 0x1021; } } while (!(in & 0x10000)); return crc & 0xFFFFU; } /** * @brief Calculate CRC16 for data buffer * @param data Pointer to data buffer * @param size Size of data in bytes * @return Calculated CRC16 value */ uint16_t crc16_calculate(const uint8_t* data, uint32_t size) { uint32_t crc = 0; const uint8_t* data_end = data + size; while (data < data_end) { crc = crc16_update(crc, *data++); } crc = crc16_update(crc, 0); crc = crc16_update(crc, 0); return crc & 0xFFFFU; } /** * @brief 接收Ymodem数据包数据 * 等待并读取完整的数据包到缓冲区中 * 该函数保持与原始实现相同的行为逻辑 */ void ymodem_read_packet_data(void) { // 重置接收计数器 ymodem_rx_count = 0; // 等待数据到达(阻塞等待) while (uart_ring_buffer_available() <= 0) { // 可选:发送确认字节(当前被禁用) // ymodem_send_response(YMODEM_ACK); delay_ms(1000); // 等待1秒后重新检查 } // 等待数据传输完成,确保接收到完整数据包 delay_ms(200); // 读取环形缓冲区中的所有可用数据 while (uart_ring_buffer_available() > 0) { int received_byte = uart_ring_buffer_get(); if (received_byte >= 0) { ymodem_rx_buffer[ymodem_rx_count++] = (uint8_t)received_byte; } } } /** * @brief Ymodem接收函数(直接移植同事的逻辑) * @param buf 未使用(保持接口兼容) * @return 接收的文件大小,负数表示错误 */ int32_t ymodem_receive(uint8_t *buf) { uint8_t file_size[FILE_SIZE_LENGTH], *file_ptr; int32_t i, j = 0, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0, isize = 0, singledata = 0; uint32_t flash_destination, ram_source; uint8_t temp = 0, eot_flag = 0, crc_high = 0, crc_low = 0; uint16_t crc_value = 0; uint32_t erase_page = APPLICATION_ADDRESS; // 从应用程序地址开始擦除 uint8_t pack = 1; // 解锁Flash并擦除应用程序区域 fmc_unlock(); flash_destination = APPLICATION_ADDRESS; // 擦除应用程序区域(从APPLICATION_ADDRESS到FLASH_END_ADDRESS) for (; erase_page < FLASH_END_ADDRESS; erase_page += 1024) { flash_erase_page(erase_page); } temp = 0; // 发送CRC16请求,等待数据 while (uart_ring_buffer_available() <= 0) { rs485_send_byte(CRC16); delay_ms(1000); } delay_ms(200); // 读取第一个数据包 ymodem_read_packet_data(); // 主循环 for (session_done = 0, errors = 0, session_begin = 0;;) { for (packets_received = 0, file_done = 0;;) { delay_ms(2000); switch (temp) { case 0: // 处理文件头数据包 if (ymodem_rx_buffer[0] == SOH) { // 128字节数据包 // 验证包序号 if (ymodem_rx_buffer[1] != ((ymodem_rx_buffer[2] ^ 0xFF) & 0xFF)) break; if (ymodem_rx_buffer[3] != 0) { // 有文件信息 // 提取文件名 for (i = 0, file_ptr = ymodem_rx_buffer + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);) { file_ptr++; } // 提取文件大小 for (i = 0, file_ptr++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH);) { file_size[i++] = *file_ptr++; } file_size[i++] = '\0'; // 转换文件大小 str_to_int(file_size, &size); // 计算需要的1K数据包数量 isize = size / PACKET_1K_SIZE; singledata = size - (isize * PACKET_1K_SIZE); // 验证CRC crc_value = crc16_calculate(&ymodem_rx_buffer[3], 128); crc_low = crc_value & 0xFF; crc_value >>= 8; crc_high = crc_value & 0xFF; if (crc_high != ymodem_rx_buffer[131] || crc_low != ymodem_rx_buffer[132]) { ymodem_rx_count = 0; ymodem_rx_buffer[0] = 0; rs485_send_byte(NAK); ymodem_read_packet_data(); break; } temp = 1; ymodem_rx_count = 0; ymodem_rx_buffer[0] = 0; rs485_send_byte(ACK); rs485_send_byte(CRC16); ymodem_read_packet_data(); } } else if (ymodem_rx_buffer[0] == CA) { // 取消传输 if (ymodem_rx_buffer[1] == CA && ymodem_rx_buffer[2] == CA && ymodem_rx_buffer[3] == CA && ymodem_rx_buffer[4] == CA) { ymodem_rx_count = 0; ymodem_rx_buffer[0] = 0; rs485_send_byte(ACK); temp = 0; } ymodem_rx_count = 0; return -3; } break; case 1: // 处理数据包 if (ymodem_rx_buffer[0] == STX) { // 1K字节数据包 // 验证包序号 if (ymodem_rx_buffer[1] != ((ymodem_rx_buffer[2] ^ 0xFF) & 0xFF) && ymodem_rx_buffer[1] == pack) { ymodem_rx_count = 0; ymodem_rx_buffer[0] = 0; rs485_send_byte(NAK); break; } // 验证CRC crc_value = crc16_calculate(&ymodem_rx_buffer[3], PACKET_1K_SIZE); crc_low = crc_value & 0xFF; crc_value >>= 8; crc_high = crc_value & 0xFF; if (crc_high != ymodem_rx_buffer[PACKET_1K_SIZE + 3] || crc_low != ymodem_rx_buffer[PACKET_1K_SIZE + 4]) { ymodem_rx_count = 0; ymodem_rx_buffer[0] = 0; rs485_send_byte(NAK); break; } // 处理单独数据(最后一包可能不满1K) if (singledata != 0) { // 预留处理不完整数据包的逻辑 } // 复制数据到临时缓冲区 memcpy(temp_buffer, ymodem_rx_buffer + PACKET_HEADER, PACKET_1K_SIZE); ram_source = (uint32_t)temp_buffer; fmc_unlock(); // 写入Flash if (flash_write_data(&flash_destination, (uint32_t*)ram_source, PACKET_1K_SIZE) == 0) { isize--; ymodem_rx_count = 0; ymodem_rx_buffer[0] = 0; pack++; rs485_send_byte(ACK); // 如果是最后一包,写入应用程序标志 if (isize == 1) { fmc_unlock(); // flash_write_app_flag(); fmc_word_program(FLASH_FLAG_ADDRESS, 0xEEEE); } ymodem_read_packet_data(); } else { rs485_send_byte(CA); rs485_send_byte(CA); temp = 0; ymodem_rx_count = 0; return -2; } } else if (ymodem_rx_buffer[0] == EOT) { // 传输结束 if (eot_flag == 1) { eot_flag = 0; ymodem_rx_count = 0; ymodem_rx_buffer[0] = 0; rs485_send_byte(ACK); rs485_send_byte(CRC16); ymodem_read_packet_data(); temp = 3; } ymodem_rx_count = 0; ymodem_rx_buffer[0] = 0; rs485_send_byte(ACK); temp = 3; } else if (ymodem_rx_buffer[0] == CA) { // 取消传输 if (ymodem_rx_buffer[1] == CA && ymodem_rx_buffer[2] == CA && ymodem_rx_buffer[3] == CA && ymodem_rx_buffer[4] == CA) { ymodem_rx_count = 0; ymodem_rx_buffer[0] = 0; rs485_send_byte(ACK); temp = 0; } ymodem_rx_count = 0; return -3; } ymodem_rx_count = 0; break; case 3: // 传输完成 temp = 0; fmc_lock(); ymodem_rx_count = 0; ymodem_rx_buffer[0] = 0; rs485_send_byte(ACK); ymodem_rx_count = 0; return size; } } } }