Files
kunlun/app/utils/iot_app_meta_buffer_handle.c
2024-09-28 14:24:04 +08:00

250 lines
9.6 KiB
C
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/****************************************************************************
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 bufferbuffer里面有这几个指针
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;
}