#include "gd32e23x.h" #include "systick.h" #include #include "main.h" #include "Fwdgt.h" #include "mb.h" #include "Led.h" #include "Key.h" #include "cfg.h" #include "main.h" #include "gd32e230x_conf.h" #include "string.h" #include "Timer.h" #include "md5.h" #define MD5_LENTH 8 //#define USR_LED_RCU RCU_GPIOB //#define USR_LED_IO GPIOB //#define USR_LED GPIO_PIN_11 uint8_t programe_erase_flag = 0; uint8_t programe_write_complete_flag = 0; uint8_t meta_erase_flag = 0; uint8_t meta_write_complete_flag = 0; uint8_t get_head_over_flag = 0; get_md_msg _msg = {0}; static uint32_t start_addr = 0x00000000; uint32_t my_addr = 0; static uint32_t erase_size = 0; uint16_t CurrentAddr = 0; uint32_t operation_cmd_cnt = 0; uint8_t flash_flag = 0; uint8_t reboot_flag = 0; MD_DATA Md_Data[Mb_Wcmd_Width] = {0}; META_DATA_S meta_data = {0}; uint8_t read_meta_data[100] = {0}; g_MD_Data g_md_data={ .count = Mb_Wcmd_Width, .data = {0}, }; uint8_t md5_head[128] = {0}; uint32_t md5_sum[MD5_LENTH] = {0}; g_MD_Data* get_md_data() { return &g_md_data; } void flash_erase_page(uint32_t addr) { fmc_unlock(); fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR); fmc_page_erase(addr); fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR); fmc_lock(); } void flash_write_meta(META_DATA_S *meta_data) { fmc_unlock(); uint32_t address = META_DATA; uint32_t *data = (uint32_t*)(meta_data); uint32_t data0 = 0; for(int i = 0; i < sizeof(META_DATA_S) / 4;i++) { data0 = *data; fmc_word_program(address,data0); data ++; fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR); address +=4; } fmc_lock(); } user_code application = NULL; __IO uint32_t JumpAddress = NULL; void UserJumpToApplication(uint32_t addr) { /* Test if user code is programmed starting from address "APPLICATION_ADDRESS" */ uint32_t JumpAddress = 0; if (((*(uint32_t*)addr)&0x2FFE0000)==0x20000000) { /* Jump to user application */ __disable_irq(); // del_md_timer(); // del_modbus_uart(); // delete_Timer14(); // DeInitKey(); SCB->VTOR = addr; //nvic_vector_table_set(NVIC_VECTTAB_FLASH,0x5400); JumpAddress = *(__IO uint32_t*) (addr + 4); application = (user_code)JumpAddress; /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t*)(addr)); application(); } } void flash_get_meta(META_DATA_S *meta) { meta->operation_flag = *(uint32_t*)(UPGRADE_FLAG_ADDR); meta->partition = *(uint32_t*)(STARTUP_PARTATION); meta->errno = *(uint32_t*)(STARTUP_ERROR); meta->error_count = *(uint32_t*)(STARTUP_NUMBEAR); meta->rom_addr = *(uint32_t*)(STARTUP_ROM_ADDR); meta->recent_running_time = *(uint32_t*)(STARTUP_LAST_RUNNING_TIME); meta->running_app_version = *(uint32_t*)(STARTUP_APP_VERSION); meta->app1_version = *(uint32_t*)(APP1_VERSION); meta->app1_rom_addr = *(uint32_t*)(APP1_ROM_ADDR); meta->app1_partition = *(uint32_t*)(APP1_PARTATION); meta->app2_version = *(uint32_t*)(APP2_VERSION); meta->app2_rom_addr = *(uint32_t*)(APP2_ROM_ADDR); meta->app2_partition = *(uint32_t*)(APP2_PARTATION); uint32_t buff[MD5_LENTH] = {0}; uint32_t addr = APP1_MD5; for(int i = 0;i < MD5_LENTH;i++) { buff[i] = *(uint32_t*)(addr); addr += 4; } memcpy(&meta->app1_md5[0],buff,sizeof(uint32_t) *MD5_LENTH); addr = APP2_MD5; for(int i = 0;i < MD5_LENTH;i++) { buff[i] = *(uint32_t*)(addr); addr += 4; } memcpy(&meta->app2_md5[0],buff,sizeof(uint32_t) *MD5_LENTH); meta->app1_size = *(uint32_t*)(APP1_SIZE); meta->app2_size = *(uint32_t*)(APP2_SIZE); } void flash_write_programe(uint32_t *addr,uint32_t* source,uint32_t lenth) { fmc_unlock(); uint32_t *data = source; uint32_t *address = addr; for(int i = 0; i < ((lenth % 4) == 0 ? (lenth/4):((lenth/4)+1));i++,*address += 4) { fmc_word_program(*address,*data++); fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR); } *addr = *address; fmc_lock(); } uint16_t cnt = 0; uint8_t md_status = 0; uint8_t upgrade_count = 0; static void break_2_boot_upgreade(void) { //__disable_irq(); //__set_FAULTMASK(1); NVIC_SystemReset(); } void operation_Flash_data(Flash_Data *data) { if(!data) return; if(data->index == 0) { if(md_status == UPGRADE_STATUS_IDE) { if(strncmp((const char *)(data->recive),MODBUS_HEAD,strlen(MODBUS_HEAD)) == 0){ //memcpy(head_buffer,data->recive,data->lenth); int lenth = strlen(MODBUS_HEAD); memcpy(&_msg.magic,data->recive,lenth); _msg.size = (data->recive[lenth]) | (data->recive[lenth+1] << 8); _msg.patition = (data->recive[lenth+2]) | (data->recive[lenth+3] << 8) | (data->recive[lenth+4] << 16) | (data->recive[lenth+5] << 24); _msg.version = (data->recive[lenth+6]) | (data->recive[lenth+6] << 8) | (data->recive[lenth+8] << 16) | (data->recive[lenth+9] << 24); //memcmp(&md5_head,&data->recive,128); memcpy(_msg.md5,&data->recive[lenth+10],32); get_head_over_flag = 1; } } }else { if(md_status == UPGRADE_STATUS_WRITE_PROGRAME) { flash_write_programe(&my_addr,(uint32_t*)(data->recive),data->lenth); upgrade_count = 0; if(data->index < 0) { programe_write_complete_flag = 1; } } } } void ModBus_CMD(void) { if(g_md_data.data[operation_cmd_cnt].flag == 1) { uint32_t base_addr = g_md_data.data[operation_cmd_cnt].base_addr; //check data is or not header metadata; switch(base_addr) { case MD_WRITE_Addr: { operation_Flash_data(&g_md_data.data[operation_cmd_cnt].flash_Data); } break; case MD_WRITE_Reset: { break_2_boot_upgreade(); } break; default: break; } g_md_data.data[operation_cmd_cnt].flag = 0; operation_cmd_cnt++; if(operation_cmd_cnt >= Mb_Wcmd_Width) { operation_cmd_cnt = 0; } } } Upgrade upgrade = {0}; Upgrade *get_upgrade() { return &upgrade; } #define CHAR(b) (((b)<=9)?((b)+0x30):((b)-10+0x61)); static void byte2char(char *chr, uint8_t b) { chr[0] = CHAR(b>>4); chr[1] = CHAR(b&0x0f); } uint8_t md5_check(uint32_t addr,uint32_t lenth,uint32_t* md5) { md5_ctx_t ctx; char m1[32]; uint8_t i,tmp[16]; md5_init(&ctx); uint32_t buff[64] = {0}; uint32_t read_lenth; if(lenth % 4 == 0) read_lenth = lenth / 4; else read_lenth = lenth / 4 + 1; uint32_t base_addr = addr; int size = 0; int check_size = (64*4); do { for(int i = 0;i < 64;i++) { buff[i] = *(uint32_t*)(base_addr); base_addr += 4; } size += 64; if(size > read_lenth) { check_size = lenth; //check md5_update(&ctx,(uint8_t*)&buff,check_size); }else { //check md5_update(&ctx,(uint8_t*)&buff,check_size); lenth -= check_size; } }while(size < read_lenth); md5_final(&ctx, tmp); for (i=0; i<16; i++) { byte2char(&m1[i*2], tmp[i]); } if(memcmp(&m1, md5, sizeof(m1))) { return 0xFF; } return 0; } int main(void) { InitLED(); InitKey(); InitTimer(); CurrentAddr = ReadKeyValue(); eMBInit(MB_RTU, CurrentAddr, 0, 115200, MB_PAR_NONE); eMBEnable(); flash_get_meta(&meta_data); //Fwdgt_Init(); //read data and uint8_t app1_checum = 0xFF; uint8_t app2_checum = 0xFF; if(meta_data.operation_flag == 0x0) { #if (!USE_ONE_APP) if(meta_data.rom_addr == PROGRAME_APP1 || meta_data.rom_addr == PROGRAME_APP2) { if(meta_data.app1_rom_addr == PROGRAME_APP1) { app1_checum = md5_check(meta_data.app1_rom_addr,meta_data.app1_size,meta_data.app1_md5); } if(meta_data.app2_rom_addr == PROGRAME_APP2) { app2_checum = md5_check(meta_data.app2_rom_addr,meta_data.app2_size,meta_data.app2_md5); } if((app1_checum == 0) && (app2_checum == 0)) { if(meta_data.errno != NOERROR && meta_data.error_count >= MAX_ERROR_COUNT) { //check current version is last versions? if(meta_data.app1_version == meta_data.app2_version) { }else { uint32_t version_max = meta_data.app1_version > meta_data.app2_version ? meta_data.app1_version :meta_data.app2_version; uint32_t version_min = meta_data.app1_version < meta_data.app2_version ? meta_data.app1_version :meta_data.app2_version; if(version_max == ERROR_VERSION) { }else if(meta_data.running_app_version == version_max) { //swtich lower version to running flash_erase_page(META_DATA); if(version_max == meta_data.app2_version){ meta_data.partition = meta_data.app1_partition; meta_data.rom_addr = meta_data.app1_rom_addr; }else { meta_data.partition = meta_data.app2_partition; meta_data.rom_addr = meta_data.app2_rom_addr; } meta_data.running_app_version = version_min; meta_data.errno = 0; meta_data.error_count = 0; flash_write_meta(&meta_data); UserJumpToApplication(meta_data.rom_addr); }else { ;; } } }else { if(meta_data.rom_addr == PROGRAME_APP1) { if(app1_checum == 0){ UserJumpToApplication(meta_data.rom_addr); if(app2_checum == 0) { flash_erase_page(META_DATA); meta_data.partition = meta_data.app2_partition; meta_data.rom_addr = meta_data.app2_rom_addr; meta_data.running_app_version = meta_data.app2_version; meta_data.errno = 0; meta_data.error_count = 0; flash_write_meta(&meta_data); UserJumpToApplication(meta_data.rom_addr); } } } if(meta_data.rom_addr == PROGRAME_APP2) { if(app2_checum == 0){ UserJumpToApplication(meta_data.rom_addr); if(app1_checum == 0) { flash_erase_page(META_DATA); meta_data.partition = meta_data.app1_partition; meta_data.rom_addr = meta_data.app1_rom_addr; meta_data.running_app_version = meta_data.app1_version; meta_data.errno = 0; meta_data.error_count = 0; flash_write_meta(&meta_data); UserJumpToApplication(meta_data.rom_addr); } } } } }else if(app1_checum == 0) { if(meta_data.errno != NOERROR && meta_data.error_count >= MAX_ERROR_COUNT) { //upgrade }else { flash_erase_page(META_DATA); meta_data.partition = meta_data.app1_partition; meta_data.rom_addr = meta_data.app1_rom_addr; meta_data.running_app_version = meta_data.app1_version; meta_data.errno = 0; meta_data.error_count = 0; flash_write_meta(&meta_data); UserJumpToApplication(meta_data.rom_addr); } }else if(app2_checum == 0) { if(meta_data.errno != NOERROR && meta_data.error_count >= MAX_ERROR_COUNT) { //upgrade }else { flash_erase_page(META_DATA); meta_data.partition = meta_data.app2_partition; meta_data.rom_addr = meta_data.app2_rom_addr; meta_data.running_app_version = meta_data.app2_version; meta_data.errno = 0; meta_data.error_count = 0; flash_write_meta(&meta_data); UserJumpToApplication(meta_data.rom_addr); } }else { ;; } } #else if(meta_data.rom_addr == PROGRAME_APP1) { if(meta_data.app1_rom_addr == PROGRAME_APP1) { app1_checum = md5_check(meta_data.app1_rom_addr,meta_data.app1_size,meta_data.app1_md5); if(app1_checum == 0) { if(meta_data.errno != NOERROR && meta_data.error_count >= MAX_ERROR_COUNT) { //upgrade }else { UserJumpToApplication(meta_data.rom_addr); } } } } #endif }else { //wait to upgrade } md_status = UPGRADE_STATUS_IDE; while(1) { eMBPoll(); //Fwdgt_reload(); if(flash_flag) { LEDFlicker2(); upgrade_count += 3; flash_flag = 0; } ModBus_CMD(); switch(md_status) { case UPGRADE_STATUS_IDE: { //get and jie xi meta_data if(get_head_over_flag) { //½âÎöMetaDataºÍ²Á³ýflash if(_msg.patition == ONE){ start_addr =PROGRAME_APP1; erase_size = PROGRAME_APP1_SIZE; md_status = UPGRADE_STATUS_ERASE_PROGRAME; } #if (!USE_ONE_APP) else if(_msg.patition == SECOND){ start_addr = PROGRAME_APP2; erase_size = PROGRAME_APP2_SIZE; md_status = UPGRADE_STATUS_ERASE_PROGRAME; } #endif else{ md_status = UPGRADE_STATUS_IDE; get_head_over_flag = 0; } } } break; case UPGRADE_STATUS_ERASE_PROGRAME: { if(programe_erase_flag == 0) { my_addr = start_addr; for(uint32_t i = 0;i < (erase_size/PAGE_SIZE);i++) { flash_erase_page(my_addr); my_addr += PAGE_SIZE; } my_addr = start_addr; programe_erase_flag = 1; md_status = UPGRADE_STATUS_WRITE_PROGRAME; upgrade_count = 0; } } break; case UPGRADE_STATUS_WRITE_PROGRAME: { if(upgrade_count > 10) { break_2_boot_upgreade(); } if(programe_write_complete_flag) { md_status = UPGRADE_STATUS_ERASE_META; } } break; case UPGRADE_STATUS_ERASE_META: { if(meta_erase_flag == 0) { meta_data.partition = _msg.patition; meta_data.running_app_version = _msg.version; meta_data.errno = 0; meta_data.error_count = 0; if(meta_data.partition == ONE){ meta_data.rom_addr =PROGRAME_APP1; meta_data.app1_partition = _msg.patition; meta_data.app1_rom_addr = PROGRAME_APP1; meta_data.app1_version = _msg.version; memcpy(meta_data.app1_md5,_msg.md5,32); meta_data.app1_size = _msg.size; } #if (!USE_ONE_APP) else if(meta_data.partition == SECOND) { meta_data.rom_addr =PROGRAME_APP2; meta_data.app2_partition = _msg.patition; meta_data.app2_rom_addr = PROGRAME_APP2; meta_data.app2_version = _msg.version; memcpy(meta_data.app2_md5,_msg.md5,32); meta_data.app2_size = _msg.size; } #endif else { // errno md_status = UPGRADE_STATUS_IDE; get_head_over_flag = 0; programe_write_complete_flag = 0; programe_erase_flag = 0; break; } meta_data.operation_flag = 0; meta_data.recent_running_time = 0; md_status = UPGRADE_STATUS_WTITE_META; flash_erase_page(META_DATA); meta_erase_flag = 1; } } break; case UPGRADE_STATUS_WTITE_META: { if(meta_write_complete_flag == 0){ flash_write_meta(&meta_data); md_status = UPGRADE_STATUS_FINISH; meta_write_complete_flag = 1; } } break; case UPGRADE_STATUS_FINISH: { //jiaoyan and break app1_checum = md5_check(meta_data.app1_rom_addr,meta_data.app1_size,meta_data.app1_md5); if(app1_checum == 0) UserJumpToApplication(start_addr); md_status = UPGRADE_STATUS_IDE; meta_write_complete_flag = 0; // meta_erase_flag = 0; get_head_over_flag = 0; programe_erase_flag = 0; programe_write_complete_flag = 0; } break; default: break; } } return 0; }