250 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			250 lines
		
	
	
		
			9.6 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_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;
							 | 
						|||
| 
								 | 
							
								}
							 | 
						|||
| 
								 | 
							
								
							 |