os_mem.c
上传用户:ht5068443
上传日期:2016-07-26
资源大小:802k
文件大小:19k
源码类别:

MacOS编程

开发平台:

C/C++

  1. /*
  2. *********************************************************************************************************
  3. *                                                uC/OS-II
  4. *                                          The Real-Time Kernel
  5. *                                            MEMORY MANAGEMENT
  6. *
  7. *                              (c) Copyright 1992-2009, Micrium, Weston, FL
  8. *                                           All Rights Reserved
  9. *
  10. * File    : OS_MEM.C
  11. * By      : Jean J. Labrosse
  12. * Version : V2.88
  13. *
  14. * LICENSING TERMS:
  15. * ---------------
  16. *   uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.  
  17. * If you plan on using  uC/OS-II  in a commercial product you need to contact Micri祄 to properly license 
  18. * its use in your product. We provide ALL the source code for your convenience and to help you experience 
  19. * uC/OS-II.   The fact that the  source is provided does  NOT  mean that you can use it without  paying a 
  20. * licensing fee.
  21. *********************************************************************************************************
  22. */
  23. #ifndef  OS_MASTER_FILE
  24. #include <ucos_ii.h>
  25. #endif
  26. #if (OS_MEM_EN > 0) && (OS_MAX_MEM_PART > 0)
  27. /*
  28. *********************************************************************************************************
  29. *                                        CREATE A MEMORY PARTITION
  30. *
  31. * Description : Create a fixed-sized memory partition that will be managed by uC/OS-II.
  32. *
  33. * Arguments   : addr     is the starting address of the memory partition
  34. *
  35. *               nblks    is the number of memory blocks to create from the partition.
  36. *
  37. *               blksize  is the size (in bytes) of each block in the memory partition.
  38. *
  39. *               perr     is a pointer to a variable containing an error message which will be set by
  40. *                        this function to either:
  41. *
  42. *                        OS_ERR_NONE              if the memory partition has been created correctly.
  43. *                        OS_ERR_MEM_INVALID_ADDR  if you are specifying an invalid address for the memory
  44. *                                                 storage of the partition or, the block does not align
  45. *                                                 on a pointer boundary
  46. *                        OS_ERR_MEM_INVALID_PART  no free partitions available
  47. *                        OS_ERR_MEM_INVALID_BLKS  user specified an invalid number of blocks (must be >= 2)
  48. *                        OS_ERR_MEM_INVALID_SIZE  user specified an invalid block size
  49. *                                                   - must be greater than the size of a pointer
  50. *                                                   - must be able to hold an integral number of pointers
  51. * Returns    : != (OS_MEM *)0  is the partition was created
  52. *              == (OS_MEM *)0  if the partition was not created because of invalid arguments or, no
  53. *                              free partition is available.
  54. *********************************************************************************************************
  55. */
  56. OS_MEM  *OSMemCreate (void   *addr, 
  57.                       INT32U  nblks, 
  58.                       INT32U  blksize, 
  59.                       INT8U  *perr)
  60. {
  61.     OS_MEM    *pmem;
  62.     INT8U     *pblk;
  63.     void     **plink;
  64.     INT32U     i;
  65. #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  66.     OS_CPU_SR  cpu_sr = 0;
  67. #endif
  68. #if OS_ARG_CHK_EN > 0              
  69.     if (perr == (INT8U *)0) {                         /* Validate 'perr'                               */
  70.         return ((OS_MEM *)0);
  71.     }
  72.     if (addr == (void *)0) {                          /* Must pass a valid address for the memory part.*/
  73.         *perr = OS_ERR_MEM_INVALID_ADDR;
  74.         return ((OS_MEM *)0);
  75.     }
  76.     if (((INT32U)addr & (sizeof(void *) - 1)) != 0){  /* Must be pointer size aligned                  */
  77.         *perr = OS_ERR_MEM_INVALID_ADDR;
  78.         return ((OS_MEM *)0);
  79.     }
  80.     if (nblks < 2) {                                  /* Must have at least 2 blocks per partition     */
  81.         *perr = OS_ERR_MEM_INVALID_BLKS;
  82.         return ((OS_MEM *)0);
  83.     }
  84.     if (blksize < sizeof(void *)) {                   /* Must contain space for at least a pointer     */
  85.         *perr = OS_ERR_MEM_INVALID_SIZE;
  86.         return ((OS_MEM *)0);
  87.     }
  88. #endif
  89.     OS_ENTER_CRITICAL();
  90.     pmem = OSMemFreeList;                             /* Get next free memory partition                */
  91.     if (OSMemFreeList != (OS_MEM *)0) {               /* See if pool of free partitions was empty      */
  92.         OSMemFreeList = (OS_MEM *)OSMemFreeList->OSMemFreeList;
  93.     }
  94.     OS_EXIT_CRITICAL();
  95.     if (pmem == (OS_MEM *)0) {                        /* See if we have a memory partition             */
  96.         *perr = OS_ERR_MEM_INVALID_PART;
  97.         return ((OS_MEM *)0);
  98.     }
  99.     plink = (void **)addr;                            /* Create linked list of free memory blocks      */
  100.     pblk  = (INT8U *)((INT32U)addr + blksize);
  101.     for (i = 0; i < (nblks - 1); i++) {
  102.        *plink = (void *)pblk;                         /* Save pointer to NEXT block in CURRENT block   */
  103.         plink = (void **)pblk;                        /* Position to  NEXT      block                  */
  104.         pblk  = (INT8U *)((INT32U)pblk + blksize);    /* Point to the FOLLOWING block                  */
  105.     }
  106.     *plink              = (void *)0;                  /* Last memory block points to NULL              */
  107.     pmem->OSMemAddr     = addr;                       /* Store start address of memory partition       */
  108.     pmem->OSMemFreeList = addr;                       /* Initialize pointer to pool of free blocks     */
  109.     pmem->OSMemNFree    = nblks;                      /* Store number of free blocks in MCB            */
  110.     pmem->OSMemNBlks    = nblks;
  111.     pmem->OSMemBlkSize  = blksize;                    /* Store block size of each memory blocks        */
  112.     *perr               = OS_ERR_NONE;
  113.     return (pmem);
  114. }
  115. /*$PAGE*/
  116. /*
  117. *********************************************************************************************************
  118. *                                          GET A MEMORY BLOCK
  119. *
  120. * Description : Get a memory block from a partition
  121. *
  122. * Arguments   : pmem    is a pointer to the memory partition control block
  123. *
  124. *               perr    is a pointer to a variable containing an error message which will be set by this
  125. *                       function to either:
  126. *
  127. *                       OS_ERR_NONE             if the memory partition has been created correctly.
  128. *                       OS_ERR_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to caller
  129. *                       OS_ERR_MEM_INVALID_PMEM if you passed a NULL pointer for 'pmem'
  130. *
  131. * Returns     : A pointer to a memory block if no error is detected
  132. *               A pointer to NULL if an error is detected
  133. *********************************************************************************************************
  134. */
  135. void  *OSMemGet (OS_MEM  *pmem, 
  136.                  INT8U   *perr)
  137. {
  138.     void      *pblk;
  139. #if OS_CRITICAL_METHOD == 3                           /* Allocate storage for CPU status register      */
  140.     OS_CPU_SR  cpu_sr = 0;
  141. #endif
  142. #if OS_ARG_CHK_EN > 0
  143.     if (perr == (INT8U *)0) {                         /* Validate 'perr'                               */
  144.         return ((void *)0);
  145.     }
  146.     if (pmem == (OS_MEM *)0) {                        /* Must point to a valid memory partition        */
  147.         *perr = OS_ERR_MEM_INVALID_PMEM;
  148.         return ((void *)0);
  149.     }
  150. #endif
  151.     OS_ENTER_CRITICAL();
  152.     if (pmem->OSMemNFree > 0) {                       /* See if there are any free memory blocks       */
  153.         pblk                = pmem->OSMemFreeList;    /* Yes, point to next free memory block          */
  154.         pmem->OSMemFreeList = *(void **)pblk;         /*      Adjust pointer to new free list          */
  155.         pmem->OSMemNFree--;                           /*      One less memory block in this partition  */
  156.         OS_EXIT_CRITICAL();
  157.         *perr = OS_ERR_NONE;                          /*      No error                                 */
  158.         return (pblk);                                /*      Return memory block to caller            */
  159.     }
  160.     OS_EXIT_CRITICAL();
  161.     *perr = OS_ERR_MEM_NO_FREE_BLKS;                  /* No,  Notify caller of empty memory partition  */
  162.     return ((void *)0);                               /*      Return NULL pointer to caller            */
  163. }
  164. /*$PAGE*/
  165. /*
  166. *********************************************************************************************************
  167. *                                   GET THE NAME OF A MEMORY PARTITION
  168. *
  169. * Description: This function is used to obtain the name assigned to a memory partition.
  170. *
  171. * Arguments  : pmem      is a pointer to the memory partition
  172. *
  173. *              pname     is a pointer to an ASCII string that will receive the name of the memory partition.
  174. *
  175. *              perr      is a pointer to an error code that can contain one of the following values:
  176. *
  177. *                        OS_ERR_NONE                if the name was copied to 'pname'
  178. *                        OS_ERR_MEM_INVALID_PMEM    if you passed a NULL pointer for 'pmem'
  179. *                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
  180. *                        OS_ERR_NAME_GET_ISR        You called this function from an ISR
  181. *
  182. * Returns    : The length of the string or 0 if 'pmem' is a NULL pointer.
  183. *********************************************************************************************************
  184. */
  185. #if OS_MEM_NAME_EN > 1
  186. INT8U  OSMemNameGet (OS_MEM  *pmem, 
  187.                      INT8U   *pname, 
  188.                      INT8U   *perr)
  189. {
  190.     INT8U      len;
  191. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  192.     OS_CPU_SR  cpu_sr = 0;
  193. #endif
  194. #if OS_ARG_CHK_EN > 0
  195.     if (perr == (INT8U *)0) {                    /* Validate 'perr'                                    */
  196.         return (0);
  197.     }
  198.     if (pmem == (OS_MEM *)0) {                   /* Is 'pmem' a NULL pointer?                          */
  199.         *perr = OS_ERR_MEM_INVALID_PMEM;
  200.         return (0);
  201.     }
  202.     if (pname == (INT8U *)0) {                   /* Is 'pname' a NULL pointer?                         */
  203.         *perr = OS_ERR_PNAME_NULL;
  204.         return (0);
  205.     }
  206. #endif
  207.     if (OSIntNesting > 0) {                      /* See if trying to call from an ISR                  */
  208.         *perr = OS_ERR_NAME_GET_ISR;
  209.         return (0);
  210.     }
  211.     OS_ENTER_CRITICAL();
  212.     pname = pmem->OSMemName;
  213.     len   = OS_StrLen(pname);
  214.     OS_EXIT_CRITICAL();
  215.     *perr = OS_ERR_NONE;
  216.     return (len);
  217. }
  218. #endif
  219. /*$PAGE*/
  220. /*
  221. *********************************************************************************************************
  222. *                                 ASSIGN A NAME TO A MEMORY PARTITION
  223. *
  224. * Description: This function assigns a name to a memory partition.
  225. *
  226. * Arguments  : pmem      is a pointer to the memory partition
  227. *
  228. *              pname     is a pointer to an ASCII string that contains the name of the memory partition.
  229. *
  230. *              perr      is a pointer to an error code that can contain one of the following values:
  231. *
  232. *                        OS_ERR_NONE                if the name was copied to 'pname'
  233. *                        OS_ERR_MEM_INVALID_PMEM    if you passed a NULL pointer for 'pmem'
  234. *                        OS_ERR_PNAME_NULL          You passed a NULL pointer for 'pname'
  235. *                        OS_ERR_MEM_NAME_TOO_LONG   if the name doesn't fit in the storage area
  236. *                        OS_ERR_NAME_SET_ISR        if you called this function from an ISR
  237. *
  238. * Returns    : None
  239. *********************************************************************************************************
  240. */
  241. #if OS_MEM_NAME_EN > 0
  242. void  OSMemNameSet (OS_MEM  *pmem, 
  243.                     INT8U   *pname, 
  244.                     INT8U   *perr)
  245. {
  246. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  247.     OS_CPU_SR  cpu_sr = 0;
  248. #endif
  249. #if OS_ARG_CHK_EN > 0
  250.     if (perr == (INT8U *)0) {                    /* Validate 'perr'                                    */
  251.         return;
  252.     }
  253.     if (pmem == (OS_MEM *)0) {                   /* Is 'pmem' a NULL pointer?                          */
  254.         *perr = OS_ERR_MEM_INVALID_PMEM;
  255.         return;
  256.     }
  257.     if (pname == (INT8U *)0) {                   /* Is 'pname' a NULL pointer?                         */
  258.         *perr = OS_ERR_PNAME_NULL;
  259.         return;
  260.     }
  261. #endif
  262.     if (OSIntNesting > 0) {                      /* See if trying to call from an ISR                  */
  263.         *perr = OS_ERR_NAME_SET_ISR;
  264.         return;
  265.     }
  266.     OS_ENTER_CRITICAL();
  267.     pmem->OSMemName = pname;
  268.     OS_EXIT_CRITICAL();
  269.     *perr           = OS_ERR_NONE;
  270. }
  271. #endif
  272. /*$PAGE*/
  273. /*
  274. *********************************************************************************************************
  275. *                                         RELEASE A MEMORY BLOCK
  276. *
  277. * Description : Returns a memory block to a partition
  278. *
  279. * Arguments   : pmem    is a pointer to the memory partition control block
  280. *
  281. *               pblk    is a pointer to the memory block being released.
  282. *
  283. * Returns     : OS_ERR_NONE              if the memory block was inserted into the partition
  284. *               OS_ERR_MEM_FULL          if you are returning a memory block to an already FULL memory
  285. *                                        partition (You freed more blocks than you allocated!)
  286. *               OS_ERR_MEM_INVALID_PMEM  if you passed a NULL pointer for 'pmem'
  287. *               OS_ERR_MEM_INVALID_PBLK  if you passed a NULL pointer for the block to release.
  288. *********************************************************************************************************
  289. */
  290. INT8U  OSMemPut (OS_MEM  *pmem, 
  291.                  void    *pblk)
  292. {
  293. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  294.     OS_CPU_SR  cpu_sr = 0;
  295. #endif
  296. #if OS_ARG_CHK_EN > 0
  297.     if (pmem == (OS_MEM *)0) {                   /* Must point to a valid memory partition             */
  298.         return (OS_ERR_MEM_INVALID_PMEM);
  299.     }
  300.     if (pblk == (void *)0) {                     /* Must release a valid block                         */
  301.         return (OS_ERR_MEM_INVALID_PBLK);
  302.     }
  303. #endif
  304.     OS_ENTER_CRITICAL();
  305.     if (pmem->OSMemNFree >= pmem->OSMemNBlks) {  /* Make sure all blocks not already returned          */
  306.         OS_EXIT_CRITICAL();
  307.         return (OS_ERR_MEM_FULL);
  308.     }
  309.     *(void **)pblk      = pmem->OSMemFreeList;   /* Insert released block into free block list         */
  310.     pmem->OSMemFreeList = pblk;
  311.     pmem->OSMemNFree++;                          /* One more memory block in this partition            */
  312.     OS_EXIT_CRITICAL();
  313.     return (OS_ERR_NONE);                        /* Notify caller that memory block was released       */
  314. }
  315. /*$PAGE*/
  316. /*
  317. *********************************************************************************************************
  318. *                                          QUERY MEMORY PARTITION
  319. *
  320. * Description : This function is used to determine the number of free memory blocks and the number of
  321. *               used memory blocks from a memory partition.
  322. *
  323. * Arguments   : pmem        is a pointer to the memory partition control block
  324. *
  325. *               p_mem_data  is a pointer to a structure that will contain information about the memory
  326. *                           partition.
  327. *
  328. * Returns     : OS_ERR_NONE               if no errors were found.
  329. *               OS_ERR_MEM_INVALID_PMEM   if you passed a NULL pointer for 'pmem'
  330. *               OS_ERR_MEM_INVALID_PDATA  if you passed a NULL pointer to the data recipient.
  331. *********************************************************************************************************
  332. */
  333. #if OS_MEM_QUERY_EN > 0
  334. INT8U  OSMemQuery (OS_MEM       *pmem, 
  335.                    OS_MEM_DATA  *p_mem_data)
  336. {
  337. #if OS_CRITICAL_METHOD == 3                      /* Allocate storage for CPU status register           */
  338.     OS_CPU_SR  cpu_sr = 0;
  339. #endif
  340. #if OS_ARG_CHK_EN > 0
  341.     if (pmem == (OS_MEM *)0) {                   /* Must point to a valid memory partition             */
  342.         return (OS_ERR_MEM_INVALID_PMEM);
  343.     }
  344.     if (p_mem_data == (OS_MEM_DATA *)0) {        /* Must release a valid storage area for the data     */
  345.         return (OS_ERR_MEM_INVALID_PDATA);
  346.     }
  347. #endif
  348.     OS_ENTER_CRITICAL();
  349.     p_mem_data->OSAddr     = pmem->OSMemAddr;
  350.     p_mem_data->OSFreeList = pmem->OSMemFreeList;
  351.     p_mem_data->OSBlkSize  = pmem->OSMemBlkSize;
  352.     p_mem_data->OSNBlks    = pmem->OSMemNBlks;
  353.     p_mem_data->OSNFree    = pmem->OSMemNFree;
  354.     OS_EXIT_CRITICAL();
  355.     p_mem_data->OSNUsed    = p_mem_data->OSNBlks - p_mem_data->OSNFree;
  356.     return (OS_ERR_NONE);
  357. }
  358. #endif                                           /* OS_MEM_QUERY_EN                                    */
  359. /*$PAGE*/
  360. /*
  361. *********************************************************************************************************
  362. *                                    INITIALIZE MEMORY PARTITION MANAGER
  363. *
  364. * Description : This function is called by uC/OS-II to initialize the memory partition manager.  Your
  365. *               application MUST NOT call this function.
  366. *
  367. * Arguments   : none
  368. *
  369. * Returns     : none
  370. *
  371. * Note(s)    : This function is INTERNAL to uC/OS-II and your application should not call it.
  372. *********************************************************************************************************
  373. */
  374. void  OS_MemInit (void)
  375. {
  376. #if OS_MAX_MEM_PART == 1
  377.     OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl));   /* Clear the memory partition table          */
  378.     OSMemFreeList               = (OS_MEM *)&OSMemTbl[0]; /* Point to beginning of free list           */
  379. #if OS_MEM_NAME_EN > 0
  380.     OSMemFreeList->OSMemName    = "?";                    /* Unknown name                              */
  381. #endif
  382. #endif
  383. #if OS_MAX_MEM_PART >= 2
  384.     OS_MEM  *pmem;
  385.     INT16U   i;
  386.     OS_MemClr((INT8U *)&OSMemTbl[0], sizeof(OSMemTbl));   /* Clear the memory partition table          */
  387.     pmem = &OSMemTbl[0];                                  /* Point to memory control block (MCB)       */
  388.     for (i = 0; i < (OS_MAX_MEM_PART - 1); i++) {         /* Init. list of free memory partitions      */
  389.         pmem->OSMemFreeList = (void *)&OSMemTbl[i+1];     /* Chain list of free partitions             */
  390. #if OS_MEM_NAME_EN > 0
  391.         pmem->OSMemName  = "?";                           /* Unknown name                              */
  392. #endif
  393.         pmem++;
  394.     }
  395.     pmem->OSMemFreeList = (void *)0;                      /* Initialize last node                      */
  396. #if OS_MEM_NAME_EN > 0
  397.     pmem->OSMemName = "?";                                /* Unknown name                              */
  398. #endif
  399.     OSMemFreeList   = &OSMemTbl[0];                       /* Point to beginning of free list           */
  400. #endif
  401. }
  402. #endif                                                    /* OS_MEM_EN                                 */