uC/OS-II源碼解析(os_mem.c)

/*
** ver   : 2.52
** file  : os_time.c
** brief : 內存管理相關操作 C 文件
*/


#ifndef  OS_MASTER_FILE
#include "includes.h"
#endif

#if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
/*
*******************************************************************************************
*                                       建立一個內存分區
*
* brief : 創建一大小固定的內存分區
*
* addr  : 內存分區的起始地址
*
* nblks : 內存分區的總的內存塊數量
*
* blksize : 每個內存塊的字節數
*
* err : 錯誤信息

* Returns : 建立的內存分區的指針
*********************************************************************************************
*/

OS_MEM  *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                         
    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;                      /* 空內存塊數目     */
    pmem->OSMemNBlks    = nblks;                      /* 內存塊總數       */
    pmem->OSMemBlkSize  = blksize;                    /* 內存塊大小       */
    *err                = OS_NO_ERR;
    return (pmem);
}
/*$PAGE*/
/*
******************************************************************************************
*                                          獲取內存塊
*
* brief  : 獲取內存塊
*
* pmem   : 指向內存控制塊的指針
*
* err    : 指向錯誤代碼的指針,可能取值爲:
*
*            OS_NO_ERR           成功
*            OS_MEM_NO_FREE_BLKS 無剩餘內存塊可用
*            OS_MEM_INVALID_PMEM 無效的內存控制塊指針
******************************************************************************************
*/

void  *OSMemGet (OS_MEM *pmem, INT8U *err)
{
#if OS_CRITICAL_METHOD == 3                             
    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--;                           /* 內存塊數減1        */
        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;                                                 
        return (pblk);                                   
    }
    OS_EXIT_CRITICAL();
    *err = OS_MEM_NO_FREE_BLKS;                       /* 無可用內存控制塊   */
    return ((void *)0);                                  
}
/*$PAGE*/
/*
****************************************************************************************
*                                         釋放內存塊
*
* breif    : 釋放內存塊
*
* pmem     : 指向內存控制塊的指針
*
* pblk     : 待釋放的內存塊的指針
*
* Returns     : OS_NO_ERR            成功
*               OS_MEM_FULL          分區已滿
*               OS_MEM_INVALID_PMEM  無效的內存控制塊指針無效的內存塊指針
*****************************************************************************************
*/

INT8U  OSMemPut (OS_MEM  *pmem, void *pblk)
{
#if OS_CRITICAL_METHOD == 3                        
    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++;                          /* 內存塊數加1   */
    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);                        
}
/*$PAGE*/
/*
****************************************************************************************
*                                          查詢內存分區狀態
*
* brief   : 查詢內存分區狀態信息.
*
* pmem    : 指向內存控制塊的指針
*
* pdata   : 指向保存內存分區信息的數據結構的指針
*
* Returns : OS_NO_ERR            成功.
*           OS_MEM_INVALID_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                         
    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                                                                         
/*$PAGE*/
/*
**************************************************************************************
*                                    初始化內存分區管理
*
* brief : 被函數 OSInit() 調用,用戶應用程序不應該調用該函數
*
**************************************************************************************
*/

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;                      
#endif

#if OS_MAX_MEM_PART >= 2                                   /* 多餘一個內存分區 */
    OS_MEM  *pmem;
    INT16U   i;


    pmem = (OS_MEM *)&OSMemTbl[0];                    /* 指向第一個內存控制塊 */
    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;                     
        pmem++;
    }
    pmem->OSMemFreeList = (void *)0;                  /* 初始化最後一個內存控制塊 */
    pmem->OSMemAddr     = (void *)0;              
    pmem->OSMemNFree    = 0;                          
    pmem->OSMemNBlks    = 0;                          
    pmem->OSMemBlkSize  = 0;                         

    OSMemFreeList       = (OS_MEM *)&OSMemTbl[0];     /* 指向第一個空內存控制塊 */
#endif
}
#endif                                                                          
發佈了47 篇原創文章 · 獲贊 85 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章