#include "soc_api.h" #include "utility.h" #include "app_log.h" #include "prf_ota.h" #include "PANSeries.h" #include "comm_prf.h" #include "flash_manager.h" #include "info.h" #define PKT_MASK_TBL_LEN (128 * 4) #define PRF_OTA_PKT_LEN 250 #define PRF_BIT_MASK_WIDTH 32 pan_prf_config_t prf_config = { .work_mode = PRF_MODE_ENHANCE, //PRF_MODE_NORMAL,PRF_MODE_ENHANCE .chip_mode = PRF_CHIP_MODE_SEL_NRF, //PRF_CHIP_MODE_SEL_NRF,//PRF_CHIP_MODE_SEL_XN297, .trx_mode = PRF_RX_MODE, .phy = PRF_PHY_2M, //PRF_PHY_250K,//PRF_PHY_1M, .crc = PRF_CRC_SEL_CRC16, .src = PRF_SRC_SEL_NOSRC, .mode_conf = PRF_BLE_CONF, .rx_timeout = 50000, //50ms .rf_channel = 2510, .tx_no_ack = DISABLE, .trf_type = PRF_TRF_NRF52, .rx_length = 5, .sync_length = 4, .crc_include_sync = DISABLE, .src_include_sync = DISABLE, .sync = { 0x71, 0x76, 0x41, 0x29 }, .pid_manual_flag = DISABLE, .tx_power = 0, .pipe = PRF_PIPE0, }; enum prf_ota_status_t { prf_ota_verify = 0x01, prf_ota_start, prf_ota_ing, prf_ota_check, prf_ota_check_ack, prf_ota_retrans, prf_ota_get_checksum, prf_ota_end, }; bool rx_data_exist = false; bool prf_verify_timeout = true; bool prf_check_status = false; enum prf_ota_status_t prf_ota_stat = prf_ota_verify; panchip_prf_payload_t rx_payload; uint16_t chunk_pk_index; uint16_t pkt_sector_num; uint16_t pkt_tbl_num; uint16_t pkt_total_num; uint8_t chunk_pk_tbl[PKT_MASK_TBL_LEN]; uint32_t calculate_chunk_len; volatile uint8_t calculate_sum; uint8_t firmware_data[PRF_OTA_PKT_LEN * PRF_BIT_MASK_WIDTH]; uint32_t firmware_len; uint8_t prf_id; uint8_t prf_pkt_len; uint8_t prf_mask_width; const uint8_t prf_verify_data[3] = {0x4F, 0x54, 0x41}; void data_printf(uint8_t const *data, uint32_t len) { uint32_t i = 0; if (len == 0) { return; } for (; i < len; i++) { APP_LOG("0x%02X ", data[i]); } APP_LOG("\n"); } void event_tx_fun(void) { panchip_prf_trx_start(); } __ramfunc void event_rx_fun(void) { rx_payload.data_length = panchip_prf_data_rec(&rx_payload); panchip_prf_payload_t ack_payload; static uint8_t ack_count = 0; if((rx_payload.data[0] == prf_ota_verify) || (rx_payload.data[0] == prf_ota_check)) { if(ack_count != (prf_id%10)) { panchip_prf_reset(); panchip_prf_trx_start(); } ack_count++; if(ack_count >= 10) { ack_count = 0; } } else { ack_count = 0; } if(rx_payload.data[0] == prf_ota_verify) { memcpy(&ack_payload.data, &rx_payload.data, rx_payload.data_length); ack_payload.data[4] = prf_id; ack_payload.data_length = rx_payload.data_length + 1; } else if(rx_payload.data[0] == prf_ota_check) { ack_payload.data[0] = prf_ota_check_ack; memcpy(&ack_payload.data[1],chunk_pk_tbl, pkt_tbl_num); ack_payload.data_length = (pkt_tbl_num + 1); } else if(rx_payload.data[0] == prf_ota_get_checksum) { ack_payload.data[0] = prf_ota_get_checksum; ack_payload.data[1] = prf_id; ack_payload.data[2] = calculate_sum; ack_payload.data_length = 3; } else { ack_payload.data_length = 0; } panchip_prf_set_ack_data(&ack_payload); rx_data_exist = true; } void event_rx_timeout_fun(void) { prf_verify_timeout = false; } void event_crc_err_fun(void) { panchip_prf_trx_start(); } void panchip_prf_isr_init(void) { isr_cb.tx_cb = event_tx_fun; isr_cb.rx_cb = event_rx_fun; isr_cb.rx_timeout_cb = event_rx_timeout_fun; isr_cb.rx_crc_err_cb = event_crc_err_fun; } void panchip_prf_irq_enable(void) { NVIC_SetPriority(LL_IRQn, 0); /* Enable RF interrupt */ NVIC_EnableIRQ(LL_IRQn); } uint8_t prf_ota_check_sum(uint8_t *data, uint32_t len) { uint8_t check_sum = 0; for(int i = 0;i < len;i++) { check_sum += data[i]; } return check_sum; } uint8_t prf_pkt_len_get(void) { if(prf_pkt_len == 0) { return 250; } else { return prf_pkt_len; } } uint8_t prf_mask_width_get(void) { if(prf_mask_width == 0) { return 32; } else { return prf_mask_width; } } void panchip_prf_ota_init(void) { if(check_info_tlv_data_prf()) { phy_value_init_from_info_prf(); } else { phy_value_init_from_code_prf(); } memset(firmware_data, 0xff, PRF_OTA_PKT_LEN * PRF_BIT_MASK_WIDTH); memset(chunk_pk_tbl, 0, sizeof(chunk_pk_tbl)); panchip_prf_init(&prf_config); // Generate a PRF ID from chip mac address extern uint8_t m_chip_mac[6]; srand(BytesToUint32(&m_chip_mac[2])); prf_id = (uint8_t)rand(); panchip_prf_set_chn(prf_config.rf_channel); /*adr match bit */ PRI_RF_SetAddrMatchBit(PRI_RF, 0); panchip_prf_trx_start(); } void panchip_prf_recv_data_prase(uint8_t *data, uint8_t len) { switch(data[0]) { case prf_ota_verify: if(!memcmp(&data[1], prf_verify_data, 3)) { firmware_len = 0; calculate_sum = 0; fm_status_refresh(); /* clear flash manager for a new ota process */ prf_ota_stat = prf_ota_start; panchip_prf_rx_timeout(0); panchip_prf_trx_start(); } break; case prf_ota_start: if(prf_ota_stat == prf_ota_start) { prf_ota_stat = prf_ota_ing; pkt_sector_num = data[1]; prf_pkt_len = data[2]; prf_mask_width = data[3]; FMC_EraseCodeArea(FLCTL, FLASH_AREA_IMAGE_START, pkt_sector_num * SECTOR_SIZE); pkt_total_num = (pkt_sector_num * SECTOR_SIZE) / PRF_OTA_PKT_LEN; if((pkt_sector_num * SECTOR_SIZE) % PRF_OTA_PKT_LEN) { pkt_total_num = pkt_total_num + 1; } pkt_tbl_num = (pkt_sector_num * SECTOR_SIZE) / (PRF_OTA_PKT_LEN * 8); if((pkt_sector_num * SECTOR_SIZE) % (PRF_OTA_PKT_LEN * 8)) { pkt_tbl_num = pkt_tbl_num + 1; } APP_LOG_INFO("pkt_tbl_num %d,%d,%d\n",pkt_sector_num, pkt_tbl_num, pkt_total_num); } break; case prf_ota_ing: if(prf_ota_stat == prf_ota_ing) { chunk_pk_index = (data[1] << 8) | data[2]; chunk_pk_tbl[(chunk_pk_index/8)] |= 1 << (chunk_pk_index - 8 * (chunk_pk_index/8)); memcpy(&firmware_data[(len - 3) * (chunk_pk_index%PRF_BIT_MASK_WIDTH)], &data[3], (len - 3)); calculate_chunk_len += (len - 3); APP_LOG_INFO("chunk_pk_index %d,%x,%d\n",chunk_pk_index,chunk_pk_tbl[(chunk_pk_index/8)],calculate_chunk_len); if((!((chunk_pk_index + 1) % PRF_BIT_MASK_WIDTH)) || (((chunk_pk_index + 1) % PRF_BIT_MASK_WIDTH) && ((chunk_pk_index + 1) == pkt_total_num))) { FMC_WriteStream(FLCTL, FLASH_AREA_IMAGE_START + firmware_len, firmware_data, PRF_OTA_PKT_LEN * PRF_BIT_MASK_WIDTH); memset(firmware_data, 0xff, PRF_OTA_PKT_LEN * PRF_BIT_MASK_WIDTH); firmware_len += PRF_OTA_PKT_LEN * PRF_BIT_MASK_WIDTH; APP_LOG_INFO("len %d,%d\n",firmware_len, calculate_chunk_len); calculate_chunk_len = 0; } } break; case prf_ota_check: for(int i = 0;i < pkt_tbl_num;i++) { if(((chunk_pk_tbl[i] & 0xff) != 0xff)) { prf_check_status = false; break; } else { prf_check_status = true; } } if(prf_check_status == false) { prf_ota_stat = prf_ota_retrans; } break; case prf_ota_retrans: if(prf_ota_stat == prf_ota_retrans) { chunk_pk_index = (data[1] << 8) | data[2]; chunk_pk_tbl[(chunk_pk_index/8)] |= 1 << (chunk_pk_index - 8 * (chunk_pk_index/8)); APP_LOG_INFO("trans %d,%d\n",chunk_pk_index,(len - 3)); FMC_WriteStream(FLCTL, FLASH_AREA_IMAGE_START + chunk_pk_index * PRF_OTA_PKT_LEN, &data[3], (len - 3)); } break; case prf_ota_get_checksum: if(calculate_sum == 0) { uint16_t read_index = 0; uint8_t m_checksum = 0; while(read_index < pkt_sector_num) { FMC_ReadStream(FLCTL,(FLASH_AREA_IMAGE_START + (read_index * SECTOR_SIZE)), CMD_DREAD, firmware_data, SECTOR_SIZE); m_checksum += prf_ota_check_sum(firmware_data, SECTOR_SIZE); read_index++; } calculate_sum = m_checksum; APP_LOG_INFO("calculate_sum %x\n",calculate_sum); } break; case prf_ota_end: SYS_UnlockReg(); CLK_ResetChip(); break; default: break; } } bool panchip_prf_ota_start(void) { panchip_prf_ota_init(); while(prf_ota_stat == prf_ota_verify) { if(rx_data_exist == true) { rx_data_exist = false; panchip_prf_recv_data_prase(rx_payload.data, rx_payload.data_length); } if(prf_verify_timeout == false) { return false; } } return true; } void on_prf_ota_enter(void) { APP_LOG_INFO("Entering Private 2.4G (PRF) OTA flow, OTA Server Init..\n"); while(prf_ota_stat != prf_ota_end) { if(rx_data_exist == true) { rx_data_exist = false; panchip_prf_recv_data_prase(rx_payload.data, rx_payload.data_length); } } }