854 lines
26 KiB
C
854 lines
26 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.
|
|
|
|
****************************************************************************/
|
|
|
|
#include "os_utils_api.h"
|
|
#include "iot_crc_api.h"
|
|
#include "iot_errno_api.h"
|
|
#include "iot_utils_api.h"
|
|
|
|
#include "iot_bsrm_common.h"
|
|
#include "iot_bsrm_rec.h"
|
|
#include "iot_bsrm_flash.h"
|
|
|
|
/* select record crc16 type */
|
|
#define IOT_BSRM_REC_CRC16_TYPE IOT_CRC16_TYPE_X25
|
|
/* define record read buffer size */
|
|
#define IOT_BSRM_REC_READ_BUF_SIZE (1024)
|
|
/* define max info of information record */
|
|
#define IOT_BSRM_REC_INFO_BRANCH_MAX (2001)
|
|
/* define max branch event record */
|
|
#define IOT_BSRM_BRANCH_EVT_MAX (251)
|
|
/* enable/disable record information data print */
|
|
#define IOT_BSRM_REC_DEBUG 0
|
|
|
|
/* define the maximum number of events supported */
|
|
#define IOT_BSRM_EVT_SUPPORT_MAX 14
|
|
|
|
#pragma pack(push) /* save the pack status */
|
|
#pragma pack(1) /* 1 byte align */
|
|
|
|
/* record head */
|
|
typedef struct iot_bsrm_rec_head {
|
|
/* record sequence number */
|
|
uint32_t rec_seq;
|
|
/* time stamp */
|
|
uint32_t ts;
|
|
/* check crc */
|
|
uint16_t crc;
|
|
/* payload label */
|
|
uint8_t data[0];
|
|
} iot_bsrm_rec_head_t;
|
|
|
|
#pragma pack(pop)
|
|
|
|
/* record region descriptor */
|
|
typedef struct iot_bsrm_rec_region_desc {
|
|
/* record entry size, contains record headers */
|
|
uint32_t entry_size;
|
|
/* region start position */
|
|
uint32_t start;
|
|
/* region size */
|
|
uint32_t size;
|
|
/* recording depth */
|
|
uint32_t rec_depth;
|
|
/* record serial number will assigned */
|
|
uint32_t seq;
|
|
/* recording depth */
|
|
uint32_t new_idx;
|
|
uint32_t oldest_idx;
|
|
/* timestamp of the latest record */
|
|
uint32_t last_rec_ts;
|
|
} iot_bsrm_rec_region_desc_t;
|
|
|
|
#if IOT_BSRM_MODE
|
|
|
|
static iot_bsrm_rec_region_desc_t g_info_region;
|
|
static iot_bsrm_rec_region_desc_t g_evt_region;
|
|
|
|
static uint8_t *g_buf;
|
|
|
|
static inline uint32_t iot_bsrm_rec_idx_inc(iot_bsrm_rec_region_desc_t *rec_desc,
|
|
uint32_t org_idx)
|
|
{
|
|
uint32_t new_idx;
|
|
new_idx = org_idx + 1;
|
|
if (new_idx >= rec_desc->rec_depth) {
|
|
new_idx = 0;
|
|
}
|
|
return new_idx;
|
|
}
|
|
|
|
static inline uint32_t iot_bsrm_rec_idx_dec(iot_bsrm_rec_region_desc_t *rec_desc,
|
|
uint32_t org_idx)
|
|
{
|
|
uint32_t new_idx;
|
|
if (org_idx)
|
|
new_idx = org_idx - 1;
|
|
else
|
|
new_idx = rec_desc->rec_depth - 1;
|
|
return new_idx;
|
|
}
|
|
|
|
static uint32_t iot_bsrm_rec_get_cnt(iot_bsrm_rec_region_desc_t *desc)
|
|
{
|
|
if (desc->new_idx >= desc->oldest_idx)
|
|
return (desc->new_idx - desc->oldest_idx);
|
|
else
|
|
return (desc->new_idx + desc->rec_depth \
|
|
- desc->oldest_idx);
|
|
}
|
|
|
|
static uint32_t iot_bsrm_rec_get_before_cnt(
|
|
iot_bsrm_rec_region_desc_t *desc, uint32_t org_idx)
|
|
{
|
|
if (org_idx >= desc->oldest_idx)
|
|
return (org_idx - desc->oldest_idx);
|
|
else
|
|
return (org_idx + desc->rec_depth \
|
|
- desc->oldest_idx);
|
|
}
|
|
|
|
static uint32_t iot_bsrm_get_ramain_cnt(iot_bsrm_rec_region_desc_t *desc,
|
|
uint32_t idx)
|
|
{
|
|
if (desc->new_idx >= idx)
|
|
return (desc->new_idx - idx);
|
|
else
|
|
return (desc->new_idx + desc->rec_depth \
|
|
- idx);
|
|
}
|
|
|
|
static uint32_t iot_bsrm_rec_seq_inc(uint32_t seq)
|
|
{
|
|
seq++;
|
|
if ((seq & 0xffffffff) == 0) {
|
|
seq = 1;
|
|
}
|
|
return seq;
|
|
}
|
|
|
|
static inline uint32_t iot_bsrm_rec_idx_sub(iot_bsrm_rec_region_desc_t *desc,
|
|
uint32_t org_idx, uint32_t sub)
|
|
{
|
|
uint32_t new_idx;
|
|
new_idx = org_idx;
|
|
while (sub-- > 0) {
|
|
new_idx = iot_bsrm_rec_idx_dec(desc, new_idx);
|
|
}
|
|
return new_idx;
|
|
}
|
|
|
|
uint8_t iot_bsrm_rec_read(iot_bsrm_rec_region_desc_t *p_rec_desc,
|
|
uint32_t last_idx, uint32_t *ts, iot_pkt_t **pkt)
|
|
{
|
|
uint8_t reason;
|
|
uint16_t crc;
|
|
uint8_t ret;
|
|
iot_pkt_t *buf;
|
|
iot_bsrm_rec_head_t *hdr;
|
|
uint32_t real_idx, pos;
|
|
|
|
if (!last_idx || last_idx > iot_bsrm_rec_get_cnt(p_rec_desc)) {
|
|
reason = 1;
|
|
goto err;
|
|
}
|
|
real_idx = iot_bsrm_rec_idx_sub(p_rec_desc, p_rec_desc->new_idx, last_idx);
|
|
pos = p_rec_desc->start + real_idx * p_rec_desc->entry_size;
|
|
buf = iot_pkt_alloc(p_rec_desc->entry_size, IOT_BSRM_MID);
|
|
if (buf == NULL) {
|
|
reason = 2;
|
|
goto err;
|
|
}
|
|
iot_pkt_put(buf, p_rec_desc->entry_size);
|
|
ret = iot_bsrm_flash_read(pos, iot_pkt_data(buf),
|
|
p_rec_desc->entry_size);
|
|
if (ret) {
|
|
reason = 3;
|
|
goto err_1;
|
|
}
|
|
|
|
hdr = (iot_bsrm_rec_head_t *)iot_pkt_data(buf);
|
|
crc = iot_getcrc16(hdr->data,
|
|
p_rec_desc->entry_size - sizeof(*hdr), IOT_BSRM_REC_CRC16_TYPE);
|
|
if (hdr->crc != crc) {
|
|
reason = 4;
|
|
goto err_1;
|
|
}
|
|
iot_pkt_set_data(buf, hdr->data);
|
|
*pkt = buf;
|
|
*ts = hdr->ts;
|
|
ret = ERR_OK;
|
|
goto out;
|
|
|
|
err_1:
|
|
iot_pkt_free(buf);
|
|
err:
|
|
ret = ERR_FAIL;
|
|
iot_bsrm_printf("%s fail reason %lu\n", __FUNCTION__, reason);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
static void iot_bsrm_rec_cnt_clear(iot_bsrm_rec_region_desc_t *desc)
|
|
{
|
|
desc->new_idx = 0;
|
|
desc->oldest_idx = 0;
|
|
desc->last_rec_ts = 0;
|
|
}
|
|
|
|
static void iot_bsrm_rec_clear(iot_bsrm_rec_region_desc_t *desc)
|
|
{
|
|
uint8_t *clear_buf = g_buf;
|
|
uint32_t total_len, clear_len, offset;
|
|
|
|
total_len = desc->size;
|
|
offset = desc->start;
|
|
os_mem_set(clear_buf, 0, IOT_BSRM_REC_READ_BUF_SIZE);
|
|
while (total_len) {
|
|
clear_len = min(total_len, IOT_BSRM_REC_READ_BUF_SIZE);
|
|
iot_bsrm_flash_write(offset, clear_buf, clear_len);
|
|
total_len -= clear_len;
|
|
offset += clear_len;
|
|
os_delay(5);
|
|
}
|
|
}
|
|
|
|
void iot_bsrm_rec_info_clear(void)
|
|
{
|
|
uint32_t ts;
|
|
|
|
if (iot_bsrm_rec_get_cnt(&g_info_region)) {
|
|
ts = os_boot_time32();
|
|
iot_bsrm_rec_cnt_clear(&g_info_region);
|
|
iot_bsrm_rec_clear(&g_info_region);
|
|
ts = os_boot_time32() - ts;
|
|
iot_bsrm_printf("%s spend %lu ms\n", __FUNCTION__, ts);
|
|
}
|
|
}
|
|
|
|
void iot_bsrm_rec_evt_clear(void)
|
|
{
|
|
uint32_t ts;
|
|
|
|
if (iot_bsrm_rec_get_cnt(&g_evt_region)) {
|
|
ts = os_boot_time32();
|
|
iot_bsrm_rec_cnt_clear(&g_evt_region);
|
|
iot_bsrm_rec_clear(&g_evt_region);
|
|
ts = os_boot_time32() - ts;
|
|
iot_bsrm_printf("%s spend %lu ms\n", __FUNCTION__, ts);
|
|
}
|
|
}
|
|
|
|
static inline uint32_t iot_bsrm_rec_idx_add(iot_bsrm_rec_region_desc_t *desc,
|
|
uint32_t org_idx, uint32_t add)
|
|
{
|
|
uint32_t new_idx;
|
|
new_idx = org_idx;
|
|
while (add-- > 0) {
|
|
new_idx = iot_bsrm_rec_idx_inc(desc, new_idx);
|
|
}
|
|
return new_idx;
|
|
}
|
|
|
|
static uint32_t iot_bsrm_rec_mid_calc(iot_bsrm_rec_region_desc_t *rec_desc,
|
|
uint32_t left, uint32_t right)
|
|
{
|
|
uint32_t cnt = 0, mid;
|
|
if (right >= left)
|
|
cnt = right - left;
|
|
else
|
|
cnt = right + rec_desc->rec_depth - left;
|
|
mid = iot_bsrm_rec_idx_add(rec_desc, left, cnt >> 1);
|
|
return mid;
|
|
}
|
|
|
|
static uint8_t iot_bsrm_info_rec_bin_search(
|
|
iot_bsrm_rec_region_desc_t *desc, uint32_t *ts, uint32_t *idx)
|
|
{
|
|
uint8_t ret = ERR_OK, *buf = g_buf;
|
|
uint16_t crc;
|
|
uint32_t l_idx, r_idx, mid_calc, real_mid;
|
|
iot_bsrm_rec_head_t *hdr;
|
|
uint32_t pos;
|
|
int32_t near_idx = -1;
|
|
uint32_t tmp_ts = *ts;
|
|
|
|
l_idx = desc->oldest_idx;
|
|
r_idx = desc->new_idx;
|
|
while (l_idx != r_idx) {
|
|
mid_calc = iot_bsrm_rec_mid_calc(desc, l_idx, r_idx);
|
|
real_mid = mid_calc;
|
|
while (real_mid != r_idx) {
|
|
pos = desc->start + real_mid * desc->entry_size;
|
|
ret = iot_bsrm_flash_read(pos, buf, desc->entry_size);
|
|
if (ret != ERR_OK) {
|
|
real_mid = iot_bsrm_rec_idx_inc(desc, real_mid);
|
|
continue;
|
|
}
|
|
hdr = (iot_bsrm_rec_head_t *)buf;
|
|
crc = iot_getcrc16(hdr->data,
|
|
desc->entry_size - sizeof(*hdr), IOT_BSRM_REC_CRC16_TYPE);
|
|
if (hdr->crc != crc) {
|
|
real_mid = iot_bsrm_rec_idx_inc(desc, real_mid);
|
|
ret = ERR_FAIL;
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
if (ret) {
|
|
r_idx = mid_calc;
|
|
continue;
|
|
}
|
|
hdr = (iot_bsrm_rec_head_t *)buf;
|
|
if (hdr->ts == *ts) {
|
|
*idx = real_mid;
|
|
return ERR_OK;
|
|
} else if (hdr->ts < *ts) {
|
|
l_idx = iot_bsrm_rec_idx_inc(desc, real_mid);
|
|
} else {
|
|
tmp_ts = hdr->ts;
|
|
near_idx = real_mid;
|
|
r_idx = real_mid;
|
|
}
|
|
}
|
|
if (near_idx != -1) {
|
|
*ts = tmp_ts;
|
|
*idx = near_idx;
|
|
return ERR_OK;
|
|
}
|
|
return ERR_FAIL;
|
|
}
|
|
|
|
int32_t iot_bsrm_branch_info_entry_assig(void *rec,
|
|
uint8_t *out_data, uint32_t len_limit)
|
|
{
|
|
iot_bsrm_branch_info_entry_t *entry;
|
|
if (len_limit < sizeof(*entry)) {
|
|
return -1;
|
|
}
|
|
entry = (iot_bsrm_branch_info_entry_t *)out_data;
|
|
if (rec == NULL) {
|
|
os_mem_set(entry, 0x00, sizeof(*entry));
|
|
} else {
|
|
os_mem_cpy(entry, rec, sizeof(*entry));
|
|
}
|
|
return (int32_t)(sizeof(*entry));
|
|
}
|
|
|
|
uint32_t iot_bsrm_info_rec_search(iot_bsrm_rec_region_desc_t *desc,
|
|
uint32_t ts, uint32_t *idx)
|
|
{
|
|
uint32_t find_idx, tmp_idx, cur_idx, pos;
|
|
uint8_t ret, i;
|
|
iot_bsrm_rec_head_t *hdr;
|
|
uint16_t crc;
|
|
uint8_t *buf;
|
|
uint32_t idx_cnt;
|
|
uint32_t rel_ts = ts;
|
|
|
|
ret = iot_bsrm_info_rec_bin_search(desc, &rel_ts, &find_idx);
|
|
if (ret != ERR_OK) {
|
|
return ret;
|
|
}
|
|
idx_cnt = iot_bsrm_rec_get_before_cnt(desc, find_idx);
|
|
idx_cnt = min(idx_cnt, 3);
|
|
tmp_idx = iot_bsrm_rec_idx_sub(desc, find_idx, idx_cnt);
|
|
cur_idx = tmp_idx;
|
|
|
|
for (i = 0; i < idx_cnt; i++) {
|
|
buf = g_buf;
|
|
pos = desc->start + cur_idx * desc->entry_size;
|
|
ret = iot_bsrm_flash_read(pos, buf, desc->entry_size);
|
|
if (ret != ERR_OK) {
|
|
return ret;
|
|
}
|
|
cur_idx = iot_bsrm_rec_idx_inc(desc, cur_idx);
|
|
hdr = (iot_bsrm_rec_head_t *)buf;
|
|
crc = iot_getcrc16(hdr->data,
|
|
desc->entry_size - sizeof(*hdr), IOT_BSRM_REC_CRC16_TYPE);
|
|
if (hdr->crc != crc) {
|
|
continue;
|
|
}
|
|
if (hdr->ts == rel_ts) {
|
|
break;
|
|
}
|
|
}
|
|
if (i == idx_cnt) {
|
|
*idx = find_idx;
|
|
} else {
|
|
*idx = iot_bsrm_rec_idx_add(desc, tmp_idx, i);
|
|
}
|
|
return ERR_OK;
|
|
}
|
|
|
|
uint8_t iot_bsrm_evt_read(uint32_t evt_num, uint8_t **evt)
|
|
{
|
|
uint8_t ret = ERR_OK, reason;
|
|
uint8_t *buf;
|
|
uint16_t crc;
|
|
uint32_t idx, pos;
|
|
iot_bsrm_rec_head_t *hdr;
|
|
iot_bsrm_rec_region_desc_t *desc = &g_evt_region;
|
|
if (!evt_num || iot_bsrm_rec_get_cnt(desc) < evt_num) {
|
|
ret = ERR_NOT_EXIST;
|
|
reason = 1;
|
|
goto err;
|
|
}
|
|
idx = iot_bsrm_rec_idx_sub(desc, desc->new_idx, evt_num);
|
|
pos = desc->start + idx * desc->entry_size;
|
|
buf = g_buf;
|
|
ret = iot_bsrm_flash_read(pos, buf, desc->entry_size);
|
|
if (ret != ERR_OK) {
|
|
ret = ERR_NOT_EXIST;
|
|
reason = 2;
|
|
goto err;
|
|
}
|
|
hdr = (iot_bsrm_rec_head_t *)buf;
|
|
crc = iot_getcrc16(hdr->data,
|
|
desc->entry_size - sizeof(*hdr), IOT_BSRM_REC_CRC16_TYPE);
|
|
if (hdr->crc != crc) {
|
|
ret = ERR_INVAL;
|
|
reason = 3;
|
|
goto err;
|
|
}
|
|
*evt = buf + sizeof(*hdr);
|
|
goto out;
|
|
err:
|
|
iot_bsrm_printf("%s fail reason %lu\n", __FUNCTION__, reason);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
uint8_t iot_bsrm_info_rec_read(uint32_t *ts, uint16_t *total_cnt,
|
|
uint8_t *n, iot_pkt_t **pkt, uint16_t start_idx)
|
|
{
|
|
uint8_t ret;
|
|
uint8_t reason = 0;
|
|
uint32_t i, j;
|
|
uint32_t find_idx = 0, pos, entry_n;
|
|
uint32_t len_limit;
|
|
iot_pkt_t *pkt_buf = NULL;
|
|
iot_bsrm_rec_region_desc_t *desc = &g_info_region;
|
|
uint8_t fill_n = 0, valid_fill_n = 0, read_n = *n;
|
|
uint8_t *out_buf;
|
|
uint32_t re_n[2] = { 0 }, cnt = 0;
|
|
uint8_t *buf;
|
|
iot_bsrm_rec_head_t *hdr;
|
|
uint16_t crc;
|
|
int32_t temp;
|
|
|
|
if (iot_bsrm_rec_get_cnt(desc) == 0) {
|
|
reason = 1;
|
|
goto err;
|
|
}
|
|
if (*ts > desc->last_rec_ts) {
|
|
reason = 2;
|
|
goto err;
|
|
}
|
|
ret = (uint8_t)iot_bsrm_info_rec_search(desc, *ts, &find_idx);
|
|
if (ret != ERR_OK) {
|
|
reason = 3;
|
|
goto err;
|
|
}
|
|
cnt = iot_bsrm_get_ramain_cnt(desc, find_idx);
|
|
*total_cnt = (uint16_t)cnt;
|
|
if (start_idx >= cnt) {
|
|
reason = 4;
|
|
goto err;
|
|
}
|
|
read_n = (uint8_t)min(cnt - start_idx, read_n);
|
|
find_idx = iot_bsrm_rec_idx_add(desc, find_idx, start_idx);
|
|
len_limit = min(sizeof(iot_bsrm_branch_info_entry_t) * (read_n),
|
|
IOT_BSRM_REC_READ_BUF_SIZE);
|
|
pkt_buf = iot_pkt_alloc(len_limit, IOT_BSRM_MID);
|
|
if (pkt_buf == NULL) {
|
|
reason = 5;
|
|
goto err;
|
|
}
|
|
out_buf = iot_pkt_data(pkt_buf);
|
|
if (find_idx < desc->new_idx) {
|
|
re_n[0] = desc->new_idx - find_idx;
|
|
} else if (find_idx > desc->new_idx) {
|
|
re_n[0] = desc->rec_depth - find_idx;
|
|
re_n[1] = desc->new_idx;
|
|
} else {
|
|
IOT_ASSERT(0);
|
|
}
|
|
for (i = 0; i < 2; i++) {
|
|
while (re_n[i]) {
|
|
pos = desc->start + find_idx * desc->entry_size;
|
|
entry_n = IOT_BSRM_REC_READ_BUF_SIZE / desc->entry_size;
|
|
entry_n = (re_n[i] > entry_n ? entry_n : re_n[i]);
|
|
buf = g_buf;
|
|
ret = iot_bsrm_flash_read(pos, buf, entry_n * desc->entry_size);
|
|
if (ret != ERR_OK) {
|
|
goto done;
|
|
}
|
|
for (j = 0; j < entry_n; j++) {
|
|
hdr = (iot_bsrm_rec_head_t *)buf;
|
|
crc = iot_getcrc16(hdr->data,
|
|
desc->entry_size - sizeof(*hdr), IOT_BSRM_REC_CRC16_TYPE);
|
|
if (hdr->crc != crc) {
|
|
buf += desc->entry_size;
|
|
continue;
|
|
}
|
|
temp = iot_bsrm_branch_info_entry_assig(hdr->data, out_buf,
|
|
len_limit);
|
|
if (temp == -1) {
|
|
goto done;
|
|
} else {
|
|
buf += desc->entry_size;
|
|
fill_n++;
|
|
valid_fill_n++;
|
|
len_limit -= temp;
|
|
out_buf += temp;
|
|
iot_pkt_put(pkt_buf, (uint32_t)temp);
|
|
if (fill_n == read_n) {
|
|
goto done;
|
|
}
|
|
}
|
|
}
|
|
re_n[i] -= entry_n;
|
|
find_idx = iot_bsrm_rec_idx_add(desc, find_idx, entry_n);
|
|
}
|
|
}
|
|
goto done;
|
|
err:
|
|
iot_bsrm_printf("%s err reason %lu\n", __FUNCTION__, reason);
|
|
valid_fill_n = 0;
|
|
done:
|
|
if (valid_fill_n) {
|
|
*pkt = pkt_buf;
|
|
*n = fill_n;
|
|
} else {
|
|
ret = ERR_NOT_EXIST;
|
|
if (pkt_buf)
|
|
iot_pkt_free(pkt_buf);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
void iot_bsrm_rec_write(iot_bsrm_rec_region_desc_t *desc, uint32_t ts,
|
|
uint8_t *rec_data, uint8_t is_overlast)
|
|
{
|
|
uint32_t pos;
|
|
uint16_t crc;
|
|
iot_bsrm_rec_head_t *hdr = (iot_bsrm_rec_head_t *)rec_data;
|
|
crc = iot_getcrc16(hdr->data,
|
|
desc->entry_size - sizeof(*hdr), IOT_BSRM_REC_CRC16_TYPE);
|
|
hdr->crc = crc;
|
|
if (is_overlast && iot_bsrm_rec_get_cnt(desc) > 0) {
|
|
desc->new_idx =
|
|
iot_bsrm_rec_idx_dec(desc, desc->new_idx);
|
|
}
|
|
pos = desc->start + desc->new_idx * desc->entry_size;
|
|
if (iot_bsrm_flash_write(pos, rec_data, desc->entry_size) != ERR_OK) {
|
|
iot_bsrm_printf("%s fail\n", __FUNCTION__);
|
|
goto out;
|
|
}
|
|
iot_bsrm_printf("%s part_%08x, addr_region[%08x - %08x]\n",
|
|
__FUNCTION__, desc->start, pos, pos + desc->entry_size - 1);
|
|
desc->new_idx = \
|
|
iot_bsrm_rec_idx_inc(desc, desc->new_idx);
|
|
desc->last_rec_ts = ts;
|
|
if (desc->new_idx == desc->oldest_idx) {
|
|
desc->oldest_idx = \
|
|
iot_bsrm_rec_idx_inc(desc, desc->oldest_idx);
|
|
}
|
|
desc->seq = iot_bsrm_rec_seq_inc(desc->seq);
|
|
out:
|
|
return;
|
|
}
|
|
|
|
void iot_bsrm_evt_rec_write(uint8_t *evt_buf)
|
|
{
|
|
uint32_t ts;
|
|
iot_time_tm_t tm;
|
|
iot_bsrm_rec_head_t *hdr;
|
|
iot_bsrm_rec_region_desc_t *desc = &g_evt_region;
|
|
|
|
iot_rtc_get(&tm);
|
|
ts = iot_bsrm_rtctime_to_time(&tm);
|
|
hdr = (iot_bsrm_rec_head_t *)g_buf;
|
|
hdr->rec_seq = desc->seq;
|
|
hdr->ts = ts;
|
|
os_mem_cpy(hdr->data, evt_buf, sizeof(iot_bsrm_branch_evt_rec_entry_t));
|
|
iot_bsrm_rec_write(desc, ts, g_buf, 0);
|
|
}
|
|
|
|
void iot_bsrm_info_rec(uint32_t ts, uint8_t len, uint8_t *data)
|
|
{
|
|
iot_bsrm_rec_region_desc_t *desc = &g_info_region;
|
|
uint32_t pos, exist_idx;
|
|
uint8_t reason, ret;
|
|
iot_bsrm_rec_head_t *hdr;
|
|
uint16_t crc;
|
|
|
|
if (ts < desc->last_rec_ts) {
|
|
pos = desc->start + desc->oldest_idx * desc->entry_size;
|
|
ret = iot_bsrm_flash_read(pos, g_buf, desc->entry_size);
|
|
if (ret != ERR_OK) {
|
|
reason = 1;
|
|
goto err;
|
|
}
|
|
hdr = (iot_bsrm_rec_head_t *)g_buf;
|
|
crc = iot_getcrc16(hdr->data,
|
|
desc->entry_size - sizeof(*hdr), IOT_BSRM_REC_CRC16_TYPE);
|
|
if (hdr->crc != crc) {
|
|
reason = 2;
|
|
goto err;
|
|
}
|
|
iot_bsrm_printf("%s war, info ts %lu less last ts %lu\n",
|
|
__FUNCTION__, ts, desc->last_rec_ts);
|
|
if (ts < hdr->ts) {
|
|
/* the point to be recorded is earlier than all the historical
|
|
* records.
|
|
*/
|
|
desc->new_idx = iot_bsrm_rec_idx_dec(desc, desc->new_idx);
|
|
desc->oldest_idx = desc->new_idx;
|
|
} else {
|
|
ret = (uint8_t)iot_bsrm_info_rec_search(desc, ts, &exist_idx);
|
|
if (ret != ERR_OK) {
|
|
desc->new_idx = iot_bsrm_rec_idx_dec(desc, desc->new_idx);
|
|
desc->oldest_idx = desc->new_idx;
|
|
} else {
|
|
desc->new_idx = exist_idx;
|
|
}
|
|
}
|
|
}
|
|
hdr = (iot_bsrm_rec_head_t *)g_buf;
|
|
hdr->rec_seq = desc->seq;
|
|
hdr->ts = ts;
|
|
os_mem_cpy(hdr->data, data, len);
|
|
iot_bsrm_rec_write(desc, ts, g_buf, 0);
|
|
goto out;
|
|
err:
|
|
iot_printf("%s err, reason %lu\n", __FUNCTION__, reason);
|
|
out:
|
|
return;
|
|
}
|
|
|
|
static uint32_t iot_bsrm_get_info_entry_size(void)
|
|
{
|
|
return sizeof(iot_bsrm_rec_head_t) +
|
|
sizeof(iot_bsrm_branch_info_entry_t);
|
|
}
|
|
|
|
static uint32_t iot_bsrm_get_evt_entry_size(void)
|
|
{
|
|
return sizeof(iot_bsrm_rec_head_t) +
|
|
sizeof(iot_bsrm_branch_evt_rec_entry_t);
|
|
}
|
|
|
|
static uint8_t iot_bsrm_rec_head_valid(iot_bsrm_rec_head_t *hdr)
|
|
{
|
|
if (hdr->rec_seq == 0) {
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
void iot_bsrm_rec_load(iot_bsrm_rec_region_desc_t *rec_desc, uint8_t
|
|
is_order)
|
|
{
|
|
uint8_t ret, *data;
|
|
uint32_t last_rec_seq = 0, oldest_rec_seq = 0xffffffff;
|
|
uint32_t part_cnt[2] = { 0 };
|
|
uint32_t ts = 0;
|
|
uint32_t i, n_per, remain_n, read_n, pos, idx, temp_idx, n, old_idx;
|
|
uint32_t find_rec_n = 0, valid_rec_n = 0;
|
|
uint8_t *buf = g_buf;
|
|
uint16_t crc;
|
|
iot_time_tm_t tm;
|
|
iot_bsrm_rec_head_t *hdr;
|
|
n_per = IOT_BSRM_REC_READ_BUF_SIZE / rec_desc->entry_size;
|
|
remain_n = rec_desc->rec_depth;
|
|
for (idx = 0, pos = rec_desc->start; remain_n; ) {
|
|
read_n = (remain_n >= n_per ? n_per : remain_n);
|
|
pos = rec_desc->start + idx * rec_desc->entry_size;
|
|
ret = iot_bsrm_flash_read(pos, buf, read_n * rec_desc->entry_size);
|
|
if (ret != ERR_OK) {
|
|
break;
|
|
}
|
|
data = buf;
|
|
for (i = 0; i < read_n; i++) {
|
|
hdr = (iot_bsrm_rec_head_t *)data;
|
|
crc = iot_getcrc16(hdr->data,
|
|
rec_desc->entry_size - sizeof(*hdr), IOT_BSRM_REC_CRC16_TYPE);
|
|
/* traverse all valid records */
|
|
if (crc == hdr->crc && iot_bsrm_rec_head_valid(hdr)) {
|
|
iot_bsrm_time_to_rtctime(hdr->ts, &tm);
|
|
#if IOT_BSRM_REC_DEBUG
|
|
iot_bsrm_printf("rec_info: time %lu-%lu-%lu %lu:%lu:%lu, "
|
|
"idx %lu, rec_seq %lu\n", tm.tm_year, tm.tm_mon,
|
|
tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec,
|
|
idx, hdr->rec_seq);
|
|
iot_bsrm_data_print("|--rec_bin", data, rec_desc->entry_size);
|
|
#endif
|
|
if (hdr->rec_seq > last_rec_seq) {
|
|
last_rec_seq = hdr->rec_seq;
|
|
rec_desc->new_idx = idx;
|
|
rec_desc->last_rec_ts = hdr->ts;
|
|
}
|
|
if (hdr->rec_seq < oldest_rec_seq) {
|
|
oldest_rec_seq = hdr->rec_seq;
|
|
rec_desc->oldest_idx = idx;
|
|
}
|
|
find_rec_n++;
|
|
}
|
|
data += rec_desc->entry_size;
|
|
idx++;
|
|
}
|
|
pos += read_n * rec_desc->entry_size;
|
|
remain_n -= read_n;
|
|
}
|
|
if (!find_rec_n) {
|
|
rec_desc->oldest_idx = 0;
|
|
rec_desc->new_idx = 0;
|
|
goto out;
|
|
}
|
|
rec_desc->new_idx = iot_bsrm_rec_idx_inc(rec_desc, \
|
|
rec_desc->new_idx);
|
|
if (rec_desc->new_idx == rec_desc->oldest_idx) {
|
|
rec_desc->oldest_idx = iot_bsrm_rec_idx_inc(rec_desc, \
|
|
rec_desc->oldest_idx);
|
|
}
|
|
out:
|
|
valid_rec_n = iot_bsrm_rec_get_cnt(rec_desc);
|
|
if (valid_rec_n <= 1 || is_order == 0) {
|
|
goto done;
|
|
}
|
|
ts = rec_desc->last_rec_ts;
|
|
idx = iot_bsrm_rec_idx_dec(rec_desc, rec_desc->new_idx);
|
|
if (idx < rec_desc->oldest_idx) {
|
|
part_cnt[0] = idx;
|
|
part_cnt[1] = rec_desc->rec_depth - rec_desc->oldest_idx;
|
|
} else {
|
|
part_cnt[0] = idx - rec_desc->oldest_idx;
|
|
}
|
|
temp_idx = idx;
|
|
old_idx = idx;
|
|
|
|
#if IOT_BSRM_REC_DEBUG
|
|
uint8_t part = 0;
|
|
if (part_cnt[1]) {
|
|
iot_bsrm_printf("part%lu: [%lu ~ %lu], cnt %lu || ", part,
|
|
rec_desc->oldest_idx, rec_desc->rec_depth - 1, part_cnt[1]);
|
|
part++;
|
|
}
|
|
if (part_cnt[0]) {
|
|
iot_bsrm_printf("part%lu: [%lu ~ %lu], cnt %lu", part,
|
|
rec_desc->oldest_idx, idx, part_cnt[0]);
|
|
part++;
|
|
}
|
|
if (part) {
|
|
iot_bsrm_printf("\n");
|
|
}
|
|
#endif
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
while (part_cnt[i]) {
|
|
read_n = (part_cnt[i] >= n_per ? n_per : part_cnt[i]);
|
|
idx = iot_bsrm_rec_idx_sub(rec_desc, idx, read_n);
|
|
pos = rec_desc->start + idx * rec_desc->entry_size;
|
|
ret = iot_bsrm_flash_read(pos, buf, read_n * rec_desc->entry_size);
|
|
if (ret) {
|
|
goto done_1;
|
|
}
|
|
n = read_n;
|
|
for (data = buf + (read_n - 1) * rec_desc->entry_size; n > 0; n--) {
|
|
hdr = (iot_bsrm_rec_head_t *)data;
|
|
crc = iot_getcrc16(hdr->data,
|
|
rec_desc->entry_size - sizeof(*hdr),
|
|
IOT_BSRM_REC_CRC16_TYPE);
|
|
if (crc != hdr->crc) {
|
|
temp_idx = iot_bsrm_rec_idx_dec(rec_desc, temp_idx);
|
|
continue;
|
|
} else if (hdr->ts > ts) {
|
|
goto done_1;
|
|
}
|
|
temp_idx = iot_bsrm_rec_idx_dec(rec_desc, temp_idx);
|
|
old_idx = temp_idx;
|
|
ts = hdr->ts;
|
|
data -= rec_desc->entry_size;
|
|
}
|
|
part_cnt[i] -= read_n;
|
|
}
|
|
}
|
|
done_1:
|
|
rec_desc->oldest_idx = old_idx;
|
|
done:
|
|
rec_desc->seq = iot_bsrm_rec_seq_inc(last_rec_seq);
|
|
valid_rec_n = iot_bsrm_rec_get_cnt(rec_desc);
|
|
iot_bsrm_time_to_rtctime(rec_desc->last_rec_ts, &tm);
|
|
iot_bsrm_printf("%s - region[%08x-%08x], find_rec_n %lu, valid_rec_n "
|
|
"%lu, idx[%lu - %lu], seq %lu, last_time %lu-%lu-%lu %lu:%lu:%lu\n",
|
|
__FUNCTION__, rec_desc->start, rec_desc->start + rec_desc->size - 1,
|
|
find_rec_n, valid_rec_n, rec_desc->oldest_idx, rec_desc->new_idx,
|
|
rec_desc->seq, tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
|
|
tm.tm_min, tm.tm_sec);
|
|
return;
|
|
}
|
|
|
|
uint32_t iot_bsrm_rec_init(void)
|
|
{
|
|
uint32_t ret = ERR_OK;
|
|
uint32_t start;
|
|
|
|
g_buf = os_mem_malloc(IOT_BSRM_MID, IOT_BSRM_REC_READ_BUF_SIZE);
|
|
if (g_buf == NULL) {
|
|
ret = ERR_NOMEM;
|
|
goto out;
|
|
}
|
|
start = IOT_BSRM_INFO_REC_REGION_START;
|
|
g_info_region.start = start;
|
|
g_info_region.entry_size = iot_bsrm_get_info_entry_size();
|
|
g_info_region.size = g_info_region.entry_size *
|
|
IOT_BSRM_REC_INFO_BRANCH_MAX;
|
|
g_info_region.rec_depth = IOT_BSRM_REC_INFO_BRANCH_MAX;
|
|
start += g_info_region.size;
|
|
iot_bsrm_printf("%s - rec_region_information: [%08x - %08x], block %lu,"
|
|
" entry_size %lu\n", __FUNCTION__,
|
|
g_info_region.start, start - 1,
|
|
g_info_region.rec_depth,
|
|
g_info_region.entry_size);
|
|
iot_bsrm_rec_load(&g_info_region, 1);
|
|
if (start % 4096 != 0) {
|
|
start = (start / 4096 + 1) * 4096;
|
|
}
|
|
IOT_ASSERT(start <= IOT_BSRM_INFO_REC_REGION_END);
|
|
|
|
start = IOT_BSRM_BRANCH_EVT_REGION_START;
|
|
g_evt_region.start = start;
|
|
g_evt_region.entry_size = iot_bsrm_get_evt_entry_size();
|
|
g_evt_region.size = g_evt_region.entry_size * IOT_BSRM_BRANCH_EVT_MAX;
|
|
g_evt_region.rec_depth = IOT_BSRM_BRANCH_EVT_MAX;
|
|
start += g_evt_region.size;
|
|
iot_bsrm_printf("%s - event_region_information: [%08x - %08x], block %lu,"
|
|
" entry_size %lu\n", __FUNCTION__,
|
|
g_evt_region.start, start - 1,
|
|
g_evt_region.rec_depth,
|
|
g_evt_region.entry_size);
|
|
iot_bsrm_rec_load(&g_evt_region, 0);
|
|
if (start % 4096 != 0) {
|
|
start = (start / 4096 + 1) * 4096;
|
|
}
|
|
IOT_ASSERT(start <= IOT_BSRM_BRANCH_EVT_REGION_END);
|
|
out:
|
|
return ret;
|
|
}
|
|
|
|
#endif /* IOT_BSRM_MODE */
|