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 */
 |