/src/compiler/ucos-vs2008/UCOS_SIM/src/ucosii/os_mem.c

http://ftk.googlecode.com/ · C · 416 lines · 236 code · 33 blank · 147 comment · 47 complexity · 4ede0aceb00ba5b25452cacc4c96986d MD5 · raw file

  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 */