單片機模塊化程序: μCOS-II中內存管理程序使用說明


 

 

 

前言

  環形隊列,鏈表,內存管理,這些典型的數據緩存處理方式

  作為一個開發者是應該掌握的知識點

  由於后面的文章涉及到了內存管理

  故,這節先說一下內存管理

 

uCOSII中的內存管理源碼

  我把uCOS中的內存管理程序拷貝出來了

  

 

 

 

  OS_MEM.C

  

/*
*********************************************************************************************************
*                                                uC/OS-II
*                                          The Real-Time Kernel
*                                            MEMORY MANAGEMENT
*
*                        (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL
*                                           All Rights Reserved
*
*                                                  V2.00
*
* File : OS_MEM.C
* By   : Jean J. Labrosse
*********************************************************************************************************
*/

#define  OS_MEM_C_
#include "OS_MEM.h"


//#if OS_MEM_EN && OS_MAX_MEM_PART >= 2
/*
*********************************************************************************************************
*                                         LOCAL GLOBAL VARIABLES
*********************************************************************************************************
*/

static  OS_MEM      *OSMemFreeList;            /* Pointer to free list of memory partitions            */
static  OS_MEM       OSMemTbl[OS_MAX_MEM_PART];/* Storage for memory partition manager                 */
/*$PAGE*/


/*
*********************************************************************************************************
*                                        CREATE A MEMORY PARTITION
*
* Description : Create a fixed-sized memory partition that will be managed by uC/OS-II.
*
* Arguments   : addr     is the starting address of the memory partition
*
*               nblks    is the number of memory blocks to create from the partition.
*
*               blksize  is the size (in bytes) of each block in the memory partition.
*
*               err      is a pointer to a variable containing an error message which will be set by
*                        this function to either:
*             
*                        OS_NO_ERR            if the memory partition has been created correctly.
*                        OS_MEM_INVALID_PART  no free partitions available
*                        OS_MEM_INVALID_BLKS  user specified an invalid number of blocks (must be >= 2)
*                        OS_MEM_INVALID_SIZE  user specified an invalid block size 
*                                             (must be greater than the size of a pointer)
* Returns    : != (OS_MEM *)0  is the partition was created 
*              == (OS_MEM *)0  if the partition was not created because of invalid arguments or, no
*                              free partition is available.
*********************************************************************************************************
*/

OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
{
    OS_MEM  *pmem;
    INT8U   *pblk;
    void   **plink;
    INT32U   i;
    //注意這里 (INT8U *)addr 和 (INT8U)*addr 完全不同啊啊,前者 addr是指向的一個地址,而這個地址內數據不知道是什么類型的
    //所以(INT8U *)說明這個地址的內容是INT8U型的,(INT8U *)addr 表示的是一個新的  addr,而后面(INT8U)*addr 表示把 *addr轉換成
    //一個八位的無符號整形數據
        
    if (nblks < 2) {                                  /* Must have at least 2 blocks per partition      */
        *err = OS_MEM_INVALID_BLKS;
        return ((OS_MEM *)0);
    }
    if (blksize < sizeof(void *)) {                   /* Must contain space for at least a pointer      */
        *err = OS_MEM_INVALID_SIZE;
        return ((OS_MEM *)0);
    }
//    OS_ENTER_CRITICAL();
    pmem = OSMemFreeList;                             /* Get next free memory partition                */
    if (OSMemFreeList != (OS_MEM *)0) {               /* See if pool of free partitions was empty      */
        OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
    }
//    OS_EXIT_CRITICAL();
    if (pmem == (OS_MEM *)0) {                        /* See if we have a memory partition             */
        *err = OS_MEM_INVALID_PART;
        return ((OS_MEM *)0);
    }

    plink = (void **)addr;                            /* Create linked list of free memory blocks      */

    pblk  = (INT8U *)addr + blksize;          
    for (i = 0; i < (nblks - 1); i++) {
        *plink = (void *)pblk;
        plink  = (void **)pblk;
        pblk   = pblk + blksize;
    }
    *plink = (void *)0;                               /* Last memory block points to NULL              */
//    OS_ENTER_CRITICAL();
    pmem->OSMemAddr     = addr;                       /* Store start address of memory partition       */
    pmem->OSMemFreeList = addr;                       /* Initialize pointer to pool of free blocks     */
    pmem->OSMemNFree    = nblks;                      /* Store number of free blocks in MCB            */
    pmem->OSMemNBlks    = nblks;
    pmem->OSMemBlkSize  = blksize;                    /* Store block size of each memory blocks        */
//    OS_EXIT_CRITICAL();
    *err   = OS_NO_ERR;
    return (pmem);
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                          GET A MEMORY BLOCK
*
* Description : Get a memory block from a partition
*
* Arguments   : pmem    is a pointer to the memory partition control block
*
*               err     is a pointer to a variable containing an error message which will be set by this
*                       function to either:
*
*                       OS_NO_ERR           if the memory partition has been created correctly.
*                       OS_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to caller
*
* Returns     : A pointer to a memory block if no error is detected
*               A pointer to NULL if an error is detected
*********************************************************************************************************
*/

void *OSMemGet (OS_MEM *pmem, INT8U *err)
{
    void    *pblk;

//    OS_ENTER_CRITICAL();
    if (pmem->OSMemNFree > 0) {                       /* See if there are any free memory blocks       */
        pblk                = pmem->OSMemFreeList;    /* Yes, point to next free memory block          */
        pmem->OSMemFreeList = *(void **)pblk;         /*      Adjust pointer to new free list          */
        pmem->OSMemNFree--;                           /*      One less memory block in this partition  */
//        OS_EXIT_CRITICAL();
        *err = OS_NO_ERR;                             /*      No error                                 */
        return (pblk);                                /*      Return memory block to caller            */
    } else {
//        OS_EXIT_CRITICAL();
        *err = OS_MEM_NO_FREE_BLKS;                   /* No,  Notify caller of empty memory partition  */
        return ((void *)0);                           /*      Return NULL pointer to caller            */
    }
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                    INITIALIZE MEMORY PARTITION MANAGER
*
* Description : This function is called by uC/OS-II to initialize the memory partition manager.  Your
*               application MUST NOT call this function.
*
* Arguments   : none
*
* Returns     : none
*********************************************************************************************************
*/

void OSMemInit (void)
{
    OS_MEM  *pmem;
    INT16U   i;


    pmem = (OS_MEM *)&OSMemTbl[0];                    /* Point to memory control block (MCB)           */
    for (i = 0; i < (OS_MAX_MEM_PART - 1); i++) {     /* Init. list of free memory partitions          */
        pmem->OSMemFreeList = (void *)&OSMemTbl[i+1]; /* Chain list of free partitions                 */
        pmem->OSMemAddr     = (void *)0;              /* Store start address of memory partition       */
        pmem->OSMemNFree    = 0;                      /* No free blocks                                */
        pmem->OSMemNBlks    = 0;                      /* No blocks                                     */
        pmem->OSMemBlkSize  = 0;                      /* Zero size                                     */
        pmem++;
    }
    OSMemTbl[OS_MAX_MEM_PART - 1].OSMemFreeList = (void *)0;
    OSMemFreeList                               = (OS_MEM *)&OSMemTbl[0];
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                         RELEASE A MEMORY BLOCK
*
* Description : Returns a memory block to a partition
*
* Arguments   : pmem    is a pointer to the memory partition control block
*
*               pblk    is a pointer to the memory block being released.
*
* Returns     : OS_NO_ERR         if the memory block was inserted into the partition
*               OS_MEM_FULL       if you are returning a memory block to an already FULL memory partition
*                                 (You freed more blocks than you allocated!)
*********************************************************************************************************
*/

INT8U OSMemPut (OS_MEM  *pmem, void *pblk)
{
//    OS_ENTER_CRITICAL();
    if (pmem->OSMemNFree >= pmem->OSMemNBlks) {  /* Make sure all blocks not already returned          */
//        OS_EXIT_CRITICAL();
        return (OS_MEM_FULL);       
    }
    *(void **)pblk      = pmem->OSMemFreeList;   /* Insert released block into free block list         */
    pmem->OSMemFreeList = pblk;
    pmem->OSMemNFree++;                          /* One more memory block in this partition            */
//    OS_EXIT_CRITICAL();
    return (OS_NO_ERR);                          /* Notify caller that memory block was released       */
}
/*$PAGE*/
/*
*********************************************************************************************************
*                                          QUERY MEMORY PARTITION
*
* Description : This function is used to determine the number of free memory blocks and the number of 
*               used memory blocks from a memory partition.
*
* Arguments   : pmem    is a pointer to the memory partition control block
*
*               pdata   is a pointer to a structure that will contain information about the memory
*                       partition.
*
* Returns     : OS_NO_ERR         Always returns no error.
*********************************************************************************************************
*/

INT8U OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *ppdata)
{
//    OS_ENTER_CRITICAL();
    ppdata->OSAddr     = pmem->OSMemAddr;
    ppdata->OSFreeList = pmem->OSMemFreeList;
    ppdata->OSBlkSize  = pmem->OSMemBlkSize;
    ppdata->OSNBlks    = pmem->OSMemNBlks;
    ppdata->OSNFree    = pmem->OSMemNFree;
//    OS_EXIT_CRITICAL();
    ppdata->OSNUsed    = ppdata->OSNBlks - ppdata->OSNFree;
    return (OS_NO_ERR);                         
}
//#endif

 

 

  OS_MEM.h

#ifndef OS_MEM_H_
#define OS_MEM_H_
#include "stm32f10x.h"

#ifndef OS_MEM_C_
#define OS_MEM_Cx_  extern
#else 
#define OS_MEM_Cx_
#endif

#define OS_MAX_MEM_PART           4 


#define OS_NO_ERR                 0
#define OS_MEM_INVALID_PART     110
#define OS_MEM_INVALID_BLKS     111
#define OS_MEM_INVALID_SIZE     112
#define OS_MEM_NO_FREE_BLKS     113
#define OS_MEM_FULL             114


typedef unsigned char  INT8U;         //無符號8位數
typedef unsigned int   INT16U;        //無符號16位數
typedef unsigned long  INT32U;        //無符號32位數


typedef struct {                       /* MEMORY CONTROL BLOCK                                         */
    void   *OSMemAddr;                 /* Pointer to beginning of memory partition                     */
    void   *OSMemFreeList;             /* Pointer to list of free memory blocks                        */
    INT32U  OSMemBlkSize;              /* Size (in bytes) of each block of memory                      */
    INT32U  OSMemNBlks;                /* Total number of blocks in this partition                     */
    INT32U  OSMemNFree;                /* Number of memory blocks remaining in this partition          */
} OS_MEM;


typedef struct {
    void   *OSAddr;                    /* Pointer to the beginning address of the memory partition     */
    void   *OSFreeList;                /* Pointer to the beginning of the free list of memory blocks   */
    INT32U  OSBlkSize;                 /* Size (in bytes) of each memory block                         */
    INT32U  OSNBlks;                   /* Total number of blocks in the partition                      */
    INT32U  OSNFree;                   /* Number of memory blocks free                                 */
    INT32U  OSNUsed;                   /* Number of memory blocks used                                 */
} OS_MEM_DATA;


OS_MEM *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err);
void *OSMemGet (OS_MEM *pmem, INT8U *err);
void OSMemInit (void);
INT8U OSMemPut (OS_MEM  *pmem, void *pblk);
INT8U OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *ppdata);



#endif

 

uCOSII提供的內存管理實質

  一,實際上就是用一些程序對一個二維的數組進行管理

  

 

 

  二,整個數組叫做 "內存分區"

 

  三,數組的行數代表內存塊的個數

 

  四,數組的每一行叫做 "內存塊",每一行的長度叫做內存塊長度

 

  五,申請內存塊,實際上就是返回數組某一行的首地址,

 

    咱可以把數據存儲到那一行里面!

 

  六,每一次申請內存塊的時候,內部會判斷哪一行沒有被申請過 

 

    然后把哪一行的首地址返回過來

 

使用

  一,創建內存

  定義了一個二維數組,行數20(20個內存塊)

  列數16(每一個內存塊最大存儲16個數據)

    

 

 

  二,申請一個內存塊

 

    

 

 

  三,往內存塊里面存儲數據

 

    

 

 

 

    實際上就是存儲到了那個二維數組里面

    現在數組的第一行存儲了數據

 

 

    

 

 

 

 

  四,再申請一個,再存儲數據

 

    

 

    現在數組的第二行存儲了數據

 

    

 

 

 

 

 

 

 

 

  四,使用存儲的數據

    操作存儲數據的首地址即可

 

    

 

 

 

 

 

 

總結

  μCOS-II提供的內存管理實際上就是對一個二維的數組進行管理

  事先先定義好內存塊,和每個內存塊長度

  二維數組的行數代表內存塊個數

  二維數組的列數代表每個內存塊的長度

  

  申請內存塊其實就是內部程序判斷數組哪一行沒有使用過

  然后返回那一行的首地址

  然后咱就可以往里面存數據

注意

  往里面存儲數據的時候不得超出內存塊長度(數組每一行的列數)

  有人可能會問,如果我有很大的數據量呢??

  辦法1.用多個內存塊存儲

  辦法2.設置內存塊的長度足夠長

 

補充1(釋放使用的內存塊)

  咱使用完某一個內存塊存儲的數據以后需要告訴內部程序

  釋放這個內存塊,以便這個內存塊可以再次被申請使用

  OSMemPut (OS_MEM  *pmem, void *pblk)

  第一個參數: 內存指針

  第二個參數:內存塊指針

  

 

 

  

 

 

 

 

 

 

補充2(查詢內存分區信息)

  

 

 

  

 

 

 

 

 

 

 

 

 

 

  

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM