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;
|
||
}
|
||
|