250 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
/****************************************************************************
 | 
						||
 | 
						||
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_timer_api.h"
 | 
						||
#include "os_lock_api.h"
 | 
						||
#include "iot_io_api.h"
 | 
						||
#include "iot_pkt_api.h"
 | 
						||
#include "iot_plc_msg_api.h"
 | 
						||
#include "iot_app_pib_api.h"
 | 
						||
#include "iot_board_api.h"
 | 
						||
#include "iot_errno_api.h"
 | 
						||
#include "iot_app_meta_handle.h"
 | 
						||
#include "iot_app_meta_buffer_handle.h"
 | 
						||
#include "iot_version_api.h"
 | 
						||
 | 
						||
/* length of meta cmd buffer */
 | 
						||
#define META_BUF_LENGTH           264
 | 
						||
 | 
						||
#pragma pack(push)  // save the pack status
 | 
						||
#pragma pack(1)     // 1 byte align
 | 
						||
 | 
						||
typedef struct _meta_buf_ctr_t
 | 
						||
{
 | 
						||
    /* mutex for meta bufer */
 | 
						||
    os_mutex_h  meta_mutex;
 | 
						||
    /* point to the buffer head */
 | 
						||
    uint8_t *    buf_head;
 | 
						||
    /* how many space left in the buffer */
 | 
						||
    int16_t      buf_rest;
 | 
						||
    /* point to the max used position in the buffer */
 | 
						||
    uint8_t *    buf_used;
 | 
						||
    /* point to the buffer end */
 | 
						||
    uint8_t *    buf_end;
 | 
						||
    /* point to the check position, next cmd will use the position */
 | 
						||
    uint8_t *    buf_check_pos;
 | 
						||
    /* point to the buffer pkt */
 | 
						||
    iot_pkt_t *  buf;
 | 
						||
} meta_buf_ctr_t;
 | 
						||
 | 
						||
#pragma pack(pop)    /* restore the pack status */
 | 
						||
 | 
						||
meta_buf_ctr_t g_meta_buf;
 | 
						||
 | 
						||
void iot_meta_bin_dump(uint8_t *data, uint32_t dlen)
 | 
						||
{
 | 
						||
    uint32_t i = 0;
 | 
						||
    uint32_t offset = 0;
 | 
						||
    iot_cus_printf("[dump count is %d]:", dlen);
 | 
						||
    for (i = 0; i < dlen; ++i) {
 | 
						||
        offset += iot_cus_printf("%02X ", data[i]);
 | 
						||
    }
 | 
						||
 | 
						||
    iot_cus_printf("\n");
 | 
						||
 | 
						||
    return;
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * @brief iot_meta_put_cmd_to_buf() - put meta cmd to the buffer
 | 
						||
 * @param cmd:point to the meta cmd data
 | 
						||
 * @return: ERR_OK, or error reason
 | 
						||
 */
 | 
						||
/* 把meta指令数据放进meta buffer,buffer里面有这几个指针,
 | 
						||
    head:     指向buffer头;
 | 
						||
    position:指向下一次开始解析的地址,
 | 
						||
    used:     指向当前使用的最大地址;
 | 
						||
    end:      指向buffer尾;
 | 
						||
    这四个地址通常如下排列
 | 
						||
    head <= position <= used <= end
 | 
						||
    1.由于position在取数据时可能向后移动,所以buffer里的head和position之间的
 | 
						||
    空间(如存在)是可释放的。
 | 
						||
    2.在buffer的used后面空间足够的情况下,优先写入这里,以减少copy次数
 | 
						||
    3.buffer的used后面空间不够时,把position到used之间的数据copy到head,释放
 | 
						||
    position之前的空间
 | 
						||
    4.如果buffer剩余空间不够,直接丢弃当前命令*/
 | 
						||
uint8_t iot_meta_put_cmd_to_buf(meta_cmd_t *cmd)
 | 
						||
{
 | 
						||
    uint8_t ret = ERR_OK;
 | 
						||
 | 
						||
    os_acquire_mutex(g_meta_buf.meta_mutex);
 | 
						||
    iot_cus_printf("cmd->datalen = %d, buf_rest = %d, front = %d\n",
 | 
						||
        cmd->datalen + MIN_META_CMD_LEN, g_meta_buf.buf_rest,
 | 
						||
        g_meta_buf.buf_check_pos - g_meta_buf.buf_head);
 | 
						||
    if (cmd->datalen + MIN_META_CMD_LEN > g_meta_buf.buf_rest +
 | 
						||
        g_meta_buf.buf_check_pos - g_meta_buf.buf_head) {
 | 
						||
        iot_cus_printf("no space for id_group=0x%X, id=0x%X\n", cmd->id_group,
 | 
						||
            cmd->id);
 | 
						||
        os_release_mutex(g_meta_buf.meta_mutex);
 | 
						||
        ret = ERR_FAIL;
 | 
						||
        goto out;
 | 
						||
    }
 | 
						||
 | 
						||
    /* 当后面的空间不够了就把之前的删除,把后面的copy前来,取数据基本改成指针偏移
 | 
						||
        只能在buffer快满或隔着取的情况下需要copy */
 | 
						||
    if (cmd->datalen + MIN_META_CMD_LEN > g_meta_buf.buf_rest) {
 | 
						||
        os_mem_set(g_meta_buf.buf_head, 0,
 | 
						||
            g_meta_buf.buf_check_pos - g_meta_buf.buf_head);
 | 
						||
        os_mem_cpy(g_meta_buf.buf_head, g_meta_buf.buf_check_pos,
 | 
						||
            g_meta_buf.buf_used - g_meta_buf.buf_check_pos);
 | 
						||
        g_meta_buf.buf_used -= (g_meta_buf.buf_check_pos - g_meta_buf.buf_head);
 | 
						||
        g_meta_buf.buf_check_pos = g_meta_buf.buf_head;
 | 
						||
        g_meta_buf.buf_rest = g_meta_buf.buf_end - g_meta_buf.buf_used;
 | 
						||
    }
 | 
						||
 | 
						||
    os_mem_cpy(g_meta_buf.buf_used, cmd, MIN_META_CMD_LEN + cmd->datalen);
 | 
						||
    g_meta_buf.buf_used += (MIN_META_CMD_LEN + cmd->datalen);
 | 
						||
    g_meta_buf.buf_rest -= (MIN_META_CMD_LEN + cmd->datalen);
 | 
						||
    os_release_mutex(g_meta_buf.meta_mutex);
 | 
						||
    iot_cus_printf("%s data\n", __FUNCTION__);
 | 
						||
    iot_meta_bin_dump(g_meta_buf.buf_head, g_meta_buf.buf_used -
 | 
						||
        g_meta_buf.buf_head);
 | 
						||
 | 
						||
out:
 | 
						||
    return ret;
 | 
						||
}
 | 
						||
 | 
						||
/* 接收方通过while循环处理每一个meta命令,从buffer的position开始,直到meta命令
 | 
						||
    全部取出或meta剩余空间不够,跳出循环,由于可能出现取后一条的情况(当前指令
 | 
						||
    需要的meta空间不够,但后面一条够),需要考虑两种情况
 | 
						||
    1:没有取后一条的情况发生,直接根据meta命令长度来,增加position值
 | 
						||
    2:只要出现取后一条的情况,本次循环position不再增加,后面将连续的meta取走
 | 
						||
    后,立即用后面的数据覆盖已取走的数据,以防止内存碎片 */
 | 
						||
uint16_t iot_meta_get_cmd_from_buf(uint8_t *meta_data, uint16_t datalen)
 | 
						||
{
 | 
						||
    uint8_t *data = meta_data;
 | 
						||
    uint8_t *data_buf;
 | 
						||
    /* 记录一次中间提取meta指令的开始 */
 | 
						||
    uint8_t *data_get_start = NULL;
 | 
						||
    /* meta不够标志,只要发现一次meta不够,就置位,
 | 
						||
        g_meta_buf.buf_check_pos不能再变,下次发数据必须从这里开始 */
 | 
						||
    uint8_t meta_small = false;
 | 
						||
    uint8_t pick_cnt = 0;
 | 
						||
    uint16_t pick_data_len = 0;
 | 
						||
    /* 为了减少copy次数,连续取走的数据所占空间一起处理,
 | 
						||
        记录连续数据在buffer里的起始地址和长度 */
 | 
						||
    uint16_t data_get_len = 0;
 | 
						||
    uint16_t meta_len = datalen;
 | 
						||
    uint16_t cmd_len;
 | 
						||
    meta_cmd_t *cmd;
 | 
						||
 | 
						||
    os_acquire_mutex(g_meta_buf.meta_mutex);
 | 
						||
    data_buf = g_meta_buf.buf_check_pos;
 | 
						||
    cmd = (meta_cmd_t *)data_buf;
 | 
						||
    cmd_len = MIN_META_CMD_LEN + cmd->datalen;
 | 
						||
 | 
						||
    while ((meta_len >= MIN_META_CMD_LEN) && cmd->id_group &&
 | 
						||
        (data_buf + MIN_META_CMD_LEN <= g_meta_buf.buf_used)) {
 | 
						||
        iot_cus_printf("%s meta_len = %d, cmd_len =%d\n", __FUNCTION__,
 | 
						||
            meta_len, cmd_len);
 | 
						||
        iot_meta_bin_dump(meta_data, datalen);
 | 
						||
        if (meta_len >= cmd_len) {
 | 
						||
            os_mem_cpy(data, (uint8_t *)cmd, cmd_len);
 | 
						||
            meta_len -= cmd_len;
 | 
						||
            pick_cnt += 1;
 | 
						||
            pick_data_len += cmd_len;
 | 
						||
            /* 本cmd空间不够,但下一个够的情况,使用 */
 | 
						||
            if ((data_get_start == NULL) &&
 | 
						||
                (g_meta_buf.buf_check_pos != data_buf)) {
 | 
						||
                /* 本次从哪里开始提取 */
 | 
						||
                data_get_start = (uint8_t *)cmd;
 | 
						||
            }
 | 
						||
 | 
						||
            data_get_len += cmd_len;
 | 
						||
            data_buf += cmd_len;
 | 
						||
            data += cmd_len;
 | 
						||
            if (meta_small == false) {
 | 
						||
                g_meta_buf.buf_check_pos = data_buf;
 | 
						||
            }
 | 
						||
 | 
						||
            iot_meta_bin_dump(meta_data, datalen);
 | 
						||
        } else {
 | 
						||
            /* 这里这段用于处理,本cmd空间不够,但下一个够的情况,这种情况下
 | 
						||
                要copy */
 | 
						||
            iot_cus_printf("meta_len : %d < cmd_len : %d\n", meta_len, cmd_len);
 | 
						||
            if (data_get_start != NULL) {
 | 
						||
                os_mem_cpy(data_get_start, data_buf,
 | 
						||
                    g_meta_buf.buf_used - data_buf);
 | 
						||
                os_mem_set(g_meta_buf.buf_used - data_get_len, 0, data_get_len);
 | 
						||
                data_buf = data_get_start + cmd_len;
 | 
						||
                g_meta_buf.buf_used -= data_get_len;
 | 
						||
                g_meta_buf.buf_rest += data_get_len;
 | 
						||
                data_get_start = NULL;
 | 
						||
            } else {
 | 
						||
                data_buf += cmd_len;
 | 
						||
            }
 | 
						||
            data_get_len = 0;
 | 
						||
            meta_small = true;
 | 
						||
        }
 | 
						||
 | 
						||
        /* 指向下一个cmd */
 | 
						||
        cmd = (meta_cmd_t *)data_buf;
 | 
						||
        cmd_len = MIN_META_CMD_LEN + cmd->datalen;
 | 
						||
    }
 | 
						||
    if (data_get_start != NULL) {
 | 
						||
        os_mem_cpy(data_get_start, data_buf, g_meta_buf.buf_used - data_buf);
 | 
						||
        os_mem_set(g_meta_buf.buf_used - data_get_len, 0, data_get_len);
 | 
						||
        g_meta_buf.buf_used -= data_get_len;
 | 
						||
        g_meta_buf.buf_rest += data_get_len;
 | 
						||
    }
 | 
						||
    os_release_mutex(g_meta_buf.meta_mutex);
 | 
						||
    iot_cus_printf("g_meta_buf.head = %d, g_meta_buf.pos = %d\n",
 | 
						||
        g_meta_buf.buf_head, g_meta_buf.buf_check_pos);
 | 
						||
    iot_meta_bin_dump(g_meta_buf.buf_head, g_meta_buf.buf_used -
 | 
						||
        g_meta_buf.buf_head);
 | 
						||
    iot_cus_printf(" %d meta cmd has been get, total %d bytes\n", pick_cnt, pick_data_len);
 | 
						||
    return pick_data_len;
 | 
						||
}
 | 
						||
 | 
						||
/**
 | 
						||
 * @brief iot_meta_buf_init() - initalize meta buffer
 | 
						||
 * @param module_id: module id
 | 
						||
 * @return: ERR_OK, or error reason
 | 
						||
 */
 | 
						||
uint8_t iot_meta_buf_init(uint16_t module_id)
 | 
						||
{
 | 
						||
    uint8_t ret = ERR_OK;
 | 
						||
 | 
						||
    os_mem_set(&g_meta_buf, 0, sizeof(meta_buf_ctr_t));
 | 
						||
    g_meta_buf.buf = iot_pkt_alloc(META_BUF_LENGTH, module_id);
 | 
						||
 | 
						||
    if (g_meta_buf.buf == NULL) {
 | 
						||
        iot_cus_printf("meta buffer alloc fail\n");
 | 
						||
        ret = ERR_FAIL;
 | 
						||
        goto out;
 | 
						||
    }
 | 
						||
 | 
						||
    g_meta_buf.buf_head = iot_pkt_put(g_meta_buf.buf, META_BUF_LENGTH);
 | 
						||
    os_mem_set(g_meta_buf.buf_head, 0, META_BUF_LENGTH);
 | 
						||
    g_meta_buf.buf_used = g_meta_buf.buf_head;
 | 
						||
    g_meta_buf.buf_rest = META_BUF_LENGTH;
 | 
						||
    g_meta_buf.buf_end = g_meta_buf.buf_head + META_BUF_LENGTH;
 | 
						||
    g_meta_buf.buf_check_pos = g_meta_buf.buf_head;
 | 
						||
    g_meta_buf.meta_mutex = os_create_mutex(module_id);
 | 
						||
 | 
						||
out:
 | 
						||
    return ret;
 | 
						||
}
 | 
						||
 |