os_mem.c
上传用户:jingkewang
上传日期:2013-04-11
资源大小:917k
文件大小:18k
源码类别:

uCOS

开发平台:

Visual C++

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