?? 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 + -