Files
kunlun/app/smart_grid/sta/iot_sg_sta_ext_upgrade.c
2024-09-28 14:24:04 +08:00

487 lines
15 KiB
C

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
/* iot common header files */
#include "iot_io_api.h"
#include "iot_plc_cco_api.h"
#include "iot_module_api.h"
#include "iot_errno_api.h"
#include "iot_dbglog_api.h"
#include "iot_task_api.h"
#include "iot_plc_msg_api.h"
#include "iot_version_api.h"
#include "iot_oem_api.h"
#include "iot_board_api.h"
/* smart grid internal header files */
#include "iot_sg_fr.h"
#include "iot_sg.h"
#include "iot_sg_msg.h"
#include "iot_sg_sta_ext_upgrade.h"
#include "iot_sg_sta_upgrade.h"
#include "iot_upgrade_api.h"
#include "iot_crc_api.h"
#if (IOT_SG_STA_UPGRADE_EXT_DEV_ENABLE)
/* upgrade timer time out function */
void iot_sg_sta_ext_dev_upgrade_func(timer_id_t timer_id, void *arg)
{
(void)timer_id;
(void)arg;
iot_sg_msg_t *msg;
msg = (iot_sg_msg_t *)iot_task_alloc_msg(p_sg_glb->task_h);
if (msg) {
msg->task_msg.type = IOT_SG_MSG_TYPE_TIMER;
msg->task_msg.id = IOT_SG_MSG_ID_TIMER_EXT_DEV_UPGRADE;
iot_task_queue_msg(p_sg_glb->task_h, &msg->task_msg,
IOT_SG_MSG_QUEUE_LP);
} else {
IOT_ASSERT(0);
}
}
static void iot_sg_sta_start_ext_dev_upgrade_timer(uint32_t duration)
{
iot_sg_sta_upgrade_info_t *upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
os_stop_timer(upgrade_info->ext_dev_upgrade_timer);
iot_task_clean_msg(p_sg_glb->task_h, IOT_SG_MSG_TYPE_TIMER,
IOT_SG_MSG_ID_TIMER_EXT_DEV_UPGRADE);
os_start_timer(upgrade_info->ext_dev_upgrade_timer, duration);
}
static void iot_sg_sta_stop_ext_dev_upgrade_timer()
{
iot_sg_sta_upgrade_info_t *upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
os_stop_timer(upgrade_info->ext_dev_upgrade_timer);
iot_task_clean_msg(p_sg_glb->task_h, IOT_SG_MSG_TYPE_TIMER,
IOT_SG_MSG_ID_TIMER_EXT_DEV_UPGRADE);
}
static void iot_sg_sta_ext_dev_upgrade_goto_state(uint8_t new_state)
{
iot_sg_sta_upgrade_info_t *upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
uint8_t pre_state = upgrade_info->ext_dev_state;
if (pre_state != new_state) {
iot_sg_printf("sg_ext_upgrade: state from %d to %d.\n", pre_state,
new_state);
upgrade_info->ext_dev_state = new_state;
iot_dbglog_input(IOT_SMART_GRID_MID, DBGLOG_ERR,
IOT_SG_STA_EXT_UPGRADE_DBG_ID, 2, 1, new_state);
}
}
void iot_sg_ext_dev_reset_upgrade_info()
{
iot_sg_sta_upgrade_info_t *upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
upgrade_info->ext_dev_start_offset = 0;
upgrade_info->ext_dev_send_len = 0;
upgrade_info->ext_dev_file_size = 0;
upgrade_info->ext_dev_upgrade_block_index = 0;
upgrade_info->ext_dev_file_crc = 0;
upgrade_info->ext_dev_upgrade_retry_cnt = 0;
upgrade_info->ext_dev_restart_flag = 0;
iot_sg_sta_ext_dev_upgrade_goto_state(IOT_SG_STA_EXT_DEV_UPGRADE_IDLE);
iot_sg_sta_stop_ext_dev_upgrade_timer();
}
static void iot_sg_sta_ext_upgrade_save_to_flash()
{
iot_sg_sta_upgrade_info_t *upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
iot_sg_printf("%s current part:%d\n", __FUNCTION__,
upgrade_info->current_part);
upgrade_info->current_crc = upgrade_info->file_crc;
iot_upgrade_save_fw_crc(upgrade_info->current_part, upgrade_info->file_crc);
}
static void iot_sg_sta_ext_upgrade_finish(uint8_t complete)
{
iot_sg_sta_upgrade_info_t *upgrade_info = &p_sg_glb->desc.sta->upgrade_info;
if (complete) {
iot_sg_sta_ext_upgrade_save_to_flash();
} else {
if (!upgrade_info->ext_dev_restart_flag) {
upgrade_info->ext_dev_restart_flag = 1;
upgrade_info->ext_dev_last_send_len = 0;
upgrade_info->ext_dev_send_len = 0;
upgrade_info->ext_dev_upgrade_block_index = 0;
upgrade_info->ext_dev_upgrade_retry_cnt = 0;
iot_sg_sta_ext_dev_upgrade_goto_state(
IOT_SG_STA_EXT_DEV_UPGRADE_START);
iot_sg_sta_start_ext_dev_upgrade_timer(
IOT_SG_STA_EXT_DEV_UPGRADE_TIMER_INTERVAL);
return;
}
}
upgrade_info->ext_dev_need_upgrade_flag = 0;
iot_sg_sta_upgrade_clear(upgrade_info->upgrade_id, 0);
return;
}
static uint32_t iot_sg_sta_ext_upgrade_send_exe()
{
iot_pkt_t *pkt = NULL;
uint8_t sta_addr[IOT_MAC_ADDR_LEN];
iot_time_tm_t time;
uint32_t ret;
time.tm_year = 0xffff;
time.tm_mon = 0xff;
time.tm_mday = 0xff;
time.tm_hour = 0xff;
time.tm_min = 0xff;
time.tm_sec = 0xff;
p_sg_glb->desc.sta->drv->get_login_addr(sta_addr);
pkt = proto_69845_build_file_exe_msg(&time, sta_addr);
if (pkt == NULL) {
IOT_ASSERT(0);
}
ret = iot_sg_sta_add_mr_req(IOT_SG_STA_MR_SRC_ID_EXT_UPGRADE, sta_addr, 0,
IOT_SG_STA_DATA_TYPE_69845, iot_pkt_data(pkt),
(uint16_t)iot_pkt_data_len(pkt), IOT_SG_STA_EXT_DEV_UPGRADE_CMD_TIMEOUT);
iot_pkt_free(pkt);
if (ret) {
return IOT_SG_STA_EXT_DEV_UPGRADE_RESULT_FAIL;
}
return IOT_SG_STA_EXT_DEV_UPGRADE_RESULT_OK;
}
static uint8_t iot_sg_sta_ext_upgrade_check_send_complete()
{
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
if (p_info->ext_dev_send_len >= p_info->ext_dev_file_size) {
return IOT_SG_STA_EXT_DEV_UPGRADE_RESULT_COMPLETE;
}
return IOT_SG_STA_EXT_DEV_UPGRADE_RESULT_FAIL;
}
static uint32_t iot_sg_sta_ext_upgrade_send_data()
{
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
iot_pkt_t *pkt = NULL;
iot_pkt_t *data_pkt = NULL;
uint8_t sta_addr[IOT_MAC_ADDR_LEN];
uint32_t read_len;
uint32_t offset;
uint32_t ret = ERR_OK;
data_pkt = iot_pkt_alloc(IOT_SG_STA_EXT_DEV_UPGRADE_BLOCK_SIZE,
IOT_SMART_GRID_MID);
if (data_pkt == NULL) {
IOT_ASSERT(0);
}
offset = p_info->ext_dev_start_offset + p_info->ext_dev_send_len;
read_len = min(p_info->ext_dev_file_size - p_info->ext_dev_send_len,
IOT_SG_STA_EXT_DEV_UPGRADE_BLOCK_SIZE);
iot_pkg_upgrade_read(iot_pkt_data(data_pkt), read_len, offset,
UPGRADE_DATA_TYPE_FW, 1);
p_sg_glb->desc.sta->drv->get_login_addr(sta_addr);
pkt = proto_69845_build_file_data_msg(iot_pkt_data(data_pkt),
(uint16_t)read_len, p_info->ext_dev_upgrade_block_index, sta_addr);
if (pkt == NULL) {
IOT_ASSERT(0);
}
iot_pkt_free(data_pkt);
iot_sg_printf("sg ext upgrade send index:%d send len:%d\n",
p_info->ext_dev_upgrade_block_index, read_len);
ret = iot_sg_sta_add_mr_req(IOT_SG_STA_MR_SRC_ID_EXT_UPGRADE, sta_addr, 0,
IOT_SG_STA_DATA_TYPE_69845, iot_pkt_data(pkt),
(uint16_t)iot_pkt_data_len(pkt), IOT_SG_STA_EXT_DEV_UPGRADE_CMD_TIMEOUT);
iot_pkt_free(pkt);
p_info->ext_dev_last_send_len = read_len;
if (ret) {
return IOT_SG_STA_EXT_DEV_UPGRADE_RESULT_FAIL;
}
return IOT_SG_STA_EXT_DEV_UPGRADE_RESULT_OK;
}
static uint32_t iot_sg_sta_ext_upgrade_send_start()
{
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
iot_pkt_t *pkt = NULL;
uint8_t sta_addr[IOT_MAC_ADDR_LEN];
uint16_t cmpt_hw_ver = 0;
uint16_t cmpt_sw_ver = 0;
uint32_t ret;
p_sg_glb->desc.sta->drv->get_login_addr(sta_addr);
pkt = proto_69845_build_file_info_msg(p_info->ext_dev_file_size,
p_info->ext_dev_file_crc & 0xFFFF,
IOT_SG_STA_EXT_DEV_UPGRADE_BLOCK_SIZE, cmpt_hw_ver, cmpt_sw_ver,
p_info->upgrade_id, sta_addr);
if (pkt == NULL) {
IOT_ASSERT(0);
}
ret = iot_sg_sta_add_mr_req(IOT_SG_STA_MR_SRC_ID_EXT_UPGRADE, sta_addr, 0,
IOT_SG_STA_DATA_TYPE_69845, iot_pkt_data(pkt),
(uint16_t)iot_pkt_data_len(pkt), IOT_SG_STA_EXT_DEV_UPGRADE_CMD_TIMEOUT);
iot_pkt_free(pkt);
if (ret) {
return IOT_SG_STA_EXT_DEV_UPGRADE_RESULT_FAIL;
}
return IOT_SG_STA_EXT_DEV_UPGRADE_RESULT_OK;
}
static uint32_t iot_sg_sta_ext_upgrade_get_file_info()
{
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
iot_upg_ext_file_info_rst ext_rst = { 0 };
uint32_t ret = ERR_FAIL;
ret = iot_upgrade_get_ext_file_info(&ext_rst);
if (ret) {
iot_sg_printf("sg ext upgrade: get external upgrade file info fail\n");
return ret;
}
p_info->ext_dev_start_offset = ext_rst.offset;
p_info->ext_dev_file_size = ext_rst.file_size;
p_info->ext_dev_file_crc = ext_rst.file_crc;
return ret;
}
static uint32_t iot_sg_sta_ext_upgrade_check_crc()
{
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
uint16_t cacl_crc = 0xFFFF;
uint16_t hrd_crc = p_info->ext_dev_file_crc & 0xFFFF;
uint32_t crc_size = p_info->ext_dev_file_size;
uint32_t offset;
uint32_t calc_len = 0;
uint32_t read_len = 0;
uint8_t buffer[64] = {0};
while (calc_len < crc_size) {
offset = p_info->ext_dev_start_offset + calc_len;
read_len = min(64, crc_size - calc_len);
iot_pkg_upgrade_read(buffer, read_len, offset, UPGRADE_DATA_TYPE_FW, 1);
cacl_crc = iot_getcrc16_update(cacl_crc, buffer, read_len, 0);
calc_len += read_len;
}
cacl_crc = cacl_crc ^ 0xFFFF;
if (cacl_crc != hrd_crc) {
iot_sg_printf("%s crc check error, cacl_crc %x hrd_crc %x\n",
__FUNCTION__, cacl_crc, hrd_crc);
return ERR_FAIL;
}
return ERR_OK;
}
void iot_sg_sta_ext_upgrade_pre_process()
{
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
uint32_t reason = 0;
iot_sg_printf("sg ext upgrade: start upgrade extern dev\n");
if (p_info->ext_dev_state != IOT_SG_STA_EXT_DEV_UPGRADE_IDLE) {
iot_sg_printf("sg ext upgrade: external upgrade has been started\n");
return;
}
p_info->ext_dev_send_len = 0;
if (iot_sg_sta_ext_upgrade_get_file_info() != ERR_OK) {
reason = 1;
goto exit;
}
if (iot_sg_sta_ext_upgrade_check_crc() != ERR_OK) {
reason = 2;
goto exit;
}
iot_sg_sta_ext_dev_upgrade_goto_state(IOT_SG_STA_EXT_DEV_UPGRADE_START);
iot_sg_sta_start_ext_dev_upgrade_timer(
IOT_SG_STA_EXT_DEV_UPGRADE_TIMER_INTERVAL);
exit:
iot_sg_printf("%s reason:%d\n", __FUNCTION__, reason);
if (reason) {
iot_sg_sta_upgrade_clear(p_info->upgrade_id, 0);
}
return;
}
/**
* @brief: timer handler for upgrading
*/
void iot_sg_sta_ext_dev_upgrade_timer_handle()
{
uint32_t ext_ret = IOT_SG_STA_EXT_DEV_UPGRADE_RESULT_OK;
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
iot_sg_printf("sg_ext_upgrade: sta external upgrade timer. state = %d\n",
p_info->ext_dev_state);
switch (p_info->ext_dev_state) {
case IOT_SG_STA_EXT_DEV_UPGRADE_START:
{
ext_ret = iot_sg_sta_ext_upgrade_send_start();
}
break;
case IOT_SG_STA_EXT_DEV_UPGRADE_SEND:
{
ext_ret = iot_sg_sta_ext_upgrade_send_data();
}
break;
case IOT_SG_STA_EXT_DEV_UPGRADE_EXE:
{
ext_ret = iot_sg_sta_ext_upgrade_send_exe();
}
break;
default:
break;
}
if (ext_ret == IOT_SG_STA_EXT_DEV_UPGRADE_RESULT_FAIL) {
if (p_info->ext_dev_upgrade_retry_cnt >
IOT_SG_STA_EXT_DEV_UPGRADE_RETRY_MAX) {
iot_sg_sta_ext_upgrade_finish(0);
} else {
p_info->ext_dev_upgrade_retry_cnt++;
iot_sg_sta_start_ext_dev_upgrade_timer(
IOT_SG_STA_EXT_DEV_UPGRADE_RETRY_INTERVAL);
}
}
}
void iot_sg_sta_upgrade_ext_handle(uint16_t seq, uint8_t data_type,
uint8_t *resp_data, uint16_t resp_len, uint8_t *req_data, uint16_t req_len)
{
(void)seq;
(void)req_data;
(void)req_len;
uint32_t ret = ERR_OK;
uint8_t start_timer = 1;
iot_sg_sta_upgrade_info_t *p_info = &p_sg_glb->desc.sta->upgrade_info;
if (data_type != IOT_SG_STA_DATA_TYPE_69845) {
iot_sg_printf("%s invalid response data\n", __FUNCTION__);
goto out;
}
if (!resp_data) {
iot_sg_printf("%s response timeout\n", __FUNCTION__);
goto out;
}
switch (p_info->ext_dev_state) {
case IOT_SG_STA_EXT_DEV_UPGRADE_START:
{
ret = proto_69845_handle_file_info_rsp(resp_data, resp_len);
if (ret == ERR_OK) {
iot_sg_sta_ext_dev_upgrade_goto_state(
IOT_SG_STA_EXT_DEV_UPGRADE_SEND);
} else {
iot_sg_sta_ext_upgrade_finish(0);
start_timer = 0;
}
}
break;
case IOT_SG_STA_EXT_DEV_UPGRADE_SEND:
{
ret = proto_69845_handle_file_data_rsp(resp_data, resp_len);
if (ret == ERR_OK) {
p_info->ext_dev_send_len += p_info->ext_dev_last_send_len;
if (iot_sg_sta_ext_upgrade_check_send_complete() ==
IOT_SG_STA_EXT_DEV_UPGRADE_RESULT_COMPLETE) {
iot_sg_sta_ext_dev_upgrade_goto_state(
IOT_SG_STA_EXT_DEV_UPGRADE_EXE);
} else {
p_info->ext_dev_upgrade_block_index++;
}
}
}
break;
case IOT_SG_STA_EXT_DEV_UPGRADE_EXE:
{
ret = proto_69845_handle_file_exe_rsp(resp_data, resp_len);
if (ret == ERR_OK) {
iot_sg_sta_ext_upgrade_finish(1);
start_timer = 0;
}
}
break;
default:
break;
}
if (ret) {
if (p_info->ext_dev_upgrade_retry_cnt >
IOT_SG_STA_EXT_DEV_UPGRADE_RETRY_MAX) {
iot_sg_sta_ext_upgrade_finish(0);
start_timer = 0;
} else {
p_info->ext_dev_upgrade_retry_cnt++;
}
} else {
p_info->ext_dev_upgrade_retry_cnt = 0;
}
out:
if (start_timer) {
iot_sg_sta_start_ext_dev_upgrade_timer(
IOT_SG_STA_EXT_DEV_UPGRADE_TIMER_INTERVAL);
}
}
#else /* IOT_SG_STA_UPGRADE_EXT_DEV_ENABLE */
void iot_sg_ext_dev_reset_upgrade_info()
{
}
void iot_sg_ext_dev_upgrade_init()
{
}
void iot_sg_sta_ext_upgrade_pre_process()
{
}
void iot_sg_sta_upgrade_ext_handle(uint16_t seq, uint8_t data_type,
uint8_t *resp_data, uint16_t resp_len, uint8_t *req_data, uint16_t req_len)
{
(void)seq;
(void)data_type;
(void)resp_data;
(void)resp_len;
(void)req_data;
(void)req_len;
}
void iot_sg_sta_ext_dev_upgrade_timer_handle()
{
}
#endif /* IOT_SG_STA_UPGRADE_EXT_DEV_ENABLE */