#include "iap.h" #include "stm32f4xx_flash.h" // #include "mcp2515.h" #include "bootloader.h" #include "can.h" #include "dwt.h" #include "global.h" #include static u8 iap_index = 0; static u16 iap_buf[IAP_BUF_SIZE] = {0}; extern SqQueue CanQueueImportant; // CAN重要数据队列 uint16_t STMFLASH_GetFlashSector(u32 addr) { if (addr < ADDR_FLASH_SECTOR_1) return FLASH_Sector_0; else if (addr < ADDR_FLASH_SECTOR_2) return FLASH_Sector_1; else if (addr < ADDR_FLASH_SECTOR_3) return FLASH_Sector_2; else if (addr < ADDR_FLASH_SECTOR_4) return FLASH_Sector_3; else if (addr < ADDR_FLASH_SECTOR_5) return FLASH_Sector_4; else if (addr < ADDR_FLASH_SECTOR_6) return FLASH_Sector_5; else if (addr < ADDR_FLASH_SECTOR_7) return FLASH_Sector_6; else if (addr < ADDR_FLASH_SECTOR_8) return FLASH_Sector_7; else if (addr < ADDR_FLASH_SECTOR_9) return FLASH_Sector_8; else if (addr < ADDR_FLASH_SECTOR_10) return FLASH_Sector_9; else if (addr < ADDR_FLASH_SECTOR_11) return FLASH_Sector_10; return FLASH_Sector_11; } u8 iap_init(void) { FLASH_Status status = FLASH_COMPLETE; FLASH_Unlock(); FLASH_DataCacheCmd(DISABLE); FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); status = FLASH_EraseSector(FLASH_Sector_8, VoltageRange_3); if (status != FLASH_COMPLETE) { FLASH_DataCacheCmd(ENABLE); // FLASH擦除结束,开启数据缓存 FLASH_Lock(); // 上锁 return 1; } status = FLASH_EraseSector(FLASH_Sector_9, VoltageRange_3); if (status != FLASH_COMPLETE) { FLASH_DataCacheCmd(ENABLE); // FLASH擦除结束,开启数据缓存 FLASH_Lock(); // 上锁 return 1; } FLASH_DataCacheCmd(ENABLE); // FLASH擦除结束,开启数据缓存 FLASH_Lock(); // 上锁 return 0; } u8 STMFLASH_ReadByte(u32 faddr) { return *(vu8 *)faddr; } u16 STMFLASH_ReadHalfWord(u32 faddr) { return *(vu16 *)faddr; } u32 STMFLASH_ReadWord(u32 faddr) { return *(vu32 *)faddr; } void copy_to_runaddr(u32 end_addr) { FLASH_Status status = FLASH_COMPLETE; u32 write_addr1 = IAP_RUN_START_SECTOR, read_addr = IAP_DOWN_BEGIN_ADDR; // u8 erase_sector = 0, index = 0; u32 temp_value = 0; // erase_sector = STMFLASH_GetFlashSector(IAP_RUN_START_SECTOR); FLASH_Unlock(); // 解锁 FLASH_DataCacheCmd(DISABLE); // FLASH擦除期间,必须禁止数据缓存 FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); status = FLASH_EraseSector(FLASH_Sector_4, VoltageRange_3); if (status != FLASH_COMPLETE) { FLASH_DataCacheCmd(ENABLE); // FLASH擦除结束,开启数据缓存 FLASH_Lock(); // 上锁 return; } status = FLASH_EraseSector(FLASH_Sector_5, VoltageRange_3); if (status != FLASH_COMPLETE) { FLASH_DataCacheCmd(ENABLE); // FLASH擦除结束,开启数据缓存 FLASH_Lock(); // 上锁 return; } while (end_addr > read_addr) { temp_value = STMFLASH_ReadWord(read_addr); if (FLASH_ProgramWord(write_addr1, temp_value) != FLASH_COMPLETE) // 写入数据 { break; // 写入异常 } write_addr1 += 4; read_addr += 4; } FLASH_DataCacheCmd(ENABLE); // FLASH擦除结束,开启数据缓存 FLASH_Lock(); // 上锁 } void iap_send_dataresp(u8 res, u32 addr, u32 sum) { u8 send_buf[8] = {0}; send_buf[0] = IAP_CMD_DOWNLOAD; send_buf[1] = addr; send_buf[2] = addr >> 8; send_buf[3] = addr >> 16; send_buf[4] = res; send_buf[5] = addr >> 24; /*send_buf[1] = addr >> 16; send_buf[2] = addr >> 8; send_buf[3] = addr; send_buf[4] = res; send_buf[5] = 0xFF;*/ send_buf[6] = (u8)(sum >> 8); send_buf[7] = (u8)sum; CAN2_Send_Msg(send_buf, DLC_8, IAP_MCU_DATA_FRAME); } void iap_send_datafinish(u16 page_num) { u8 send_buf[8] = {0}; send_buf[0] = IAP_CMD_DOWNLOAD_END; send_buf[1] = (u8)page_num; send_buf[2] = (u8)(page_num >> 8); send_buf[3] = 0xFF; send_buf[4] = 0xFF; send_buf[5] = 0xFF; send_buf[6] = 0xFF; send_buf[7] = 0xFF; CAN2_Send_Msg(send_buf, DLC_8, IAP_MCU_DATA_FRAME); } u8 stm_flash_write(u32 addr, u16 *array, u32 len) { u8 res = TRUE; u32 index = 0, temp_addr = addr; FLASH_Status status = FLASH_COMPLETE; FLASH_Unlock(); FLASH_DataCacheCmd(DISABLE); for (index = 0; index < len;) { if (STMFLASH_ReadHalfWord(temp_addr) != 0xFFFF) { status = FLASH_EraseSector(STMFLASH_GetFlashSector(temp_addr), VoltageRange_3); if (status != FLASH_COMPLETE) { res = FALSE; break; } } else { index++; temp_addr += 2; } } if (status == FLASH_COMPLETE) { for (index = 0; index < len; index++) { if (FLASH_ProgramHalfWord(addr, array[index]) != FLASH_COMPLETE) // 写入数据 { res = FALSE; break; // 写入异常 } addr += 2; // array++; } } FLASH_DataCacheCmd(ENABLE); FLASH_Lock(); return res; } void stm_flash_write_word(u32 addr, u32 value) { u32 temp_addr = addr; FLASH_Status status = FLASH_COMPLETE; FLASH_Unlock(); FLASH_DataCacheCmd(DISABLE); if (STMFLASH_ReadWord(temp_addr) != 0xFFFFFFFF) { status = FLASH_EraseSector(STMFLASH_GetFlashSector(temp_addr), VoltageRange_3); if (status != FLASH_COMPLETE) { return; } } if (status == FLASH_COMPLETE) { if (FLASH_ProgramWord(addr, value) != FLASH_COMPLETE) // 写入数据 { return; } } FLASH_DataCacheCmd(ENABLE); FLASH_Lock(); } void stm_flash_write_byte(u32 addr, u8 value) { u32 temp_addr = addr; FLASH_Status status = FLASH_COMPLETE; FLASH_Unlock(); FLASH_DataCacheCmd(DISABLE); if (STMFLASH_ReadByte(temp_addr) != 0xFF) { status = FLASH_EraseSector(STMFLASH_GetFlashSector(temp_addr), VoltageRange_3); if (status != FLASH_COMPLETE) { return; } } if (status == FLASH_COMPLETE) { if (FLASH_ProgramByte(addr, value) != FLASH_COMPLETE) // 写入数据 { return; } } FLASH_DataCacheCmd(ENABLE); FLASH_Lock(); } void iap_process(CanData_TypeDef *rx_msg) { // 握手帧回复,最后一个字节为前7个字节累加和 u8 handle_buf[DLC_8] = {'S', 'U', 'C', 'C', 'E', 'S', 'S', 0x19}; u8 pc_frame[DLC_8] = {'A', 'P', 'P', 'L', 'O', 'A', 'D', 0x01}; u8 index = 0, pc_cmd = 0, pack_num = 0, res = 0; u16 rec_page_num = 0; u32 temp_addr = 0; // FLASH_Status flash_res = FLASH_COMPLETE; static u16 cnt = 0; static u16 total_page_num = 0; static u32 iap_sum = 0; static u32 pack_receive = 0; static u32 write_addr = 0, old_write_addr = 0; // static u32 write_test = IAP_DOWN_BEGIN_ADDR; if (rx_msg->can_id == IAP_PC_BEGINE_FRAME) { cnt = 0; if (memcmp(rx_msg->buf, pc_frame, 7) == 0) { // res = iap_init(); total_page_num = 0; if (res == 0) { InitQueue(&CanQueueImportant); CAN2_Send_Msg(handle_buf, DLC_8, IAP_MCU_BIGEN_FRAME); write_addr = IAP_RUN_START_SECTOR; // IAP_DOWN_BEGIN_ADDR; } else { return; } } } else if (rx_msg->can_id == IAP_PC_DATA_FRAME) { cnt = 0; pc_cmd = rx_msg->buf[0]; switch (pc_cmd) { case IAP_CMD_DOWNLOAD: pack_num = rx_msg->buf[1]; if (pack_num == 0x01) { iap_sum = 0; iap_index = 0; pack_receive = 0; pack_receive |= (1 << (pack_num - 1)); write_addr = (rx_msg->buf[6] << 24) + (rx_msg->buf[5] << 16) + (rx_msg->buf[4] << 8) + rx_msg->buf[3]; } else if ((pack_num > 0x01) && (pack_num < 0x17)) { if (((pack_receive & 0x00000001) != 0x00000001) || ((pack_receive & (1 << (pack_num - 1))) == (1 << (pack_num - 1)))) { break; } iap_index = (pack_num - 2) * 3; for (index = 0; index < 3; index++) { if (iap_index < (IAP_BUF_SIZE - 1)) { pack_receive |= 1 << (pack_num - 1); iap_buf[iap_index] = ((u16)rx_msg->buf[2 * index + 3] << 8) + rx_msg->buf[2 * index + 2]; iap_sum += iap_buf[iap_index]; iap_index++; } } } else if (pack_num == 0x17) { if (((pack_receive & 0x00000001) != 0x00000001) || ((pack_receive & (1 << (pack_num - 1))) == (1 << (pack_num - 1)))) { break; } iap_index = 63; pack_receive |= 1 << (pack_num - 1); iap_buf[iap_index] = ((u16)rx_msg->buf[3] << 8) + rx_msg->buf[2]; iap_sum += iap_buf[iap_index]; } if ((pack_receive & 0x007FFFFF) == 0x007FFFFF) { // stm_flash_write(write_test, iap_buf, iap_index+1); // write_test += 2 * (iap_index+1); temp_addr = write_addr; if ((write_addr >= ADDR_FLASH_SECTOR_4) && (write_addr <= ADDR_FLASH_SECTOR_END) && (stm_flash_write(temp_addr, iap_buf, IAP_BUF_SIZE) == TRUE)) { iap_send_dataresp(MCU_DOWNLOAD_SUCC, write_addr, iap_sum); if (write_addr != old_write_addr) { total_page_num++; old_write_addr = write_addr; } } else { iap_send_dataresp(MCU_DOWNLOAD_FAIL, write_addr, iap_sum); } iap_sum = 0; iap_index = 0; pack_receive = 0; } break; case IAP_CMD_DOWNLOAD_END: rec_page_num = rx_msg->buf[2]; rec_page_num = (rec_page_num << 8) | rx_msg->buf[1]; if (rec_page_num != total_page_num) { break; } iap_send_datafinish(total_page_num); // copy_to_runaddr(write_addr-2); // copy_to_runaddr(write_test-2); write_addr = IAP_RUN_START_SECTOR; // IAP_DOWN_BEGIN_ADDR; total_page_num = 0; bsp_DelayMS(300); boot_goto_app(APP_ADDRESS); break; } } else { cnt++; bsp_DelayMS(10); if (cnt > 50) { boot_goto_app(APP_ADDRESS); } } } u8 flash_up_is_ok(void) { u32 len = 0; len = STMFLASH_ReadWord(IAP_FLASH_UP_LEN); if ((len > 0) && (len < 455680)) // 445K { return TRUE; } else { return FALSE; } } void Iap_from_Flash(void) { u32 value = 0, read_add = IAP_FLASH_UP_ADDR, write_add = IAP_RUN_START_SECTOR; // IAP_DOWN_BEGIN_ADDR; u32 len = 0; len = STMFLASH_ReadWord(IAP_FLASH_UP_LEN); while (len >= 4) { value = STMFLASH_ReadWord(read_add); stm_flash_write_word(write_add, value); read_add += 4; write_add += 4; len -= 4; } // if(len != 0) // { // value = STMFLASH_ReadWord(read_add); // stm_flash_write_word(write_add, value); // } for (; len > 0; len--) { value = STMFLASH_ReadByte(read_add); stm_flash_write_byte(write_add, (u8)value); write_add++; } FLASH_Unlock(); // FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR // | FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR | FLASH_FLAG_PGSERR); FLASH_DataCacheCmd(DISABLE); FLASH_EraseSector(FLASH_Sector_8, VoltageRange_3); FLASH_EraseSector(FLASH_Sector_9, VoltageRange_3); FLASH_EraseSector(FLASH_Sector_10, VoltageRange_3); FLASH_EraseSector(FLASH_Sector_11, VoltageRange_3); FLASH_DataCacheCmd(ENABLE); FLASH_Lock(); }