847 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			847 lines
		
	
	
		
			23 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 "iot_pkt.h"
 | |
| #include "iot_mem_pool.h"
 | |
| #include "iot_module.h"
 | |
| #include "iot_errno.h"
 | |
| #include "iot_dbglog_api.h"
 | |
| #include "iot_dbglog.h"
 | |
| #include "iot_config.h"
 | |
| #include "iot_io.h"
 | |
| #include "iot_system_api.h"
 | |
| 
 | |
| typedef struct _iot_pkt_global {
 | |
|     uint32_t pool_cnt : 16,
 | |
|         req_cnt : 16;
 | |
|     iot_pkt_config_t config;
 | |
|     iot_mem_pool_t *pool[IOT_PKT_POOL_MAX];
 | |
| #if DEBUG_PKT_OVERWRITE
 | |
|     os_mutex_h mutex;
 | |
| #endif
 | |
| #if PLC_MEM_ALLOC_STAT > 1
 | |
|     uint16_t efficiency[IOT_PKT_POOL_MAX];
 | |
| #endif
 | |
| #if IOT_PKT_FREE_CALLBACK_ENABLE
 | |
|     os_mutex_h free_callback_lock;
 | |
| #endif
 | |
| } iot_pkt_global_t;
 | |
| 
 | |
| static iot_pkt_global_t *p_pkt_glb = NULL;
 | |
| 
 | |
| static inline void __iot_pkt_reset(iot_pkt_t* buf, uint32_t size)
 | |
| {
 | |
|     buf->head = (uint8_t*)buf + sizeof(iot_pkt_t);
 | |
|     buf->data = buf->head;
 | |
|     buf->tail = buf->head;
 | |
| 
 | |
|     buf->end = buf->head + size;
 | |
| 
 | |
| #if IOT_PKT_FREE_CALLBACK_ENABLE
 | |
|     iot_list_head_t *entry;
 | |
|     entry = (iot_list_head_t *)&(buf->entry);
 | |
|     iot_list_init(entry);
 | |
| 
 | |
|     buf->free_func = NULL;
 | |
|     buf->param = NULL;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| #if IOT_PKT_INFO_DUMP_DEBUG
 | |
| void iot_pkt_dump_info(void)
 | |
| {
 | |
|     uint32_t toltal_cnt, buf_size, free_cnt, i;
 | |
| 
 | |
|     for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | |
|         toltal_cnt = p_pkt_glb->config.pool_cfg[i].count;
 | |
|         buf_size = p_pkt_glb->config.pool_cfg[i].size;
 | |
|         free_cnt = iot_mem_pool_get_freenum(p_pkt_glb->pool[i]);
 | |
|         iot_printf("PKT:%d-%d/%d. ", buf_size, free_cnt, toltal_cnt);
 | |
|     }
 | |
|     iot_printf("\n");
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /* according to MID, get the pool owner mask */
 | |
| static inline uint32_t iot_pkt_get_target_owner(module_id_t module_id)
 | |
| {
 | |
|     uint32_t owner = 0;
 | |
| 
 | |
|     if (IOT_CLI_MID == module_id)
 | |
|     {
 | |
|         owner= PKT_OWNER_IOT;
 | |
|     }
 | |
|     else if ((module_id >= PLC_MID_BASE) && (module_id < NB_MID_BASE))
 | |
|     {
 | |
|         owner = PKT_OWNER_PLC;
 | |
|     }
 | |
|     else if ((module_id >= NB_MID_BASE) && (module_id < OS_RISCV_BASE))
 | |
|     {
 | |
|         owner = PKT_OWNER_NB;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         owner = PKT_OWNER_PLC;
 | |
|     }
 | |
|     return owner;
 | |
| }
 | |
| 
 | |
| void iot_pkt_init(const iot_pkt_config_t *cfg)
 | |
| {
 | |
|     uint16_t size, count;
 | |
|     uint32_t i, j, owner;
 | |
|     iot_mem_pool_t *tmp_pool;
 | |
|     iot_pkt_config_t *config;
 | |
| 
 | |
|     p_pkt_glb = os_mem_malloc(IOT_PKT_MID, sizeof(*p_pkt_glb));
 | |
|     IOT_ASSERT(p_pkt_glb);
 | |
| #if DEBUG_PKT_OVERWRITE
 | |
|     if (NULL == (p_pkt_glb->mutex = os_create_mutex(IOT_PKT_MID))) {
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
| #if IOT_PKT_FREE_CALLBACK_ENABLE
 | |
|     if (NULL ==
 | |
|         (p_pkt_glb->free_callback_lock = os_create_mutex(IOT_PKT_MID))) {
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
| #endif
 | |
|     config = &p_pkt_glb->config;
 | |
| 
 | |
|     for (i = 0; i < IOT_PKT_POOL_MAX; i++) {
 | |
|         if (cfg->pool_cfg[i].count == 0)
 | |
|             break;
 | |
|         config->pool_cfg[i].size = cfg->pool_cfg[i].size;
 | |
|         config->pool_cfg[i].count = cfg->pool_cfg[i].count;
 | |
|         config->pool_cfg[i].owner = cfg->pool_cfg[i].owner;
 | |
|     }
 | |
|     p_pkt_glb->pool_cnt = i;
 | |
|     IOT_ASSERT(p_pkt_glb->pool_cnt);
 | |
|     p_pkt_glb->req_cnt = 0;
 | |
| 
 | |
|     for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | |
|         if (config->pool_cfg[i].count) {
 | |
|             iot_mem_pool_new(IOT_PKT_MID, config->pool_cfg[i].count,
 | |
|                  sizeof(iot_pkt_t) + config->pool_cfg[i].size,
 | |
|                  &p_pkt_glb->pool[i], 1);
 | |
|             IOT_ASSERT(p_pkt_glb->pool[i]);
 | |
| #if PLC_MEM_ALLOC_STAT
 | |
|             iot_printf("data buf: %d, num %d x size %d = %d bytes, owner = 0x%X, "
 | |
|                     "@0x%x, align_size:%d\n", \
 | |
|             i, config->pool_cfg[i].count, \
 | |
|                 sizeof(iot_pkt_t) + config->pool_cfg[i].size,
 | |
|                 config->pool_cfg[i].count * \
 | |
|                 (sizeof(iot_pkt_t) + config->pool_cfg[i].size),
 | |
|                 config->pool_cfg[i].owner, p_pkt_glb->pool[i],\
 | |
|                 iot_mem_pool_get_align_size(p_pkt_glb->pool[i]));
 | |
| #endif
 | |
|         } else {
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /* sort the pkt size pool from least to largest */
 | |
|     for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | |
|         for (j = i + 1; j < p_pkt_glb->pool_cnt; j++) {
 | |
|             if (config->pool_cfg[i].size > config->pool_cfg[j].size) {
 | |
|                 size = config->pool_cfg[i].size;
 | |
|                 count = config->pool_cfg[i].count;
 | |
|                 owner = config->pool_cfg[i].owner;
 | |
|                 tmp_pool = p_pkt_glb->pool[i];
 | |
|                 config->pool_cfg[i].size = config->pool_cfg[j].size;
 | |
|                 config->pool_cfg[i].count = config->pool_cfg[j].count;
 | |
|                 config->pool_cfg[i].owner = config->pool_cfg[j].owner;
 | |
|                 p_pkt_glb->pool[i] = p_pkt_glb->pool[j];
 | |
|                 config->pool_cfg[j].size = size;
 | |
|                 config->pool_cfg[j].count = count;
 | |
|                 config->pool_cfg[j].owner = owner;
 | |
|                 p_pkt_glb->pool[j] = tmp_pool;
 | |
|             } else if (config->pool_cfg[i].size == config->pool_cfg[j].size) {
 | |
|                 IOT_ASSERT(0);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| #if IOT_PKT_DEBUG
 | |
| 
 | |
| iot_pkt_t* iot_pkt_mem_alloc(uint32_t size, module_id_t module_id,
 | |
|     uint8_t init_mem, const char *file_name, uint32_t line_num)
 | |
| {
 | |
|     uint32_t i, n, next, module_owner;
 | |
|     iot_pkt_t* result = NULL;
 | |
|     iot_pkt_t* printf_buf = NULL;
 | |
|     iot_mem_pool_entry_t* p_entry = NULL;
 | |
|     if (size == 0) {
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     module_owner = iot_pkt_get_target_owner(module_id);
 | |
|     for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | |
|         if (size <= p_pkt_glb->config.pool_cfg[i].size) {
 | |
|             if (p_pkt_glb->config.pool_cfg[i].owner & module_owner)
 | |
|             {
 | |
|                 result = iot_mem_pool_alloc(p_pkt_glb->pool[i]);
 | |
|                 if (result) {
 | |
|                     result->file_name = file_name;
 | |
|                     result->line_num = line_num;
 | |
|                     __iot_pkt_reset(result, p_pkt_glb->config.pool_cfg[i].size);
 | |
|                     if (init_mem) {
 | |
|                         os_mem_set(result->head, 0,
 | |
|                             (result->end - result->head));
 | |
|                     }
 | |
|                     goto out;
 | |
|                 } else {
 | |
|                     iot_printf("%s in Line %d ----buf_size:%d, pool_size:%d, "
 | |
|                         "this pool use up\n", file_name, line_num, size,
 | |
|                         p_pkt_glb->config.pool_cfg[i].size);
 | |
|                     p_entry = p_pkt_glb->pool[i]->entries;
 | |
|                     next = p_pkt_glb->pool[i]->align_block_word_size;
 | |
|                     if (p_entry != NULL) {
 | |
|                         for (n = 0; n < p_pkt_glb->pool[i]->num; n++) {
 | |
|                             printf_buf = (iot_pkt_t*)p_entry;
 | |
|                             iot_printf("%s in Line %d ----pool_size:%d, "
 | |
|                                 "addr = [0x%08X]\n", printf_buf->file_name,
 | |
|                                 printf_buf->line_num,
 | |
|                                 p_pkt_glb->config.pool_cfg[i].size, printf_buf);
 | |
|                             p_entry = p_entry + next;
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| out:
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| #else /* IOT_PKT_DEBUG */
 | |
| 
 | |
| iot_pkt_t* iot_pkt_mem_alloc(uint32_t size, module_id_t module_id,
 | |
|     uint8_t init_mem)
 | |
| {
 | |
|     uint32_t i = 0, module_owner;
 | |
|     iot_pkt_t* result = NULL;
 | |
| #if DEBUG_PKT_OVERWRITE
 | |
|     uint32_t ast_ra = 0;
 | |
|     RISC_GET_REG_RA(ast_ra);
 | |
| #endif
 | |
| 
 | |
|     if (size == 0) {
 | |
|         goto out;
 | |
|     }
 | |
| 
 | |
|     module_owner = iot_pkt_get_target_owner(module_id);
 | |
|     for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | |
|         if (size <= p_pkt_glb->config.pool_cfg[i].size) {
 | |
|             if ( p_pkt_glb->config.pool_cfg[i].owner & module_owner) {
 | |
|                 result = iot_mem_pool_alloc(p_pkt_glb->pool[i]);
 | |
|                 if (result) {
 | |
|                     __iot_pkt_reset(result,
 | |
|                         p_pkt_glb->config.pool_cfg[i].size);
 | |
| #if DEBUG_PKT_OVERWRITE
 | |
|                     iot_printf("pkt_alloc:@%x,ra:0x%x\n", \
 | |
|                         (uint32_t)result, ast_ra);
 | |
|                     os_acquire_mutex(p_pkt_glb->mutex);
 | |
|                     iot_pkt_check_end_overwrite(result);
 | |
|                     os_release_mutex(p_pkt_glb->mutex);
 | |
| #endif
 | |
|                     if (init_mem) {
 | |
|                         os_mem_set(result->head, 0,
 | |
|                             (result->end - result->head));
 | |
|                     }
 | |
| #if PLC_MEM_ALLOC_STAT > 1
 | |
|                     /* 1/8 avg efficiency contribution for this time */
 | |
|                     p_pkt_glb->efficiency[i] = \
 | |
|                         (p_pkt_glb->efficiency[i] - \
 | |
|                             (p_pkt_glb->efficiency[i] >> 3)) + \
 | |
|                             ((size & 0xffff) >> 3);
 | |
| #endif
 | |
|                     goto out;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| out:
 | |
| #if PLC_MEM_ALLOC_STAT > 1
 | |
|     if ((++p_pkt_glb->req_cnt & IOTPKT_STAT_DISPLAY_FREQ) \
 | |
|         == IOTPKT_STAT_DISPLAY_FREQ)
 | |
|     {
 | |
|         for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | |
|             iot_printf("pu%dpm%d/%d:e%d/%d;",
 | |
|             p_pkt_glb->pool[i]->num - p_pkt_glb->pool[i]->free_num,
 | |
|             p_pkt_glb->pool[i]->max_num,
 | |
|             p_pkt_glb->pool[i]->num, p_pkt_glb->efficiency[i],
 | |
|             (p_pkt_glb->pool[i]->align_block_word_size << 2));
 | |
|         }
 | |
|         iot_printf("\n");
 | |
|     }
 | |
| #endif
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| #endif /* IOT_PKT_DEBUG */
 | |
| 
 | |
| uint32_t iot_pkt_set_free_callback(iot_pkt_t *buf,
 | |
|     iot_pkt_free_func_t free_callback, void *param)
 | |
| {
 | |
| #if IOT_PKT_FREE_CALLBACK_ENABLE
 | |
|     if (buf) {
 | |
|         buf->free_func = free_callback;
 | |
|         buf->param = param;
 | |
|         return ERR_OK;
 | |
|     }
 | |
| #else
 | |
|     (void)buf;
 | |
|     (void)free_callback;
 | |
|     (void)param;
 | |
| #endif
 | |
|     return ERR_FAIL;
 | |
| }
 | |
| 
 | |
| void iot_pkt_get_free_callback(iot_pkt_t *buf,
 | |
|     iot_pkt_free_func_t *free_callback, void **param)
 | |
| {
 | |
| 
 | |
| #if IOT_PKT_FREE_CALLBACK_ENABLE
 | |
|     if (buf && buf->free_func) {
 | |
|         *free_callback = buf->free_func;
 | |
|         *param = buf->param;
 | |
|         return;
 | |
|     }
 | |
| #endif
 | |
|     (void)buf;
 | |
|     *free_callback = NULL;
 | |
|     *param = NULL;
 | |
| }
 | |
| 
 | |
| static void iot_pkt_exe_free_callback(iot_pkt_t *buf, uint8_t state)
 | |
| {
 | |
| #if IOT_PKT_FREE_CALLBACK_ENABLE
 | |
|     uint32_t ret;
 | |
|     iot_list_head_t *entry = (iot_list_head_t *)&(buf->entry);
 | |
| 
 | |
|     os_acquire_mutex(p_pkt_glb->free_callback_lock);
 | |
|     ret = iot_list_empty(entry);
 | |
|     if (!ret) {
 | |
|         iot_list_del(entry);
 | |
|     }
 | |
|     os_release_mutex(p_pkt_glb->free_callback_lock);
 | |
| 
 | |
|     if (ret && buf->free_func) {
 | |
|         buf->free_func(buf->param, state);
 | |
|     }
 | |
| #else
 | |
|     (void)buf;
 | |
|     (void)state;
 | |
| #endif
 | |
| }
 | |
| 
 | |
| void iot_pkt_free(iot_pkt_t* buf)
 | |
| {
 | |
|     iot_pkt_free_tx_done(buf, IOT_PKT_STATE_UNKNOWN);
 | |
| }
 | |
| 
 | |
| void iot_pkt_free_tx_done(iot_pkt_t* buf, uint8_t state)
 | |
| {
 | |
|     uint32_t i, buf_len;
 | |
| #if DEBUG_PKT_OVERWRITE
 | |
|     uint32_t ast_ra = 0;
 | |
|     RISC_GET_REG_RA(ast_ra);
 | |
| #endif
 | |
| 
 | |
|     if (buf == NULL) {
 | |
|         IOT_ASSERT(0);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     buf_len = iot_pkt_block_len(buf, IOT_PKT_BLOCK_ALL);
 | |
| 
 | |
|     for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | |
|         if (buf_len == p_pkt_glb->config.pool_cfg[i].size) {
 | |
|             iot_pkt_exe_free_callback(buf, state);
 | |
| #if DEBUG_PKT_OVERWRITE
 | |
|             iot_printf("pkt_free@%x,ra:0x%x\n", (uint32_t)buf, ast_ra);
 | |
|             os_acquire_mutex(p_pkt_glb->mutex);
 | |
|             iot_pkt_check_end_overwrite(buf);
 | |
|             /* init the tail and end value for debug. */
 | |
|             buf->tail = NULL;
 | |
|             buf->end = NULL;
 | |
|             iot_mem_pool_free(p_pkt_glb->pool[i], buf);
 | |
|             os_release_mutex(p_pkt_glb->mutex);
 | |
| #else
 | |
|             iot_mem_pool_free(p_pkt_glb->pool[i], buf);
 | |
| #endif
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (i >= p_pkt_glb->pool_cnt) {
 | |
|         uint32_t ret;
 | |
|         /* buffer corrupted */
 | |
|         iot_printf("pkt 0x%x not found with len %d\n", buf, buf_len);
 | |
|         iot_pkt_exe_free_callback(buf, state);
 | |
|         for (i = 0; i < p_pkt_glb->pool_cnt; i++) {
 | |
|             ret = iot_mem_pool_force_free(p_pkt_glb->pool[i], buf);
 | |
|             if (ret == ERR_OK) {
 | |
|                 goto out;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
| 
 | |
| out:
 | |
|     return;
 | |
| }
 | |
| 
 | |
| uint8_t** iot_pkt_dataptr_addr(iot_pkt_t* buf)
 | |
| {
 | |
|     if (buf) {
 | |
|         return (&buf->data);
 | |
|     }
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| uint8_t* iot_pkt_reserve(iot_pkt_t* buf, uint32_t size)
 | |
| {
 | |
|     if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
|     if (buf && buf->tail + size <= buf->end) {
 | |
|         buf->data += size;
 | |
|         buf->tail += size;
 | |
| 
 | |
|         return buf->data;
 | |
|     }
 | |
|     IOT_ASSERT(0);
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| uint8_t* iot_pkt_put(iot_pkt_t* buf, uint32_t size)
 | |
| {
 | |
|     if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
|     if (buf && buf->tail + size <= buf->end) {
 | |
|         buf->tail += size;
 | |
| 
 | |
|         return buf->data;
 | |
|     }
 | |
|     IOT_ASSERT(0);
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| uint8_t* iot_pkt_shrink(iot_pkt_t* buf, uint32_t size)
 | |
| {
 | |
|     if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
|     if (buf && buf->tail - size >= buf->data) {
 | |
|         buf->tail -= size;
 | |
| 
 | |
|         return buf->data;
 | |
|     }
 | |
|     IOT_ASSERT(0);
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| uint8_t* iot_pkt_push(iot_pkt_t* buf, uint32_t size)
 | |
| {
 | |
|     if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
|     if (buf && buf->data - size >= buf->head) {
 | |
|         buf->data -= size;
 | |
| 
 | |
|         return buf->data;
 | |
|     }
 | |
|     IOT_ASSERT(0);
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| uint8_t* iot_pkt_pull(iot_pkt_t* buf, uint32_t size)
 | |
| {
 | |
|     if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
|     if (buf && buf->data + size <= buf->tail) {
 | |
|         buf->data += size;
 | |
| 
 | |
|         return buf->data;
 | |
|     }
 | |
|     IOT_ASSERT(0);
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| uint8_t* IRAM_ATTR iot_pkt_set_data(iot_pkt_t* buf, void* new_data)
 | |
| {
 | |
|     if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
|     if (buf && (uint8_t*)new_data >= buf->head
 | |
|         && (uint8_t*)new_data <= buf->tail) {
 | |
|         buf->data = (uint8_t*)new_data;
 | |
| 
 | |
|         return buf->data;
 | |
|     }
 | |
|     IOT_ASSERT(0);
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| uint8_t* IRAM_ATTR iot_pkt_set_tail(iot_pkt_t* buf, void* new_tail)
 | |
| {
 | |
|     if (buf->data == (uint8_t*)IOT_MEM_POOL_POISON) {
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
|     if (buf && (uint8_t*)new_tail >= buf->data
 | |
|                 && (uint8_t*)new_tail <= buf->end) {
 | |
|         buf->tail = (uint8_t*)new_tail;
 | |
| 
 | |
|         return buf->data;
 | |
|     }
 | |
|     IOT_ASSERT(0);
 | |
| 
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| uint8_t* IRAM_ATTR iot_pkt_block_ptr(iot_pkt_t* buf, uint8_t block_type)
 | |
| {
 | |
|     if (buf == NULL) {
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     void* result = NULL;
 | |
|     switch (block_type)
 | |
|     {
 | |
|     case IOT_PKT_BLOCK_ALL:
 | |
|     case IOT_PKT_BLOCK_HEAD:
 | |
|         result = buf->head;
 | |
|         break;
 | |
|     case IOT_PKT_BLOCK_DATA:
 | |
|         result = buf->data;
 | |
|         break;
 | |
|     case IOT_PKT_BLOCK_TAIL:
 | |
|         result = buf->tail;
 | |
|         break;
 | |
|     case IOT_PKT_BLOCK_END:
 | |
|         result = buf->end;
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
| 
 | |
|     return result;
 | |
| }
 | |
| 
 | |
| uint32_t IRAM_ATTR iot_pkt_block_len(iot_pkt_t* buf, uint8_t block_type)
 | |
| {
 | |
|     if (buf == NULL) {
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     uint32_t len = 0;
 | |
|     switch (block_type)
 | |
|     {
 | |
|     case IOT_PKT_BLOCK_ALL:
 | |
|         len = buf->end - buf->head;
 | |
|         break;
 | |
|     case IOT_PKT_BLOCK_HEAD:
 | |
|         len = buf->data - buf->head;
 | |
|         break;
 | |
|     case IOT_PKT_BLOCK_DATA:
 | |
|         len = buf->tail - buf->data;
 | |
|         break;
 | |
|     case IOT_PKT_BLOCK_TAIL:
 | |
|         len = buf->end - buf->tail;
 | |
|         break;
 | |
|     default:
 | |
|         IOT_ASSERT(0);
 | |
|     }
 | |
| 
 | |
|     return len;
 | |
| }
 | |
| 
 | |
| void iot_pkt_reset(iot_pkt_t *buf)
 | |
| {
 | |
|     os_mem_set(buf->head, 0, (buf->end - buf->head));
 | |
|     buf->data = buf->tail = buf->head;
 | |
| }
 | |
| 
 | |
| void iot_pkt_cpy(iot_pkt_t *dst, iot_pkt_t *src)
 | |
| {
 | |
|     if ((dst->end - dst->head) < (src->tail - src->head)) {
 | |
|         IOT_ASSERT(0);
 | |
|     } else {
 | |
|         dst->data = dst->head + (src->data - src->head);
 | |
|         dst->tail = dst->data + (src->tail - src->data);
 | |
|         os_mem_cpy(dst->data, src->data, (src->tail - src->data));
 | |
| 
 | |
| #if IOT_PKT_FREE_CALLBACK_ENABLE
 | |
|         iot_list_head_t *src_entry, *dst_entry;
 | |
|         src_entry = (iot_list_head_t *)&(src->entry);
 | |
|         dst_entry = (iot_list_head_t *)&(dst->entry);
 | |
|         os_acquire_mutex(p_pkt_glb->free_callback_lock);
 | |
|         iot_list_add(dst_entry, src_entry);
 | |
|         os_release_mutex(p_pkt_glb->free_callback_lock);
 | |
| 
 | |
|         if (src->free_func) {
 | |
|             dst->free_func = src->free_func;
 | |
|             dst->param = src->param;
 | |
|         }
 | |
| #endif
 | |
|     }
 | |
| }
 | |
| 
 | |
| void iot_pkt_cpy_with_head(iot_pkt_t *dst, iot_pkt_t *src)
 | |
| {
 | |
|     iot_pkt_cpy(dst, src);
 | |
|     os_mem_cpy(dst->head, src->head, (src->data - src->head));
 | |
| }
 | |
| 
 | |
| uint32_t iot_pkt_list_block_data_len(iot_pkt_ls *pkt_list)
 | |
| {
 | |
|     uint32_t toltal_len = 0;
 | |
|     iot_pkt_ls *lst = pkt_list;
 | |
| 
 | |
|     while(lst)
 | |
|     {
 | |
|         if(lst->pkt)
 | |
|             toltal_len += iot_pkt_block_len(lst->pkt, IOT_PKT_BLOCK_DATA);
 | |
|         lst = lst->next;
 | |
|     }
 | |
| 
 | |
|     return toltal_len;
 | |
| }
 | |
| 
 | |
| uint32_t iot_pkt_list_item_count(iot_pkt_ls *pkt_list)
 | |
| {
 | |
|     uint32_t cnt = 0;
 | |
|     iot_pkt_ls *lst = pkt_list;
 | |
| 
 | |
|     while(lst)
 | |
|     {
 | |
|         cnt ++;
 | |
|         lst = lst->next;
 | |
|     }
 | |
| 
 | |
|     return cnt;
 | |
| }
 | |
| 
 | |
| void iot_pkt_list_free_every_pkt_mem(iot_pkt_ls *pkt_list)
 | |
| {
 | |
|     iot_pkt_ls *lst = pkt_list;
 | |
| 
 | |
|     while(lst)
 | |
|     {
 | |
|         if(lst->pkt)
 | |
|         {
 | |
|             iot_pkt_free(lst->pkt);
 | |
|             lst->pkt = NULL;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return;
 | |
| }
 | |
| 
 | |
| uint32_t iot_pkt_pktpool_status(uint8_t pool_idx, uint32_t* bufsz, \
 | |
|     uint32_t* freenum, uint32_t* totalnum)
 | |
| {
 | |
|     if ((pool_idx >= IOT_PKT_POOL_MAX) || (bufsz == NULL) ||
 | |
|         (freenum == NULL) || (totalnum == NULL))
 | |
|     {
 | |
|            return ERR_INVAL;
 | |
|     }
 | |
| 
 | |
|     *bufsz =  p_pkt_glb->config.pool_cfg[pool_idx].size;
 | |
|     *freenum = iot_mem_pool_get_freenum(p_pkt_glb->pool[pool_idx]);
 | |
|     *totalnum = p_pkt_glb->config.pool_cfg[pool_idx].count;
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| 
 | |
| void mem_dump(uint32_t *word_ptr, uint32_t word_cnt)
 | |
| {
 | |
|     for (uint32_t j = 0; j < (word_cnt >> 2); j++) {
 | |
|         iot_printf("0x%08x:", word_ptr + (j << 2));
 | |
|         for (uint32_t i = 0; i < 4; i++)
 | |
|         {
 | |
|             iot_printf("0x%08x ", *(word_ptr + (j << 2) + i));
 | |
|         }
 | |
|         iot_printf("\n");
 | |
|     }
 | |
|     return;
 | |
| }
 | |
| 
 | |
| void mem_dump_byte(uint8_t *byte_ptr, uint32_t byte_cnt)
 | |
| {
 | |
|     uint32_t i, j;
 | |
|     for (i = 0; i < byte_cnt; ) {
 | |
|         iot_printf("0x%08x:", (uint32_t)byte_ptr + i);
 | |
|         for (j = 0; j < 8; j++) {
 | |
|             if ((i + j) >= byte_cnt) {
 | |
|                 break;
 | |
|             }
 | |
|             iot_printf("0x%02x ", byte_ptr[i + j]);
 | |
|         }
 | |
|         iot_printf("\n");
 | |
|         i += j;
 | |
|     }
 | |
| }
 | |
| 
 | |
| uint32_t iot_pkt_validation(iot_pkt_t *pkt)
 | |
| {
 | |
|     if (!iot_data_addr_legal(
 | |
|              (uint32_t) iot_pkt_block_ptr(pkt,
 | |
|                  IOT_PKT_BLOCK_HEAD))
 | |
|         || !iot_data_addr_legal(
 | |
|              (uint32_t) iot_pkt_block_ptr(pkt,
 | |
|                  IOT_PKT_BLOCK_DATA))
 | |
|         || !iot_data_addr_legal(
 | |
|              (uint32_t) iot_pkt_block_ptr(pkt,
 | |
|                  IOT_PKT_BLOCK_TAIL))
 | |
|         || !iot_data_addr_legal(
 | |
|              (uint32_t) iot_pkt_block_ptr(pkt,
 | |
|                  IOT_PKT_BLOCK_END)))
 | |
|     {
 | |
|         iot_printf("iot_pkt overwrite found @0x%x, "
 | |
|             "4 pointers' are: 0x%x, 0x%x, 0x%x, 0x%x\n",
 | |
|             pkt,
 | |
|             iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_HEAD),
 | |
|             iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA),
 | |
|             iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_TAIL),
 | |
|             iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_END));
 | |
|         iot_dbglog_input(PLC_MAC_RX_HW_MID, DBGLOG_ERR,
 | |
|             IOT_MAC_RX_OVERWRITE_ID, 5, pkt,
 | |
|             iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_HEAD),
 | |
|             iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA),
 | |
|             iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_TAIL),
 | |
|             iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_END));
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| #if DEBUG_PKT_OVERWRITE
 | |
| 
 | |
| uint32_t iot_pkt_check_end_overwrite(iot_pkt_t *buf)
 | |
| {
 | |
|     uint32_t align_size = 0;
 | |
|     uint32_t pool_num, size, count;
 | |
|     uint32_t head_addr, data_addr, tail_addr, end_addr;
 | |
|     uint32_t last_pkt_addr;
 | |
| 
 | |
|     if (!buf) {
 | |
|         iot_printf("pkt_check invalid\n");
 | |
|         IOT_ASSERT(0);
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
| 
 | |
|     size = iot_pkt_block_len(buf, IOT_PKT_BLOCK_ALL);
 | |
|     for (pool_num = 0; pool_num < p_pkt_glb->pool_cnt; ) {
 | |
|         if (size == p_pkt_glb->config.pool_cfg[pool_num].size) {
 | |
|             align_size = iot_mem_pool_get_align_size(p_pkt_glb->pool[pool_num]);
 | |
|             break;
 | |
|         }
 | |
|         ++pool_num;
 | |
|     }
 | |
| 
 | |
|     if (align_size == 0) {
 | |
|         iot_printf("pkt_check not found pool\n");
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
| 
 | |
|     /* calculation the actual next pkt */
 | |
|     iot_pkt_t *pkt = (iot_pkt_t *)((uint32_t)buf + align_size);
 | |
| 
 | |
|     size = iot_mem_pool_get_align_size(p_pkt_glb->pool[pool_num]);
 | |
|     count = p_pkt_glb->config.pool_cfg[pool_num].count;
 | |
|     /* get this pool last pkt addr */
 | |
|     last_pkt_addr = (uint32_t)p_pkt_glb->pool[pool_num]->entries \
 | |
|         + (size * (count - 1));
 | |
| 
 | |
|     /* the next pkt is the next pool first pkt.
 | |
|      * but each pool address is discontinuous.
 | |
|      */
 | |
|     if ((uint32_t)pkt > last_pkt_addr) {
 | |
|         pool_num++; // set pool to next pool num
 | |
|         /* next pool's pkt size = 0, means current pool is last pool.
 | |
|          * don't need to check the next pkt. */
 | |
|         if (0 == p_pkt_glb->config.pool_cfg[pool_num].size) {
 | |
|             return ERR_OK;
 | |
|         }
 | |
|         pkt = (iot_pkt_t *)p_pkt_glb->pool[pool_num]->entries;
 | |
|     }
 | |
| 
 | |
|     if (!pkt) {
 | |
|         iot_printf("pkt_check buf=0x%x, last=0x%x\n",
 | |
|             (uint32_t)buf, (uint32_t)last_pkt_addr);
 | |
|         //align_size * 2 / 4
 | |
|         IOT_ASSERT_DUMP(0, (uint32_t *)buf, align_size >> 1);
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
| 
 | |
|     /* get this pkt's head/data/tail/end address */
 | |
|     head_addr = (uint32_t)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_HEAD);
 | |
|     data_addr = (uint32_t)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_DATA);
 | |
|     tail_addr = (uint32_t)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_TAIL);
 | |
|     end_addr = (uint32_t)iot_pkt_block_ptr(pkt, IOT_PKT_BLOCK_END);
 | |
| 
 | |
|     if (((0 == head_addr) || iot_data_addr_legal(head_addr))
 | |
|         && ((uint32_t)IOT_MEM_POOL_POISON == data_addr)
 | |
|         && !tail_addr
 | |
|         && !end_addr) {
 | |
|         /* the next pkt not allocated ,not need check.
 | |
|          * for the not allocated pkt:
 | |
|          * pkt->head is the pool block's head, the value is NULL or
 | |
|          *      next_pool_block_ptr.
 | |
|          * pkt->data must be IOT_MEM_POOL_POISON
 | |
|          * pkt->tail and pkt->end must be NULL
 | |
|          * for the allocated pkt, the head/data/tail/end must be valid address.
 | |
|          */
 | |
|         return ERR_OK;
 | |
|     }
 | |
| 
 | |
|     /* next pkt */
 | |
|     if (ERR_OK != iot_pkt_validation(pkt)) {
 | |
|         //align_size * 2 / 4
 | |
|         iot_printf("pkt_end_overwrite:0x%x-0x%x\n",
 | |
|             (uint32_t)buf, (uint32_t)pkt);
 | |
|         IOT_ASSERT_DUMP(0, (uint32_t *)buf, align_size >> 1);
 | |
|         return ERR_INVAL;
 | |
|     }
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| #else /* DEBUG_PKT_OVERWRITE */
 | |
| 
 | |
| uint32_t iot_pkt_check_end_overwrite(iot_pkt_t *buf)
 | |
| {
 | |
|     (void)buf;
 | |
|     return ERR_OK;
 | |
| }
 | |
| 
 | |
| #endif /* DEBUG_PKT_OVERWRITE */
 | |
| 
 |