硬汉嵌入式论坛

 找回密码
 立即注册
查看: 356|回复: 5
收起左侧

[RL-TCPnet V7.X] RL-TCPnet的动态内存管理

[复制链接]

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
119430
QQ
发表于 2025-10-10 10:15:48 | 显示全部楼层 |阅读模式



之前没有源码,想手动获取动态内存剩余不方便,现在有源码了,可以方便的查看了

[C] 纯文本查看 复制代码
/*------------------------------------------------------------------------------
 * MDK Middleware - Component ::Network
 * Copyright (c) 2004-2023 Arm Limited (or its affiliates). All rights reserved.
 *------------------------------------------------------------------------------
 * Name:    net_mem.c
 * Purpose: Dynamic Memory Management
 *----------------------------------------------------------------------------*/

#include <string.h>
#include "rl_net_lib.h"
#include "net_sys.h"
#include "net_mem.h"
#include "net_common.h"
#include "net_dbg.h"

/* Local variables */
static NET_MEM_CTRL  mem_control;
#define mem        (&mem_control)

/* Local functions */
static void mem_lock (void);
static void mem_unlock (void);

/**
  \brief       Initialize dynamic memory pool.
  \return      none.
*/
void net_mem_init (void) {
  NET_MEMP *init_ptr;

  DEBUGF (MEM,"Init MemPool %d bytes\n",sysc->MemSize);
  init_ptr       = (NET_MEMP *)sysc->MemPool;
  init_ptr->next = (NET_MEMP *)((uint32_t)sysc->MemPool + sysc->MemSize - sizeof (NET_MEMP *));
  init_ptr->next->next = NULL;
  init_ptr->len  = 0;
  mem->load      = 0;
  mem->count     = 0;
  mem->mutex     = netos_mutex_create (1);

  /* Usage limit for non critical allocations.     */
  /*   Limit[0] - ethernet & bsd receive buffering */
  /*   Limit[1] - TCP send buffering (low priority)*/
  if (sysc->MemSize < 65536) {
    /* Limit[0] at 75% of mpool */
    /* Limit[1] at 50% of mpool */
    mem->limit[0] = sysc->MemSize * 3 / 4;
    mem->limit[1] = sysc->MemSize / 2;
  }
  else {
    /* Limit[0] at mpsize-16k */
    /* Limit[1] at mpsize-32k */
    mem->limit[0] = sysc->MemSize - 16384;
    mem->limit[1] = sysc->MemSize - 32768;
  }
  if (sysc->TxQueUsed) {
    /* PPP or SLIP enabled, keep space for TX queue */
    mem->limit[1] = mem->limit[0] / 2;
  }
  DEBUGF (MEM," base=0x%X (limit_0=%d, limit_1=%d)\n",
               (uint32_t)sysc->MemPool, mem->limit[0], mem->limit[1]);
  EvrNetMEM_InitMemory (sysc->MemPool, sysc->MemSize, mem->limit[0], mem->limit[1]);
}

/**
  \brief       De-initialize dynamic memory pool.
  \return      none.
*/
void net_mem_uninit (void) {
  DEBUGF (MEM,"Uninit MemPool\n");
  EvrNetMEM_UninitMemory ();

  memset (sysc->MemPool, 0, sysc->MemSize);
  netos_mutex_delete (mem->mutex);
  memset (mem, 0, sizeof (*mem));
}

/**
  \brief       Allocate memory for the network frame.
  \param[in]   byte_size  buffer size in bytes.
  \return      Pointer to the allocated memory.
*/
NET_FRAME *net_mem_alloc (uint32_t byte_size) {
  NET_MEMP *search_ptr, *new_ptr;
  NET_FRAME *frame;
  uint32_t hole_size, req_size;

  /* Make sure that block is 4-byte aligned */
  req_size = (byte_size & ~0xC0000000) + MEM_HEADER_LEN + NET_HEADER_LEN;
  req_size = (req_size + 3) & ~3u;

  mem_lock ();

  DEBUGF (MEM,"Alloc %d bytes\n",req_size);
  if (byte_size & 0xC0000000) {
    /* Ethernet or BSD socket, keep at least 25% of the Pool free. */
    if ((mem->load + req_size) > mem->limit[0]) {
      DEBUGF (MEM," Failed, limit_0 exceeded\n");
      EvrNetMEM_AllocLimitExceeded (req_size, mem->load, mem->count);
      mem_unlock ();
      return (NULL);
    }
  }

  search_ptr = (NET_MEMP *)sysc->MemPool;
  while (true) {
    hole_size  = (uint32_t)search_ptr->next - (uint32_t)search_ptr;
    hole_size -= search_ptr->len;
    /* Check if the hole size is big enough */
    if (hole_size >= req_size) {
      break;
    }

    search_ptr = search_ptr->next;
    if (search_ptr->next == NULL) {
      /* Failed, we are at the end of the list */
      ERRORF (MEM,"Alloc, No memory (used=%d, blocks=%d)\n",mem->load,mem->count);
      EvrNetMEM_AllocOutOfMemory (req_size, mem->load, mem->count);
      mem_unlock ();
      if (!(byte_size & 0xC0000000)) {
        /* No sys_error trap for Ethernet or BSD socket */
        net_sys_error (NET_ERROR_MEM_ALLOC);
      }
      return (NULL);
    }
  }

  if (search_ptr->len == 0) {
    /* No block is allocated, set the Length of the first element */
    search_ptr->len = req_size;
    frame = __FRAME(search_ptr->content);
  }
  else {
    /* Insert a new list element into the memory list */
    new_ptr = (NET_MEMP *)((uint32_t)search_ptr + search_ptr->len);
    new_ptr->next    = search_ptr->next;
    search_ptr->next = new_ptr;
    new_ptr->len     = req_size;
    frame = __FRAME(new_ptr->content);
  }
  mem->load += req_size;
  mem->count++;
  DEBUGF (MEM," 0x%X (used=%d, blocks=%d)\n",(uint32_t)__MEMP(frame),mem->load,mem->count);
  EvrNetMEM_AllocMemory (__MEMP(frame), req_size, mem->load, mem->count);

  mem_unlock ();

  frame->length = byte_size & 0xFFFF;
  frame->index  = 0;
  return (frame);
}

/**
  \brief       Shrink allocated memory block.
  \param[in]   mem_ptr   pointer to allocated memory.
  \param[in]   new_size  size of utilized memory.
  \return      none.
  \note        This function is used, when full size memory block
               is allocated, but only small part utilized.
*/
void net_mem_shrink (NET_FRAME *mem_ptr, uint32_t new_size) {
  NET_MEMP *block_ptr;

  if (mem_ptr == NULL) {
    return;
  }

  mem_ptr->length = new_size & 0xFFFF;
  new_size += (MEM_HEADER_LEN + NET_HEADER_LEN);
  new_size  = (new_size + 3U) & ~3U;
  block_ptr = __MEMP(mem_ptr);

  if (new_size < block_ptr->len) {
    mem_lock ();

    DEBUGF (MEM,"Shrink 0x%X (new_size=%d)\n",(uint32_t)block_ptr,new_size);
    EvrNetMEM_ShrinkMemory (block_ptr, new_size);
    mem->load     -= (block_ptr->len - new_size);
    block_ptr->len = new_size;

    mem_unlock ();
  }
}

/**
  \brief       Release allocated memory.
  \param[in]   mem_ptr  pointer to the allocated memory.
  \return      none.
*/
void net_mem_free (NET_FRAME *mem_ptr) {
  NET_MEMP *prev_ptr, *search_ptr, *return_ptr, *limit_ptr;

  if (mem_ptr == NULL) {
    return;
  }

  mem_lock ();

  return_ptr = __MEMP(mem_ptr);

  /* Set list header */
  search_ptr = (NET_MEMP *)sysc->MemPool;
  limit_ptr  = (NET_MEMP *)((uint32_t)search_ptr + sysc->MemSize);
  prev_ptr   = NULL;
  while (search_ptr != return_ptr) {
    prev_ptr   = search_ptr;
    search_ptr = search_ptr->next;
    if (search_ptr == NULL) {
      /* This is not a valid Memory Block pointer */
      ERRORF (MEM,"Free, 0x%X invalid block\n",(uint32_t)return_ptr);
      EvrNetMEM_FreeInvalidBlock (return_ptr);

      mem_unlock ();
      net_sys_error (NET_ERROR_MEM_FREE);
      return;
    }
    if ((search_ptr <= (NET_MEMP *)&prev_ptr->content) ||
        (search_ptr >= limit_ptr) || ((uint32_t)search_ptr & 3)) {
      /* Pointer out of bounds or not aligned */
      ERRORF (MEM,"Free, 0x%X link corrupted\n",(uint32_t)search_ptr);
      EvrNetMEM_FreeLinkCorrupted (search_ptr);

      mem_unlock ();
      net_sys_error (NET_ERROR_MEM_CORRUPT);
      return;
    }
  }
  mem->load -= search_ptr->len;
  mem->count--;

  DEBUGF (MEM,"Free %d bytes\n",search_ptr->len);
  DEBUGF (MEM," 0x%X (used=%d, blocks=%d)\n",(uint32_t)search_ptr,mem->load,mem->count);
  EvrNetMEM_FreeMemory (search_ptr, search_ptr->len, mem->load, mem->count);
  if (search_ptr == (NET_MEMP *)sysc->MemPool) {
    /* First element to be freed, only set length to 0 */
    search_ptr->len = 0;
  }
  else {
    /* Discard list element */
    prev_ptr->next = search_ptr->next;
  }

  mem_unlock ();
}

/**
  \brief       Check if memory available for allocation.
  \param[in]   level  priority level of requester.
  \return      status:
               - true  = memory is available,
               - false = no memory available.
*/
bool net_mem_avail (int32_t level) {
  if (mem->load < mem->limit[level]) {
    return (true);
  }
  return (false);
}

/**
  \brief       Acquire memory protection mutex.
  \return      none.
*/
static void mem_lock (void) {
  netos_lock (mem->mutex);
}

/**
  \brief       Release memory protection mutex.
  \return      none.
*/
static void mem_unlock (void) {
  netos_unlock (mem->mutex);
}

回复

使用道具 举报

20

主题

255

回帖

315

积分

高级会员

积分
315
发表于 2025-10-10 10:36:07 | 显示全部楼层
源码开源了吗?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
119430
QQ
 楼主| 发表于 2025-10-10 10:49:19 | 显示全部楼层

是的,开源免费了。

RTX5全家桶源码综合模板发布V3.0,含FreeRTOS内核版本,将其打造成直接面向实际项目应用的综合框架(2025-03-10)
https://forum.anfulai.cn/forum.p ... 4516&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

20

主题

255

回帖

315

积分

高级会员

积分
315
发表于 2025-10-10 21:50:03 | 显示全部楼层
eric2013 发表于 2025-10-10 10:49
是的,开源免费了。

RTX5全家桶源码综合模板发布V3.0,含FreeRTOS内核版本,将其打造成直接面向实际项 ...

没有找到github的开源地址啊
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
119430
QQ
 楼主| 发表于 2025-10-11 09:05:22 | 显示全部楼层
回复

使用道具 举报

20

主题

255

回帖

315

积分

高级会员

积分
315
发表于 2025-10-11 10:09:39 | 显示全部楼层
eric2013 发表于 2025-10-11 09:05
https://github.com/ARM-software/MDK-Middleware

多谢硬汉
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-11-22 06:00 , Processed in 0.041222 second(s), 24 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表