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