/****************************************************************************************** update Function STM32F103RCT6 256K flash 48K RAM flash : 0-15k API API : 0x0800,0000-0x0800,3FFF : 16-17, params : 0x0800,4000-0x0800,47FF : 18-19k key : 0x0800,4800-0x0800,4FFF : 20K - 137K app : 0x0800,5000-0x0802,27FF : 138K- 255K update app: 0x0802,2800-0x0803,FFFF typedef struct { u8 file_indication; u8 file_property; u8 file_instr; u16 total_packets; u32 current_packet_No; u16 packet_length; u8 * data; }st_update_packet; typedef enum { UPDATE_END = 0, UPDATE_RUNNING, UPDATE_FINISH, UPDATE_SUCCESS, UPDATE_FAILED, UPDATE_SALVE, }EM_UPDATE_STATUS; ******************************************************************************/ #include "apl.h" #include "update.h" #include "Flash.h" #include "uart.h" #include "Mem.h" #include "addr.h" #include "General.h" #include "MD5.h" #include "Led.h" st_update_params st_update; static u8 packet_nnmber; extern const u16 CRC16_Table[]; static u8 g_update_ctrl = UPDATE_NONE; static QueueHandle_t updateQueue; #define UPDATE_BUF_LEN 255 /***************************************************************************** * Function : write_update_ctrlner * Description : none * Input : u8 ctrlner * Output : None * Return : * Others : * Record * 1.Date : 20170314 * Author : barry * Modification: Created function *****************************************************************************/ void write_update_ctrlner(u8 ctrlner) { if (ctrlner < UPDATE_MAX) { g_update_ctrl = ctrlner; } } /***************************************************************************** * Function : read_update_ctrlner * Description : none * Input : void * Output : None * Return : * Others : * Record * 1.Date : 20170314 * Author : barry * Modification: Created function *****************************************************************************/ u8 read_update_ctrlner(void) { return g_update_ctrl; } /***************************************************************************** * Function : set_update_packetState * Description : none * Input : u16 packetNo * Output : None * Return : * Others : * Record * 1.Date : 20170314 * Author : barry * Modification: Created function *****************************************************************************/ void set_update_packetState(u16 packetNo) { st_update.packetsState[packetNo/8] |= (1<<(packetNo%8)); } /***************************************************************************** * Function : check_update_packect_state * Description : none * Input : u16 packetNo * Output : None * Return : * Others : * Record * 1.Date : 20170314 * Author : barry * Modification: Created function *****************************************************************************/ bool check_update_packect_state(u16 packetNo) { if (st_update.packetsState[packetNo/8] & (1<<(packetNo%8)) ) { return TRUE; } else { return FALSE; } } /***************************************************************************** * check if all packet reserved * *****************************************************************************/ bool check_update_state(u16 total_packets) { for (u16 j = 0; j < total_packets; j++) { if (check_update_packect_state(j) == FALSE) { return FALSE; } } return TRUE; } /***************************************************************************** * check if update data reserved right * *****************************************************************************/ bool update_software_check(u32 totalBytes) { u16 temp; u16 crc16 = 0xFFFF; u32 count = totalBytes -2; u8 flash_temp; u32 current_flash_addr = FLASH_APP_BACK_ADDRESS; if (totalBytes <= 2) { return FALSE; } while (count--) { //GDflash_read(current_flash_addr, &flash_temp, 1); flash_temp = *((u8*)current_flash_addr); current_flash_addr++; crc16 = (crc16 >> 8 ) ^ CRC16_Table[(crc16 ^ flash_temp) & 0xFF]; } crc16 ^= 0xFFFF; //GDflash_read(current_flash_addr, &flash_temp, 1); flash_temp = *((u8*)current_flash_addr); current_flash_addr++; temp = (u16)flash_temp*256; //GDflash_read(current_flash_addr, &flash_temp, 1); flash_temp = *((u8*)current_flash_addr); current_flash_addr++; temp += flash_temp; if (crc16 == temp) { return TRUE; } else { return FALSE; } } /***************************************************************************** * write update packet in flash * *****************************************************************************/ void FLASH_Write_update_page(u16 packetNo, u8 * Data, u8 length) { u32 packet_start_addr = FLASH_APP_BACK_ADDRESS + packetNo * UPDATE_DEFAULT_PACKET_SIZE; u8 buf[128]; MemCpy(buf, Data, length); __disable_irq(); STM32_FlashWrite(packet_start_addr, Data, length); __enable_irq(); } /******************************************************************************** * read update params from flash * *********************************************************************************/ bool read_update_flash(st_update_params *st_update_Structure) { memcpy(st_update_Structure, (u8*)FLASH_UPDATE_PARAMS_ADDRESS,sizeof(st_update_params)); if ( GetCRC16((u8*)st_update_Structure, sizeof(st_update_params) -2) == (st_update_Structure->crc) ) { return TRUE; } else { return FALSE; } } /******************************************************************************** * write update params in flash * *********************************************************************************/ void write_update_flash(st_update_params *st_update_Structure ) { st_update_Structure->crc = GetCRC16((u8*)st_update_Structure, sizeof(st_update_params) - 2); if (STM32_FlashPageErase(FLASH_UPDATE_PARAMS_ADDRESS) == FLH_SUCCESS) { STM32_FlashWrite( FLASH_UPDATE_PARAMS_ADDRESS, (u8*)st_update_Structure, sizeof(st_update_params)); } } /***************************************************************************** * * *****************************************************************************/ void reset_update_params(void) { memset(&st_update, 0 , sizeof(st_update)); write_update_flash(&st_update); } void update_ack(u8 number, u32 current_packet_No, u8 ctrl, u8 ctrlner) { static st_AFN15_ack afn15ack; afn15ack.head.start = 0x68; afn15ack.head.len = 0x13; afn15ack.head.ctrl = ctrl | 0xc0; afn15ack.head.info_route = 0; afn15ack.head.info_slave = 0; afn15ack.head.info_com_module = 0; afn15ack.head.info_conflict = 0; afn15ack.head.info_relay = 0; afn15ack.head.info[0] = 0; afn15ack.head.info[1] = 0; afn15ack.head.info[2] = 0; afn15ack.head.info[3] = 0; afn15ack.head.number = number; afn15ack.afn = 0x15; afn15ack.dt1 = 0x01; afn15ack.dt2 = 0x00; afn15ack.current_packet_No = current_packet_No; afn15ack.cs = GetSum((u8*)(&afn15ack)+ 3, 14); afn15ack.end = 0x16; if (ctrlner == UPDATE_485) { debug_Tx( (u8*)&afn15ack, sizeof(st_AFN15_ack)); } else { plc_uart_Tx( (u8*)&afn15ack, sizeof(st_AFN15_ack)); } } u16 get_DT(u8 DT1, u8 DT2) { u16 temp = 0; for (u8 i = 0; i < 8; i++) { temp += ((DT1 >> i) & 0x01); } if (temp != 1) { return 0xFF; } temp = 0; do{ DT1 = DT1 >> 1; if (DT1 == 0) { break; } temp++; }while(1); return (0xF1 + DT2*8 + temp); } void decode_dt(u16 DT, u8 *dt1, u8 *dt2) { *dt2 = (DT - 0xF1)/ 8; *dt1 = (1 << (DT - 0xF1) % 8); } void defaut_13762head_ack_write(st_13762_head * head, u8 length, bool com_module_exist, u8 ctrl) { head->start = 0x68; head->len = length; head->ctrl = ctrl | 0x80; head->info_route = 0; head->info_slave = 0; head->info_com_module = (u8)com_module_exist; head->info_conflict = 0; head->info_relay = 0; MemSet(head->info, 0, 4); head->number = packet_nnmber; } void apl_process_1372(u8 * ptr1372, u8 ctrlner) { static st_13762 temp_1372_frame; static st_13762 *ptr_1372 = &temp_1372_frame; static st_13762_03F1_ack ack_ptr_13762_03f1; u8 *current_ptr = NULL; u16 DT; memcpy(ptr_1372, ptr1372, 10); u16 length = temp_1372_frame.lenL + temp_1372_frame.lenH *256; ptr_1372->cs = ptr1372[length - 2]; ptr_1372->end = ptr1372[length - 1]; if ((ptr_1372->ctrl & 0x08) == 1) { return ; } current_ptr = &ptr1372[10]; packet_nnmber = ptr_1372->number; if (ptr_1372->info_com_module) { ptr_1372->source_addr = current_ptr; current_ptr += 6; if (cmp_addr(ptr_1372->source_addr) == ADDR_NEQ) { return; } if (ptr_1372->info_relay) { ptr_1372->relay_addr = current_ptr; current_ptr += ptr_1372->info_relay*6; } ptr_1372->desc_addr = current_ptr; current_ptr += 6; } ptr_1372->AFN = *current_ptr; ptr_1372->DT1 = *(current_ptr + 1); ptr_1372->DT2 = *(current_ptr + 2); current_ptr += 3; DT = get_DT(ptr_1372->DT1, ptr_1372->DT2); ptr_1372->data = current_ptr; if (!(ptr_1372->info_com_module)) { switch (ptr_1372->AFN) { case 0x03: if (DT == 0xF1) { if (ctrlner == UPDATE_PLC) { defaut_13762head_ack_write(&ack_ptr_13762_03f1.head, sizeof(st_13762_03F1_ack), FALSE, ptr_1372->ctrl); ack_ptr_13762_03f1.AFN = 0x03; ack_ptr_13762_03f1.DT1 = 0x01; ack_ptr_13762_03f1.DT2 = 0x00; MemCpy(ack_ptr_13762_03f1.Manu_code, (u8*)get_apl_version_ptr(), sizeof(Manufacturer_Version)); ack_ptr_13762_03f1.cs = GetSum( (u8*)&ack_ptr_13762_03f1 + 3, sizeof(st_13762_03F1_ack) - 5); ack_ptr_13762_03f1.end = 0x16; plc_uart_Tx((u8*)&ack_ptr_13762_03f1, sizeof(st_13762_03F1_ack)); } } break; case 0x15: if (DT == 0xF1) { if (read_update_ctrlner() == UPDATE_NONE) { write_update_ctrlner(ctrlner); xQueueSendToBack( updateQueue, (u8*)ptr_1372->data, 10); } else if (read_update_ctrlner() == ctrlner) { xQueueSendToBack( updateQueue, (u8*)ptr_1372->data, 10); } } break; default: break; } } } bool check_13762_packet(u8 *buf) { u8 len = buf[1] + buf[2]*256; if ( (buf[0] == 0x68) && (buf[len -1] == 0x16) ) { if (buf[len -2] == GetSum(buf + 3, len - 5)) { return TRUE; } } return FALSE; } void transparent_Proc(void) { //transparent xx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx u8 *start_pos = NULL; // u8 transparent_cmd[] = "transparent 00 "; start_pos = get_debugBuf() + sizeof("transparent 00 ") - 1; if (check_13762_packet(start_pos)) { apl_process_1372(start_pos, UPDATE_485); } } uint16_t get_packets(uint32_t totalBytes ) { uint16_t packet; packet = totalBytes /FLASH_PAGE_SIZE; if (totalBytes % FLASH_PAGE_SIZE ) { packet += 1; } return packet; } /***************************************************************************** * Function : update_iap * Description : none * Input : u32 totalBytes * Output : None * Return : * Others : * Record * 1.Date : 20170425 * Author : barry * Modification: Created function 此处还需要修改,不要使用1页的内存来存储,用小内存,或者直接用半字的方式来处理 *****************************************************************************/ bool update_iap(u32 totalBytes) { //static u8 updateBuf[FLASH_PAGE_SIZE]; u16 iap_flash_pages = get_packets(totalBytes); for (u32 j = 0; j < iap_flash_pages; j++) { // memcpy(updateBuf, (u8*)(FLASH_APP_BACK_ADDRESS + j*FLASH_PAGE_SIZE), FLASH_PAGE_SIZE); if (STM32_FlashPageErase(FLASH_API_ADDRESS + FLASH_PAGE_SIZE*j) == FLH_SUCCESS) { if (STM32_FlashWrite(FLASH_API_ADDRESS + FLASH_PAGE_SIZE*j, (u8*)(FLASH_APP_BACK_ADDRESS + j*FLASH_PAGE_SIZE) , FLASH_PAGE_SIZE) != FLH_SUCCESS) { return FALSE; } } else { return FALSE; } } return TRUE; } bool proceess_packet(st_update_packet * current_ptr, st_update_params * flash_ptr) { if (check_update_packect_state( current_ptr->current_packet_No)) { printf("the same packet\r\n"); return FALSE; } printf("write packet %d in flash\r\n", current_ptr->current_packet_No); FLASH_Write_update_page(current_ptr->current_packet_No, current_ptr->data, current_ptr->packet_length); set_update_packetState(current_ptr->current_packet_No); flash_ptr->received_packets++; flash_ptr->current_packets = current_ptr->current_packet_No; if (current_ptr->current_packet_No >= (current_ptr->total_packets - 1)) { if (check_update_state(flash_ptr->total_packets) == TRUE) { printf("all packet received\r\n"); printf("total updte bytes = %d\r\n", flash_ptr->totalBytes ); flash_ptr->totalBytes = (current_ptr->total_packets - 1)*UPDATE_DEFAULT_PACKET_SIZE + current_ptr->packet_length; if (current_ptr->file_indication == 0x03) { flash_ptr->status = UPDATE_FINISH; write_update_flash(flash_ptr); return TRUE; } else if (current_ptr->file_indication == 0xFD ) { return TRUE; } else { reset_update_params(); printf("update file indication err\r\n"); return FALSE; } } else { reset_update_params(); printf("update file err\r\n"); return FALSE; } } else { return FALSE; } } void erase_128k(void) { for (u32 i = 0; i < FLASH_APPL_BACK_PAGES; i++) { STM32_FlashPageErase(FLASH_APP_BACK_ADDRESS + i*2048); } } static bool is_update_process = false; bool get_update_process() { return is_update_process; } void set_update_process() { is_update_process = true; } void update_process_task(void *ptr) { static st_update_packet update_packet; static bool update_finish_state = FALSE; static u8 tempBuf[UPDATE_BUF_LEN]; static u32 last_packet_No = 0; updateQueue = xQueueCreate(1, UPDATE_BUF_LEN); for (;;) { xQueueReceive(updateQueue, tempBuf, portMAX_DELAY ); memcpy(&update_packet, tempBuf, sizeof(st_update_packet) - 4); update_packet.data = tempBuf + sizeof(st_update_packet) -4; if (update_packet.current_packet_No != 0) { continue; } printf("update start\r\n"); set_update_process(); vTaskDelay(1000/portTICK_RATE_MS); close_printf(); memset(&st_update, 0 , sizeof(st_update)); erase_128k(); vTaskDelay(1000/portTICK_RATE_MS); st_update.status = UPDATE_RUNNING; st_update.total_packets = update_packet.total_packets; printf("update_totalPackets = %d\r\n", st_update.total_packets); last_packet_No = 0; update_finish_state = proceess_packet(&update_packet, &st_update); update_ack(packet_nnmber, update_packet.current_packet_No, 0x0A, g_update_ctrl); if ( g_update_ctrl == UPDATE_PLC) { vTaskDelay(100/portTICK_RATE_MS); set_PLC_UART_baud(57600); } while(1) { if( xQueueReceive(updateQueue, tempBuf, 3000/portTICK_RATE_MS ) == pdPASS) { memcpy(&update_packet, tempBuf, sizeof(st_update_packet) - 4); update_packet.data = tempBuf + sizeof(st_update_packet) -4; if (update_packet.current_packet_No != (last_packet_No + 1)) { reset_update_params(); open_printf(); if ( g_update_ctrl == UPDATE_PLC) { set_PLC_UART_baud(COM_PLC_BAUD); } break; } else { last_packet_No += 1; update_finish_state = proceess_packet(&update_packet, &st_update); update_ack(packet_nnmber, update_packet.current_packet_No, 0x0A, g_update_ctrl); if (update_finish_state) { update_finish_state = FALSE; if (update_packet.file_indication == 0x03 ) //升级自身 { vTaskDelay(300/portTICK_RATE_MS); SysReset(); } else if (update_packet.file_indication == 0xFD ) //升级IAP { if (update_software_check(st_update.totalBytes)) { bool iap_result = update_iap(st_update.totalBytes); if (iap_result) { SysReset(); } } set_PLC_UART_baud(COM_PLC_BAUD); reset_update_params(); } else //升级标志错误 { set_PLC_UART_baud(COM_PLC_BAUD); reset_update_params(); } } } } else { if ( g_update_ctrl == UPDATE_PLC) { set_PLC_UART_baud(COM_PLC_BAUD); } memset(&st_update, 0 , sizeof(st_update)); break; } } } } void create_update_task(void) { xTaskCreate( update_process_task, NULL, 200, NULL, 3, NULL); } void updata_finish(u32 total_packets) { reset_update_params(); st_update.status = UPDATE_FINISH; st_update.totalBytes = total_packets; write_update_flash(&st_update); } /* #define ONE_HOUR_TIME 3600000 #define HALF_HOUR_TIME 1800000 PROCESS(apl_update_process, "update_process "); PROCESS_THREAD(apl_update_process, ev, data) { static st_update_packet update_packet; static bool update_finish_state = FALSE; static struct etimer update_timer; static struct etimer timeout_timer; static u8 tempBuf[255]; static u8 buf[12]; PROCESS_BEGIN(); if (ev == PROCESS_EVENT_INIT) { read_update_flash(&st_update); if (st_update.status == UPDATE_SUCCESS) { all_light_delay(); reset_update_params(); } memset(&st_update, 0 , sizeof(st_update)); } while (1) { PROCESS_WAIT_EVENT(); if (ev == PROCESS_EVENT_MSG) { memcpy(tempBuf, (u8*)data, COM_PLC_RX_BUFFER_SIZE); memcpy(&update_packet, tempBuf, sizeof(st_update_packet) - 4); update_packet.data = tempBuf + sizeof(st_update_packet) -4; if (update_packet.current_packet_No >= update_packet.total_packets ) { printf("packet no error\r\n"); continue; } if (update_packet.current_packet_No == 0) { close_printf(); printf("update start\r\n"); memset(&st_update, 0 , sizeof(st_update)); erase_128k(); etimer_set(&update_timer, 1000); PROCESS_WAIT_EVENT_UNTIL((ev == PROCESS_EVENT_TIMER) && ((struct etimer *)data == &update_timer)); etimer_set(&update_timer, HALF_HOUR_TIME); st_update.status = UPDATE_RUNNING; st_update.total_packets = update_packet.total_packets; printf("update_totalPackets = %d\r\n", st_update.total_packets); } else { if (st_update.status != UPDATE_RUNNING) { reset_update_params(); open_printf(); continue; } } update_finish_state = proceess_packet(&update_packet, &st_update); update_ack(packet_nnmber, update_packet.current_packet_No, 0x0A, g_update_ctrl); if ((update_packet.current_packet_No == 0) && (g_update_ctrl == UPDATE_PLC)) { etimer_set(&update_timer, 100); PROCESS_WAIT_EVENT_UNTIL((ev == PROCESS_EVENT_TIMER) && ((struct etimer *)data == &update_timer)); set_PLC_UART_baud(57600); } if (update_packet.current_packet_No == update_packet.total_packets -1) { etimer_stop(&timeout_timer); } if (update_finish_state) { update_finish_state = FALSE; if (update_packet.file_indication == 0x03 ) { etimer_set(&update_timer, 300); PROCESS_WAIT_EVENT_UNTIL((ev == PROCESS_EVENT_TIMER) && ((struct etimer *)data == &update_timer)); SysReset(); } else if (update_packet.file_indication == 0xFD ) { if (update_software_check(st_update.totalBytes)) { if (!update_iap(st_update.totalBytes)) { SysReset(); } set_PLC_UART_baud(9600); } } else { reset_update_params(); } } } else if ((ev == PROCESS_EVENT_TIMER) && ((struct etimer *)data == &timeout_timer)) { reset_update_params(); set_PLC_UART_baud(9600); open_printf(); } } PROCESS_END(); } */ /******************* (C) COPYRIGHT 2013 Robulink Technology Ltd.*****END OF FILE****/