os_mem.c
上传用户:zbk8730
上传日期:2017-08-10
资源大小:12168k
文件大小:19k
源码类别:

uCOS

开发平台:

C/C++

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