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

3506 lines
115 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.
****************************************************************************/
/* os_shim header files */
#include "os_types_api.h"
#include "os_timer_api.h"
#include "os_utils_api.h"
#include "os_mem_api.h"
/* iot common header files */
#include "iot_errno_api.h"
#include "iot_dbglog_api.h"
#include "iot_io_api.h"
#include "iot_crc_api.h"
#include "iot_oem_api.h"
#include "iot_bitmap_api.h"
#include "iot_rtc_api.h"
/* smart grid internal header files */
#include "iot_sg_fr.h"
#include "iot_sg_cfg.h"
#include "iot_sg.h"
#include "iot_sg_msg.h"
#include "iot_sg_flash.h"
#include "iot_sg_sta_flash.h"
#include "proto_645.h"
#include "iot_sg_sta.h"
#include "iot_sg_sta_drv_api.h"
#include "iot_sg_sta_ext.h"
#include "iot_sg_sta_cfg_flash.h"
#if (IOT_SMART_GRID_FLASH_ENABLE)
/* define length of buffer used to cache CRC check data */
#define IOT_SG_STA_FLASH_CRC_BUF_LEN 256
/* define default length of buffer used to cache reset data */
#define IOT_SG_STA_FLASH_RESET_DEF_BUF_LEN 1024
/* define max length of buffer used to cache reset data */
#define IOT_SG_STA_FLASH_RESET_MAX_BUF_LEN 2048
/* define max length of buffer used to cache reset data */
#define IOT_SG_STA_FLASH_ERASE_MAX_LEN (32 * 1024)
/* sta flash storage mode */
/* defines the sg app sta flash storage mode used to LN */
#define IOT_SG_STA_FLASH_SM_LN (0)
/* defines the sg app sta flash storage mode used to GX */
#define IOT_SG_STA_FLASH_SM_GX (1)
/* defines the sg app sta flash storage mode used to XIAN */
#define IOT_SG_STA_FLASH_SM_XIAN (2)
/* defines the sg app sta flash storage mode used to GUANGDONG */
#define IOT_SG_STA_FLASH_SM_GUANGDONG (3)
/* defines the sg app sta flash storage mode used to GUANGZHOU */
#define IOT_SG_STA_FLASH_SM_GUANGZHOU (4)
/* defines the sg app sta flash storage mode used to PEIWANG */
#define IOT_SG_STA_FLASH_SM_PW (5)
/* defines the sg app sta flash storage mode used to JIANGSU */
#define IOT_SG_STA_FLASH_SM_JS (6)
/* defines the sg app sta flash storage mode used to JIANGSU.
* only for three-phase module
*/
#define IOT_SG_STA_FLASH_SM_THREE_JS (7)
/* defines the sg app sta flash storage mode used to JIANGSU.
* only for single-phase module
*/
#define IOT_SG_STA_FLASH_SM_SIG_JS (8)
/* defines the sg app sta flash storage mode used to FUJIAN. */
#define IOT_SG_STA_FLASH_SM_FJ (9)
/* defines the sg app sta flash storage mode used to NW. */
#define IOT_SG_STA_FLASH_SM_NW (10)
/* defines the sg app sta flash storage mode used to GW. */
#define IOT_SG_STA_FLASH_SM_GW (11)
/* define cnt of flash storage mode */
#define IOT_SG_STA_FLASH_MODE_CNT (IOT_SG_STA_FLASH_SM_GW + 1)
/* sta flash storage meter cnt */
/* defines the sg app sta flash storage meter cnt to LN */
#define IOT_SG_STA_FLASH_SM_METER_CNT_LN (1)
/* defines the sg app sta flash storage meter cnt to GX */
#define IOT_SG_STA_FLASH_SM_METER_CNT_GX (24)
/* defines the sg app sta flash storage meter cnt to XIAN */
#define IOT_SG_STA_FLASH_SM_METER_CNT_XIAN (1)
/* defines the sg app sta flash storage meter cnt to GUANGDONG */
#define IOT_SG_STA_FLASH_SM_METER_CNT_GUANGDONG (1)
/* defines the sg app sta flash storage meter cnt to GUANGZHOU */
#define IOT_SG_STA_FLASH_SM_METER_CNT_GUANGZHOU (32)
/* defines the sg app sta flash storage meter cnt to PW */
#define IOT_SG_STA_FLASH_SM_METER_CNT_PW (32)
/* defines the sg app sta flash storage meter cnt to JIANGSU */
#define IOT_SG_STA_FLASH_SM_METER_CNT_JS (12)
/* defines the sg app sta flash storage meter cnt to JIANGSU.
* only for single-phase moudle
*/
#define IOT_SG_STA_FLASH_SM_SIG_METER_CNT_JS (1)
/* defines the sg app sta flash storage meter cnt to NW */
#define IOT_SG_STA_FLASH_SM_METER_CNT_NW (1)
#define IOT_SG_STA_FLASH_SM_METER_CNT_NW_IC (4)
#define IOT_SG_STA_FLASH_SM_METER_CNT_NW_IIC (6)
/* defines the sg app sta flash storage meter cnt to GW */
#define IOT_SG_STA_FLASH_SM_METER_CNT_GW (1)
/* sta flash storage data cnt in a meter */
/* defines the sg app sta flash storage data cnt to LN */
#define IOT_SG_STA_FLASH_SM_DATA_CNT_LN (3)
/* defines the sg app sta flash storage data cnt to GX */
#define IOT_SG_STA_FLASH_SM_DATA_CNT_GX (1)
/* defines the sg app sta flash storage data cnt to XIAN */
#define IOT_SG_STA_FLASH_SM_DATA_CNT_XIAN (2)
/* defines the sg app sta flash storage data cnt to GUANGDONG */
#define IOT_SG_STA_FLASH_SM_DATA_CNT_GUANGDONG (5)
/* defines the sg app sta flash storage data cnt to GUANGZHOU */
#define IOT_SG_STA_FLASH_SM_DATA_CNT_GUANGZHOU (1)
/* defines the sg app sta flash storage data cnt to PW */
#define IOT_SG_STA_FLASH_SM_DATA_CNT_PW (1)
/* defines the sg app sta flash storage data cnt to JIANGSU */
#define IOT_SG_STA_FLASH_SM_DATA_CNT_JS (4)
/* defines the sg app sta flash storage data cnt to FUJIAN. */
#define IOT_SG_STA_FLASH_SM_DATA_CNT_FJ (16)
/* defines the sg app sta flash storage data cnt to NW. */
#define IOT_SG_STA_FLASH_SM_DATA_CNT_NW (2)
/* defines the sg app sta flash storage data cnt to GW */
#define IOT_SG_STA_FLASH_SM_DATA_CNT_GW (8)
/**
* The size of flash storage space reserved by each provincial network
* (used for version judgment). If the size is inconsistent with the
* value stored in flash, the flash data will be invalid.
*/
/* Increase flash space size to 233472 to fit the current version */
#define IOT_SG_STA_METER_SPACE_SIZE_RSVD_JS (4080)
/* Increase flash space size to 94208 to fit the current version */
#define IOT_SG_STA_METER_SPACE_SIZE_RSVD_JS_SIG (2240)
/* Increase flash space size to 233472 to fit the current version */
#define IOT_SG_STA_METER_SPACE_SIZE_RSVD_JS_THREE (4080)
/* increase flash space size to 2560 to fit the current version */
#define IOT_SG_STA_METER_SPACE_SIZE_RSVD_GX (228)
/* increase flash space size to 3000 to fit the current version */
#define IOT_SG_STA_METER_SPACE_SIZE_RSVD_PW (92)
/* increase flash space size to 3665233 to fit the current version */
#define IOT_SG_STA_METER_SPACE_SIZE_RSVD_FJ (1)
/* sta flash desc total length */
/* defines flash desc total length to LN */
#define IOT_SG_STA_FLASH_DESC_LEN_LN \
((sizeof(iot_sg_sta_flash_meter_desc_t) * \
IOT_SG_STA_FLASH_SM_METER_CNT_LN) + \
(sizeof(iot_sg_sta_flash_meter_data_desc_t) * \
IOT_SG_STA_FLASH_SM_DATA_CNT_LN * IOT_SG_STA_FLASH_SM_METER_CNT_LN))
/* defines flash desc total length to GX */
#define IOT_SG_STA_FLASH_DESC_LEN_GX \
((sizeof(iot_sg_sta_flash_meter_desc_t) * \
IOT_SG_STA_FLASH_SM_METER_CNT_GX) + \
(sizeof(iot_sg_sta_flash_meter_data_desc_t) * \
IOT_SG_STA_FLASH_SM_DATA_CNT_GX * IOT_SG_STA_FLASH_SM_METER_CNT_GX))
/* defines flash desc total length to XIAN */
#define IOT_SG_STA_FLASH_DESC_LEN_XIAN \
((sizeof(iot_sg_sta_flash_meter_desc_t) * \
IOT_SG_STA_FLASH_SM_METER_CNT_XIAN) + \
(sizeof(iot_sg_sta_flash_meter_data_desc_t) * \
IOT_SG_STA_FLASH_SM_DATA_CNT_XIAN * IOT_SG_STA_FLASH_SM_METER_CNT_XIAN))
/* defines flash desc total length to GUANGDONG */
#define IOT_SG_STA_FLASH_DESC_LEN_GUANGDONG \
((sizeof(iot_sg_sta_flash_meter_desc_t) * \
IOT_SG_STA_FLASH_SM_METER_CNT_GUANGDONG) + \
(sizeof(iot_sg_sta_flash_meter_data_desc_t) * \
IOT_SG_STA_FLASH_SM_DATA_CNT_GUANGDONG * \
IOT_SG_STA_FLASH_SM_METER_CNT_GUANGDONG))
/* defines flash desc total length to GUANGZHOU */
#define IOT_SG_STA_FLASH_DESC_LEN_GUANGZHOU \
((sizeof(iot_sg_sta_flash_meter_desc_t) * \
IOT_SG_STA_FLASH_SM_METER_CNT_GUANGZHOU) + \
(sizeof(iot_sg_sta_flash_meter_data_desc_t) * \
IOT_SG_STA_FLASH_SM_DATA_CNT_GUANGZHOU * \
IOT_SG_STA_FLASH_SM_METER_CNT_GUANGZHOU))
/* defines flash desc total length to PEIWANG */
#define IOT_SG_STA_FLASH_DESC_LEN_PW \
((sizeof(iot_sg_sta_flash_meter_desc_t) * \
IOT_SG_STA_FLASH_SM_METER_CNT_PW) + \
(sizeof(iot_sg_sta_flash_meter_data_desc_t) * \
IOT_SG_STA_FLASH_SM_DATA_CNT_PW * IOT_SG_STA_FLASH_SM_METER_CNT_PW))
/* defines flash desc total length to JIANGSU */
#define IOT_SG_STA_FLASH_DESC_LEN_JS \
((sizeof(iot_sg_sta_flash_meter_desc_t) * \
IOT_SG_STA_FLASH_SM_METER_CNT_JS) + \
(sizeof(iot_sg_sta_flash_meter_data_desc_t) * \
IOT_SG_STA_FLASH_SM_DATA_CNT_JS * IOT_SG_STA_FLASH_SM_METER_CNT_JS))
/* defines meter desc total length to JIANGSU.
* only for single-phase module
*/
#define IOT_SG_STA_FLASH_DESC_LEN_SIG_JS \
((sizeof(iot_sg_sta_flash_meter_desc_t) * \
IOT_SG_STA_FLASH_SM_SIG_METER_CNT_JS) + \
(sizeof(iot_sg_sta_flash_meter_data_desc_t) * \
IOT_SG_STA_FLASH_SM_DATA_CNT_JS * IOT_SG_STA_FLASH_SM_SIG_METER_CNT_JS))
/* defines meter desc total length to NW. */
#define IOT_SG_STA_FLASH_DESC_LEN_NW \
((sizeof(iot_sg_sta_flash_meter_desc_t) * \
IOT_SG_STA_FLASH_SM_METER_CNT_NW_IIC) + \
(sizeof(iot_sg_sta_flash_meter_data_desc_t) * \
IOT_SG_STA_FLASH_SM_DATA_CNT_NW * IOT_SG_STA_FLASH_SM_METER_CNT_NW_IIC))
/* defines meter desc total length to GW. */
#define IOT_SG_STA_FLASH_DESC_LEN_GW \
((sizeof(iot_sg_sta_flash_meter_desc_t) * \
IOT_SG_STA_FLASH_SM_METER_CNT_GW) + \
(sizeof(iot_sg_sta_flash_meter_data_desc_t) * \
IOT_SG_STA_FLASH_SM_DATA_CNT_GW * IOT_SG_STA_FLASH_SM_METER_CNT_GW))
/* define flash cache data buf length */
#define IOT_SG_STA_FLASH_DESC_BUF_LEN \
max(IOT_SG_STA_FLASH_DESC_LEN_LN, \
max(IOT_SG_STA_FLASH_DESC_LEN_GX, \
max(IOT_SG_STA_FLASH_DESC_LEN_XIAN, \
max(IOT_SG_STA_FLASH_DESC_LEN_GUANGDONG,\
max(IOT_SG_STA_FLASH_DESC_LEN_GUANGZHOU, \
max(IOT_SG_STA_FLASH_DESC_LEN_PW, \
max(IOT_SG_STA_FLASH_DESC_LEN_JS,\
max(IOT_SG_STA_FLASH_DESC_LEN_NW,\
max(IOT_SG_STA_FLASH_DESC_LEN_GW,\
IOT_SG_STA_FLASH_DESC_LEN_SIG_JS)))))))))
/* define multi uint data buf length */
#define IOT_SG_STA_FLASH_MULTI_BUF_LEN (1024)
/* define maximum number of times to find unit data */
#define IOT_SG_STA_FLASH_UNIT_DATA_FIND_BY_TIME_MAX_CNT 5
/* define sta collection task unit write and read mode */
#define IOT_SG_STA_FLASH_CT_WR_MODE_INDEX 0
#define IOT_SG_STA_FLASH_CT_WR_MODE_OFFSET 1
/* define the size of flash erase unit: 256 Byte */
#define IOT_SG_STA_FLASH_ERASE_SIZE_256B (0x100)
/* define the size of flash erase unit: 4096 Byte */
#define IOT_SG_STA_FLASH_ERASE_SIZE_4K (0x1000)
/* define the reserved data length of provincials unit data node. */
/* Jiangsu Three phase / IIC minutes freeze for 4K erase size */
#define IOT_SG_STA_METER_JS_MIN_DATA_RSCD_LEN_4K (140)
/* JiangSu single phase minutes freeze for 4K erase size */
#define IOT_SG_STA_METER_JS_SIG_MIN_DATA_RSCD_LEN_4K (158)
#define IOT_SG_STA_METER_XIAN_LC_DATA_RSVD_LEN_256B (3)
#define IOT_SG_STA_METER_XIAN_LC_DATA_RSVD_LEN_4K (39)
#define IOT_SG_STA_METER_GX_LC_DATA_RSVD_LEN_256B (5)
#define IOT_SG_STA_METER_GX_LC_DATA_RSVD_LEN_4K (57)
#define IOT_SG_STA_METER_PW_LC_DATA_RSVD_LEN_4K (4)
/* Used to save flash mode information */
/* TODO It can be deleted after kunlun3 completed for all provincial */
static iot_sg_sta_flash_storage_mode_t flash_meter_mode = {0};
/* define flash erase mode */
/* erase the flash current page each time writing flash */
#define IOT_SG_STA_FLASH_ERASE_MODE_EACH_WRITE (0)
/* erase the flash current page at the beginning of each time
* write flash page
*/
#define IOT_SG_STA_FLASH_ERASE_MODE_EACH_PAGE_BEG (1)
static iot_sg_sta_flash_storage_mode_t flash_meter_mode_list[
IOT_SG_STA_FLASH_MODE_CNT] = {
[IOT_SG_STA_FLASH_SM_LN] = {
.meter_cnt = IOT_SG_STA_FLASH_SM_METER_CNT_LN,
.space_size = 4096,
.cnt = IOT_SG_STA_FLASH_SM_DATA_CNT_LN,
.data = {
{
.type = IOT_SG_STA_METER_DATA_TYPE_DF,
.len = IOT_SG_STA_METER_TYPE_DF_MAX_LEN,
},
{
.type = IOT_SG_STA_METER_DATA_TYPE_IA,
.len = IOT_SG_STA_METER_TYPE_IA_MAX_LEN,
},
{
.type = IOT_SG_STA_METER_DATA_TYPE_HF,
.len = IOT_SG_STA_METER_TYPE_HF_MAX_LEN,
},
},
},
[IOT_SG_STA_FLASH_SM_GUANGDONG] = {
.meter_cnt = IOT_SG_STA_FLASH_SM_METER_CNT_GUANGDONG,
.space_size = 45056,
.cnt = IOT_SG_STA_FLASH_SM_DATA_CNT_GUANGDONG,
.data = {
{
.type = IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT,
.len = IOT_SG_STA_METER_TYPE_GUANGDONG_MAX_LEN,
},
{
.type = IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT,
.len = IOT_SG_STA_METER_TYPE_GUANGDONG_MAX_LEN,
},
{
.type = IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT,
.len = IOT_SG_STA_METER_TYPE_GUANGDONG_MAX_LEN,
},
{
.type = IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT,
.len = IOT_SG_STA_METER_TYPE_GUANGDONG_MAX_LEN,
},
{
.type = IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT,
.len = IOT_SG_STA_METER_TYPE_GUANGDONG_MAX_LEN,
},
},
},
[IOT_SG_STA_FLASH_SM_GUANGZHOU] = {
.meter_cnt = IOT_SG_STA_FLASH_SM_METER_CNT_GUANGZHOU,
.space_size = 1024,
.cnt = IOT_SG_STA_FLASH_SM_DATA_CNT_GUANGZHOU,
.data = {
{
.type = IOT_SG_STA_METER_DATA_TYPE_GUANGZHOU_SS,
.len = IOT_SG_STA_METER_TYPE_GUANGZHOU_MAX_LEN,
},
},
},
[IOT_SG_STA_FLASH_SM_NW] = {
.meter_cnt = IOT_SG_STA_FLASH_SM_METER_CNT_NW,
.space_size = 77848,
.cnt = IOT_SG_STA_FLASH_SM_DATA_CNT_NW,
.data = {
{
.type = IOT_SG_STA_METER_DATA_TYPE_NW_TASK,
.len = IOT_SG_STA_METER_TYPE_NW_LC_MAX_LEN,
},
{
.type = IOT_SG_STA_METER_DATA_TYPE_EC,
.len = IOT_SG_STA_METER_TYPE_EC_MAX_LEN,
},
},
},
};
static uint32_t iot_sg_sta_flash_alignment_handle(uint32_t value)
{
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
uint32_t alignment_value = value;
if (flash_info->erase_mode != IOT_SG_STA_FLASH_ERASE_MODE_EACH_PAGE_BEG) {
goto out;
}
if (!flash_info->erase_unit_size) {
goto out;
}
if ((value % flash_info->erase_unit_size) == 0) {
goto out;
}
alignment_value = ((value / flash_info->erase_unit_size) + 1) *
flash_info->erase_unit_size;
out:
return alignment_value;
}
static uint32_t iot_sg_sta_flash_get_data_type_len_alignment(
uint8_t data_type, uint32_t *length)
{
uint32_t size = 0, ret = ERR_FAIL;
uint16_t unit_length = 0, max_cnt = 0;
IOT_ASSERT(length);
if (iot_sg_sta_flash_unit_get_data_info(data_type, &unit_length,
&max_cnt)) {
goto out;
}
size += IOT_SG_STA_METER_DATA_HEADER_LEN;
if (data_type == IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
size += sizeof(iot_sg_sta_drv_meter_ct_hdr_t);
}
/* align the meter data storage space with the smallest erasing unit */
size = iot_sg_sta_flash_alignment_handle(size);
/* align the unit data storage space with the smallest erasing unit */
size += iot_sg_sta_flash_alignment_handle(max_cnt * unit_length);
size -= IOT_SG_STA_METER_DATA_HEADER_LEN;
*length = size;
ret = ERR_OK;
out:
return ret;
}
static uint32_t iot_sg_sta_flash_get_data_type_len(
uint8_t data_type, uint32_t *length)
{
uint32_t size = 0, ret = ERR_FAIL;
uint16_t unit_length = 0, max_cnt = 0;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
IOT_ASSERT(length);
if (iot_sg_sta_flash_unit_get_data_info(data_type, &unit_length,
&max_cnt)) {
goto out;
}
size = max_cnt * unit_length;
if (data_type == IOT_SG_STA_METER_DATA_TYPE_FJ_TASK ||
data_type == IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
size += sizeof(iot_sg_sta_drv_meter_ct_hdr_t);
}
if (flash_info->erase_unit_size == IOT_SG_STA_FLASH_ERASE_SIZE_4K) {
size += IOT_SG_STA_METER_DATA_HEADER_LEN;
/* Align the storage space with the smallest erasing unit */
size &= ~(flash_info->erase_unit_size - 1);
size += flash_info->erase_unit_size;
size -= IOT_SG_STA_METER_DATA_HEADER_LEN;
} else {
/**
* In order to adapt the space length of the existing version,
* memory alignment is not performed.
*/
if (iot_sg_sta_flash_mode_js_sig_check() ||
data_type == IOT_SG_STA_METER_DATA_TYPE_XIAN_LC ||
data_type == IOT_SG_STA_METER_DATA_TYPE_AI_LL ||
data_type == IOT_SG_STA_METER_DATA_TYPE_GX_LC ||
data_type == IOT_SG_STA_METER_DATA_TYPE_PW_LC ||
data_type == IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) {
size = ((size >> 2) + 1) << 2;
} else {
/* jiangsu IIC and three-phase use 4KByte alignment */
size += IOT_SG_STA_METER_DATA_HEADER_LEN;
if (size & 0x00000fff) {
size = ((size >> 12) + 1);
size = size << 12;
}
size -= IOT_SG_STA_METER_DATA_HEADER_LEN;
}
}
*length = size;
ret = ERR_OK;
out:
return ret;
}
static uint32_t iot_sg_sta_flash_get_storage_mode(uint8_t mode_id,
iot_sg_sta_flash_info_t *flash_info)
{
uint8_t i, new_flag = 1;
uint32_t ret = ERR_OK, length = IOT_SG_STA_METER_HEADER_LEN;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
switch (mode_id) {
case IOT_SG_STA_FLASH_SM_JS:
case IOT_SG_STA_FLASH_SM_SIG_JS:
case IOT_SG_STA_FLASH_SM_THREE_JS:
{
if (mode_id == IOT_SG_STA_FLASH_SM_JS) {
flash_meter_mode.meter_cnt = IOT_SG_STA_FLASH_SM_METER_CNT_JS;
flash_meter_mode.space_size = IOT_SG_STA_METER_SPACE_SIZE_RSVD_JS;
} else if (mode_id == IOT_SG_STA_FLASH_SM_THREE_JS) {
flash_meter_mode.meter_cnt = IOT_SG_STA_FLASH_SM_SIG_METER_CNT_JS;
flash_meter_mode.space_size =
IOT_SG_STA_METER_SPACE_SIZE_RSVD_JS_THREE;
} else {
flash_meter_mode.meter_cnt = IOT_SG_STA_FLASH_SM_SIG_METER_CNT_JS;
flash_meter_mode.space_size =
IOT_SG_STA_METER_SPACE_SIZE_RSVD_JS_SIG;
}
flash_meter_mode.data[0].type = IOT_SG_STA_METER_DATA_TYPE_JS_MF;
flash_meter_mode.data[1].type = IOT_SG_STA_METER_DATA_TYPE_JS_DF;
flash_meter_mode.data[2].type =
IOT_SG_STA_METER_DATA_TYPE_JS_15MIN_CURVE;
flash_meter_mode.data[3].type =
IOT_SG_STA_METER_DATA_TYPE_JS_1MIN_CURVE;
flash_meter_mode.cnt = IOT_SG_STA_FLASH_SM_DATA_CNT_JS;
flash_meter_mode.space_size += IOT_SG_STA_METER_HEADER_LEN;
break;
}
case IOT_SG_STA_FLASH_SM_XIAN:
{
flash_meter_mode.meter_cnt = IOT_SG_STA_FLASH_SM_METER_CNT_XIAN;
flash_meter_mode.space_size = IOT_SG_STA_METER_HEADER_LEN;
flash_meter_mode.data[0].type = IOT_SG_STA_METER_DATA_TYPE_XIAN_LC;
flash_meter_mode.data[1].type = IOT_SG_STA_METER_DATA_TYPE_AI_LL;
flash_meter_mode.cnt = IOT_SG_STA_FLASH_SM_DATA_CNT_XIAN;
break;
}
case IOT_SG_STA_FLASH_SM_GX:
{
flash_meter_mode.meter_cnt = IOT_SG_STA_FLASH_SM_METER_CNT_GX;
flash_meter_mode.space_size =
IOT_SG_STA_METER_SPACE_SIZE_RSVD_GX + IOT_SG_STA_METER_HEADER_LEN;
flash_meter_mode.data[0].type = IOT_SG_STA_METER_DATA_TYPE_GX_LC;
flash_meter_mode.cnt = IOT_SG_STA_FLASH_SM_DATA_CNT_GX;
break;
}
case IOT_SG_STA_FLASH_SM_PW:
{
flash_meter_mode.meter_cnt = IOT_SG_STA_FLASH_SM_METER_CNT_PW;
flash_meter_mode.space_size =
IOT_SG_STA_METER_SPACE_SIZE_RSVD_PW + IOT_SG_STA_METER_HEADER_LEN;
flash_meter_mode.data[0].type = IOT_SG_STA_METER_DATA_TYPE_PW_LC;
flash_meter_mode.cnt = IOT_SG_STA_FLASH_SM_DATA_CNT_PW;
break;
}
case IOT_SG_STA_FLASH_SM_FJ:
{
flash_meter_mode.meter_cnt = IOT_SG_STA_FLASH_SM_METER_CNT_FJ;
flash_meter_mode.space_size =
IOT_SG_STA_METER_SPACE_SIZE_RSVD_FJ + IOT_SG_STA_METER_HEADER_LEN;
flash_meter_mode.cnt = IOT_SG_STA_FLASH_SM_DATA_CNT_FJ;
for (i = 0; i < flash_meter_mode.cnt; i++) {
flash_meter_mode.data[i].type = IOT_SG_STA_METER_DATA_TYPE_FJ_TASK;
}
break;
}
case IOT_SG_STA_FLASH_SM_GW:
{
flash_meter_mode.meter_cnt = IOT_SG_STA_FLASH_SM_METER_CNT_GW;
flash_meter_mode.space_size = IOT_SG_STA_METER_HEADER_LEN;
flash_meter_mode.cnt = IOT_SG_STA_FLASH_SM_DATA_CNT_GW;
for (i = 0; i < flash_meter_mode.cnt; i++) {
flash_meter_mode.data[i].type = IOT_SG_STA_METER_DATA_TYPE_GW_TASK;
}
break;
}
case IOT_SG_STA_FLASH_SM_NW:
{
flash_info->flash_mode = &flash_meter_mode_list[
IOT_SG_STA_FLASH_SM_NW];
if (sta_glb->drv->dev_type == IOT_SG_STA_DEV_TYPE_COLLECTOR_T2) {
flash_info->flash_mode->meter_cnt =
IOT_SG_STA_FLASH_SM_METER_CNT_NW_IIC;
} else if (sta_glb->drv->dev_type == IOT_SG_STA_DEV_TYPE_COLLECTOR_T1) {
flash_info->flash_mode->meter_cnt =
IOT_SG_STA_FLASH_SM_METER_CNT_NW_IC;
}
new_flag = 0;
break;
}
default:
if (mode_id < IOT_SG_STA_FLASH_MODE_CNT) {
flash_info->flash_mode = &flash_meter_mode_list[mode_id];
} else {
ret = ERR_NOSUPP;
goto out;
}
new_flag = 0;
break;
}
if (new_flag) {
for (i = 0; i < flash_meter_mode.cnt; i++) {
ret = iot_sg_sta_flash_get_data_type_len(
flash_meter_mode.data[i].type, &flash_meter_mode.data[i].len);
if (ret) {
goto out;
}
flash_meter_mode.space_size += (flash_meter_mode.data[i].len +
IOT_SG_STA_METER_DATA_HEADER_LEN);
}
flash_info->flash_mode = &flash_meter_mode;
}
IOT_ASSERT(flash_info->flash_mode->cnt <=
IOT_SG_STA_FLASH_METER_DATA_MAX_CNT);
for (i = 0; i < flash_info->flash_mode->cnt; i++) {
if (flash_info->flash_mode->data[i].len) {
length += flash_info->flash_mode->data[i].len;
length += IOT_SG_STA_METER_DATA_HEADER_LEN;
}
}
iot_sg_printf("total storage space %d byte / %d byte\n",
length, flash_info->flash_mode->space_size);
IOT_ASSERT(length <= flash_info->flash_mode->space_size);
IOT_ASSERT(flash_info->flash_mode->meter_cnt <= IOT_SG_STA_FLASH_METER_MAX_CNT);
out:
return ret;
}
static uint32_t iot_sg_sta_flash_get_storage_mode_alignment(uint8_t mode_id,
iot_sg_sta_flash_info_t *flash_info)
{
uint8_t i;
uint32_t ret = ERR_OK, length = IOT_SG_STA_METER_HEADER_LEN;
length = iot_sg_sta_flash_alignment_handle(length);
switch (mode_id) {
case IOT_SG_STA_FLASH_SM_GW:
{
flash_meter_mode.meter_cnt = IOT_SG_STA_FLASH_SM_METER_CNT_GW;
flash_meter_mode.space_size = IOT_SG_STA_METER_HEADER_LEN;
flash_meter_mode.cnt = IOT_SG_STA_FLASH_SM_DATA_CNT_GW;
for (i = 0; i < flash_meter_mode.cnt; i++) {
flash_meter_mode.data[i].type = IOT_SG_STA_METER_DATA_TYPE_GW_TASK;
}
break;
}
default:
ret = ERR_NOSUPP;
goto out;
}
flash_meter_mode.space_size =
iot_sg_sta_flash_alignment_handle(flash_meter_mode.space_size);
for (i = 0; i < flash_meter_mode.cnt; i++) {
ret = iot_sg_sta_flash_get_data_type_len_alignment(
flash_meter_mode.data[i].type, &flash_meter_mode.data[i].len);
if (ret) {
goto out;
}
flash_meter_mode.space_size += (flash_meter_mode.data[i].len +
IOT_SG_STA_METER_DATA_HEADER_LEN);
}
flash_info->flash_mode = &flash_meter_mode;
IOT_ASSERT(flash_info->flash_mode->cnt <=
IOT_SG_STA_FLASH_METER_DATA_MAX_CNT);
for (i = 0; i < flash_info->flash_mode->cnt; i++) {
if (flash_info->flash_mode->data[i].len) {
length += flash_info->flash_mode->data[i].len;
length += IOT_SG_STA_METER_DATA_HEADER_LEN;
}
}
iot_sg_printf("total storage space %d byte / %d byte\n",
length, flash_info->flash_mode->space_size);
IOT_ASSERT(length <= flash_info->flash_mode->space_size);
IOT_ASSERT(flash_info->flash_mode->meter_cnt <=
IOT_SG_STA_FLASH_METER_MAX_CNT);
out:
return ret;
}
static iot_sg_sta_flash_meter_desc_t* iot_sg_sta_flash_meter_find(uint8_t *addr)
{
uint8_t i;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL, *meter_list = NULL;
IOT_ASSERT(flash_info->total_meter_cnt <= IOT_SG_STA_FLASH_METER_MAX_CNT);
meter_list = (iot_sg_sta_flash_meter_desc_t*)flash_info->flash_desc_buf;
for (i = 0; i < flash_info->total_meter_cnt; i++) {
if (iot_mac_addr_cmp(meter_list[i].meter_hdr.mac, addr)) {
meter_info = &meter_list[i];
break;
}
}
return meter_info;
}
static iot_sg_sta_flash_meter_desc_t* iot_sg_sta_flash_meter_alloc(void)
{
uint8_t i;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL, *meter_list = NULL;
IOT_ASSERT(flash_info->total_meter_cnt <= IOT_SG_STA_FLASH_METER_MAX_CNT);
if (!flash_info->free_meter_cnt) {
goto out;
}
meter_list = (iot_sg_sta_flash_meter_desc_t*)flash_info->flash_desc_buf;
for (i = 0; i < flash_info->total_meter_cnt; i++) {
if (!iot_mac_addr_valid(meter_list[i].meter_hdr.mac)) {
meter_info = &meter_list[i];
flash_info->free_meter_cnt--;
break;
}
}
out:
return meter_info;
}
uint16_t iot_sg_sta_flash_get_crc(uint32_t offset, uint32_t len,
uint8_t crc_type)
{
uint16_t crc = 0;
uint32_t data_offset, length, ret, data_len;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
IOT_ASSERT(flash_info->crc_buf);
data_offset = offset;
length = len;
crc = 0xffff;
while (length) {
data_len = min(length, IOT_SG_STA_FLASH_CRC_BUF_LEN);
ret = iot_sg_flash_read(data_offset, data_len, flash_info->crc_buf);
if (ret) {
iot_sg_printf("%s flash read err\n", __FUNCTION__);
}
switch (crc_type) {
case IOT_SG_STA_FLASH_CRC16:
{
crc = iot_getcrc16_update(crc, flash_info->crc_buf, length, 0);
break;
}
case IOT_SG_STA_FLASH_CRC8:
{
crc = iot_getcrc8_update((uint8_t)crc, flash_info->crc_buf,
length);
break;
}
default:
IOT_ASSERT(0);
break;
}
data_offset += data_len;
length -= data_len;
}
return crc;
}
static void iot_sg_sta_flash_meter_data_init(uint32_t offset,
iot_sg_sta_flash_meter_data_desc_t *data_desc,
uint8_t data_type, uint32_t data_len)
{
iot_pkt_t *pkt_buff = NULL;
uint32_t ret;
iot_sg_sta_drv_meter_data_hdr_t *data_hdr = &data_desc->data_hdr;
iot_sg_sta_drv_meter_ct_hdr_info_t *ct_info = &data_desc->ct_info;
iot_sg_sta_drv_meter_ct_hdr_t *ct_hdr;
ret = iot_sg_flash_read(offset, sizeof(*data_hdr), (uint8_t*)data_hdr);
if (ret) {
iot_sg_printf("%s flash read head err\n", __FUNCTION__);
}
data_desc->offset = offset;
if ((data_hdr->data_type != data_type)
|| (data_hdr->data_len != data_len)) {
goto drop;
}
if (data_hdr->hdr_crc != iot_getcrc8((uint8_t*)data_hdr,
(sizeof(*data_hdr) - 1))) {
goto drop;
}
if (data_type == IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT
|| data_type == IOT_SG_STA_METER_DATA_TYPE_FJ_TASK
|| data_type == IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
pkt_buff = iot_pkt_alloc(sizeof(*ct_hdr), IOT_SMART_GRID_MID);
if (pkt_buff == NULL) {
goto drop;
}
ct_hdr = (iot_sg_sta_drv_meter_ct_hdr_t*)iot_pkt_put(pkt_buff,
sizeof(*ct_hdr));
ret = iot_sg_flash_read(offset + sizeof(*data_hdr), sizeof(*ct_hdr),
(uint8_t*)ct_hdr);
if (ret) {
iot_sg_printf("%s flash read clct task head err\n", __FUNCTION__);
goto drop;
}
if (!ct_hdr->task_id) {
goto drop;
}
if (ct_hdr->hdr_crc != iot_getcrc8((uint8_t*)ct_hdr,
(sizeof(*ct_hdr) - 1))) {
goto drop;
}
ct_info->task_id = ct_hdr->task_id;
ct_info->sn = ct_hdr->sn;
ct_info->unit_cnt = ct_hdr->unit_cnt;
ct_info->unit_len = ct_hdr->unit_len;
}
goto out;
drop:
os_mem_set(&data_desc->data_hdr, 0, sizeof(data_desc->data_hdr));
os_mem_set(&data_desc->ct_info, 0, sizeof(data_desc->ct_info));
data_hdr->data_type = data_type;
data_hdr->data_len = data_len;
out:
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
return;
}
static uint32_t iot_sg_sta_flash_meter_init(uint32_t offset,
iot_sg_sta_flash_meter_desc_t *meter_desc)
{
uint8_t i, crc8;
uint32_t ret = ERR_OK, data_offset, meter_data_len;
iot_sg_sta_flash_meter_data_desc_t *data_list;
iot_sg_sta_drv_meter_hdr_t *meter_hdr = &meter_desc->meter_hdr;
const iot_sg_sta_flash_storage_mode_t *storage_mode =
p_sg_glb->desc.sta->flash_info.flash_mode;
meter_desc->offset = offset;
ret = iot_sg_flash_read(offset, sizeof(*meter_hdr), (uint8_t*)meter_hdr);
if (ret) {
iot_sg_printf("%s flash read err\n", __FUNCTION__);
}
meter_data_len = storage_mode->space_size - IOT_SG_STA_METER_HEADER_LEN;
if (meter_hdr->data_len != meter_data_len) {
ret = ERR_FAIL;
goto drop;
}
crc8 = iot_getcrc8((uint8_t*)meter_hdr, (sizeof(*meter_hdr) - 1));
if (meter_hdr->hdr_crc != crc8) {
ret = ERR_FAIL;
goto drop;
}
data_list = meter_desc->data_list;
data_offset = offset + IOT_SG_STA_METER_HEADER_LEN;
data_offset = iot_sg_sta_flash_alignment_handle(data_offset);
for (i = 0; i < storage_mode->cnt; i++) {
iot_sg_sta_flash_meter_data_init(data_offset, &data_list[i],
storage_mode->data[i].type, storage_mode->data[i].len);
data_offset += (storage_mode->data[i].len + \
IOT_SG_STA_METER_DATA_HEADER_LEN);
}
goto out;
drop:
os_mem_set(&meter_desc->meter_hdr, 0, sizeof(meter_desc->meter_hdr));
data_list = meter_desc->data_list;
os_mem_set(data_list, 0, (sizeof(iot_sg_sta_flash_meter_data_desc_t)
* meter_desc->data_cnt));
out:
return ret;
}
uint8_t iot_sg_sta_flash_mode_js_sig_check(void)
{
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
return flash_info->mode == IOT_SG_STA_FLASH_SM_SIG_JS ? 1 : 0;
}
static uint32_t iot_sg_sta_flash_meter_desc_init(uint8_t meter_cnt,
uint8_t data_cnt, uint8_t *desc_buf, uint16_t buf_len)
{
uint8_t m;
uint16_t total_len;
uint32_t ret = ERR_FAIL;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
iot_sg_sta_flash_meter_desc_t *meter_desc = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_desc = NULL;
total_len = (sizeof(*meter_desc) * meter_cnt) +
(sizeof(*data_desc) * meter_cnt * data_cnt);
if (total_len > buf_len) {
goto drop;
}
os_mem_set(desc_buf, 0, buf_len);
meter_desc = (iot_sg_sta_flash_meter_desc_t*)desc_buf;
data_desc = (iot_sg_sta_flash_meter_data_desc_t*)(desc_buf
+ sizeof(*meter_desc) * meter_cnt);
for (m = 0; m < meter_cnt; m++) {
meter_desc[m].data_list = data_desc
+ (m * data_cnt);
meter_desc[m].data_cnt = data_cnt;
}
flash_info->total_meter_cnt = meter_cnt;
flash_info->free_meter_cnt = flash_info->total_meter_cnt;
ret = ERR_OK;
goto out;
drop:
iot_sg_printf("%s fail\n", __FUNCTION__);
flash_info->total_meter_cnt = 0;
flash_info->free_meter_cnt = 0;
out:
return ret;
}
uint32_t iot_sg_sta_flash_init()
{
uint8_t i, reason = 0, dev_type, flash_mode;
uint8_t user_type = iot_sg_sta_get_user_type();
uint8_t *crc_buf = NULL, total_cnt, *desc_buf = NULL;
uint32_t ret = ERR_OK, flash_size, total_size, offset;
uint32_t cfg_len = 0;
iot_sg_sta_flash_meter_desc_t *meter_list;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
iot_sg_sta_global_t *sta_glb = p_sg_glb->desc.sta;
if (flash_info->flash_en) {
goto out;
}
if (!sta_glb->drv) {
ret = ERR_NOSUPP;
reason = 1;
goto drop;
}
dev_type = (uint8_t)sta_glb->drv->get_device_type();
switch (dev_type) {
case IOT_SG_STA_DEV_TYPE_POWER_METER:
{
/* if dev type is a power meter, sta initialize flash. */
if (user_type == USER_TYPE_SOUTHEN_POWER_GRID_GX) {
flash_mode = IOT_SG_STA_FLASH_SM_GX;
} else if (user_type == USER_TYPE_STATE_GRID_HEBEI ||
user_type == USER_TYPE_STATE_GRID_HUNAN ||
user_type == USER_TYPE_STATE_GRID_MENGDONG_LC) {
flash_mode = IOT_SG_STA_FLASH_SM_XIAN;
} else if (user_type == USER_TYPE_STATE_GRID_XIAN) {
#if IOT_SMART_GRID_GW_V28_ENABLE
flash_mode = IOT_SG_STA_FLASH_SM_GW;
#else
flash_mode = IOT_SG_STA_FLASH_SM_XIAN;
#endif
} else if (user_type == USER_TYPE_SOUTHEN_POWER_GRID_GUANGDONG) {
flash_mode = IOT_SG_STA_FLASH_SM_GUANGDONG;
} else if (user_type == USER_TYPE_SOUTHEN_POWER_GRID_GUANGZHOU) {
flash_mode = IOT_SG_STA_FLASH_SM_GUANGZHOU;
} else if (user_type == USER_TYPE_STATE_GRID_JIANGSU) {
if (iot_sg_sta_is_3p_module()) {
flash_mode = IOT_SG_STA_FLASH_SM_THREE_JS;
} else {
flash_mode = IOT_SG_STA_FLASH_SM_SIG_JS;
}
} else if (user_type == USER_TYPE_BRM_PEIWANG ||
user_type == USER_TYPE_BRM_PEIWANG_DUAL_NET) {
flash_mode = IOT_SG_STA_FLASH_SM_PW;
} else if (user_type == USER_TYPE_STATE_GRID_FUJIAN) {
flash_mode = IOT_SG_STA_FLASH_SM_FJ;
} else if (sta_glb->proto == IOT_SG_STA_APP_PROTO_NW) {
flash_mode = IOT_SG_STA_FLASH_SM_NW;
} else {
ret = ERR_NOSUPP;
reason = 2;
goto drop;
}
break;
}
case IOT_SG_STA_DEV_TYPE_COLLECTOR_T2:
{
if (user_type == USER_TYPE_SOUTHEN_POWER_GRID_GX) {
flash_mode = IOT_SG_STA_FLASH_SM_GX;
} else if (user_type ==
USER_TYPE_SOUTHEN_POWER_GRID_GUANGZHOU) {
flash_mode = IOT_SG_STA_FLASH_SM_GUANGZHOU;
} else if (user_type == USER_TYPE_STATE_GRID_JIANGSU) {
flash_mode = IOT_SG_STA_FLASH_SM_JS;
} else if (user_type == USER_TYPE_BRM_PEIWANG_DUAL_NET) {
flash_mode = IOT_SG_STA_FLASH_SM_PW;
} else if (sta_glb->proto == IOT_SG_STA_APP_PROTO_NW) {
flash_mode = IOT_SG_STA_FLASH_SM_NW;
} else {
ret = ERR_NOSUPP;
reason = 3;
goto drop;
}
break;
}
case IOT_SG_STA_DEV_TYPE_COLLECTOR_T3:
{
if (sta_glb->proto == IOT_SG_STA_APP_PROTO_NW) {
flash_mode = IOT_SG_STA_FLASH_SM_NW;
} else {
flash_mode = IOT_SG_STA_FLASH_SM_PW;
}
break;
}
case IOT_SG_STA_DEV_TYPE_COLLECTOR_T1:
{
if (sta_glb->proto == IOT_SG_STA_APP_PROTO_NW) {
flash_mode = IOT_SG_STA_FLASH_SM_NW;
} else {
ret = ERR_NOSUPP;
reason = 4;
goto drop;
}
break;
}
default:
ret = ERR_NOSUPP;
reason = 5;
goto drop;
}
flash_info->mode = flash_mode;
flash_size = iot_sg_flash_init();
flash_info->erase_unit_size = (uint16_t)iot_sg_flash_erase_once_query();
if (flash_mode == IOT_SG_STA_FLASH_SM_GW &&
iot_sg_flash_type_is_internal_check() == ERR_OK &&
(flash_info->erase_unit_size == IOT_SG_STA_FLASH_ERASE_SIZE_4K ||
flash_info->erase_unit_size == IOT_SG_STA_FLASH_ERASE_SIZE_256B)) {
flash_info->erase_mode = IOT_SG_STA_FLASH_ERASE_MODE_EACH_PAGE_BEG;
ret = iot_sg_sta_flash_get_storage_mode_alignment(flash_mode,
flash_info);
} else {
flash_info->erase_mode = IOT_SG_STA_FLASH_ERASE_MODE_EACH_WRITE;
ret = iot_sg_sta_flash_get_storage_mode(flash_mode, flash_info);
}
iot_sg_printf("user_type %d, dev_type %d, erase_size %d erase_mode %d\n",
user_type, dev_type, flash_info->erase_unit_size,
flash_info->erase_mode);
if (ret) {
reason = 6;
goto drop;
}
cfg_len = iot_sg_sta_flash_cfg_get_cfg_len();
cfg_len = iot_sg_sta_flash_alignment_handle(cfg_len);
total_size = flash_info->flash_mode->space_size *
flash_info->flash_mode->meter_cnt + cfg_len;
iot_sg_printf("%s Flash size %lu, demand size %lu\n", __FUNCTION__,
flash_size, total_size);
if (flash_size < total_size) {
ret = ERR_NOSUPP;
reason = 7;
goto drop;
}
flash_size -= cfg_len;
crc_buf = os_mem_malloc(IOT_SMART_GRID_MID, IOT_SG_STA_FLASH_CRC_BUF_LEN);
if (crc_buf == NULL) {
ret = ERR_NOMEM;
reason = 8;
goto drop;
}
desc_buf = os_mem_malloc(IOT_SMART_GRID_MID, IOT_SG_STA_FLASH_DESC_BUF_LEN);
if (desc_buf == NULL) {
ret = ERR_NOMEM;
reason = 9;
goto drop;
}
total_cnt = min((uint8_t)(flash_size / flash_info->flash_mode->space_size),
min(IOT_SG_STA_FLASH_METER_MAX_CNT, flash_info->flash_mode->meter_cnt));
if (!total_cnt) {
ret = ERR_NOSUPP;
reason = 10;
goto drop;
}
ret = iot_sg_sta_flash_meter_desc_init(total_cnt,
flash_info->flash_mode->cnt, desc_buf, IOT_SG_STA_FLASH_DESC_BUF_LEN);
if (ret) {
ret = ERR_NOSUPP;
reason = 11;
goto drop;
}
flash_info->crc_buf = crc_buf;
flash_info->flash_desc_buf = desc_buf;
offset = IOT_SG_STA_METER_START_OFFSET + cfg_len;
offset = iot_sg_sta_flash_alignment_handle(offset);
meter_list = (iot_sg_sta_flash_meter_desc_t*)flash_info->flash_desc_buf;
for (i = 0; i < flash_info->total_meter_cnt; i++) {
ret = iot_sg_sta_flash_meter_init(offset, &meter_list[i]);
if (ret == ERR_OK) {
flash_info->free_meter_cnt--;
}
offset += flash_info->flash_mode->space_size;
}
flash_info->flash_en = 1;
ret = ERR_OK;
goto out;
drop:
if (crc_buf) {
os_mem_free(crc_buf);
}
flash_info->crc_buf = NULL;
if (desc_buf) {
os_mem_free(desc_buf);
}
flash_info->flash_desc_buf = NULL;
flash_info->flash_en = 0;
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
void iot_sg_sta_flash_deinit(void)
{
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
if (flash_info->flash_en) {
if (flash_info->crc_buf) {
os_mem_free(flash_info->crc_buf);
}
if (flash_info->flash_desc_buf) {
os_mem_free(flash_info->flash_desc_buf);
}
flash_info->flash_desc_buf = NULL;
flash_info->crc_buf = NULL;
flash_info->flash_en = 0;
}
}
static uint32_t iot_sg_sta_flash_get_meter_sn_max(void)
{
uint8_t i;
uint32_t sn = 0;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
iot_sg_sta_flash_meter_desc_t *meter_list = NULL;
IOT_ASSERT(flash_info->total_meter_cnt <= IOT_SG_STA_FLASH_METER_MAX_CNT);
meter_list = (iot_sg_sta_flash_meter_desc_t*)flash_info->flash_desc_buf;
for (i = 0; i < flash_info->total_meter_cnt; i++) {
if (!iot_mac_addr_valid(meter_list[i].meter_hdr.mac)) {
continue;
}
if (meter_list[i].meter_hdr.sn > sn) {
sn = meter_list[i].meter_hdr.sn;
}
}
return sn;
}
static iot_sg_sta_flash_meter_desc_t* iot_sg_sta_flash_find_sn_min_meter(void)
{
uint8_t i;
uint32_t sn = 0;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
iot_sg_sta_flash_meter_desc_t *meter_list, *meter_info = NULL;
IOT_ASSERT(flash_info->total_meter_cnt);
meter_list = (iot_sg_sta_flash_meter_desc_t*)flash_info->flash_desc_buf;
for (i = 0; i < flash_info->total_meter_cnt; i++) {
if (!iot_mac_addr_valid(meter_list[i].meter_hdr.mac)) {
continue;
}
if (sn == 0) {
sn = meter_list[i].meter_hdr.sn;
meter_info = &meter_list[i];
} else {
if (meter_list[i].meter_hdr.sn < sn) {
sn = meter_list[i].meter_hdr.sn;
meter_info = &meter_list[i];
}
}
}
return meter_info;
}
static void iot_sg_sta_flash_data_reset(uint32_t offset, uint32_t len)
{
iot_pkt_t *pkt;
uint8_t *buf;
uint32_t data_offset = offset;
uint32_t data_len = len, reset_len, buf_len;
if (iot_sg_flash_type_is_internal_check() != ERR_OK) {
iot_sg_flash_erase(offset, len);
} else {
buf_len = min(data_len, IOT_SG_STA_FLASH_RESET_MAX_BUF_LEN);
pkt = iot_pkt_alloc(buf_len, IOT_SMART_GRID_MID);
if ((pkt == NULL) && (buf_len == IOT_SG_STA_FLASH_RESET_MAX_BUF_LEN)) {
buf_len = IOT_SG_STA_FLASH_RESET_DEF_BUF_LEN;
pkt = iot_pkt_alloc(buf_len, IOT_SMART_GRID_MID);
}
if (pkt == NULL) {
goto out;
}
buf = iot_pkt_put(pkt, buf_len);
os_mem_set(buf, 0, buf_len);
while (data_len) {
reset_len = min(data_len, buf_len);
iot_sg_flash_write_without_erase(data_offset, reset_len, buf);
data_len -= reset_len;
data_offset += reset_len;
os_delay(5);
}
iot_pkt_free(pkt);
}
out:
return;
}
uint32_t iot_sg_sta_flash_meter_add(uint8_t *addr)
{
uint8_t i;
uint32_t ret = ERR_OK, offset;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_list = NULL;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
if (!flash_info->flash_en) {
ret = ERR_NOSUPP;
goto out;
}
meter_info = iot_sg_sta_flash_meter_find(addr);
if (meter_info) {
meter_info->meter_hdr.sn = iot_sg_sta_flash_get_meter_sn_max() + 1;
goto update;
}
meter_info = iot_sg_sta_flash_meter_alloc();
if (!meter_info) {
/* delete old meter information in flash */
meter_info = iot_sg_sta_flash_find_sn_min_meter();
}
if (!meter_info) {
ret = ERR_NOMEM;
goto out;
}
os_mem_set(&meter_info->meter_hdr, 0, sizeof(meter_info->meter_hdr));
os_mem_set(meter_info->data_list, 0,
sizeof(iot_sg_sta_flash_meter_data_desc_t) * meter_info->data_cnt);
iot_mac_addr_cpy(meter_info->meter_hdr.mac, addr);
meter_info->meter_hdr.data_len = (flash_info->flash_mode->space_size -
IOT_SG_STA_METER_HEADER_LEN);
iot_sg_sta_flash_data_reset(meter_info->offset + \
sizeof(iot_sg_sta_drv_meter_hdr_t), meter_info->meter_hdr.data_len);
meter_info->meter_hdr.cnt = flash_info->flash_mode->cnt;
meter_info->meter_hdr.sn = iot_sg_sta_flash_get_meter_sn_max() + 1;
offset = (meter_info->offset + sizeof(meter_info->meter_hdr));
offset = iot_sg_sta_flash_alignment_handle(offset);
data_list = meter_info->data_list;
for (i = 0; i < flash_info->flash_mode->cnt; i++) {
data_list[i].offset = offset;
data_list[i].data_hdr.data_type =
flash_info->flash_mode->data[i].type;
data_list[i].data_hdr.data_len =
flash_info->flash_mode->data[i].len;
data_list[i].data_hdr.hdr_crc =
iot_getcrc8((uint8_t*)&data_list[i].data_hdr,
(sizeof(data_list[i].data_hdr) - 1));
ret = iot_sg_flash_write(data_list[i].offset,
sizeof(data_list[i].data_hdr), (uint8_t*)&data_list[i].data_hdr);
if (ret) {
iot_sg_printf("%s flash write err\n", __FUNCTION__);
}
offset += (flash_info->flash_mode->data[i].len +
IOT_SG_STA_METER_DATA_HEADER_LEN);
}
update:
meter_info->meter_hdr.hdr_crc =
iot_getcrc8((uint8_t*)&meter_info->meter_hdr,
(sizeof(meter_info->meter_hdr) - 1));
ret = iot_sg_flash_write(meter_info->offset, sizeof(meter_info->meter_hdr),
(uint8_t*)&meter_info->meter_hdr);
if (ret) {
iot_sg_printf("%s flash update err\n", __FUNCTION__);
}
out:
return ret;
}
uint32_t iot_sg_sta_flash_meter_delete(uint8_t *addr)
{
uint32_t ret = ERR_OK;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
iot_sg_sta_flash_meter_data_desc_t *data_list;
if (!flash_info->flash_en) {
ret = ERR_NOSUPP;
goto out;
}
meter_info = iot_sg_sta_flash_meter_find(addr);
if (!meter_info) {
ret = ERR_NOT_EXIST;
goto out;
}
data_list = meter_info->data_list;
os_mem_set(&meter_info->meter_hdr, 0, sizeof(meter_info->meter_hdr));
os_mem_set(data_list, 0, (sizeof(iot_sg_sta_flash_meter_data_desc_t)
* meter_info->data_cnt));
ret = iot_sg_flash_write(meter_info->offset, sizeof(meter_info->meter_hdr),
(uint8_t*)&meter_info->meter_hdr);
if (ret) {
iot_sg_printf("%s flash write err\n", __FUNCTION__);
}
flash_info->free_meter_cnt++;
out:
return ret;
}
static uint32_t iot_sg_sta_flash_meter_data_read(uint8_t *addr,
uint8_t data_type, uint8_t *data, uint32_t len, uint32_t offset)
{
uint8_t i;
uint32_t data_offset;
uint32_t ret = ERR_OK;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_list = NULL;
if (!data || !len) {
ret = ERR_FAIL;
goto out;
}
meter_info = iot_sg_sta_flash_meter_find(addr);
if (!meter_info) {
ret = ERR_NOT_EXIST;
goto out;
}
data_list = meter_info->data_list;
for (i = 0; i < meter_info->data_cnt; i++) {
if (data_list[i].data_hdr.data_type == data_type) {
data_info = &data_list[i];
}
}
if (data_info == NULL) {
ret = ERR_NOT_EXIST;
goto out;
}
if ((offset + len) > data_info->data_hdr.data_len) {
ret = ERR_NOT_EXIST;
goto out;
}
data_offset = data_info->offset + IOT_SG_STA_METER_DATA_HEADER_LEN + offset;
ret = iot_sg_flash_read(data_offset, len, data);
out:
return ret;
}
static uint32_t iot_sg_sta_flash_meter_data_write(uint8_t *addr,
uint8_t data_type, uint8_t *data, uint32_t len, uint32_t offset,
uint8_t flag_erase)
{
uint8_t i;
uint32_t data_offset;
uint32_t ret = ERR_OK;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_list = NULL;
if (!data || !len) {
ret = ERR_FAIL;
goto out;
}
meter_info = iot_sg_sta_flash_meter_find(addr);
if (!meter_info) {
ret = ERR_NOT_EXIST;
goto out;
}
data_list = meter_info->data_list;
for (i = 0; i < meter_info->data_cnt; i++) {
if (data_list[i].data_hdr.data_type == data_type) {
data_info = &data_list[i];
}
}
if (data_info == NULL) {
ret = ERR_NOT_EXIST;
goto out;
}
if ((offset + len) > data_info->data_hdr.data_len) {
ret = ERR_FAIL;
goto out;
}
data_offset = data_info->offset + IOT_SG_STA_METER_DATA_HEADER_LEN + offset;
if (flag_erase) {
ret = iot_sg_flash_write(data_offset, len, data);
} else {
ret = iot_sg_flash_write_without_erase(data_offset, len, data);
}
out:
return ret;
}
static uint16_t iot_sg_sta_flash_unit_get_rsvd_len(uint8_t data_type)
{
uint16_t rsvd_len = 0;
uint16_t erase_size = p_sg_glb->desc.sta->flash_info.erase_unit_size;
switch (data_type) {
case IOT_SG_STA_METER_DATA_TYPE_JS_1MIN_CURVE:
if (iot_sg_sta_flash_mode_js_sig_check()) {
if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_4K) {
rsvd_len = IOT_SG_STA_METER_JS_SIG_MIN_DATA_RSCD_LEN_4K;
}
} else {
if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_4K) {
rsvd_len = IOT_SG_STA_METER_JS_MIN_DATA_RSCD_LEN_4K;
}
}
break;
case IOT_SG_STA_METER_DATA_TYPE_XIAN_LC:
if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_4K) {
rsvd_len = IOT_SG_STA_METER_XIAN_LC_DATA_RSVD_LEN_4K;
} else if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_256B) {
rsvd_len = IOT_SG_STA_METER_XIAN_LC_DATA_RSVD_LEN_256B;
}
break;
case IOT_SG_STA_METER_DATA_TYPE_GX_LC:
if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_256B) {
rsvd_len = IOT_SG_STA_METER_GX_LC_DATA_RSVD_LEN_256B;
} else if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_4K) {
rsvd_len = IOT_SG_STA_METER_GX_LC_DATA_RSVD_LEN_4K;
}
break;
case IOT_SG_STA_METER_DATA_TYPE_PW_LC:
if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_4K) {
rsvd_len = IOT_SG_STA_METER_PW_LC_DATA_RSVD_LEN_4K;
}
break;
default:
break;
}
return rsvd_len;
}
uint32_t iot_sg_sta_flash_unit_get_data_info(uint8_t data_type,
uint16_t *unit_len, uint16_t *max_cnt)
{
uint32_t ret = ERR_NOSUPP;
uint16_t node_cnt_max = 0, node_unit_len = IOT_SG_STA_FLASH_CRC_LENGTH;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
uint16_t erase_size = flash_info->erase_unit_size;
if (unit_len == NULL && max_cnt == NULL) {
ret = ERR_INVAL;
goto out;
}
switch (data_type) {
case IOT_SG_STA_METER_DATA_TYPE_GX_LC:
{
node_unit_len += sizeof(iot_sg_meter_gx_lc_uint_data_t);
if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_4K) {
node_cnt_max = IOT_SG_STA_METER_GX_LC_CNT_4K;
} else if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_256B) {
node_cnt_max = IOT_SG_STA_METER_GX_LC_CNT_256B;
} else {
goto out;
}
break;
}
case IOT_SG_STA_METER_DATA_TYPE_XIAN_LC:
{
node_unit_len += sizeof(iot_sg_meter_lc_uint_xian_data_t);
if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_4K) {
node_cnt_max = IOT_SG_STA_METER_XIAN_LC_CNT_4K;
} else if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_256B) {
node_cnt_max = IOT_SG_STA_METER_XIAN_LC_CNT_256B;
} else {
goto out;
}
break;
}
case IOT_SG_STA_METER_DATA_TYPE_PW_LC:
{
node_unit_len += sizeof(iot_sg_meter_pw_lc_uint_data_t);
if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_4K) {
node_cnt_max = IOT_SG_STA_METER_PW_LC_CNT_4K;
} else if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_256B) {
node_cnt_max = IOT_SG_STA_METER_PW_LC_CNT_256B;
} else {
goto out;
}
break;
}
case IOT_SG_STA_METER_DATA_TYPE_JS_MF:
{
node_unit_len += sizeof(iot_sg_meter_js_frozen_uint_data_t);
node_cnt_max = IOT_SG_STA_METER_JS_MF_MARK_MAX_CNT;
break;
}
case IOT_SG_STA_METER_DATA_TYPE_JS_DF:
{
node_unit_len += sizeof(iot_sg_meter_js_frozen_uint_data_t);
node_cnt_max = IOT_SG_STA_METER_JS_DF_MARK_MAX_CNT;
break;
}
case IOT_SG_STA_METER_DATA_TYPE_JS_15MIN_CURVE:
{
if (iot_sg_sta_flash_mode_js_sig_check()) {
node_unit_len += sizeof(iot_sg_meter_js_sig_frozen_uint_data_t);
} else {
node_unit_len += sizeof(iot_sg_meter_js_frozen_uint_data_t);
}
node_cnt_max = IOT_SG_STA_METER_JS_15MIN_CURVE_MARK_MAX_CNT;
break;
}
case IOT_SG_STA_METER_DATA_TYPE_JS_1MIN_CURVE:
{
if (iot_sg_sta_flash_mode_js_sig_check()) {
node_unit_len += sizeof(iot_sg_meter_js_sig_frozen_uint_data_t);
} else {
node_unit_len += sizeof(iot_sg_meter_js_min_curve_uint_data_t);
}
node_cnt_max = IOT_SG_STA_METER_JS_1MIN_CURVE_MARK_MAX_CNT;
break;
}
case IOT_SG_STA_METER_DATA_TYPE_NW_TASK:
{
node_unit_len = sizeof(iot_sg_meter_lc_uint_nw_data_t);
node_cnt_max = IOT_SG_STA_METER_NW_LC_CNT;
break;
}
case IOT_SG_STA_METER_DATA_TYPE_FJ_TASK:
{
node_unit_len += sizeof(iot_sg_sta_drv_meter_fj_task_unit_t);
node_cnt_max = IOT_SG_STA_METER_FJ_FRZ_TASK_MARK_MAX_CNT;
break;
}
case IOT_SG_STA_METER_DATA_TYPE_AI_LL:
{
node_unit_len += sizeof(iot_sg_meter_ai_ll_unit_data_t);
node_cnt_max = IOT_SG_STA_METER_AI_LL_CNT;
break;
}
case IOT_SG_STA_METER_DATA_TYPE_GW_TASK:
{
node_unit_len += sizeof(iot_sg_meter_lc_uint_xian_data_t);
if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_4K) {
node_cnt_max = IOT_SG_STA_METER_GW_CLCT_CNT_4K;
} else if (erase_size == IOT_SG_STA_FLASH_ERASE_SIZE_256B) {
node_cnt_max = IOT_SG_STA_METER_GW_CLCT_CNT_256B;
} else {
goto out;
}
break;
}
case IOT_SG_STA_METER_DATA_TYPE_EC:
{
node_unit_len = sizeof(iot_sg_sta_drv_meter_ss_data_t);
node_cnt_max = IOT_SG_STA_METER_NW_EC_CNT;
break;
}
default:
ret = ERR_NOSUPP;
goto out;
}
node_unit_len += iot_sg_sta_flash_unit_get_rsvd_len(data_type);
if (max_cnt) {
*max_cnt = node_cnt_max;
}
if (unit_len) {
*unit_len = node_unit_len;
}
ret = ERR_OK;
out:
return ret;
}
uint32_t iot_sg_sta_flash_unit_data_save(uint8_t *addr,
uint16_t index, uint8_t *data, uint16_t len, uint8_t data_type)
{
uint16_t index_max, unit_len;
uint32_t ret, offset = 0;
iot_sg_meter_lc_uint_nw_data_t *flash_nw_data;
ret = iot_sg_sta_flash_unit_get_data_info(data_type, &unit_len, &index_max);
if (ret) {
goto out;
}
if ((index >= index_max) || (len < unit_len)) {
ret = ERR_FAIL;
goto out;
}
offset += index * unit_len;
switch (data_type) {
case IOT_SG_STA_METER_DATA_TYPE_PW_LC:
case IOT_SG_STA_METER_DATA_TYPE_JS_MF:
case IOT_SG_STA_METER_DATA_TYPE_JS_DF:
case IOT_SG_STA_METER_DATA_TYPE_JS_15MIN_CURVE:
case IOT_SG_STA_METER_DATA_TYPE_JS_1MIN_CURVE:
case IOT_SG_STA_METER_DATA_TYPE_XIAN_LC:
case IOT_SG_STA_METER_DATA_TYPE_AI_LL:
case IOT_SG_STA_METER_DATA_TYPE_GX_LC:
{
data[unit_len - 1] = iot_getcrc8(data, unit_len - 1);
break;
}
case IOT_SG_STA_METER_DATA_TYPE_NW_TASK:
{
flash_nw_data = (iot_sg_meter_lc_uint_nw_data_t *)data;
flash_nw_data->crc = iot_getcrc8((uint8_t *)flash_nw_data,
sizeof(*flash_nw_data) - 1);
break;
}
default:
IOT_ASSERT(0);
}
ret = iot_sg_sta_flash_meter_data_write(addr, data_type, data, unit_len,
offset, 1);
out:
return ret;
}
uint32_t iot_sg_sta_flash_unit_data_read(uint8_t *addr,
uint16_t index, uint8_t *data, uint16_t len, uint8_t data_type)
{
uint8_t crc;
uint16_t index_max, unit_len;
uint32_t offset = 0, ret = ERR_FAIL;
iot_sg_meter_lc_uint_nw_data_t *flash_nw_data;
ret = iot_sg_sta_flash_unit_get_data_info(data_type, &unit_len, &index_max);
if (ret) {
goto out;
}
if ((index >= index_max) || (len < unit_len)) {
goto out;
}
offset += index * unit_len;
ret = iot_sg_sta_flash_meter_data_read(addr, data_type,
data, unit_len, offset);
if (ret != ERR_OK) {
goto out;
}
switch (data_type) {
case IOT_SG_STA_METER_DATA_TYPE_PW_LC:
case IOT_SG_STA_METER_DATA_TYPE_JS_MF:
case IOT_SG_STA_METER_DATA_TYPE_JS_DF:
case IOT_SG_STA_METER_DATA_TYPE_JS_15MIN_CURVE:
case IOT_SG_STA_METER_DATA_TYPE_JS_1MIN_CURVE:
case IOT_SG_STA_METER_DATA_TYPE_XIAN_LC:
case IOT_SG_STA_METER_DATA_TYPE_AI_LL:
case IOT_SG_STA_METER_DATA_TYPE_GX_LC:
{
if (data[unit_len - 1] != iot_getcrc8(data, unit_len - 1)) {
ret = ERR_FAIL;
}
break;
}
case IOT_SG_STA_METER_DATA_TYPE_NW_TASK:
{
flash_nw_data = (iot_sg_meter_lc_uint_nw_data_t*)data;
crc = iot_getcrc8((uint8_t*)flash_nw_data,
(sizeof(*flash_nw_data) - 1));
if (crc != flash_nw_data->crc) {
ret = ERR_FAIL;
}
break;
}
default:
IOT_ASSERT(0);
}
out:
return ret;
}
static iot_pkt_t *iot_sg_sta_flash_unit_cache_alloc(uint8_t data_type)
{
iot_pkt_t *pkt = NULL;
uint16_t pkt_len = 0;
switch (data_type) {
case IOT_SG_STA_METER_DATA_TYPE_JS_MF:
case IOT_SG_STA_METER_DATA_TYPE_JS_DF:
case IOT_SG_STA_METER_DATA_TYPE_JS_15MIN_CURVE:
case IOT_SG_STA_METER_DATA_TYPE_JS_1MIN_CURVE:
pkt_len = IOT_SG_STA_FLASH_MULTI_BUF_LEN;
break;
default:
if (iot_sg_sta_flash_unit_get_data_info(data_type, &pkt_len, NULL)) {
goto out;
}
break;
}
pkt = iot_pkt_alloc(pkt_len, IOT_SMART_GRID_MID);
if (!pkt) {
iot_sg_printf("%s pkt err\n", __FUNCTION__);
goto out;
}
iot_pkt_put(pkt, pkt_len);
out:
return pkt;
}
uint32_t iot_sg_sta_flash_get_uint_time(uint8_t *data, uint16_t len,
uint8_t data_type, iot_time_tm_t *curr_ts)
{
uint32_t ret = ERR_FAIL;
iot_sg_meter_unit_time_with_sec_t *unit_time_with_sec;
iot_sg_sta_drv_meter_ct_unit_head_t *ct_time;
iot_sg_meter_unit_time_t *unit_time;
if (data_type == IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT) {
if (len < sizeof(*ct_time)) {
goto out;
}
ct_time = (iot_sg_sta_drv_meter_ct_unit_head_t*)data;
curr_ts->tm_year = (uint16_t)ct_time->year + 2000;
curr_ts->tm_mon = (uint8_t)ct_time->month;
curr_ts->tm_mday = (uint8_t)ct_time->day;
curr_ts->tm_hour = (uint8_t)ct_time->hour;
curr_ts->tm_min = (uint8_t)ct_time->minute;
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_FJ_TASK
|| data_type == IOT_SG_STA_METER_DATA_TYPE_AI_LL) {
if (len < sizeof(*unit_time_with_sec)) {
goto out;
}
unit_time_with_sec = (iot_sg_meter_unit_time_with_sec_t*)data;
curr_ts->tm_year = (uint16_t)unit_time_with_sec->year + 2000;
curr_ts->tm_mon = (uint8_t)unit_time_with_sec->month;
curr_ts->tm_mday = (uint8_t)unit_time_with_sec->day;
curr_ts->tm_hour = (uint8_t)unit_time_with_sec->hour;
curr_ts->tm_min = (uint8_t)unit_time_with_sec->minute;
curr_ts->tm_sec = unit_time_with_sec->second;
} else {
if (len < sizeof(*unit_time)) {
goto out;
}
unit_time = (iot_sg_meter_unit_time_t*)data;
curr_ts->tm_year = (uint16_t)unit_time->year + 2000;
curr_ts->tm_mon = (uint8_t)unit_time->month;
curr_ts->tm_mday = (uint8_t)unit_time->day;
curr_ts->tm_hour = (uint8_t)unit_time->hour;
curr_ts->tm_min = (uint8_t)unit_time->minute;
}
if (iot_time_ymdhms_valid(curr_ts)) {
ret = ERR_OK;
}
out:
return ret;
}
static uint32_t iot_sg_sta_flash_find_by_latest(uint8_t *dst,
uint16_t *dst_index, uint8_t *src, uint16_t start_idx, uint16_t unit_cnt,
uint16_t unit_len, iot_time_tm_t *last_ts, uint8_t data_type)
{
uint8_t *data = src, crc;
uint16_t i;
uint32_t complete = 0;
int64_t delta;
iot_time_tm_t curr_ts = { 0 };
iot_sg_meter_unit_time_t *unit_time;
iot_sg_meter_unit_time_with_sec_t *unit_time_with_sec;
for (i = 0; i < unit_cnt; i++) {
crc = iot_getcrc8(data, (unit_len - 1));
if (crc != data[unit_len - 1]) {
goto next;
}
if (iot_sg_sta_flash_get_uint_time(data, (unit_len - 1), data_type,
&curr_ts)) {
goto out;
}
if (data_type == IOT_SG_STA_METER_DATA_TYPE_FJ_TASK
|| data_type == IOT_SG_STA_METER_DATA_TYPE_AI_LL) {
unit_time_with_sec = (iot_sg_meter_unit_time_with_sec_t*)data;
curr_ts.tm_year = (uint16_t)unit_time_with_sec->year + 2000;
curr_ts.tm_mon = (uint8_t)unit_time_with_sec->month;
curr_ts.tm_mday = (uint8_t)unit_time_with_sec->day;
curr_ts.tm_hour = (uint8_t)unit_time_with_sec->hour;
curr_ts.tm_min = (uint8_t)unit_time_with_sec->minute;
curr_ts.tm_sec = unit_time_with_sec->second;
} else {
unit_time = (iot_sg_meter_unit_time_t*)data;
curr_ts.tm_year = (uint16_t)unit_time->year + 2000;
curr_ts.tm_mon = (uint8_t)unit_time->month;
curr_ts.tm_mday = (uint8_t)unit_time->day;
curr_ts.tm_hour = (uint8_t)unit_time->hour;
curr_ts.tm_min = (uint8_t)unit_time->minute;
}
delta = iot_rtc_delta_calc(last_ts, &curr_ts);
if (delta >= 0) {
*dst_index = start_idx + i;
os_mem_cpy(dst, data, unit_len);
*last_ts = curr_ts;
complete = 1;
}
next:
data += unit_len;
}
out:
return complete;
}
uint32_t iot_sg_sta_flash_unit_data_find_latest(uint8_t *addr,
uint16_t *index_ptr, uint8_t *data, uint16_t len, uint8_t data_type)
{
uint8_t *buf;
uint16_t unit_len, index, buf_len, max_cnt = 0, valid_cnt = 0;
uint32_t ret, complete = 0, offset, valid_len;
iot_pkt_t *pkt;
iot_time_tm_t last_ts = { 0 };
pkt = iot_sg_sta_flash_unit_cache_alloc(data_type);
if (!pkt) {
goto out;
}
buf = iot_pkt_data(pkt);
buf_len = (uint16_t)iot_pkt_data_len(pkt);
last_ts.tm_year = 2000;
last_ts.tm_mon = 1;
last_ts.tm_mday = 1;
ret = iot_sg_sta_flash_unit_get_data_info(data_type, &unit_len, &max_cnt);
if ((data == NULL) || (len < unit_len) || (buf_len < len) || ret) {
goto out;
}
for (index = 0; index < max_cnt;
index = (valid_cnt ? (index + valid_cnt) : (index + 1))) {
valid_cnt = buf_len / unit_len;
if (index + valid_cnt >= max_cnt) {
valid_cnt = max_cnt - index;
}
offset = index * unit_len;
valid_len = valid_cnt * unit_len;
ret = iot_sg_sta_flash_meter_data_read(addr, data_type,
buf, valid_len, offset);
if (ret != ERR_OK) {
continue;
}
if (iot_sg_sta_flash_find_by_latest(data, index_ptr,
buf, index, valid_cnt, unit_len, &last_ts, data_type)) {
complete = 1;
}
}
out:
if (complete) {
ret = ERR_OK;
} else {
ret = ERR_FAIL;
}
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
static uint32_t iot_sg_sta_flash_find_by_time(uint8_t *dst,
uint16_t *dst_index, uint8_t *src, uint16_t start_idx, uint16_t unit_cnt,
uint16_t unit_len, iot_time_tm_t *tm, int64_t *last_delta, uint8_t *is_over,
uint8_t flag_up, uint8_t data_type)
{
uint8_t *data = src, crc;
uint16_t i;
uint32_t complete = 0;
int64_t delta;
iot_time_tm_t curr_ts = { 0 };
for (i = 0; i < unit_cnt; i++) {
crc = iot_getcrc8(data, (unit_len - 1));
if (crc != data[unit_len - 1]) {
goto next;
}
if (iot_sg_sta_flash_get_uint_time(data, (unit_len - 1), data_type,
&curr_ts)) {
goto out;
}
if (flag_up) {
delta = iot_rtc_delta_calc(&curr_ts, tm);
} else {
delta = iot_rtc_delta_calc(tm, &curr_ts);
}
if (delta == 0) {
*dst_index = start_idx + i;
os_mem_cpy(dst, data, unit_len);
*is_over = 1;
complete = 1;
goto out;
} else {
if ((delta > 0) && (!(*last_delta) || (delta < (*last_delta)))) {
*dst_index = start_idx + i;
os_mem_cpy(dst, data, unit_len);
*last_delta = delta;
complete = 1;
}
}
next:
data += unit_len;
}
out:
return complete;
}
uint32_t iot_sg_sta_flash_unit_data_find_by_time(uint8_t *addr,
uint16_t *index_ptr, iot_time_tm_t *tm, uint8_t *data, uint16_t len,
uint8_t data_type, uint8_t flag_up)
{
uint8_t *buf, is_over;
uint16_t unit_len, index, buf_len, max_cnt = 0, valid_cnt = 0;
uint32_t ret, complete = 0, offset, valid_len;
int64_t last_delta = 0;
iot_pkt_t *pkt = NULL;
pkt = iot_sg_sta_flash_unit_cache_alloc(data_type);
if (!pkt) {
goto out;
}
buf = iot_pkt_data(pkt);
buf_len = (uint16_t)iot_pkt_data_len(pkt);
ret = iot_sg_sta_flash_unit_get_data_info(data_type, &unit_len, &max_cnt);
if ((data == NULL) || (len < unit_len) || (buf_len < len) || ret) {
goto out;
}
for (index = 0; index < max_cnt;
index = (valid_cnt ? (index + valid_cnt) : (index + 1))) {
valid_cnt = buf_len / unit_len;
if (index + valid_cnt >= max_cnt) {
valid_cnt = max_cnt - index;
}
offset = index * unit_len;
valid_len = valid_cnt * unit_len;
ret = iot_sg_sta_flash_meter_data_read(addr, data_type,
buf, valid_len, offset);
if (ret != ERR_OK) {
continue;
}
is_over = 0;
if (iot_sg_sta_flash_find_by_time(data, index_ptr,
buf, index, valid_cnt, unit_len, tm, &last_delta, &is_over,
flag_up, data_type)) {
complete = 1;
}
if (is_over) {
goto out;
}
}
out:
if (complete) {
ret = ERR_OK;
} else {
ret = ERR_FAIL;
}
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
uint32_t iot_sg_sta_flash_unit_data_find_by_multiple_time(uint8_t *addr,
uint16_t *index_ptr, iot_time_tm_t *tm, uint8_t tm_cnt, uint8_t data_type,
uint8_t *flag_up)
{
uint8_t *buf, *tmp_buf = NULL, is_over, i;
uint16_t unit_len, index, buf_len, max_cnt = 0, valid_cnt = 0;
uint32_t ret, complete = 0, offset, valid_len, tm_bm = 0;
int64_t last_delta[IOT_SG_STA_FLASH_UNIT_DATA_FIND_BY_TIME_MAX_CNT] = { 0 };
iot_pkt_t *pkt = NULL, *tmp_pkt = NULL;
os_mem_set(index_ptr, 0xff, sizeof(*index_ptr) * tm_cnt);
ret = iot_sg_sta_flash_unit_get_data_info(data_type, &unit_len, &max_cnt);
if (ret) {
goto out;
}
if (tm_cnt > IOT_SG_STA_FLASH_UNIT_DATA_FIND_BY_TIME_MAX_CNT) {
tm_cnt = IOT_SG_STA_FLASH_UNIT_DATA_FIND_BY_TIME_MAX_CNT;
}
pkt = iot_sg_sta_flash_unit_cache_alloc(data_type);
if (!pkt) {
goto out;
}
buf = iot_pkt_data(pkt);
buf_len = (uint16_t)iot_pkt_data_len(pkt);
tmp_pkt = iot_pkt_alloc(unit_len, IOT_SMART_GRID_MID);
if (!tmp_pkt) {
goto out;
}
tmp_buf = iot_pkt_put(tmp_pkt, unit_len);
for (index = 0; index < max_cnt;
index = (valid_cnt ? (index + valid_cnt) : (index + 1))) {
valid_cnt = buf_len / unit_len;
if (index + valid_cnt >= max_cnt) {
valid_cnt = max_cnt - index;
}
offset = index * unit_len;
valid_len = valid_cnt * unit_len;
ret = iot_sg_sta_flash_meter_data_read(addr, data_type,
buf, valid_len, offset);
if (ret != ERR_OK) {
continue;
}
is_over = 0;
for (i = 0; i < tm_cnt; i++) {
if (tm_bm & (1 << i)) {
continue;
}
if (iot_sg_sta_flash_find_by_time(tmp_buf, &index_ptr[i], buf,
index, valid_cnt, unit_len, &tm[i], &last_delta[i],
&is_over, flag_up[i], data_type)) {
complete = 1;
}
if (is_over) {
is_over = 0;
tm_bm |= (1 << i);
if (iot_bitmap_cbs((uint8_t *)&tm_bm, sizeof(tm_bm)) >=
tm_cnt) {
goto out;
}
}
}
}
out:
if (complete) {
ret = ERR_OK;
} else {
ret = ERR_FAIL;
}
if (pkt) {
iot_pkt_free(pkt);
}
if (tmp_pkt) {
iot_pkt_free(tmp_pkt);
}
return ret;
}
static uint16_t iot_sg_sta_flash_uint_clear_by_time(uint8_t *src,
uint32_t start_offset, uint16_t unit_cnt, uint16_t unit_len,
iot_time_tm_t *tm, uint8_t *addr, uint8_t data_type)
{
uint8_t *data = src, crc;
uint16_t i, start = 0xffff, end = 0xffff, clear_cnt = 0;
uint32_t clear_len, clear_offset;
int64_t delta;
iot_time_tm_t curr_ts = { 0 };
iot_sg_meter_unit_time_t *unit_time;
iot_sg_meter_unit_time_with_sec_t *unit_time_with_sec;
for (i = 0; i < unit_cnt; i++) {
crc = iot_getcrc8(data, (unit_len - 1));
if (crc != data[unit_len - 1]) {
goto next;
}
if (data_type == IOT_SG_STA_METER_DATA_TYPE_AI_LL) {
unit_time_with_sec = (iot_sg_meter_unit_time_with_sec_t*)data;
curr_ts.tm_year = (uint16_t)unit_time_with_sec->year + 2000;
curr_ts.tm_mon = (uint8_t)unit_time_with_sec->month;
curr_ts.tm_mday = (uint8_t)unit_time_with_sec->day;
curr_ts.tm_hour = (uint8_t)unit_time_with_sec->hour;
curr_ts.tm_min = (uint8_t)unit_time_with_sec->minute;
curr_ts.tm_sec = unit_time_with_sec->second;
} else {
unit_time = (iot_sg_meter_unit_time_t*)data;
curr_ts.tm_year = (uint16_t)unit_time->year + 2000;
curr_ts.tm_mon = (uint8_t)unit_time->month;
curr_ts.tm_mday = (uint8_t)unit_time->day;
curr_ts.tm_hour = (uint8_t)unit_time->hour;
curr_ts.tm_min = (uint8_t)unit_time->minute;
}
unit_time = (iot_sg_meter_unit_time_t*)data;
curr_ts.tm_year = (uint16_t)unit_time->year + 2000;
curr_ts.tm_mon = (uint8_t)unit_time->month;
curr_ts.tm_mday = (uint8_t)unit_time->day;
curr_ts.tm_hour = (uint8_t)unit_time->hour;
curr_ts.tm_min = (uint8_t)unit_time->minute;
delta = iot_rtc_delta_calc(tm, &curr_ts);
if (delta > 0) {
if (start == 0xffff) {
start = i;
}
end = i + 1;
} else if (delta < 0) {
break;
}
next:
data += unit_len;
}
if (start != 0xffff) {
clear_len = (end - start) * unit_len;
os_mem_set(src, 0, clear_len);
clear_offset = start_offset + start * unit_len;
iot_sg_sta_flash_meter_data_write(addr, data_type,
src, clear_len, clear_offset, 0);
clear_cnt = end - start;
}
return clear_cnt;
}
uint16_t iot_sg_sta_flash_unit_data_check(uint8_t *addr, uint16_t index,
iot_time_tm_t *tm, uint8_t data_type)
{
uint8_t *buf;
uint16_t unit_len, i, buf_len, clear_cnt = 0, max_cnt = 0, valid_cnt = 0;
uint32_t ret, offset, valid_len;
iot_pkt_t *pkt;
pkt = iot_sg_sta_flash_unit_cache_alloc(data_type);
if (!pkt) {
goto out;
}
buf = iot_pkt_data(pkt);
buf_len = (uint16_t)iot_pkt_data_len(pkt);
ret = iot_sg_sta_flash_unit_get_data_info(data_type, &unit_len, &max_cnt);
if ((buf_len < unit_len) || ret) {
goto out;
}
for (i = 0; i < max_cnt; i = (valid_cnt ? (i + valid_cnt) : (i + 1))) {
valid_cnt = buf_len / unit_len;
if (index + valid_cnt >= max_cnt) {
valid_cnt = max_cnt - index;
}
offset = index * unit_len;
valid_len = valid_cnt * unit_len;
ret = iot_sg_sta_flash_meter_data_read(addr, data_type,
buf, valid_len, offset);
if (ret != ERR_OK) {
goto next;
}
clear_cnt += iot_sg_sta_flash_uint_clear_by_time(buf, offset,
valid_cnt, unit_len, tm, addr, data_type);
next:
index = (valid_cnt ? (index + valid_cnt) : (index + 1));
if (index >= max_cnt) {
index = 0;
}
}
out:
if (pkt) {
iot_pkt_free(pkt);
}
return clear_cnt;
}
static iot_sg_sta_flash_meter_data_desc_t*
iot_sg_sta_flash_clct_find_desc_by_task_id(
iot_sg_sta_flash_meter_desc_t *meter_info, uint8_t task_id)
{
uint8_t i;
iot_sg_sta_flash_meter_data_desc_t *meter_data = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_list = NULL;
if (!task_id || !meter_info) {
goto out;
}
data_list = meter_info->data_list;
for (i = 0; i < meter_info->data_cnt; i++) {
if (data_list[i].ct_info.task_id == task_id) {
meter_data = &data_list[i];
break;
}
}
out:
return meter_data;
}
static uint32_t iot_sg_sta_flash_ct_task_data_read(uint8_t *addr,
uint8_t task_id, uint8_t *data, uint32_t len, uint32_t offset_idx,
uint8_t type)
{
uint32_t data_offset, alignment_offset;
uint32_t ret = ERR_OK;
iot_sg_sta_drv_meter_ct_unit_tail_t *tail;
iot_sg_sta_flash_meter_data_desc_t *data_info = NULL;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
if (!data || !len) {
ret = ERR_FAIL;
goto out;
}
data_info = iot_sg_sta_flash_clct_find_desc_by_task_id(
iot_sg_sta_flash_meter_find(addr), task_id);
if (data_info == NULL) {
ret = ERR_NOT_EXIST;
goto out;
}
if (type == IOT_SG_STA_FLASH_CT_WR_MODE_INDEX) {
if ((offset_idx >= data_info->ct_info.unit_cnt) ||
(len != data_info->ct_info.unit_len)) {
ret = ERR_FAIL;
goto out;
}
data_offset = sizeof(iot_sg_sta_drv_meter_ct_hdr_t) +
(offset_idx * data_info->ct_info.unit_len);
} else {
data_offset = sizeof(iot_sg_sta_drv_meter_ct_hdr_t) + offset_idx;
}
if (flash_info->erase_mode == IOT_SG_STA_FLASH_ERASE_MODE_EACH_PAGE_BEG) {
alignment_offset = data_info->offset + IOT_SG_STA_METER_DATA_HEADER_LEN
+ sizeof(iot_sg_sta_drv_meter_ct_hdr_t);
alignment_offset = iot_sg_sta_flash_alignment_handle(alignment_offset) -
alignment_offset;
data_offset += alignment_offset;
}
if ((data_offset + len) > data_info->data_hdr.data_len) {
ret = ERR_NOT_EXIST;
goto out;
}
data_offset = data_info->offset + IOT_SG_STA_METER_DATA_HEADER_LEN
+ data_offset;
ret = iot_sg_flash_read(data_offset, len, data);
if (ret != ERR_OK) {
goto out;
}
if (type == IOT_SG_STA_FLASH_CT_WR_MODE_INDEX) {
tail = (iot_sg_sta_drv_meter_ct_unit_tail_t *)(data +
len - sizeof(*tail));
if (tail->crc != iot_getcrc8(data, (len - sizeof(*tail)))) {
ret = ERR_FAIL;
}
}
out:
return ret;
}
static uint32_t iot_sg_sta_flash_ct_task_data_write(uint8_t *addr,
uint8_t task_id, uint8_t *data, uint32_t len, uint32_t offset_idx,
uint8_t type, uint8_t is_earse)
{
uint32_t data_offset;
uint32_t ret = ERR_OK, alignment_offset;
iot_sg_sta_drv_meter_ct_unit_tail_t *tail;
iot_sg_sta_flash_meter_data_desc_t *data_info = NULL;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
if (!data || !len) {
ret = ERR_FAIL;
goto out;
}
data_info = iot_sg_sta_flash_clct_find_desc_by_task_id(
iot_sg_sta_flash_meter_find(addr), task_id);
if (data_info == NULL) {
ret = ERR_NOT_EXIST;
goto out;
}
if (type == IOT_SG_STA_FLASH_CT_WR_MODE_INDEX) {
if ((offset_idx >= data_info->ct_info.unit_cnt) ||
(len != data_info->ct_info.unit_len)) {
ret = ERR_FAIL;
goto out;
}
tail = (iot_sg_sta_drv_meter_ct_unit_tail_t *)(data +
len - sizeof(*tail));
tail->crc = iot_getcrc8(data, (len - sizeof(*tail)));
data_offset = sizeof(iot_sg_sta_drv_meter_ct_hdr_t) +
(offset_idx * data_info->ct_info.unit_len);
} else {
data_offset = sizeof(iot_sg_sta_drv_meter_ct_hdr_t) + offset_idx;
}
if (flash_info->erase_mode == IOT_SG_STA_FLASH_ERASE_MODE_EACH_PAGE_BEG) {
alignment_offset = data_info->offset + IOT_SG_STA_METER_DATA_HEADER_LEN
+ sizeof(iot_sg_sta_drv_meter_ct_hdr_t);
alignment_offset = iot_sg_sta_flash_alignment_handle(alignment_offset) -
alignment_offset;
data_offset += alignment_offset;
}
if ((data_offset + len) > data_info->data_hdr.data_len) {
ret = ERR_FAIL;
goto out;
}
data_offset = data_info->offset + IOT_SG_STA_METER_DATA_HEADER_LEN
+ data_offset;
if (is_earse) {
ret = iot_sg_flash_write(data_offset, len, data);
} else {
ret = iot_sg_flash_write_without_erase(data_offset, len, data);
}
out:
return ret;
}
static uint32_t iot_sg_sta_flash_data_erase_check(uint32_t offset,
uint32_t data_len)
{
uint8_t *data;
uint32_t ret = ERR_FAIL;
iot_pkt_t *pkt = iot_pkt_alloc(data_len, IOT_SMART_GRID_MID);
if (pkt == NULL) {
goto out;
}
data = iot_pkt_put(pkt, data_len);
if (iot_sg_flash_read(offset, data_len, data) != ERR_OK) {
goto out;
}
if (iot_bitmap_ffz(data, (uint16_t)data_len)) {
goto out;
}
ret = ERR_OK;
out:
if (pkt) {
iot_pkt_free(pkt);
}
iot_sg_printf("%s ret %d\n", __FUNCTION__, ret);
return ret;
}
static uint32_t iot_sg_sta_flash_data_erase_handle(uint32_t offset,
uint32_t data_len)
{
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
uint32_t erase_uint = flash_info->erase_unit_size;
uint32_t ret = ERR_FAIL, start_offset, alignment_offset, erased_len;
if (!erase_uint) {
goto out;
}
while (data_len) {
alignment_offset = iot_sg_sta_flash_alignment_handle(offset);
if ((offset % erase_uint) == 0) {
start_offset = offset;
erased_len = 0;
} else if (offset + data_len > alignment_offset) {
start_offset = alignment_offset;
erased_len = start_offset - offset;
} else {
/* the current storage space has been erased*/
ret = ERR_OK;
break;
}
ret = iot_sg_flash_erase(start_offset, erase_uint);
if (ret != ERR_OK) {
break;
}
iot_sg_printf("%s start_offset %04x\n", __FUNCTION__, start_offset);
erased_len += erase_uint;
offset = start_offset + erase_uint;
if (data_len < erased_len) {
data_len = 0;
} else {
data_len -= erased_len;
}
}
out:
return ret;
}
static uint32_t iot_sg_sta_flash_ct_erase_once_save(uint8_t *addr,
uint16_t index, uint8_t *data, uint16_t len, uint8_t task_id)
{
uint32_t data_offset;
uint32_t ret = ERR_OK;
iot_sg_sta_drv_meter_ct_unit_tail_t *tail;
iot_sg_sta_flash_meter_data_desc_t *data_info = NULL;
if (!data || !len) {
ret = ERR_FAIL;
goto out;
}
data_info = iot_sg_sta_flash_clct_find_desc_by_task_id(
iot_sg_sta_flash_meter_find(addr), task_id);
if (data_info == NULL) {
ret = ERR_NOT_EXIST;
goto out;
}
if ((index >= data_info->ct_info.unit_cnt) ||
(len != data_info->ct_info.unit_len)) {
ret = ERR_FAIL;
goto out;
}
tail = (iot_sg_sta_drv_meter_ct_unit_tail_t *)(data +
len - sizeof(*tail));
tail->crc = iot_getcrc8(data, (len - sizeof(*tail)));
data_offset = IOT_SG_STA_METER_DATA_HEADER_LEN +
sizeof(iot_sg_sta_drv_meter_ct_hdr_t);
data_offset = iot_sg_sta_flash_alignment_handle(data_offset);
data_offset += (index * data_info->ct_info.unit_len);
if ((data_offset + len) > data_info->data_hdr.data_len +
IOT_SG_STA_METER_DATA_HEADER_LEN) {
ret = ERR_FAIL;
goto out;
}
data_offset = data_info->offset + data_offset;
if (iot_sg_sta_flash_data_erase_handle(data_offset, len) != ERR_OK) {
ret = iot_sg_flash_write(data_offset, len, data);
goto out;
}
/* erase check is to prevent the presence of non erased data in storage
* space, for example, when time goes back, there will be data that has
* not been erased.
*/
if (iot_sg_sta_flash_data_erase_check(data_offset, len) != ERR_OK) {
ret = iot_sg_flash_write(data_offset, len, data);
goto out;
}
ret = iot_sg_flash_write_without_erase(data_offset, len, data);
out:
return ret;
}
uint32_t iot_sg_sta_flash_ct_unit_data_save(uint8_t *addr,
uint16_t index, uint8_t *data, uint16_t len, uint8_t task_id)
{
uint32_t ret;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
if (flash_info->erase_mode == IOT_SG_STA_FLASH_ERASE_MODE_EACH_PAGE_BEG) {
ret = iot_sg_sta_flash_ct_erase_once_save(addr, index, data, len,
task_id);
} else {
ret = iot_sg_sta_flash_ct_task_data_write(addr, task_id, data, len,
index, IOT_SG_STA_FLASH_CT_WR_MODE_INDEX, 1);
}
return ret;
}
uint32_t iot_sg_sta_flash_ct_unit_data_list_save(uint8_t *addr, uint16_t start_index,
uint8_t *data, uint16_t len, uint16_t unit_len, uint8_t task_id)
{
uint8_t i = 0, *node = NULL, *write_data = data;
uint16_t count = 0, write_count = 0, write_len = 0, write_index = start_index;
uint32_t ret = ERR_OK, write_offset = 0;
iot_sg_sta_drv_meter_ct_unit_tail_t *tail = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_info = NULL;
IOT_ASSERT(len >= unit_len);
count = len / unit_len;
data_info = iot_sg_sta_flash_clct_find_desc_by_task_id(
iot_sg_sta_flash_meter_find(addr), task_id);
if (data_info == NULL) {
ret = ERR_NOT_EXIST;
goto out;
}
if ((start_index >= data_info->ct_info.unit_cnt) ||
(unit_len != data_info->ct_info.unit_len)) {
ret = ERR_FAIL;
goto out;
}
if (count > data_info->ct_info.unit_cnt) {
ret = ERR_FAIL;
goto out;
}
for (i = 0; i < count; i++) {
node = data + i * unit_len;
tail = (iot_sg_sta_drv_meter_ct_unit_tail_t *)
(node + (unit_len - sizeof(*tail)));
tail->crc = iot_getcrc8(node, (unit_len - sizeof(*tail)));
}
/* if the data written reaches a new loop, write the remaining space first
* and then start writing from the beginning.
*/
if ((data_info->ct_info.unit_cnt - start_index) < count) {
write_count = data_info->ct_info.unit_cnt - start_index;
} else {
write_count = count;
}
write_len = write_count * unit_len;
write:
write_offset = (write_index * unit_len);
ret = iot_sg_sta_flash_ct_task_data_write(addr, task_id, write_data,
write_len, write_offset, IOT_SG_STA_FLASH_CT_WR_MODE_OFFSET, 1);
if (write_count < count) {
/* If the data is not completely written, the remaining data will be
* written from index 0 onwards*/
write_index = 0;
write_data = write_data + unit_len * write_count;
write_len = len - write_len;
write_count = count;
goto write;
}
out:
return ret;
}
uint32_t iot_sg_sta_flash_ct_unit_data_read(
uint8_t *addr, uint16_t index, uint8_t *data, uint16_t len, uint8_t task_id)
{
return iot_sg_sta_flash_ct_task_data_read(addr, task_id, data, len, index,
IOT_SG_STA_FLASH_CT_WR_MODE_INDEX);
}
uint32_t iot_sg_sta_flash_ct_unit_data_find_latest(uint8_t *addr,
uint16_t *index_ptr, uint8_t *data, uint16_t len, uint8_t task_id,
uint8_t data_type)
{
uint8_t *buf, reason = 0;
uint16_t unit_len, index, max_cnt;
uint16_t buf_len = IOT_SG_STA_FLASH_MULTI_BUF_LEN, valid_cnt = 0;
uint32_t ret, complete = 0, offset, valid_len;
iot_pkt_t *pkt = NULL;
iot_time_tm_t last_ts = { 0 };
iot_sg_sta_flash_meter_data_desc_t *meter_data = NULL;
if (data_type != IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT
&& data_type != IOT_SG_STA_METER_DATA_TYPE_FJ_TASK
&& data_type != IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
reason = 1;
goto out;
}
meter_data = iot_sg_sta_flash_clct_find_desc_by_task_id(
iot_sg_sta_flash_meter_find(addr), task_id);
if (!meter_data) {
reason = 2;
goto out;
}
if ((data == NULL) || (len != meter_data->ct_info.unit_len)) {
reason = 3;
goto out;
}
pkt = iot_pkt_alloc(buf_len, IOT_SMART_GRID_MID);
if (!pkt) {
reason = 4;
goto out;
}
buf = iot_pkt_put(pkt, buf_len);
unit_len = meter_data->ct_info.unit_len;
max_cnt = meter_data->ct_info.unit_cnt;
last_ts.tm_year = 2000;
last_ts.tm_mon = 1;
last_ts.tm_mday = 1;
for (index = 0; index < max_cnt;
index = (valid_cnt ? (index + valid_cnt) : (index + 1))) {
valid_cnt = buf_len / unit_len;
if (index + valid_cnt >= max_cnt) {
valid_cnt = max_cnt - index;
}
offset = index * unit_len;
valid_len = valid_cnt * unit_len;
ret = iot_sg_sta_flash_ct_task_data_read(addr, task_id,
buf, valid_len, offset, IOT_SG_STA_FLASH_CT_WR_MODE_OFFSET);
if (ret != ERR_OK) {
continue;
}
if (iot_sg_sta_flash_find_by_latest(data, index_ptr,
buf, index, valid_cnt, unit_len, &last_ts, data_type)) {
complete = 1;
}
}
out:
if (complete) {
ret = ERR_OK;
} else {
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
ret = ERR_FAIL;
}
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
uint32_t iot_sg_sta_flash_ct_unit_data_find_by_time(uint8_t *addr,
uint16_t *index_ptr, iot_time_tm_t *tm, uint8_t *data, uint16_t len,
uint8_t task_id, uint8_t flag_up, uint8_t data_type)
{
uint8_t *buf, reason = 0, is_over;
uint16_t unit_len, index, max_cnt;
uint16_t buf_len = IOT_SG_STA_FLASH_MULTI_BUF_LEN, valid_cnt = 0;
uint32_t ret, complete = 0, offset, valid_len;
int64_t last_delta = 0;
iot_pkt_t *pkt = NULL;
iot_sg_sta_flash_meter_data_desc_t *meter_data = NULL;
if (data_type != IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT
&& data_type != IOT_SG_STA_METER_DATA_TYPE_FJ_TASK
&& data_type != IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
reason = 1;
goto out;
}
meter_data = iot_sg_sta_flash_clct_find_desc_by_task_id(
iot_sg_sta_flash_meter_find(addr), task_id);
if (!meter_data) {
reason = 2;
goto out;
}
if ((data == NULL) || (len != meter_data->ct_info.unit_len)) {
reason = 3;
goto out;
}
pkt = iot_pkt_alloc(buf_len, IOT_SMART_GRID_MID);
if (!pkt) {
reason = 4;
goto out;
}
buf = iot_pkt_put(pkt, buf_len);
unit_len = meter_data->ct_info.unit_len;
max_cnt = meter_data->ct_info.unit_cnt;
for (index = 0; index < max_cnt;
index = (valid_cnt ? (index + valid_cnt) : (index + 1))) {
valid_cnt = buf_len / unit_len;
if (index + valid_cnt >= max_cnt) {
valid_cnt = max_cnt - index;
}
offset = index * unit_len;
valid_len = valid_cnt * unit_len;
ret = iot_sg_sta_flash_ct_task_data_read(addr, task_id,
buf, valid_len, offset, IOT_SG_STA_FLASH_CT_WR_MODE_OFFSET);
if (ret != ERR_OK) {
continue;
}
is_over = 0;
if (iot_sg_sta_flash_find_by_time(data, index_ptr,
buf, index, valid_cnt, unit_len, tm, &last_delta, &is_over,
flag_up, data_type)) {
complete = 1;
}
if (is_over) {
goto out;
}
}
out:
if (complete) {
ret = ERR_OK;
} else {
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
ret = ERR_FAIL;
}
if (pkt) {
iot_pkt_free(pkt);
}
return ret;
}
static uint16_t iot_sg_sta_flash_ct_clear_by_time(uint8_t *src,
uint32_t start_offset, uint16_t unit_cnt, uint16_t unit_len,
iot_time_tm_t *tm, uint8_t *addr, uint8_t task_id, uint8_t data_type)
{
uint8_t *data = src, crc;
uint16_t i, start = 0xffff, end = 0xffff, clear_cnt = 0;
uint32_t clear_len, clear_offset;
int64_t delta;
iot_time_tm_t curr_ts = { 0 };
for (i = 0; i < unit_cnt; i++) {
crc = iot_getcrc8(data, (unit_len - 1));
if (crc != data[unit_len - 1]) {
goto next;
}
if (iot_sg_sta_flash_get_uint_time(data, (unit_len - 1), data_type,
&curr_ts)) {
goto out;
}
delta = iot_rtc_delta_calc(tm, &curr_ts);
if (delta > 0) {
if (start == 0xffff) {
start = i;
}
end = i + 1;
} else if (delta < 0) {
break;
}
next:
data += unit_len;
}
if (start != 0xffff) {
clear_len = (end - start) * unit_len;
os_mem_set(src, 0, clear_len);
clear_offset = start_offset + start * unit_len;
iot_sg_sta_flash_ct_task_data_write(addr, task_id,
src, clear_len, clear_offset, IOT_SG_STA_FLASH_CT_WR_MODE_OFFSET,
0);
iot_sg_printf("%s clear_offset %04x clear_len %d\n", __FUNCTION__,
clear_offset, clear_len);
clear_cnt = end - start;
}
out:
return clear_cnt;
}
void iot_sg_sta_flash_ct_unit_data_check(uint8_t *addr, uint16_t index,
iot_time_tm_t *tm, uint8_t task_id, uint8_t data_type)
{
uint8_t *buf, reason = 0;
uint16_t unit_len, max_cnt, i, clear_cnt = 0, valid_cnt = 0, idx = index;
uint16_t buf_len = IOT_SG_STA_FLASH_MULTI_BUF_LEN;
uint32_t ret, offset, valid_len;
iot_pkt_t *pkt = NULL;
iot_sg_sta_flash_meter_data_desc_t *meter_data = NULL;
if (data_type != IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT
&& data_type != IOT_SG_STA_METER_DATA_TYPE_FJ_TASK
&& data_type != IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
reason = 1;
goto out;
}
meter_data = iot_sg_sta_flash_clct_find_desc_by_task_id(
iot_sg_sta_flash_meter_find(addr), task_id);
if (!meter_data) {
reason = 2;
goto out;
}
pkt = iot_pkt_alloc(buf_len, IOT_SMART_GRID_MID);
if (!pkt) {
reason = 3;
goto out;
}
buf = iot_pkt_put(pkt, buf_len);
unit_len = meter_data->ct_info.unit_len;
max_cnt = meter_data->ct_info.unit_cnt;
for (i = 0; i < max_cnt; i = (valid_cnt ? (i + valid_cnt) : (i + 1))) {
valid_cnt = buf_len / unit_len;
if (idx + valid_cnt >= max_cnt) {
valid_cnt = max_cnt - idx;
}
offset = idx * unit_len;
valid_len = valid_cnt * unit_len;
ret = iot_sg_sta_flash_ct_task_data_read(addr, task_id,
buf, valid_len, offset, IOT_SG_STA_FLASH_CT_WR_MODE_OFFSET);
if (ret != ERR_OK) {
goto next;
}
clear_cnt += iot_sg_sta_flash_ct_clear_by_time(buf, offset,
valid_cnt, unit_len, tm, addr, task_id, data_type);
next:
idx = (valid_cnt ? (idx + valid_cnt) : (idx + 1));
if (idx >= max_cnt) {
idx = 0;
}
}
out:
if (pkt) {
iot_pkt_free(pkt);
}
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
return;
}
uint32_t iot_sg_sta_flash_clct_task_info_get(uint8_t *addr, uint8_t task_id,
uint8_t *task_ptr, uint32_t len, uint8_t data_type)
{
uint8_t reason;
uint16_t crc;
uint32_t ret = ERR_INVAL, offset, task_len;
iot_pkt_t *pkt_buff = NULL;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *meter_data = NULL;
iot_sg_sta_drv_meter_ct_hdr_t *ct_hdr;
if (data_type == IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT) {
task_len = sizeof(iot_sg_sta_drv_meter_x4_task_info_t);
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) {
task_len = sizeof(iot_sg_sta_drv_meter_fj_task_info_t);
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
task_len = sizeof(iot_sg_sta_drv_meter_gw_clct_task_info_t);
} else {
reason = 1;
goto drop;
}
if (task_len != len) {
reason = 2;
goto drop;
}
pkt_buff = iot_pkt_alloc(sizeof(*ct_hdr), IOT_SMART_GRID_MID);
if (pkt_buff == NULL) {
reason = 3;
goto drop;
}
ct_hdr = (iot_sg_sta_drv_meter_ct_hdr_t*)iot_pkt_put(pkt_buff,
sizeof(*ct_hdr));
meter_info = iot_sg_sta_flash_meter_find(addr);
if (meter_info == NULL) {
reason = 4;
goto drop;
}
meter_data = iot_sg_sta_flash_clct_find_desc_by_task_id(meter_info,
task_id);
if (meter_data == NULL) {
reason = 5;
goto drop;
}
offset = meter_data->offset + sizeof(iot_sg_sta_drv_meter_data_hdr_t);
ret = iot_sg_flash_read(offset, sizeof(*ct_hdr), (uint8_t*)ct_hdr);
if (ret != ERR_OK) {
reason = 6;
goto drop;
}
crc = iot_getcrc8((uint8_t*)ct_hdr, (sizeof(*ct_hdr) - 1));
if (crc != ct_hdr->hdr_crc) {
reason = 7;
goto drop;
}
ret = ERR_OK;
os_mem_cpy(task_ptr, &ct_hdr->desc, task_len);
goto out;
drop:
ret = ERR_INVAL;
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
return ret;
}
static uint32_t iot_sg_sta_flash_clct_task_meter_data_reset(
iot_sg_sta_flash_meter_data_desc_t *meter_data, uint8_t data_type)
{
uint32_t ret, offset, reset_len;
iot_sg_sta_flash_info_t *flash_info = &p_sg_glb->desc.sta->flash_info;
if (!meter_data) {
goto drop;
}
offset = meter_data->offset + IOT_SG_STA_METER_DATA_HEADER_LEN;
if (data_type == IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT) {
reset_len = IOT_SG_STA_METER_TYPE_GUANGDONG_MAX_LEN;
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) {
iot_sg_sta_flash_get_data_type_len(data_type, &reset_len);
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
if (flash_info->erase_mode ==
IOT_SG_STA_FLASH_ERASE_MODE_EACH_PAGE_BEG) {
iot_sg_sta_flash_get_data_type_len_alignment(data_type, &reset_len);
} else {
iot_sg_sta_flash_get_data_type_len(data_type, &reset_len);
}
} else {
goto drop;
}
iot_sg_sta_flash_data_reset(offset, reset_len);
ret = ERR_OK;
goto out;
drop:
ret = ERR_FAIL;
out:
return ret;
}
static iot_sg_sta_flash_meter_data_desc_t*
iot_sg_sta_flash_clct_task_meter_data_alloc(
iot_sg_sta_flash_meter_desc_t *meter_info)
{
uint8_t i;
iot_sg_sta_flash_meter_data_desc_t *meter_data = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_list = NULL;
if (!meter_info) {
goto out;
}
data_list = meter_info->data_list;
for (i = 0; i < meter_info->data_cnt; i++) {
if (!data_list[i].ct_info.task_id) {
meter_data = &data_list[i];
break;
}
}
out:
return meter_data;
}
static uint16_t iot_sg_sta_flash_clct_task_max_sn_get(
iot_sg_sta_flash_meter_desc_t *meter_info)
{
uint8_t i;
uint16_t sn = 0;
iot_sg_sta_flash_meter_data_desc_t *data_list = NULL;
data_list = meter_info->data_list;
for (i = 0; i < meter_info->data_cnt; i++) {
if (sn < data_list[i].ct_info.sn) {
sn = data_list[i].ct_info.sn;
}
}
return sn;
}
static uint32_t iot_sg_sta_flash_clct_task_info_init(uint16_t sn,
iot_sg_sta_flash_meter_data_desc_t *meter_data,
uint8_t *task_ptr, uint32_t len, uint8_t data_type)
{
uint8_t i, reason = 0;
uint16_t unit_len = 0, node_max = 0;
uint32_t ret = ERR_INVAL, offset, task_len;
iot_pkt_t *pkt_buff = NULL;
iot_sg_sta_drv_meter_ct_hdr_t *ct_hdr;
iot_sg_sta_drv_meter_x4_task_info_t *x4_task = NULL;
iot_sg_sta_drv_meter_fj_task_info_t *fj_task = NULL;
iot_sg_sta_drv_meter_gw_clct_task_info_t *gw_task = NULL;
if (data_type == IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT) {
task_len = sizeof(*x4_task);
x4_task = (iot_sg_sta_drv_meter_x4_task_info_t*)task_ptr;
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) {
task_len = sizeof(*fj_task);
fj_task = (iot_sg_sta_drv_meter_fj_task_info_t*)task_ptr;
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
task_len = sizeof(*gw_task);
gw_task = (iot_sg_sta_drv_meter_gw_clct_task_info_t *)task_ptr;
} else {
reason = 1;
goto drop;
}
if (task_len != len) {
reason = 2;
goto drop;
}
pkt_buff = iot_pkt_alloc(sizeof(*ct_hdr), IOT_SMART_GRID_MID);
if (pkt_buff == NULL) {
reason = 3;
goto drop;
}
ct_hdr = (iot_sg_sta_drv_meter_ct_hdr_t*)iot_pkt_put(pkt_buff,
sizeof(*ct_hdr));
if (data_type == IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT) {
ct_hdr->task_id = x4_task->id;
os_mem_cpy(ct_hdr->desc, task_ptr, task_len);
ct_hdr->unit_len = sizeof(iot_sg_sta_drv_meter_ct_unit_head_t);
for (i = 0; i < x4_task->di_cnt; i++) {
ct_hdr->unit_len += (sizeof(iot_sg_sta_drv_meter_ct_unit_data_t) +
x4_task->di_info[i].data_len);
}
ct_hdr->unit_len += sizeof(iot_sg_sta_drv_meter_ct_unit_tail_t);
ct_hdr->unit_cnt =
IOT_SG_STA_CLCT_TASK_UNIT_DATA_TOTAL_LEN / ct_hdr->unit_len;
ct_hdr->sn = sn;
ct_hdr->hdr_crc = iot_getcrc8((uint8_t*)ct_hdr,
(sizeof(*ct_hdr) - 1));
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) {
ct_hdr->task_id = fj_task->id;
os_mem_cpy(ct_hdr->desc, task_ptr, task_len);
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_FJ_TASK, &unit_len, &node_max);
ct_hdr->unit_len = unit_len;
ct_hdr->unit_cnt = node_max;
ct_hdr->sn = sn;
ct_hdr->hdr_crc = iot_getcrc8((uint8_t*)ct_hdr,
(sizeof(*ct_hdr) - 1));
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
ct_hdr->task_id = gw_task->id;
os_mem_cpy(ct_hdr->desc, task_ptr, task_len);
iot_sg_sta_flash_unit_get_data_info(
IOT_SG_STA_METER_DATA_TYPE_GW_TASK, &unit_len, &node_max);
ct_hdr->unit_len = unit_len;
ct_hdr->unit_cnt = node_max;
ct_hdr->sn = sn;
ct_hdr->hdr_crc = iot_getcrc8((uint8_t *)ct_hdr, (sizeof(*ct_hdr) - 1));
} else {
reason = 3;
goto drop;
}
offset = meter_data->offset + IOT_SG_STA_METER_DATA_HEADER_LEN;
ret = iot_sg_flash_write(offset, sizeof(*ct_hdr), (uint8_t*)ct_hdr);
if (ret == ERR_OK) {
meter_data->ct_info.sn = ct_hdr->sn;
meter_data->ct_info.task_id = ct_hdr->task_id;
meter_data->ct_info.unit_len = ct_hdr->unit_len;
meter_data->ct_info.unit_cnt = ct_hdr->unit_cnt;
meter_data->ct_info.flag_reset = 0;
goto out;
}
reason = 4;
drop:
ret = ERR_INVAL;
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
if (pkt_buff) {
iot_pkt_free(pkt_buff);
}
return ret;
}
uint32_t iot_sg_sta_flash_clct_task_add(uint8_t *addr,
uint8_t *task_ptr, uint32_t len, uint8_t data_type)
{
uint8_t reason = 0, task_id;
uint16_t sn;
uint32_t ret = ERR_OK, task_len;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *meter_data = NULL;
iot_sg_sta_drv_meter_x4_task_info_t *x4_task;
iot_sg_sta_drv_meter_fj_task_info_t *fj_task;
iot_sg_sta_drv_meter_gw_clct_task_info_t *gw_task;
BUILD_BUG_ON(sizeof(*x4_task) <= IOT_SG_STA_METER_TASK_DESC_MAX_LEN);
BUILD_BUG_ON(sizeof(*fj_task) <= IOT_SG_STA_METER_TASK_DESC_MAX_LEN);
BUILD_BUG_ON(sizeof(*gw_task) <= IOT_SG_STA_METER_TASK_DESC_MAX_LEN);
if (data_type == IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT) {
task_len = sizeof(*x4_task);
x4_task = (iot_sg_sta_drv_meter_x4_task_info_t*)task_ptr;
task_id = x4_task->id;
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) {
task_len = sizeof(*fj_task);
fj_task = (iot_sg_sta_drv_meter_fj_task_info_t*)task_ptr;
task_id = fj_task->id;
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
task_len = sizeof(*gw_task);
gw_task = (iot_sg_sta_drv_meter_gw_clct_task_info_t *)task_ptr;
task_id = gw_task->id;
} else {
ret = ERR_INVAL;
reason = 1;
goto drop;
}
if (task_len != len) {
ret = ERR_INVAL;
reason = 2;
goto drop;
}
meter_info = iot_sg_sta_flash_meter_find(addr);
if (meter_info == NULL) {
ret = ERR_INVAL;
reason = 3;
goto drop;
}
meter_data = iot_sg_sta_flash_clct_find_desc_by_task_id(meter_info,
task_id);
if (!meter_data) {
meter_data = iot_sg_sta_flash_clct_task_meter_data_alloc(meter_info);
}
if (meter_data == NULL) {
ret = ERR_NOMEM;
reason = 4;
goto drop;
}
if (!meter_data->ct_info.flag_reset) {
iot_sg_sta_flash_clct_task_meter_data_reset(meter_data, data_type);
}
sn = iot_sg_sta_flash_clct_task_max_sn_get(meter_info) + 1;
ret = iot_sg_sta_flash_clct_task_info_init(sn, meter_data, task_ptr,
len, data_type);
if (ret == ERR_OK) {
iot_sg_printf("%s task id:%lu ok\n", __FUNCTION__, task_id);
goto out;
} else {
reason = 5;
}
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
uint32_t iot_sg_sta_flash_clct_task_del(uint8_t *addr, uint8_t task_id,
uint8_t flag_reset, uint8_t data_type)
{
uint32_t ret = ERR_OK;
uint8_t reason;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *meter_data = NULL;
meter_info = iot_sg_sta_flash_meter_find(addr);
if (meter_info == NULL) {
ret = ERR_NOT_EXIST;
reason = 1;
goto drop;
}
meter_data = iot_sg_sta_flash_clct_find_desc_by_task_id(meter_info,
task_id);
if (meter_data == NULL) {
ret = ERR_NOT_EXIST;
reason = 2;
goto drop;
}
if (flag_reset) {
meter_data->ct_info.flag_reset = 1;
iot_sg_sta_flash_clct_task_meter_data_reset(meter_data, data_type);
}
meter_data->ct_info.sn = 0;
meter_data->ct_info.task_id = 0;
meter_data->ct_info.unit_cnt = 0;
meter_data->ct_info.unit_len = 0;
iot_sg_printf("%s task id:%lu ok\n", __FUNCTION__, task_id);
goto out;
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
uint8_t iot_sg_sta_flash_clct_find_oldest_task(uint8_t *addr)
{
uint8_t i, old_i = 0, old_task_id = 0;
uint16_t old_sn = 0;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_list = NULL;
meter_info = iot_sg_sta_flash_meter_find(addr);
if (meter_info == NULL) {
goto out;
}
data_list = meter_info->data_list;
for (i = 0; i < meter_info->data_cnt; i++) {
if (!data_list[i].ct_info.sn) {
continue;
}
if (!old_sn) {
old_sn = data_list[i].ct_info.sn;
old_i = i;
} else {
if (old_sn > data_list[i].ct_info.sn) {
old_sn = data_list[i].ct_info.sn;
old_i = i;
}
}
}
if (old_sn) {
old_task_id = data_list[old_i].ct_info.task_id;
}
out:
return old_task_id;
}
uint32_t iot_sg_sta_flash_clct_task_info_update(uint8_t *addr,
uint8_t *task_ptr, uint32_t len, uint8_t data_type)
{
uint8_t reason = 0, task_id;
uint32_t ret = ERR_OK, task_len;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *meter_data = NULL;
iot_sg_sta_drv_meter_x4_task_info_t *x4_task;
iot_sg_sta_drv_meter_fj_task_info_t *fj_task;
iot_sg_sta_drv_meter_gw_clct_task_info_t *gw_task;
if (data_type == IOT_SG_STA_METER_DATA_TYPE_GUANGDONG_CT) {
task_len = sizeof(*x4_task);
x4_task = (iot_sg_sta_drv_meter_x4_task_info_t*)task_ptr;
task_id = x4_task->id;
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_FJ_TASK) {
task_len = sizeof(*fj_task);
fj_task = (iot_sg_sta_drv_meter_fj_task_info_t*)task_ptr;
task_id = fj_task->id;
} else if (data_type == IOT_SG_STA_METER_DATA_TYPE_GW_TASK) {
task_len = sizeof(*gw_task);
gw_task = (iot_sg_sta_drv_meter_gw_clct_task_info_t *)task_ptr;
task_id = gw_task->id;
} else {
ret = ERR_INVAL;
reason = 1;
goto drop;
}
if (task_len != len) {
ret = ERR_INVAL;
reason = 2;
goto drop;
}
meter_info = iot_sg_sta_flash_meter_find(addr);
if (meter_info == NULL) {
ret = ERR_INVAL;
reason = 3;
goto drop;
}
meter_data = iot_sg_sta_flash_clct_find_desc_by_task_id(meter_info,
task_id);
if (meter_data == NULL) {
ret = ERR_INVAL;
reason = 3;
goto drop;
}
ret = iot_sg_sta_flash_clct_task_info_init(meter_data->ct_info.sn,
meter_data, task_ptr, len, data_type);
if (ret == ERR_OK) {
iot_sg_printf("%s task id:%lu ok\n", __FUNCTION__, task_id);
goto out;
} else {
reason = 3;
}
drop:
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
out:
return ret;
}
uint32_t iot_sg_sta_flash_ct_unit_data_len_get(uint8_t *addr, uint8_t task_id)
{
uint32_t data_len = 0;
iot_sg_sta_flash_meter_data_desc_t *meter_data = NULL;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
meter_info = iot_sg_sta_flash_meter_find(addr);
if (!meter_info) {
goto out;
}
meter_data = iot_sg_sta_flash_clct_find_desc_by_task_id(meter_info,
task_id);
if (!meter_data) {
goto out;
}
data_len = meter_data->ct_info.unit_len;
out:
return data_len;
}
uint16_t iot_sg_sta_flash_ct_unit_cnt_get(uint8_t *addr, uint8_t task_id)
{
uint16_t uint_cnt = 0;
iot_sg_sta_flash_meter_data_desc_t *meter_data = NULL;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
meter_info = iot_sg_sta_flash_meter_find(addr);
if (!meter_info) {
goto out;
}
meter_data = iot_sg_sta_flash_clct_find_desc_by_task_id(meter_info,
task_id);
if (!meter_data) {
goto out;
}
uint_cnt = meter_data->ct_info.unit_cnt;
out:
return uint_cnt;
}
iot_pkt_t *iot_sg_sta_flash_clct_task_id_info_get(uint8_t *addr)
{
uint8_t i, reason = 0;
uint8_t len;
iot_pkt_t *pkt = NULL;
iot_sg_sta_flash_clct_task_id_t *id_info;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_list;
meter_info = iot_sg_sta_flash_meter_find(addr);
if (!meter_info) {
reason = 1;
goto out;
}
data_list = meter_info->data_list;
len = meter_info->data_cnt * sizeof(data_list->ct_info.task_id)
+ sizeof(*id_info);
pkt = iot_pkt_alloc(len, IOT_SMART_GRID_MID);
if (pkt == NULL) {
reason = 2;
goto out;
}
id_info = (iot_sg_sta_flash_clct_task_id_t*)iot_pkt_put(pkt, len);
for (i = 0; i < meter_info->data_cnt; i++) {
if (data_list[i].ct_info.task_id) {
id_info->task_id[id_info->cnt] = data_list[i].ct_info.task_id;
id_info->cnt++;
}
}
out:
if (reason) {
iot_sg_printf("%s err %lu\n", __FUNCTION__, reason);
}
return pkt;
}
uint32_t iot_sg_sta_flash_score_data_save(uint8_t *addr, uint8_t *data,
uint16_t len, uint8_t data_type)
{
uint8_t i;
uint32_t data_offset = 0, ret = ERR_OK;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_list = NULL;
iot_sg_sta_drv_meter_ss_data_t *ss_data = NULL;
if (!data || len != sizeof(*ss_data)) {
ret = ERR_FAIL;
goto out;
}
if (data_type != IOT_SG_STA_METER_DATA_TYPE_GUANGZHOU_SS &&
data_type != IOT_SG_STA_METER_DATA_TYPE_EC) {
ret = ERR_NOSUPP;
goto out;
}
meter_info = iot_sg_sta_flash_meter_find(addr);
if (!meter_info) {
ret = ERR_NOT_EXIST;
goto out;
}
data_list = meter_info->data_list;
for (i = 0; i < meter_info->data_cnt; i++) {
if (data_list[i].data_hdr.data_type == data_type) {
data_info = &data_list[i];
break;
}
}
if (data_info == NULL) {
ret = ERR_NOT_EXIST;
goto out;
}
ss_data = (iot_sg_sta_drv_meter_ss_data_t *)data;
ss_data->crc = iot_getcrc8((uint8_t*)ss_data, sizeof(*ss_data) - 1);
data_offset = data_info->offset + IOT_SG_STA_METER_DATA_HEADER_LEN;
ret = iot_sg_flash_write(data_offset, len, (uint8_t *)ss_data);
out:
return ret;
}
uint32_t iot_sg_sta_flash_score_data_read(uint8_t *addr, uint8_t *data,
uint16_t len, uint8_t data_type)
{
uint8_t i, crc;
uint32_t data_offset = 0, ret = ERR_OK;
iot_sg_sta_flash_meter_desc_t *meter_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_info = NULL;
iot_sg_sta_flash_meter_data_desc_t *data_list = NULL;
iot_sg_sta_drv_meter_ss_data_t *ss_data = NULL;
if (!data || len != sizeof(*ss_data)) {
ret = ERR_FAIL;
goto out;
}
if (data_type != IOT_SG_STA_METER_DATA_TYPE_GUANGZHOU_SS &&
data_type != IOT_SG_STA_METER_DATA_TYPE_EC) {
ret = ERR_NOSUPP;
goto out;
}
meter_info = iot_sg_sta_flash_meter_find(addr);
if (!meter_info) {
ret = ERR_NOT_EXIST;
goto out;
}
data_list = meter_info->data_list;
for (i = 0; i < meter_info->data_cnt; i++) {
if (data_list[i].data_hdr.data_type == data_type) {
data_info = &data_list[i];
break;
}
}
if (data_info == NULL) {
ret = ERR_NOT_EXIST;
goto out;
}
data_offset = data_info->offset + IOT_SG_STA_METER_DATA_HEADER_LEN;
ret = iot_sg_flash_read(data_offset, len, data);
if (ret != ERR_OK) {
goto out;
}
ss_data = (iot_sg_sta_drv_meter_ss_data_t *)data;
crc = iot_getcrc8((uint8_t*)ss_data, sizeof(*ss_data) - 1);
if (crc != ss_data->crc) {
ret = ERR_INVAL;
}
out:
return ret;
}
#else /* IOT_SMART_GRID_FLASH_ENABLE */
uint32_t iot_sg_sta_flash_init()
{
return ERR_NOSUPP;
}
void iot_sg_sta_flash_deinit(void)
{
return;
}
uint32_t iot_sg_sta_flash_meter_add(uint8_t *addr)
{
(void)addr;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_meter_delete(uint8_t *addr)
{
(void)addr;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_unit_data_save(uint8_t *addr,
uint16_t index, uint8_t *data, uint16_t len, uint8_t data_type)
{
(void)addr;
(void)index;
(void)data;
(void)len;
(void)data_type;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_unit_data_read(uint8_t *addr,
uint16_t index, uint8_t *data, uint16_t len, uint8_t data_type)
{
(void)addr;
(void)index;
(void)data;
(void)len;
(void)data_type;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_unit_data_find_latest(uint8_t *addr,
uint16_t *index_ptr, uint8_t *data, uint16_t len, uint8_t data_type)
{
(void)addr;
(void)index_ptr;
(void)data;
(void)len;
(void)data_type;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_unit_data_find_by_time(uint8_t *addr,
uint16_t *index_ptr, iot_time_tm_t *tm, uint8_t *data, uint16_t len,
uint8_t data_type, uint8_t flag_up)
{
(void)addr;
(void)index_ptr;
(void)tm;
(void)data;
(void)len;
(void)data_type;
(void)flag_up;
return ERR_NOSUPP;
}
uint16_t iot_sg_sta_flash_unit_data_check(uint8_t *addr, uint16_t index,
iot_time_tm_t *tm, uint8_t data_type)
{
(void)addr;
(void)index;
(void)tm;
(void)data_type;
return 0;
}
uint32_t iot_sg_sta_flash_ct_unit_data_save(uint8_t *addr,
uint16_t index, uint8_t *data, uint16_t len, uint8_t task_id)
{
(void)addr;
(void)index;
(void)data;
(void)len;
(void)task_id;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_ct_unit_data_read(uint8_t *addr,
uint16_t index, uint8_t *data, uint16_t len, uint8_t task_id)
{
(void)addr;
(void)index;
(void)data;
(void)len;
(void)task_id;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_ct_unit_data_find_latest(uint8_t *addr,
uint16_t *index_ptr, uint8_t *data, uint16_t len, uint8_t task_id,
uint8_t data_type)
{
(void)addr;
(void)index_ptr;
(void)data;
(void)len;
(void)task_id;
(void)data_type;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_ct_unit_data_find_by_time(uint8_t *addr,
uint16_t *index_ptr, iot_time_tm_t *tm, uint8_t *data, uint16_t len,
uint8_t task_id, uint8_t flag_up, uint8_t data_type)
{
(void)addr;
(void)index_ptr;
(void)tm;
(void)data;
(void)len;
(void)task_id;
(void)flag_up;
(void)data_type;
return ERR_NOSUPP;
}
void iot_sg_sta_flash_ct_unit_data_check(uint8_t *addr, uint16_t index,
iot_time_tm_t *tm, uint8_t task_id, uint8_t data_type)
{
(void)addr;
(void)index;
(void)tm;
(void)task_id;
(void)data_type;
}
uint32_t iot_sg_sta_flash_clct_task_info_get(uint8_t *addr, uint8_t task_id,
uint8_t *task_ptr, uint32_t len, uint8_t data_type)
{
(void)addr;
(void)task_id;
(void)task_ptr;
(void)len;
(void)data_type;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_clct_task_add(uint8_t *addr,
uint8_t *task_ptr, uint32_t len, uint8_t data_type)
{
(void)addr;
(void)task_ptr;
(void)len;
(void)data_type;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_clct_task_del(uint8_t *addr, uint8_t task_id,
uint8_t flag_reset, uint8_t data_type)
{
(void)addr;
(void)task_id;
(void)flag_reset;
(void)data_type;
return ERR_NOSUPP;
}
uint8_t iot_sg_sta_flash_clct_find_oldest_task(uint8_t *addr)
{
(void)addr;
return 0;
}
uint32_t iot_sg_sta_flash_clct_task_info_update(uint8_t *addr,
uint8_t *task_ptr, uint32_t len, uint8_t data_type)
{
(void)addr;
(void)task_ptr;
(void)len;
(void)data_type;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_ct_unit_data_len_get(uint8_t *addr, uint8_t task_id)
{
(void)addr;
(void)task_id;
return 0;
}
uint16_t iot_sg_sta_flash_ct_unit_cnt_get(uint8_t *addr, uint8_t task_id)
{
(void)addr;
(void)task_id;
return 0;
}
iot_pkt_t *iot_sg_sta_flash_clct_task_id_info_get(uint8_t *addr)
{
(void)addr;
return NULL;
}
uint32_t iot_sg_sta_flash_score_data_save(uint8_t *addr, uint8_t *data,
uint16_t len, uint8_t data_type)
{
(void)addr;
(void)data;
(void)len;
(void)data_type;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_score_data_read(uint8_t *addr, uint8_t *data,
uint16_t len, uint8_t data_type)
{
(void)addr;
(void)data;
(void)len;
(void)data_type;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_unit_data_find_by_multiple_time(uint8_t *addr,
uint16_t *index_ptr, iot_time_tm_t *tm, uint8_t tm_cnt, uint8_t data_type,
uint8_t *flag_up)
{
(void)addr;
(void)index_ptr;
(void)tm;
(void)tm_cnt;
(void)data_type;
(void)flag_up;
return ERR_NOSUPP;
}
uint32_t iot_sg_sta_flash_unit_get_data_info(uint8_t data_type,
uint16_t *unit_len, uint16_t *max_cnt)
{
(void)data_type;
(void)unit_len;
(void)max_cnt;
return ERR_NOSUPP;
}
#endif /* IOT_SMART_GRID_FLASH_ENABLE */