📄 os_mem.c
字号:
/*
*********************************************************************************************************
* uC/OS-II 实时内核
* 内存管理
*
* (c) 版权 1992-2002, 所有版权归Jean J. Labrosse, Weston, FL 所有
*
*
* 文件名称 : OS_MEM.C
* 程序作者 : Jean J. Labrosse
*********************************************************************************************************
*/
#ifndef OS_MASTER_FILE
#include "includes.h"
#endif
#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
/*
*********************************************************************************************************
* 创建一个内存分区
*
* 程序描述 : 创建一个由 uC/OS-II 管理的固定容量的内存分区.
*
* 输入参数 : addr 内存分区的起始地址
*
* nblks 分区中的内存块数量
*
* blksize 分区中每个内存块的大小(字节)
*
* err 指向出错信息的指针:
*
* OS_NO_ERR 内存分区正确创建.
* OS_MEM_INVALID_ADDR 为内存分区指定的地址无效
* OS_MEM_INVALID_PART 无空余的有效分区
* OS_MEM_INVALID_BLKS 指定的内存块数无效 (必须大于等于 2)
* OS_MEM_INVALID_SIZE 指定的内存块大小无效(必须有放的下一个指针的大小)
* 返回值 : != (OS_MEM *)0 分区成功创建
* == (OS_MEM *)0 由于参数无效或无空余分区,内存分区未创建。
*********************************************************************************************************
*/
OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
OS_MEM *pmem;
INT8U *pblk;
void **plink;
INT32U i;
#if OS_ARG_CHK_EN > 0
if (addr == (void *)0)
{ /* 为内存分区指定的地址是否有效 ?*/
*err = OS_MEM_INVALID_ADDR;
return ((OS_MEM *)0);
}
if (nblks < 2)
{ /* 每个分区是否至少有两个块? */
*err = OS_MEM_INVALID_BLKS;
return ((OS_MEM *)0);
}
if (blksize < sizeof(void *))
{ /* 每个块是否放的下一个指针? */
*err = OS_MEM_INVALID_SIZE;
return ((OS_MEM *)0);
}
#endif
OS_ENTER_CRITICAL();
pmem = OSMemFreeList; /* 得到一个内存分区块 */
if (OSMemFreeList != (OS_MEM *)0) /* 看空余分区池是否为空? */
{
OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
}
OS_EXIT_CRITICAL();
if (pmem == (OS_MEM *)0)
{ /* 看是否有一个内存分区? */
*err = OS_MEM_INVALID_PART;
return ((OS_MEM *)0);
}
plink = (void **)addr; /* 创建空闲内存块链接表 */
pblk = (INT8U *)addr + blksize;
for (i = 0; i < (nblks - 1); i++)
{
*plink = (void *)pblk;
plink = (void **)pblk;
pblk = pblk + blksize;
}
*plink = (void *)0; /* 最后的内存块指向空 */
pmem->OSMemAddr = addr; /* 保存内存分区的起始地址 */
pmem->OSMemFreeList = addr; /* 指向空余内存分区块池的指针 */
pmem->OSMemNFree = nblks; /* 在MCB中保存空闲的内存块 */
pmem->OSMemNBlks = nblks;
pmem->OSMemBlkSize = blksize; /* 保存每个内存块的块大小 */
*err = OS_NO_ERR;
return (pmem);
}
/*$PAGE*/
/*
*********************************************************************************************************
* 得到一个内存块
*
* 函数描述 : 从分区中得到内存块
*
* 输入参数 : pmem 指向MCB的指针
*
* err 指向出错信息的指针:
*
* OS_NO_ERR 内存分区正确创建
* OS_MEM_NO_FREE_BLKS 没有空闲内存块分配
* OS_MEM_INVALID_PMEM 给'pmem'传递一个空指针
*
* 返回值 :如无错给内存块一个指针
* 如有错返回空指针
*********************************************************************************************************
*/
void *OSMemGet (OS_MEM *pmem, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
void *pblk;
#if OS_ARG_CHK_EN > 0
if (pmem == (OS_MEM *)0)
{ /* 是否指向一个有效的内存分区? */
*err = OS_MEM_INVALID_PMEM;
return ((OS_MEM *)0);
}
#endif
OS_ENTER_CRITICAL();
if (pmem->OSMemNFree > 0) /* 看是否有空闲的内存块? */
{
pblk = pmem->OSMemFreeList; /* 是,指向下一个空闲内存块 */
pmem->OSMemFreeList = *(void **)pblk; /* 调整空闲列表的指针 */
pmem->OSMemNFree--; /* 分区中减少一个空闲块 */
OS_EXIT_CRITICAL();
*err = OS_NO_ERR; /* 无错 */
return (pblk); /* 返回内存块给调用者 */
}
OS_EXIT_CRITICAL();
*err = OS_MEM_NO_FREE_BLKS; /* 没有, 通知调用者无空闲块 */
return ((void *)0); /* 返回空指针 */
}
/*$PAGE*/
/*
*********************************************************************************************************
* 释放一个内存块
*
* 函数描述 : 返回一个内存块
*
* 输入参数 : pmem 指向MCB的指针
*
* pblk 指向被释放的内存块的指针
*
* Returns : OS_NO_ERR 内存块被插进分区
* OS_MEM_FULL 返回一个内存块到满内存分区中。
* OS_MEM_INVALID_PMEM 给 'pmem'传递了一个空指针
* OS_MEM_INVALID_PBLK 为释放的内存块传递了一个空指针
*********************************************************************************************************
*/
INT8U OSMemPut (OS_MEM *pmem, void *pblk)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
#if OS_ARG_CHK_EN > 0 /* 必须指向有效的内存分区 */
if (pmem == (OS_MEM *)0)
{
return (OS_MEM_INVALID_PMEM);
}
if (pblk == (void *)0) /* 释放一个有效的内存块 */
{
return (OS_MEM_INVALID_PBLK);
}
#endif
OS_ENTER_CRITICAL();
if (pmem->OSMemNFree >= pmem->OSMemNBlks) /* 内存分区是否已满? */
{
OS_EXIT_CRITICAL();
return (OS_MEM_FULL);
}
*(void **)pblk = pmem->OSMemFreeList; /* 把释放块查进空闲块列表中 */
pmem->OSMemFreeList = pblk;
pmem->OSMemNFree++; /* 在分区中加一个内存块 */
OS_EXIT_CRITICAL();
return (OS_NO_ERR); /* 通知调用者内存块被释放 */
}
/*$PAGE*/
/*
*********************************************************************************************************
* 查询内存分区
*
* 描述函数 : 该函数用于确定一个内存分区中空闲内存块的数量,以及使用的内存块的数量。
*
* 输入参数 : pmem 指向MCB的指针
*
* pdata 指向包含内存分区的数据结构的指针
*
*
* 返回值 : OS_NO_ERR 没有错误
* OS_MEM_INVALID_PMEM 给 'pmem'传递了一个空指针
* OS_MEM_INVALID_PDATA 给释放的块传递了一个空指针
*********************************************************************************************************
*/
#if OS_MEM_QUERY_EN > 0
INT8U OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* 为CPU状态寄存器分配存储变量 */
OS_CPU_SR cpu_sr;
#endif
#if OS_ARG_CHK_EN > 0
if (pmem == (OS_MEM *)0) /* 必须指向有效的内存分区 */
{
return (OS_MEM_INVALID_PMEM);
}
if (pdata == (OS_MEM_DATA *)0) /* 必须释放一个有效的存储区 */
{
return (OS_MEM_INVALID_PDATA);
}
#endif
OS_ENTER_CRITICAL();
pdata->OSAddr = pmem->OSMemAddr;
pdata->OSFreeList = pmem->OSMemFreeList;
pdata->OSBlkSize = pmem->OSMemBlkSize;
pdata->OSNBlks = pmem->OSMemNBlks;
pdata->OSNFree = pmem->OSMemNFree;
OS_EXIT_CRITICAL();
pdata->OSNUsed = pdata->OSNBlks - pdata->OSNFree;
return (OS_NO_ERR);
}
#endif /* OS_MEM_QUERY_EN */
/*$PAGE*/
/*
*********************************************************************************************************
* 初始化内存分区管理
*
* 描述函数 : 该函数由 uC/OS-II调用以初始化内存分区管理器,应用程序不必调用。
*
* 输入参数 : 无
*
* 返回值 : 无
*
* 注释 : 该函数是 uC/OS-II的内部函数,应用程序不必调用.
*********************************************************************************************************
*/
void OS_MemInit (void)
{
#if OS_MAX_MEM_PART == 1
OSMemFreeList = (OS_MEM *)&OSMemTbl[0]; /* 指向空余列表起始 */
OSMemFreeList->OSMemFreeList = (void *)0; /* 初始化最后的节点 */
OSMemFreeList->OSMemAddr = (void *)0; /* 存储内存分区的起始地址 */
OSMemFreeList->OSMemNFree = 0; /* 无空闲块 */
OSMemFreeList->OSMemNBlks = 0; /* 无存储块 */
OSMemFreeList->OSMemBlkSize = 0; /* 块大小为0 */
#endif
#if OS_MAX_MEM_PART >= 2
OS_MEM *pmem;
INT16U i;
pmem = (OS_MEM *)&OSMemTbl[0]; /* 指向内存控制块(MCB) */
for (i = 0; i < (OS_MAX_MEM_PART - 1); i++) /* 初始化空余内存分区列表 */
{
pmem->OSMemFreeList = (void *)&OSMemTbl[i+1]; /* 链接空余内存分区 */
pmem->OSMemAddr = (void *)0; /* 存储内存分区的起始地址 */
pmem->OSMemNFree = 0; /* 无空闲块 */
pmem->OSMemNBlks = 0; /* 无存储块 */
pmem->OSMemBlkSize = 0; /* 块大小为0 */
pmem++;
}
pmem->OSMemFreeList = (void *)0; /* 初始化最后的节点 */
pmem->OSMemAddr = (void *)0; /* 存储内存分区的起始地址 */
pmem->OSMemNFree = 0; /* 无空闲块 */
pmem->OSMemNBlks = 0; /* 无存储块 */
pmem->OSMemBlkSize = 0; /* 块大小为0 */
OSMemFreeList = (OS_MEM *)&OSMemTbl[0]; /* 指向内存分区的空余列表的开始 */
#endif
}
#endif /* OS_MEM_EN */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -