OS_MEM.C
上传用户:zfj3589
上传日期:2022-07-13
资源大小:635k
文件大小:14k
源码类别:

微处理器开发

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                            MEMORY MANAGEMENT
  6. *
  7. *                          (c) Copyright 1992-2001, 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 "includes.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.     OS_ENTER_CRITICAL();
  87.     pmem->OSMemAddr     = addr;                       /* Store start address of memory partition       */
  88.     pmem->OSMemFreeList = addr;                       /* Initialize pointer to pool of free blocks     */
  89.     pmem->OSMemNFree    = nblks;                      /* Store number of free blocks in MCB            */
  90.     pmem->OSMemNBlks    = nblks;
  91.     pmem->OSMemBlkSize  = blksize;                    /* Store block size of each memory blocks        */
  92.     OS_EXIT_CRITICAL();
  93.     *err   = OS_NO_ERR;
  94.     return (pmem);
  95. }
  96. /*$PAGE*/
  97. /*
  98. *********************************************************************************************************
  99. *                                          GET A MEMORY BLOCK
  100. *
  101. * Description : Get a memory block from a partition
  102. *
  103. * Arguments   : pmem    is a pointer to the memory partition control block
  104. *
  105. *               err     is a pointer to a variable containing an error message which will be set by this
  106. *                       function to either:
  107. *
  108. *                       OS_NO_ERR           if the memory partition has been created correctly.
  109. *                       OS_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to caller
  110. *                       OS_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem'
  111. *
  112. * Returns     : A pointer to a memory block if no error is detected
  113. *               A pointer to NULL if an error is detected
  114. *********************************************************************************************************
  115. */
  116. void  *OSMemGet (OS_MEM *pmem, INT8U *err)
  117. {
  118. #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  119.     OS_CPU_SR  cpu_sr;
  120. #endif    
  121.     void      *pblk;
  122. #if OS_ARG_CHK_EN > 0
  123.     if (pmem == (OS_MEM *)0) {                        /* Must point to a valid memory partition         */
  124.         *err = OS_MEM_INVALID_PMEM;
  125.         return ((OS_MEM *)0);
  126.     }
  127. #endif
  128.     OS_ENTER_CRITICAL();
  129.     if (pmem->OSMemNFree > 0) {                       /* See if there are any free memory blocks       */
  130.         pblk                = pmem->OSMemFreeList;    /* Yes, point to next free memory block          */
  131.         pmem->OSMemFreeList = *(void **)pblk;         /*      Adjust pointer to new free list          */
  132.         pmem->OSMemNFree--;                           /*      One less memory block in this partition  */
  133.         OS_EXIT_CRITICAL();
  134.         *err = OS_NO_ERR;                             /*      No error                                 */
  135.         return (pblk);                                /*      Return memory block to caller            */
  136.     }
  137.     OS_EXIT_CRITICAL();
  138.     *err = OS_MEM_NO_FREE_BLKS;                       /* No,  Notify caller of empty memory partition  */
  139.     return ((void *)0);                               /*      Return NULL pointer to caller            */
  140. }
  141. /*$PAGE*/
  142. /*
  143. *********************************************************************************************************
  144. *                                         RELEASE A MEMORY BLOCK
  145. *
  146. * Description : Returns a memory block to a partition
  147. *
  148. * Arguments   : pmem    is a pointer to the memory partition control block
  149. *
  150. *               pblk    is a pointer to the memory block being released.
  151. *
  152. * Returns     : OS_NO_ERR            if the memory block was inserted into the partition
  153. *               OS_MEM_FULL          if you are returning a memory block to an already FULL memory 
  154. *                                    partition (You freed more blocks than you allocated!)
  155. *               OS_MEM_INVALID_PMEM  if you passed a NULL pointer for 'pmem'
  156. *               OS_MEM_INVALID_PBLK  if you passed a NULL pointer for the block to release.
  157. *********************************************************************************************************
  158. */
  159. INT8U  OSMemPut (OS_MEM  *pmem, void *pblk)
  160. {
  161. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  162.     OS_CPU_SR  cpu_sr;
  163. #endif    
  164.     
  165.     
  166. #if OS_ARG_CHK_EN > 0
  167.     if (pmem == (OS_MEM *)0) {                   /* Must point to a valid memory partition             */
  168.         return (OS_MEM_INVALID_PMEM);
  169.     }
  170.     if (pblk == (void *)0) {                     /* Must release a valid block                         */
  171.         return (OS_MEM_INVALID_PBLK);
  172.     }
  173. #endif
  174.     OS_ENTER_CRITICAL();
  175.     if (pmem->OSMemNFree >= pmem->OSMemNBlks) {  /* Make sure all blocks not already returned          */
  176.         OS_EXIT_CRITICAL();
  177.         return (OS_MEM_FULL);
  178.     }
  179.     *(void **)pblk      = pmem->OSMemFreeList;   /* Insert released block into free block list         */
  180.     pmem->OSMemFreeList = pblk;
  181.     pmem->OSMemNFree++;                          /* One more memory block in this partition            */
  182.     OS_EXIT_CRITICAL();
  183.     return (OS_NO_ERR);                          /* Notify caller that memory block was released       */
  184. }
  185. /*$PAGE*/
  186. /*
  187. *********************************************************************************************************
  188. *                                          QUERY MEMORY PARTITION
  189. *
  190. * Description : This function is used to determine the number of free memory blocks and the number of
  191. *               used memory blocks from a memory partition.
  192. *
  193. * Arguments   : pmem    is a pointer to the memory partition control block
  194. *
  195. *               pdata   is a pointer to a structure that will contain information about the memory
  196. *                       partition.
  197. *
  198. * Returns     : OS_NO_ERR            If no errors were found.
  199. *               OS_MEM_INVALID_PMEM  if you passed a NULL pointer for 'pmem'
  200. *               OS_MEM_INVALID_PDATA if you passed a NULL pointer for the block to release.
  201. *********************************************************************************************************
  202. */
  203. #if OS_MEM_QUERY_EN > 0
  204. INT8U  OSMemQuery (OS_MEM *pmem, OS_MEM_DATA *pdata)
  205. {
  206. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  207.     OS_CPU_SR  cpu_sr;
  208. #endif    
  209.     
  210.     
  211. #if OS_ARG_CHK_EN > 0
  212.     if (pmem == (OS_MEM *)0) {                   /* Must point to a valid memory partition             */
  213.         return (OS_MEM_INVALID_PMEM);
  214.     }
  215.     if (pdata == (OS_MEM_DATA *)0) {             /* Must release a valid storage area for the data     */
  216.         return (OS_MEM_INVALID_PDATA);
  217.     }
  218. #endif
  219.     OS_ENTER_CRITICAL();
  220.     pdata->OSAddr     = pmem->OSMemAddr;
  221.     pdata->OSFreeList = pmem->OSMemFreeList;
  222.     pdata->OSBlkSize  = pmem->OSMemBlkSize;
  223.     pdata->OSNBlks    = pmem->OSMemNBlks;
  224.     pdata->OSNFree    = pmem->OSMemNFree;
  225.     OS_EXIT_CRITICAL();
  226.     pdata->OSNUsed    = pdata->OSNBlks - pdata->OSNFree;
  227.     return (OS_NO_ERR);
  228. }
  229. #endif                                           /* OS_MEM_QUERY_EN                                    */
  230. /*$PAGE*/
  231. /*
  232. *********************************************************************************************************
  233. *                                    INITIALIZE MEMORY PARTITION MANAGER
  234. *
  235. * Description : This function is called by uC/OS-II to initialize the memory partition manager.  Your
  236. *               application MUST NOT call this function.
  237. *
  238. * Arguments   : none
  239. *
  240. * Returns     : none
  241. *
  242. * Note(s)    : This function is INTERNAL to uC/OS-II and your application should not call it.
  243. *********************************************************************************************************
  244. */
  245. void  OS_MemInit (void)
  246. {
  247. #if OS_MAX_MEM_PART == 1
  248.     OSMemFreeList                = (OS_MEM *)&OSMemTbl[0]; /* Point to beginning of free list          */
  249.     OSMemFreeList->OSMemFreeList = (void *)0;              /* Initialize last node                     */
  250.     OSMemFreeList->OSMemAddr     = (void *)0;              /* Store start address of memory partition  */
  251.     OSMemFreeList->OSMemNFree    = 0;                      /* No free blocks                           */
  252.     OSMemFreeList->OSMemNBlks    = 0;                      /* No blocks                                */
  253.     OSMemFreeList->OSMemBlkSize  = 0;                      /* Zero size                                */
  254. #endif
  255. #if OS_MAX_MEM_PART >= 2
  256.     OS_MEM  *pmem;
  257.     INT16U   i;
  258.     pmem = (OS_MEM *)&OSMemTbl[0];                    /* Point to memory control block (MCB)           */
  259.     for (i = 0; i < (OS_MAX_MEM_PART - 1); i++) {     /* Init. list of free memory partitions          */
  260.         pmem->OSMemFreeList = (void *)&OSMemTbl[i+1]; /* Chain list of free partitions                 */
  261.         pmem->OSMemAddr     = (void *)0;              /* Store start address of memory partition       */
  262.         pmem->OSMemNFree    = 0;                      /* No free blocks                                */
  263.         pmem->OSMemNBlks    = 0;                      /* No blocks                                     */
  264.         pmem->OSMemBlkSize  = 0;                      /* Zero size                                     */
  265.         pmem++;
  266.     }
  267.     pmem->OSMemFreeList = (void *)0;                  /* Initialize last node                          */
  268.     pmem->OSMemAddr     = (void *)0;                  /* Store start address of memory partition       */
  269.     pmem->OSMemNFree    = 0;                          /* No free blocks                                */
  270.     pmem->OSMemNBlks    = 0;                          /* No blocks                                     */
  271.     pmem->OSMemBlkSize  = 0;                          /* Zero size                                     */
  272.     OSMemFreeList       = (OS_MEM *)&OSMemTbl[0];     /* Point to beginning of free list               */
  273. #endif
  274. }
  275. #endif                                           /* OS_MEM_EN                                          */