/************************************************************************************************ * Include * ************************************************************************************************/ #include "iap.h" #include "can_id_deal.h" #include "flash.h" #include "queue.h" #include #include /************************************************************************************************ * Config * ************************************************************************************************/ extern uint8_t jump_flag; uint8_t can_rx_flag; // extern can_receive_message receive_iap_message; static uint16_t jump_boot_time = 0; uint8_t send_buff[8] = {0, 0, 0, 0, 0, 0, 0, 0}; unsigned char recv_crc[2]; unsigned char recvdata_ema[204]; unsigned char recvdata_buffer[210]; #define SW_VER 0x2446 #define SW_VER_HI_ASCII ((('0' + ((uint8_t)((SW_VER >> 8) & 0x000F))) << 8) | \ ('0' + ((uint8_t)((SW_VER >> 12) & 0x000F)))) #define SW_VER_L0_ASCII ((('0' + ((uint8_t)(SW_VER & 0x000F))) << 8) | \ ('0' + ((uint8_t)((SW_VER >> 4) & 0x000F)))) #define PACK_TYPE 1 #define PACK_TYPE_ASCII ((('0' + PACK_TYPE) << 8) | ('0')) uint16_t firm_ver[UPGRADE_APP_DATA_SIZE] = {IAP_CMD_JUMP_OVER, SW_VER_HI_ASCII, SW_VER_L0_ASCII, 0xFFFF}; uint16_t firm_ver_buff[UPGRADE_BUFF_DATA_SIZE] = {0}; uint8_t iap_disconnect_count = 0; /************************************************************************************************ * Data structs * ************************************************************************************************/ iap_type g_iap; upgrade_param upgrade; /************************************************************************************************ * implements * ************************************************************************************************/ void invert_uint8() { } void iap_connect_clear(void) { iap_disconnect_count = 0; send_buff[0] = 0x00; send_buff[1] = 0x00; send_buff[2] = 0x00; send_buff[3] = 0x00; send_buff[4] = 0x00; send_buff[5] = 0x00; send_buff[6] = 0x00; send_buff[7] = 0x00; } void iap_disconnect_check(void) { if (++iap_disconnect_count >= 5) { iap_disconnect_count = 5; } } // iap相关参数初始化 void iap_param_init(void) { g_iap.recv_len = 0; g_iap.total_packages = 0; g_iap.current_packages = 0; g_iap.crc16 = 0xFFFF; g_iap.total_bytes = 0; g_iap.count_bytes = 0; g_iap.count_packages = 0; g_iap.firmware_crc16 = 0; g_iap.firmware_ver = 0; } // 清除升级信息标志位 void set_firmver(void) { fmc_clear_flag_star(); fmc_read_n_half_word(UPGRADE_FLAG_START_ADDR, firm_ver_buff, UPGRADE_BUFF_DATA_SIZE); fmc_erase_pages(UPGRADE_FLAG_START_ADDR, 1); for (uint8_t i = 0; i < UPGRADE_APP_DATA_SIZE; i++) { firm_ver_buff[i + UPGRADE_FLAG_DATA_SIZE] = firm_ver[i]; } fmc_write_n_half_word(UPGRADE_FLAG_START_ADDR, firm_ver_buff, UPGRADE_BUFF_DATA_SIZE); fmc_clear_flag_end(); } void iap_flag_release(void) { fmc_read_n_half_word(UPGRADE_FLAG_START_ADDR, upgrade.infor_buf, UPGRADE_FLAG_DATA_SIZE); if (upgrade.param.sign == UPGRADE_SIGN) { fmc_clear_flag_star(); fmc_erase_pages(UPGRADE_FLAG_START_ADDR, 1); fmc_write_n_half_word(UPGRADE_FLAG_START_ADDR + (UPGRADE_FLAG_DATA_SIZE * 2), firm_ver, UPGRADE_APP_DATA_SIZE); fmc_clear_flag_end(); for (uint8_t i = 0; i < (UPGRADE_APP_DATA_SIZE * 2); i++) { send_buff[i] = fmc_read_byte(UPGRADE_FLAG_START_ADDR + (UPGRADE_FLAG_DATA_SIZE * 2) + i); } can_msg_tx(0x18000001, CAN_Id_Extended, send_buff, 8); CAN_ITConfig(CAN1, CAN_IT_TME, ENABLE); } } uint8_t erase_app_flash(uint32_t start_address, uint32_t end_addr) { uint8_t status = 0; uint16_t page_len = 0; // page_len = (end_addr - start_address) / FMC_PAGE_SIZE; if ((start_address == ADDR_FLASH_SECTOR_2)) { status = fmc_erase_pages(start_address, 5); } else if ((start_address == ADDR_FLASH_SECTOR_8)) { status = fmc_erase_pages(start_address, 3); } else { status = 1; } return status; } void jump_boot_time_ctrl(void) { if (jump_boot_time > 0) { jump_boot_time--; if (jump_boot_time == 0) { // jump_flag = 1; __set_FAULTMASK(1); // 关闭所有中断 NVIC_SystemReset(); // 复位 } } } void write_app_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num) { static uint32_t w_start_addr = 0; w_start_addr = pack_num * 6 + APP_START_ADDR; fmc_write_n_half_word(w_start_addr, buf, pack_len); } void read_app_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num) { static uint32_t w_start_addr = 0; w_start_addr = pack_num * 6 + APP_START_ADDR; fmc_read_n_half_word(w_start_addr, buf, pack_len); } uint8_t write_download_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num) { uint8_t status = 0; static uint32_t w_start_addr = 0; w_start_addr = pack_num * 6 + DOWNLOAD_START_ADDR; status = fmc_write_n_half_word(w_start_addr, buf, pack_len); return status; } void read_download_flash(uint16_t *buf, uint16_t pack_len, uint16_t pack_num) { static uint32_t w_start_addr = 0; w_start_addr = pack_num * 6 + DOWNLOAD_START_ADDR; fmc_read_n_half_word(w_start_addr, buf, pack_len); } void iap_rec_handler(pdu_tag rec_msg) { uint8_t erase_flag = 0x01; g_can_ota_id = rec_msg.id.r; if (rec_msg.data.u8_buf[0] != IAP_CMD_VERSION) iap_connect_clear(); if (rec_msg.data.u8_buf[0] >> 7) { if (rec_msg.id.b.sa == 0xE1) { g_iap.recv_len = rec_msg.reg.dlc - 2; g_iap.current_packages = ((uint16_t)(rec_msg.data.u8_buf[0] & 0x7F) << 8) | rec_msg.data.u8_buf[1]; memcpy(g_iap.flash_data.u8_buf, &rec_msg.data.u8_buf[2], g_iap.recv_len); if ((g_iap.count_packages == g_iap.current_packages) && (g_iap.current_packages < g_iap.total_packages)) { g_iap.count_bytes += g_iap.recv_len; if ((g_iap.recv_len % 2) != 0) { g_iap.flash_data.u8_buf[g_iap.recv_len] = 0xFF; g_iap.recv_len++; } fmc_clear_flag_star(); erase_flag = write_download_flash(g_iap.flash_data.u16_buf, g_iap.recv_len / 2, g_iap.count_packages); fmc_clear_flag_end(); g_iap.crc16 = firmware_crc16_ccitt_false(g_iap.crc16, g_iap.flash_data.u8_buf, g_iap.recv_len); send_buff[0] = IAP_CMD_DATA; send_buff[1] = !erase_flag; g_iap.count_packages++; } else { send_buff[0] = IAP_CMD_DATA; send_buff[1] = 0x06; } send_buff[2] = rec_msg.data.u8_buf[0] & 0x7F; send_buff[3] = rec_msg.data.u8_buf[1]; send_buff[4] = g_iap.count_packages >> 8; send_buff[5] = g_iap.count_packages & 0xFF; } } else { switch (rec_msg.data.u8_buf[0]) { case IAP_CMD_VERSION: iap_param_init(); for (uint8_t i = 0; i < (UPGRADE_APP_DATA_SIZE * 2); i++) { send_buff[i] = fmc_read_byte(UPGRADE_FLAG_START_ADDR + (UPGRADE_FLAG_DATA_SIZE * 2) + i); } send_buff[0] = IAP_CMD_VERSION; send_buff[1] = 0x01; break; case IAP_CMD_INFO: g_iap.total_bytes = (uint16_t)rec_msg.data.u8_buf[1] << 8 | rec_msg.data.u8_buf[2]; g_iap.total_bytes <<= 16; g_iap.total_bytes |= (uint16_t)rec_msg.data.u8_buf[3] << 8 | rec_msg.data.u8_buf[4]; g_iap.total_packages = (uint16_t)rec_msg.data.u8_buf[5] << 8 | rec_msg.data.u8_buf[6]; send_buff[0] = IAP_CMD_INFO; send_buff[1] = 0x01; break; case IAP_CMD_ERASE: g_iap.firmware_crc16 = (uint16_t)rec_msg.data.u8_buf[2] << 8 | rec_msg.data.u8_buf[3]; if (rec_msg.data.u8_buf[1]) { // 喂狗 fmc_clear_flag_star(); erase_flag = erase_app_flash(DOWNLOAD_START_ADDR, DOWNLOAD_END_ADDR); fmc_clear_flag_end(); // 喂狗 g_iap.count_bytes = 0; g_iap.count_packages = 0; } send_buff[0] = IAP_CMD_ERASE; send_buff[1] = !erase_flag; break; case IAP_CMD_CRC: send_buff[0] = IAP_CMD_CRC; send_buff[1] = (g_iap.crc16 == g_iap.firmware_crc16 ? 1 : 0); break; case IAP_CMD_JUMP: if (g_iap.crc16 != g_iap.firmware_crc16) { send_buff[1] = 0x00; } else { fmc_clear_flag_star(); fmc_erase_pages(UPGRADE_FLAG_START_ADDR, 1); upgrade.param.sign = UPGRADE_SIGN; upgrade.param.crc16 = g_iap.crc16; upgrade.param.moving_size = g_iap.total_bytes; fmc_write_n_half_word(UPGRADE_FLAG_START_ADDR, upgrade.infor_buf, UPGRADE_FLAG_DATA_SIZE); fmc_clear_flag_end(); jump_boot_time = 10; send_buff[1] = 0x01; } send_buff[0] = IAP_CMD_JUMP; break; case IAP_CMD_MODEL_TYPE: send_buff[0] = IAP_CMD_MODEL_TYPE; send_buff[1] = 0x01; send_buff[2] = DEVICE_ID >> 8; send_buff[3] = DEVICE_ID & 0xFF; } } push_can_message_to_queue(get_ota_id(CAN_IAP), 8, send_buff); }