402 lines
9.2 KiB
C
402 lines
9.2 KiB
C
/*
|
|
* pbuf.c
|
|
*
|
|
* Created on: 2022年12月5日
|
|
* Author: xushenghao
|
|
*/
|
|
#include "../inc/debug.h"
|
|
#include "../inc/pbuf.h"
|
|
#include "../inc/osel_arch.h"
|
|
#define PBUF_DATA_SIZE(pbuf) (pbuf->end - pbuf->head)
|
|
|
|
typedef struct _pbuf_type_t
|
|
{
|
|
uint8_t type;
|
|
uint16_t size;
|
|
uint8_t num;
|
|
} pbuf_type_t;
|
|
|
|
static list_head_t pbuf_freez_blocks[PBUF_TYPE_MAX_NUM];
|
|
uint8_t pbuf_cnt[PBUF_TYPE_MAX_NUM] = {0};
|
|
|
|
#if PBUF_DBG_EN > 0
|
|
static pbuf_t *pbuf_used_p[PBUF_TYPE_MAX_NUM][PBUF_NUM_MAX];
|
|
#endif
|
|
|
|
static void poly_type_pbuf_init(uint8_t type, uint16_t pkt_len, uint8_t num)
|
|
{
|
|
void *mem = NULL;
|
|
pbuf_t *pbuf = NULL;
|
|
|
|
list_init(&pbuf_freez_blocks[type]);
|
|
|
|
if (num == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
mem = osel_mem_alloc((sizeof(pbuf_t) + pkt_len) * num);
|
|
DBG_ASSERT(mem != NULL __DBG_LINE);
|
|
|
|
for (uint8_t i = 0; i < num; i++)
|
|
{
|
|
pbuf = (pbuf_t *)((uint8_t *)mem + i * (sizeof(pbuf_t) + pkt_len));
|
|
pbuf->head = (uint8_t *)pbuf + sizeof(pbuf_t);
|
|
pbuf->end = (uint8_t *)pbuf + sizeof(pbuf_t) + pkt_len;
|
|
pbuf->data_p = pbuf->head;
|
|
list_add_to_head(&pbuf->list, &pbuf_freez_blocks[type]);
|
|
}
|
|
|
|
pbuf_cnt[type] = num;
|
|
}
|
|
|
|
void pbuf_initz(void)
|
|
{
|
|
poly_type_pbuf_init(SMALL_PBUF,
|
|
SMALL_PBUF_BUFFER_SIZE,
|
|
SMALL_PBUF_NUM);
|
|
|
|
poly_type_pbuf_init(MEDIUM_PBUF,
|
|
MEDIUM_PBUF_BUFFER_SIZE,
|
|
MEDIUM_PBUF_NUM);
|
|
|
|
poly_type_pbuf_init(LARGE_PBUF,
|
|
LARGE_PBUF_BUFFER_SIZE,
|
|
LARGE_PBUF_NUM);
|
|
}
|
|
|
|
static pbuf_type_t search_free_pbuf(uint8_t pbuf_type)
|
|
{
|
|
pbuf_type_t free_pbuf_temp;
|
|
|
|
switch (pbuf_type)
|
|
{ // 没有break让代码顺序执行
|
|
case SMALL_PBUF:
|
|
if (!list_empty(&pbuf_freez_blocks[SMALL_PBUF]))
|
|
{
|
|
free_pbuf_temp.type = SMALL_PBUF;
|
|
free_pbuf_temp.size = SMALL_PBUF_BUFFER_SIZE;
|
|
free_pbuf_temp.num = SMALL_PBUF_NUM;
|
|
}
|
|
break;
|
|
case MEDIUM_PBUF:
|
|
if (!list_empty(&pbuf_freez_blocks[MEDIUM_PBUF]))
|
|
{
|
|
free_pbuf_temp.type = MEDIUM_PBUF;
|
|
free_pbuf_temp.size = MEDIUM_PBUF_BUFFER_SIZE;
|
|
free_pbuf_temp.num = MEDIUM_PBUF_NUM;
|
|
}
|
|
break;
|
|
case LARGE_PBUF:
|
|
if (!list_empty(&pbuf_freez_blocks[LARGE_PBUF]))
|
|
{
|
|
free_pbuf_temp.type = LARGE_PBUF;
|
|
free_pbuf_temp.size = LARGE_PBUF_BUFFER_SIZE;
|
|
free_pbuf_temp.num = LARGE_PBUF_NUM;
|
|
}
|
|
break;
|
|
default:
|
|
free_pbuf_temp.type = PBUF_TYPE_INVALID;
|
|
}
|
|
return free_pbuf_temp;
|
|
}
|
|
|
|
static pbuf_type_t pbuf_type_select(uint16_t size)
|
|
{
|
|
pbuf_type_t free_pbuf;
|
|
if (size <= SMALL_PBUF_BUFFER_SIZE)
|
|
{
|
|
free_pbuf = search_free_pbuf(SMALL_PBUF);
|
|
}
|
|
else if ((size > SMALL_PBUF_BUFFER_SIZE) && (size <= MEDIUM_PBUF_BUFFER_SIZE))
|
|
{
|
|
free_pbuf = search_free_pbuf(MEDIUM_PBUF);
|
|
}
|
|
else if ((size > MEDIUM_PBUF_BUFFER_SIZE) && (size <= LARGE_PBUF_BUFFER_SIZE))
|
|
{
|
|
free_pbuf = search_free_pbuf(LARGE_PBUF);
|
|
}
|
|
else
|
|
{
|
|
DBG_ASSERT(false __DBG_LINE);
|
|
}
|
|
|
|
if (free_pbuf.type == PBUF_TYPE_INVALID)
|
|
{
|
|
// DBG_ASSERT(false __DBG_LINE);
|
|
}
|
|
|
|
return free_pbuf;
|
|
}
|
|
|
|
#if PBUF_DBG_EN > 0
|
|
static void add_to_pbuf_used_ptr(pbuf_t *pbuf, pbuf_type_t pbuf_type)
|
|
{
|
|
// // hal_int_state_t s;
|
|
// // HAL_ENTER_CRITICAL(s);
|
|
for (uint8_t i = 0; i < PBUF_NUM_MAX; i++)
|
|
{
|
|
if (pbuf_used_p[pbuf_type.type][i] == NULL)
|
|
{
|
|
pbuf_used_p[pbuf_type.type][i] = pbuf;
|
|
break;
|
|
}
|
|
}
|
|
// // HAL_EXIT_CRITICAL(s);
|
|
}
|
|
#endif
|
|
|
|
pbuf_t *pbuf_allocz(uint16_t size _PLINE1_)
|
|
{
|
|
|
|
pbuf_type_t avilable_pbuf_type;
|
|
pbuf_t *pbuf = NULL;
|
|
// hal_int_state_t s;
|
|
// HAL_ENTER_CRITICAL(s);
|
|
avilable_pbuf_type = pbuf_type_select(size);
|
|
if (avilable_pbuf_type.type == PBUF_TYPE_INVALID)
|
|
{
|
|
return NULL;
|
|
}
|
|
pbuf = list_entry_decap(&pbuf_freez_blocks[avilable_pbuf_type.type],
|
|
pbuf_t,
|
|
list);
|
|
pbuf_cnt[avilable_pbuf_type.type]--;
|
|
// HAL_EXIT_CRITICAL(s);
|
|
|
|
DBG_ASSERT(pbuf != NULL __DBG_LINE);
|
|
if (pbuf == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
osel_memset(pbuf->head, 0, avilable_pbuf_type.size);
|
|
osel_memset((uint8_t *)&pbuf->attri, 0, sizeof(pbuf->attri));
|
|
|
|
// HAL_ENTER_CRITICAL(s);
|
|
pbuf->used = true;
|
|
pbuf->data_len = 0;
|
|
pbuf->data_p = pbuf->head;
|
|
list_init(&pbuf->list);
|
|
// HAL_EXIT_CRITICAL(s);
|
|
|
|
#if PBUF_DBG_EN > 0
|
|
pbuf->alloc_line = line;
|
|
pbuf->free_line = 0;
|
|
add_to_pbuf_used_ptr(pbuf, avilable_pbuf_type);
|
|
#endif
|
|
return pbuf;
|
|
}
|
|
|
|
static pbuf_type_t get_pbuf_type(pbuf_t **pbuf)
|
|
{
|
|
pbuf_type_t current_pbuf_type;
|
|
uint16_t size_temp;
|
|
|
|
DBG_ASSERT(*pbuf != NULL __DBG_LINE);
|
|
DBG_ASSERT(pbuf != NULL __DBG_LINE);
|
|
|
|
size_temp = (*pbuf)->end - (*pbuf)->head;
|
|
|
|
if (size_temp == SMALL_PBUF_BUFFER_SIZE)
|
|
{
|
|
current_pbuf_type.type = SMALL_PBUF;
|
|
current_pbuf_type.size = SMALL_PBUF_BUFFER_SIZE;
|
|
current_pbuf_type.num = SMALL_PBUF_NUM;
|
|
}
|
|
|
|
else if (size_temp == MEDIUM_PBUF_BUFFER_SIZE)
|
|
{
|
|
current_pbuf_type.type = MEDIUM_PBUF;
|
|
current_pbuf_type.size = MEDIUM_PBUF_BUFFER_SIZE;
|
|
current_pbuf_type.num = MEDIUM_PBUF_NUM;
|
|
}
|
|
|
|
else if (size_temp == LARGE_PBUF_BUFFER_SIZE)
|
|
{
|
|
current_pbuf_type.type = LARGE_PBUF;
|
|
current_pbuf_type.size = LARGE_PBUF_BUFFER_SIZE;
|
|
current_pbuf_type.num = LARGE_PBUF_NUM;
|
|
}
|
|
else
|
|
{
|
|
DBG_ASSERT(false __DBG_LINE);
|
|
}
|
|
|
|
return current_pbuf_type;
|
|
}
|
|
|
|
#if PBUF_DBG_EN > 0
|
|
static void delete_from_pbuf_used_ptr(pbuf_t **pbuf, pbuf_type_t pbuf_type_temp)
|
|
{
|
|
// hal_int_state_t s;
|
|
// HAL_ENTER_CRITICAL(s);
|
|
|
|
for (uint8_t i = 0; i < PBUF_NUM_MAX; i++)
|
|
{
|
|
if (pbuf_used_p[pbuf_type_temp.type][i] == *pbuf)
|
|
{
|
|
pbuf_used_p[pbuf_type_temp.type][i] = NULL;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// HAL_EXIT_CRITICAL(s);
|
|
}
|
|
#endif
|
|
|
|
void pbuf_freez(pbuf_t **const pbuf _PLINE2_)
|
|
{
|
|
|
|
pbuf_type_t pbuf_type;
|
|
// hal_int_state_t s;
|
|
DBG_ASSERT(*pbuf != NULL __DBG_LINE);
|
|
DBG_ASSERT(pbuf != NULL __DBG_LINE);
|
|
DBG_ASSERT((*pbuf)->used == true __DBG_LINE); // 用于检测嵌套的重复释放
|
|
|
|
if (pbuf == NULL || *pbuf == NULL || (*pbuf)->used == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
pbuf_type = get_pbuf_type(pbuf);
|
|
|
|
#if PBUF_DBG_EN > 0
|
|
delete_from_pbuf_used_ptr(pbuf, pbuf_type);
|
|
(*pbuf)->free_line = line;
|
|
#endif
|
|
osel_memset((*pbuf)->head, 0, pbuf_type.size);
|
|
osel_memset((uint8_t *)&((*pbuf)->attri), 0, sizeof((*pbuf)->attri));
|
|
|
|
// HAL_ENTER_CRITICAL(s);
|
|
|
|
if ((*pbuf)->data_len > ((*pbuf)->end - (*pbuf)->head))
|
|
{
|
|
DBG_ASSERT(false __DBG_LINE);
|
|
}
|
|
|
|
(*pbuf)->used = false;
|
|
(*pbuf)->data_len = 0;
|
|
(*pbuf)->data_p = (*pbuf)->head;
|
|
list_init(&(*pbuf)->list);
|
|
|
|
list_add_to_tail(&(*pbuf)->list, &pbuf_freez_blocks[pbuf_type.type]);
|
|
|
|
#if PBUF_DBG_EN > 0
|
|
uint8_t list_cnt = 0;
|
|
list_count(&pbuf_freez_blocks[pbuf_type.type], list_cnt);
|
|
DBG_ASSERT(list_cnt != 0 __DBG_LINE);
|
|
#endif
|
|
|
|
pbuf_cnt[pbuf_type.type]++;
|
|
|
|
#if PBUF_DBG_EN > 0
|
|
(*pbuf)->alloc_line = 0;
|
|
#endif
|
|
|
|
// HAL_EXIT_CRITICAL(s);
|
|
|
|
*pbuf = NULL;
|
|
}
|
|
|
|
uint8_t *pbuf_skip_datap_forward(pbuf_t *const pbuf, uint8_t len)
|
|
{
|
|
uint8_t *datap_tmp = NULL;
|
|
// hal_int_state_t s;
|
|
DBG_ASSERT(pbuf != NULL __DBG_LINE);
|
|
if (pbuf == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// HAL_ENTER_CRITICAL(s);
|
|
|
|
if ((pbuf->data_p + len) > pbuf->end)
|
|
{
|
|
// HAL_EXIT_CRITICAL(s);
|
|
return NULL;
|
|
}
|
|
|
|
pbuf->data_p += len;
|
|
datap_tmp = pbuf->data_p;
|
|
|
|
// HAL_EXIT_CRITICAL(s);
|
|
return datap_tmp;
|
|
}
|
|
|
|
uint8_t *pbuf_skip_datap_backward(pbuf_t *const pbuf, uint8_t len)
|
|
{
|
|
uint8_t *datap_tmp = NULL;
|
|
// hal_int_state_t s;
|
|
DBG_ASSERT(pbuf != NULL __DBG_LINE);
|
|
if (pbuf == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// HAL_ENTER_CRITICAL(s);
|
|
|
|
if ((pbuf->data_p - len) < pbuf->head)
|
|
{
|
|
// HAL_EXIT_CRITICAL(s);
|
|
return NULL;
|
|
}
|
|
|
|
pbuf->data_p -= len;
|
|
datap_tmp = pbuf->data_p;
|
|
|
|
// HAL_EXIT_CRITICAL(s);
|
|
return datap_tmp;
|
|
}
|
|
|
|
bool pbuf_copy_data_in(pbuf_t *const pbuf, const uint8_t *const src, uint8_t len)
|
|
{
|
|
DBG_ASSERT(pbuf != NULL __DBG_LINE);
|
|
if (pbuf == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
// hal_int_state_t s;
|
|
// HAL_ENTER_CRITICAL(s);
|
|
|
|
if ((pbuf->data_p + len) > pbuf->end)
|
|
{
|
|
// HAL_EXIT_CRITICAL(s);
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
osel_memcpy(pbuf->data_p, src, len);
|
|
pbuf->data_p += len;
|
|
pbuf->data_len += len;
|
|
|
|
// HAL_EXIT_CRITICAL(s);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
bool pbuf_copy_data_out(uint8_t *const dst, pbuf_t *const pbuf, uint8_t len)
|
|
{
|
|
DBG_ASSERT(pbuf != NULL __DBG_LINE);
|
|
if (pbuf == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
// hal_int_state_t s;
|
|
// HAL_ENTER_CRITICAL(s);
|
|
|
|
if ((pbuf->data_p + len) > pbuf->end)
|
|
{
|
|
// HAL_EXIT_CRITICAL(s);
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
osel_memcpy(dst, pbuf->data_p, len);
|
|
pbuf->data_p += len;
|
|
|
|
// HAL_EXIT_CRITICAL(s);
|
|
return true;
|
|
}
|
|
}
|