os_mem.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /*
  2. ************************************************************************************************************************
  3. * uC/OS-III
  4. * The Real-Time Kernel
  5. *
  6. * (c) Copyright 2009-2011; Micrium, Inc.; Weston, FL
  7. * All rights reserved. Protected by international copyright laws.
  8. *
  9. * MEMORY PARTITION MANAGEMENT
  10. *
  11. * File : OS_MEM.C
  12. * By : JJL
  13. * Version : V3.02.00
  14. *
  15. * LICENSING TERMS:
  16. * ---------------
  17. * uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or
  18. * for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/
  19. * product then, you need to contact Micrium to properly license uC/OS-III for its use in your
  20. * application/product. We provide ALL the source code for your convenience and to help you
  21. * experience uC/OS-III. The fact that the source is provided does NOT mean that you can use
  22. * it commercially without paying a licensing fee.
  23. *
  24. * Knowledge of the source code may NOT be used to develop a similar product.
  25. *
  26. * Please help us continue to provide the embedded community with the finest software available.
  27. * Your honesty is greatly appreciated.
  28. *
  29. * You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
  30. ************************************************************************************************************************
  31. */
  32. #include <os.h>
  33. #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
  34. const CPU_CHAR *os_mem__c = "$Id: $";
  35. #endif
  36. #if OS_CFG_MEM_EN > 0u
  37. /*
  38. ************************************************************************************************************************
  39. * CREATE A MEMORY PARTITION
  40. *
  41. * Description : Create a fixed-sized memory partition that will be managed by uC/OS-III.
  42. *
  43. * Arguments : p_mem is a pointer to a memory partition control block which is allocated in user memory space.
  44. *
  45. * p_name is a pointer to an ASCII string to provide a name to the memory partition.
  46. *
  47. * p_addr is the starting address of the memory partition
  48. *
  49. * n_blks is the number of memory blocks to create from the partition.
  50. *
  51. * blk_size is the size (in bytes) of each block in the memory partition.
  52. *
  53. * p_err is a pointer to a variable containing an error message which will be set by this function to
  54. * either:
  55. *
  56. * OS_ERR_NONE if the memory partition has been created correctly.
  57. * OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the memory partition after you
  58. * called OSSafetyCriticalStart().
  59. * OS_ERR_MEM_INVALID_BLKS user specified an invalid number of blocks (must be >= 2)
  60. * OS_ERR_MEM_INVALID_P_ADDR if you are specifying an invalid address for the memory
  61. * storage of the partition or, the block does not align on a
  62. * pointer boundary
  63. * OS_ERR_MEM_INVALID_SIZE user specified an invalid block size
  64. * - must be greater than the size of a pointer
  65. * - must be able to hold an integral number of pointers
  66. * Returns : none
  67. ************************************************************************************************************************
  68. */
  69. void OSMemCreate (OS_MEM *p_mem,
  70. CPU_CHAR *p_name,
  71. void *p_addr,
  72. OS_MEM_QTY n_blks,
  73. OS_MEM_SIZE blk_size,
  74. OS_ERR *p_err)
  75. {
  76. #if OS_CFG_ARG_CHK_EN > 0u
  77. CPU_DATA align_msk;
  78. #endif
  79. OS_MEM_QTY i;
  80. OS_MEM_QTY loops;
  81. CPU_INT08U *p_blk;
  82. void **p_link;
  83. CPU_SR_ALLOC();
  84. #ifdef OS_SAFETY_CRITICAL
  85. if (p_err == (OS_ERR *)0) {
  86. OS_SAFETY_CRITICAL_EXCEPTION();
  87. return;
  88. }
  89. #endif
  90. #ifdef OS_SAFETY_CRITICAL_IEC61508
  91. if (OSSafetyCriticalStartFlag == DEF_TRUE) {
  92. *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
  93. return;
  94. }
  95. #endif
  96. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  97. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
  98. *p_err = OS_ERR_MEM_CREATE_ISR;
  99. return;
  100. }
  101. #endif
  102. #if OS_CFG_ARG_CHK_EN > 0u
  103. if (p_addr == (void *)0) { /* Must pass a valid address for the memory part. */
  104. *p_err = OS_ERR_MEM_INVALID_P_ADDR;
  105. return;
  106. }
  107. if (n_blks < (OS_MEM_QTY)2) { /* Must have at least 2 blocks per partition */
  108. *p_err = OS_ERR_MEM_INVALID_BLKS;
  109. return;
  110. }
  111. if (blk_size < sizeof(void *)) { /* Must contain space for at least a pointer */
  112. *p_err = OS_ERR_MEM_INVALID_SIZE;
  113. return;
  114. }
  115. align_msk = sizeof(void *) - 1u;
  116. if (align_msk > 0) {
  117. if (((CPU_ADDR)p_addr & align_msk) != 0u){ /* Must be pointer size aligned */
  118. *p_err = OS_ERR_MEM_INVALID_P_ADDR;
  119. return;
  120. }
  121. if ((blk_size & align_msk) != 0u) { /* Block size must be a multiple address size */
  122. *p_err = OS_ERR_MEM_INVALID_SIZE;
  123. }
  124. }
  125. #endif
  126. p_link = (void **)p_addr; /* Create linked list of free memory blocks */
  127. p_blk = p_addr;
  128. loops = n_blks - 1u;
  129. for (i = 0u; i < loops; i++) {
  130. p_blk += blk_size;
  131. *p_link = (void *)p_blk; /* Save pointer to NEXT block in CURRENT block */
  132. p_link = (void **)(void *)p_blk; /* Position to NEXT block */
  133. }
  134. *p_link = (void *)0; /* Last memory block points to NULL */
  135. OS_CRITICAL_ENTER();
  136. p_mem->Type = OS_OBJ_TYPE_MEM; /* Set the type of object */
  137. p_mem->NamePtr = p_name; /* Save name of memory partition */
  138. p_mem->AddrPtr = p_addr; /* Store start address of memory partition */
  139. p_mem->FreeListPtr = p_addr; /* Initialize pointer to pool of free blocks */
  140. p_mem->NbrFree = n_blks; /* Store number of free blocks in MCB */
  141. p_mem->NbrMax = n_blks;
  142. p_mem->BlkSize = blk_size; /* Store block size of each memory blocks */
  143. #if OS_CFG_DBG_EN > 0u
  144. OS_MemDbgListAdd(p_mem);
  145. #endif
  146. OSMemQty++;
  147. OS_CRITICAL_EXIT();
  148. *p_err = OS_ERR_NONE;
  149. }
  150. /*$PAGE*/
  151. /*
  152. ************************************************************************************************************************
  153. * GET A MEMORY BLOCK
  154. *
  155. * Description : Get a memory block from a partition
  156. *
  157. * Arguments : p_mem is a pointer to the memory partition control block
  158. *
  159. * p_err is a pointer to a variable containing an error message which will be set by this function to
  160. * either:
  161. *
  162. * OS_ERR_NONE if the memory partition has been created correctly.
  163. * OS_ERR_MEM_INVALID_P_MEM if you passed a NULL pointer for 'p_mem'
  164. * OS_ERR_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to the caller
  165. *
  166. * Returns : A pointer to a memory block if no error is detected
  167. * A pointer to NULL if an error is detected
  168. ************************************************************************************************************************
  169. */
  170. void *OSMemGet (OS_MEM *p_mem,
  171. OS_ERR *p_err)
  172. {
  173. void *p_blk;
  174. CPU_SR_ALLOC();
  175. #ifdef OS_SAFETY_CRITICAL
  176. if (p_err == (OS_ERR *)0) {
  177. OS_SAFETY_CRITICAL_EXCEPTION();
  178. return ((void *)0);
  179. }
  180. #endif
  181. #if OS_CFG_ARG_CHK_EN > 0u
  182. if (p_mem == (OS_MEM *)0) { /* Must point to a valid memory partition */
  183. *p_err = OS_ERR_MEM_INVALID_P_MEM;
  184. return ((void *)0);
  185. }
  186. #endif
  187. CPU_CRITICAL_ENTER();
  188. if (p_mem->NbrFree == (OS_MEM_QTY)0) { /* See if there are any free memory blocks */
  189. CPU_CRITICAL_EXIT();
  190. *p_err = OS_ERR_MEM_NO_FREE_BLKS; /* No, Notify caller of empty memory partition */
  191. return ((void *)0); /* Return NULL pointer to caller */
  192. }
  193. p_blk = p_mem->FreeListPtr; /* Yes, point to next free memory block */
  194. p_mem->FreeListPtr = *(void **)p_blk; /* Adjust pointer to new free list */
  195. p_mem->NbrFree--; /* One less memory block in this partition */
  196. CPU_CRITICAL_EXIT();
  197. *p_err = OS_ERR_NONE; /* No error */
  198. return (p_blk); /* Return memory block to caller */
  199. }
  200. /*$PAGE*/
  201. /*
  202. ************************************************************************************************************************
  203. * RELEASE A MEMORY BLOCK
  204. *
  205. * Description : Returns a memory block to a partition
  206. *
  207. * Arguments : p_mem is a pointer to the memory partition control block
  208. *
  209. * p_blk is a pointer to the memory block being released.
  210. *
  211. * p_err is a pointer to a variable that will contain an error code returned by this function.
  212. *
  213. * OS_ERR_NONE if the memory block was inserted into the partition
  214. * OS_ERR_MEM_FULL if you are returning a memory block to an already FULL memory
  215. * partition (You freed more blocks than you allocated!)
  216. * OS_ERR_MEM_INVALID_P_BLK if you passed a NULL pointer for the block to release.
  217. * OS_ERR_MEM_INVALID_P_MEM if you passed a NULL pointer for 'p_mem'
  218. ************************************************************************************************************************
  219. */
  220. void OSMemPut (OS_MEM *p_mem,
  221. void *p_blk,
  222. OS_ERR *p_err)
  223. {
  224. CPU_SR_ALLOC();
  225. #ifdef OS_SAFETY_CRITICAL
  226. if (p_err == (OS_ERR *)0) {
  227. OS_SAFETY_CRITICAL_EXCEPTION();
  228. return;
  229. }
  230. #endif
  231. #if OS_CFG_ARG_CHK_EN > 0u
  232. if (p_mem == (OS_MEM *)0) { /* Must point to a valid memory partition */
  233. *p_err = OS_ERR_MEM_INVALID_P_MEM;
  234. return;
  235. }
  236. if (p_blk == (void *)0) { /* Must release a valid block */
  237. *p_err = OS_ERR_MEM_INVALID_P_BLK;
  238. return;
  239. }
  240. #endif
  241. CPU_CRITICAL_ENTER();
  242. if (p_mem->NbrFree >= p_mem->NbrMax) { /* Make sure all blocks not already returned */
  243. CPU_CRITICAL_EXIT();
  244. *p_err = OS_ERR_MEM_FULL;
  245. return;
  246. }
  247. *(void **)p_blk = p_mem->FreeListPtr; /* Insert released block into free block list */
  248. p_mem->FreeListPtr = p_blk;
  249. p_mem->NbrFree++; /* One more memory block in this partition */
  250. CPU_CRITICAL_EXIT();
  251. *p_err = OS_ERR_NONE; /* Notify caller that memory block was released */
  252. }
  253. /*$PAGE*/
  254. /*
  255. ************************************************************************************************************************
  256. * ADD MEMORY PARTITION TO DEBUG LIST
  257. *
  258. * Description : This function is called by OSMemCreate() to add the memory partition to the debug table.
  259. *
  260. * Arguments : p_mem Is a pointer to the memory partition
  261. *
  262. * Returns : none
  263. *
  264. * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
  265. ************************************************************************************************************************
  266. */
  267. #if OS_CFG_DBG_EN > 0u
  268. void OS_MemDbgListAdd (OS_MEM *p_mem)
  269. {
  270. p_mem->DbgPrevPtr = (OS_MEM *)0;
  271. if (OSMemDbgListPtr == (OS_MEM *)0) {
  272. p_mem->DbgNextPtr = (OS_MEM *)0;
  273. } else {
  274. p_mem->DbgNextPtr = OSMemDbgListPtr;
  275. OSMemDbgListPtr->DbgPrevPtr = p_mem;
  276. }
  277. OSMemDbgListPtr = p_mem;
  278. }
  279. #endif
  280. /*$PAGE*/
  281. /*
  282. ************************************************************************************************************************
  283. * INITIALIZE MEMORY PARTITION MANAGER
  284. *
  285. * Description : This function is called by uC/OS-III to initialize the memory partition manager. Your
  286. * application MUST NOT call this function.
  287. *
  288. * Arguments : none
  289. *
  290. * Returns : none
  291. *
  292. * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
  293. ************************************************************************************************************************
  294. */
  295. void OS_MemInit (OS_ERR *p_err)
  296. {
  297. #ifdef OS_SAFETY_CRITICAL
  298. if (p_err == (OS_ERR *)0) {
  299. OS_SAFETY_CRITICAL_EXCEPTION();
  300. return;
  301. }
  302. #endif
  303. #if OS_CFG_DBG_EN > 0u
  304. OSMemDbgListPtr = (OS_MEM *)0;
  305. #endif
  306. OSMemQty = (OS_OBJ_QTY)0;
  307. *p_err = OS_ERR_NONE;
  308. }
  309. #endif