OS_MEM.C
上传用户:ssllxx2007
上传日期:2022-06-12
资源大小:784k
文件大小:14k
源码类别:

uCOS

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                            MEMORY MANAGEMENT
  6. *
  7. *                          (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
  8. *                                           All Rights Reserved
  9. *
  10. * File : OS_MEM.C
  11. * By   : Jean J. Labrosse
  12. *********************************************************************************************************
  13. */
  14. #ifndef  OS_MASTER_FILE
  15. #include "..APPincludes.h"
  16. #endif
  17. #if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
  18. /*
  19. *********************************************************************************************************
  20. *                                        CREATE A MEMORY PARTITION
  21. *
  22. * Description : Create a fixed-sized memory partition that will be managed by uC/OS-II.
  23. *
  24. * Arguments   : addr     is the starting address of the memory partition
  25. *
  26. *               nblks    is the number of memory blocks to create from the partition.
  27. *
  28. *               blksize  is the size (in bytes) of each block in the memory partition.
  29. *
  30. *               err      is a pointer to a variable containing an error message which will be set by
  31. *                        this function to either:
  32. *
  33. *                        OS_NO_ERR            if the memory partition has been created correctly.
  34. *                        OS_MEM_INVALID_ADDR  you are specifying an invalid address for the memory 
  35. *                                             storage of the partition.
  36. *                        OS_MEM_INVALID_PART  no free partitions available
  37. *                        OS_MEM_INVALID_BLKS  user specified an invalid number of blocks (must be >= 2)
  38. *                        OS_MEM_INVALID_SIZE  user specified an invalid block size
  39. *                                             (must be greater than the size of a pointer)
  40. * Returns    : != (OS_MEM *)0  is the partition was created
  41. *              == (OS_MEM *)0  if the partition was not created because of invalid arguments or, no
  42. *                              free partition is available.
  43. *********************************************************************************************************
  44. */
  45. OS_MEM  *OSMemCreate (void *addr, INT32U nblks, INT32U blksize, INT8U *err)
  46. {
  47. #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  48.     OS_CPU_SR  cpu_sr;
  49. #endif    
  50.     OS_MEM    *pmem;
  51.     INT8U     *pblk;
  52.     void     **plink;
  53.     INT32U     i;
  54. #if OS_ARG_CHK_EN > 0
  55.     if (addr == (void *)0) {                          /* Must pass a valid address for the memory part. */
  56.         *err = OS_MEM_INVALID_ADDR;
  57.         return ((OS_MEM *)0);
  58.     }
  59.     if (nblks < 2) {                                  /* Must have at least 2 blocks per partition      */
  60.         *err = OS_MEM_INVALID_BLKS;
  61.         return ((OS_MEM *)0);
  62.     }
  63.     if (blksize < sizeof(void *)) {                   /* Must contain space for at least a pointer      */
  64.         *err = OS_MEM_INVALID_SIZE;
  65.         return ((OS_MEM *)0);
  66.     }
  67. #endif
  68.     OS_ENTER_CRITICAL();
  69.     pmem = OSMemFreeList;                             /* Get next free memory partition                */
  70.     if (OSMemFreeList != (OS_MEM *)0) {               /* See if pool of free partitions was empty      */
  71.         OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
  72.     }
  73.     OS_EXIT_CRITICAL();
  74.     if (pmem == (OS_MEM *)0) {                        /* See if we have a memory partition             */
  75.         *err = OS_MEM_INVALID_PART;
  76.         return ((OS_MEM *)0);
  77.     }
  78.     plink = (void **)addr;                            /* Create linked list of free memory blocks      */
  79.     pblk  = (INT8U *)addr + blksize;
  80.     for (i = 0; i < (nblks - 1); i++) {
  81.         *plink = (void *)pblk;
  82.         plink  = (void **)pblk;
  83.         pblk   = pblk + blksize;
  84.     }
  85.     *plink              = (void *)0;                  /* Last memory block points to NULL              */
  86.     pmem->OSMemAddr     = addr;                       /* Store start address of memory partition       */
  87.     pmem->OSMemFreeList = addr;                       /* Initialize pointer to pool of free blocks     */
  88.     pmem->OSMemNFree    = nblks;                      /* Store number of free blocks in MCB            */
  89.     pmem->OSMemNBlks    = nblks;
  90.     pmem->OSMemBlkSize  = blksize;                    /* Store block size of each memory blocks        */
  91.     *err                = OS_NO_ERR;
  92.     return (pmem);
  93. }
  94. /*$PAGE*/
  95. /*
  96. *********************************************************************************************************
  97. *                                          GET A MEMORY BLOCK
  98. *
  99. * Description : Get a memory block from a partition
  100. *
  101. * Arguments   : pmem    is a pointer to the memory partition control block
  102. *
  103. *               err     is a pointer to a variable containing an error message which will be set by this
  104. *                       function to either:
  105. *
  106. *                       OS_NO_ERR           if the memory partition has been created correctly.
  107. *                       OS_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to caller
  108. *                       OS_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem'
  109. *
  110. * Returns     : A pointer to a memory block if no error is detected
  111. *               A pointer to NULL if an error is detected
  112. *********************************************************************************************************
  113. */
  114. void  *OSMemGet (OS_MEM *pmem, INT8U *err)
  115. {
  116. #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  117.     OS_CPU_SR  cpu_sr;
  118. #endif    
  119.     void      *pblk;
  120. #if OS_ARG_CHK_EN > 0
  121.     if (pmem == (OS_MEM *)0) {                        /* Must point to a valid memory partition         */
  122.         *err = OS_MEM_INVALID_PMEM;
  123.         return ((OS_MEM *)0);
  124.     }
  125. #endif
  126.     OS_ENTER_CRITICAL();
  127.     if (pmem->OSMemNFree > 0) {                       /* See if there are any free memory blocks       */
  128.         pblk                = pmem->OSMemFreeList;    /* Yes, point to next free memory block          */
  129.         pmem->OSMemFreeList = *(void **)pblk;         /*      Adjust pointer to new free list          */
  130.         pmem->OSMemNFree--;                           /*      One less memory block in this partition  */
  131.         OS_EXIT_CRITICAL();
  132.         *err = OS_NO_ERR;                             /*      No error                                 */
  133.         return (pblk);                                /*      Return memory block to caller            */
  134.     }
  135.     OS_EXIT_CRITICAL();
  136.     *err = OS_MEM_NO_FREE_BLKS;                       /* No,  Notify caller of empty memory partition  */
  137.     return ((void *)0);                               /*      Return NULL pointer to caller            */
  138. }
  139. /*$PAGE*/
  140. /*
  141. *********************************************************************************************************
  142. *                                         RELEASE A MEMORY BLOCK
  143. *
  144. * Description : Returns a memory block to a partition
  145. *
  146. * Arguments   : pmem    is a pointer to the memory partition control block
  147. *
  148. *               pblk    is a pointer to the memory block being released.
  149. *
  150. * Returns     : OS_NO_ERR            if the memory block was inserted into the partition
  151. *               OS_MEM_FULL          if you are returning a memory block to an already FULL memory 
  152. *                                    partition (You freed more blocks than you allocated!)
  153. *               OS_MEM_INVALID_PMEM  if you passed a NULL pointer for 'pmem'
  154. *               OS_MEM_INVALID_PBLK  if you passed a NULL pointer for the block to release.
  155. *********************************************************************************************************
  156. */
  157. INT8U  OSMemPut (OS_MEM  *pmem, void *pblk)
  158. {
  159. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  160.     OS_CPU_SR  cpu_sr;
  161. #endif    
  162.     
  163.     
  164. #if OS_ARG_CHK_EN > 0
  165.     if (pmem == (OS_MEM *)0) {                   /* Must point to a valid memory partition             */
  166.         return (OS_MEM_INVALID_PMEM);
  167.     }
  168.     if (pblk == (void *)0) {                     /* Must release a valid block                         */
  169.         return (OS_MEM_INVALID_PBLK);
  170.     }
  171. #endif
  172.     OS_ENTER_CRITICAL();
  173.     if (pmem->OSMemNFree >= pmem->OSMemNBlks) {  /* Make sure all blocks not already returned          */
  174.         OS_EXIT_CRITICAL();
  175.         return (OS_MEM_FULL);
  176.     }
  177.     *(void **)pblk      = pmem->OSMemFreeList;   /* Insert released block into free block list         */
  178.     pmem->OSMemFreeList = pblk;
  179.     pmem->OSMemNFree++;                          /* One more memory block in this partition            */
  180.     OS_EXIT_CRITICAL();
  181.     return (OS_NO_ERR);                          /* Notify caller that memory block was released       */
  182. }
  183. /*$PAGE*/
  184. /*
  185. *********************************************************************************************************
  186. *                                          QUERY MEMORY PARTITION
  187. *
  188. * Description : This function is used to determine the number of free memory blocks and the number of
  189. *               used memory blocks from a memory partition.
  190. *
  191. * Arguments   : pmem    is a pointer to the memory partition control block
  192. *
  193. *               pdata   is a pointer to a structure that will contain information about the memory
  194. *                       partition.
  195. *
  196. * Returns     : OS_NO_ERR            If no errors were found.
  197. *               OS_MEM_INVALID_PMEM  if you passed a NULL pointer for 'pmem'
  198. *               OS_MEM_INVALID_PDATA if you passed a NULL pointer for the block to release.
  199. *********************************************************************************************************
  200. */
  201. #if OS_MEM_QUERY_EN > 0
  202. INT8U  OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *pdata)
  203. {
  204. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  205.     OS_CPU_SR  cpu_sr;
  206. #endif    
  207.     
  208.     
  209. #if OS_ARG_CHK_EN > 0
  210.     if (pmem == (OS_MEM *)0) {                   /* Must point to a valid memory partition             */
  211.         return (OS_MEM_INVALID_PMEM);
  212.     }
  213.     if (pdata == (OS_MEM_DATA *)0) {             /* Must release a valid storage area for the data     */
  214.         return (OS_MEM_INVALID_PDATA);
  215.     }
  216. #endif
  217.     OS_ENTER_CRITICAL();
  218.     pdata->OSAddr     = pmem->OSMemAddr;
  219.     pdata->OSFreeList = pmem->OSMemFreeList;
  220.     pdata->OSBlkSize  = pmem->OSMemBlkSize;
  221.     pdata->OSNBlks    = pmem->OSMemNBlks;
  222.     pdata->OSNFree    = pmem->OSMemNFree;
  223.     OS_EXIT_CRITICAL();
  224.     pdata->OSNUsed    = pdata->OSNBlks - pdata->OSNFree;
  225.     return (OS_NO_ERR);
  226. }
  227. #endif                                           /* OS_MEM_QUERY_EN                                    */
  228. /*$PAGE*/
  229. /*
  230. *********************************************************************************************************
  231. *                                    INITIALIZE MEMORY PARTITION MANAGER
  232. *
  233. * Description : This function is called by uC/OS-II to initialize the memory partition manager.  Your
  234. *               application MUST NOT call this function.
  235. *
  236. * Arguments   : none
  237. *
  238. * Returns     : none
  239. *
  240. * Note(s)    : This function is INTERNAL to uC/OS-II and your application should not call it.
  241. *********************************************************************************************************
  242. */
  243. void  OS_MemInit (void)
  244. {
  245. #if OS_MAX_MEM_PART == 1
  246.     OSMemFreeList                = (OS_MEM *)&OSMemTbl[0]; /* Point to beginning of free list          */
  247.     OSMemFreeList->OSMemFreeList = (void *)0;              /* Initialize last node                     */
  248.     OSMemFreeList->OSMemAddr     = (void *)0;              /* Store start address of memory partition  */
  249.     OSMemFreeList->OSMemNFree    = 0;                      /* No free blocks                           */
  250.     OSMemFreeList->OSMemNBlks    = 0;                      /* No blocks                                */
  251.     OSMemFreeList->OSMemBlkSize  = 0;                      /* Zero size                                */
  252. #endif
  253. #if OS_MAX_MEM_PART >= 2
  254.     OS_MEM  *pmem;
  255.     INT16U   i;
  256.     pmem = (OS_MEM *)&OSMemTbl[0];                    /* Point to memory control block (MCB)           */
  257.     for (i = 0; i < (OS_MAX_MEM_PART - 1); i++) {     /* Init. list of free memory partitions          */
  258.         pmem->OSMemFreeList = (void *)&OSMemTbl[i+1]; /* Chain list of free partitions                 */
  259.         pmem->OSMemAddr     = (void *)0;              /* Store start address of memory partition       */
  260.         pmem->OSMemNFree    = 0;                      /* No free blocks                                */
  261.         pmem->OSMemNBlks    = 0;                      /* No blocks                                     */
  262.         pmem->OSMemBlkSize  = 0;                      /* Zero size                                     */
  263.         pmem++;
  264.     }
  265.     pmem->OSMemFreeList = (void *)0;                  /* Initialize last node                          */
  266.     pmem->OSMemAddr     = (void *)0;                  /* Store start address of memory partition       */
  267.     pmem->OSMemNFree    = 0;                          /* No free blocks                                */
  268.     pmem->OSMemNBlks    = 0;                          /* No blocks                                     */
  269.     pmem->OSMemBlkSize  = 0;                          /* Zero size                                     */
  270.     OSMemFreeList       = (OS_MEM *)&OSMemTbl[0];     /* Point to beginning of free list               */
  271. #endif
  272. }
  273. #endif                                           /* OS_MEM_EN                                          */