LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
os_mem.c
Go to the documentation of this file.
1 /*
2 ************************************************************************************************************************
3 * uC/OS-III
4 * The Real-Time Kernel
5 *
6 * (c) Copyright 2009-2012; 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.03.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 
33 #define MICRIUM_SOURCE
34 #include <os.h>
35 
36 #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
37 const CPU_CHAR *os_mem__c = "$Id: $";
38 #endif
39 
40 
41 #if OS_CFG_MEM_EN > 0u
42 /*
43 ************************************************************************************************************************
44 * CREATE A MEMORY PARTITION
45 *
46 * Description : Create a fixed-sized memory partition that will be managed by uC/OS-III.
47 *
48 * Arguments : p_mem is a pointer to a memory partition control block which is allocated in user memory space.
49 *
50 * p_name is a pointer to an ASCII string to provide a name to the memory partition.
51 *
52 * p_addr is the starting address of the memory partition
53 *
54 * n_blks is the number of memory blocks to create from the partition.
55 *
56 * blk_size is the size (in bytes) of each block in the memory partition.
57 *
58 * p_err is a pointer to a variable containing an error message which will be set by this function to
59 * either:
60 *
61 * OS_ERR_NONE if the memory partition has been created correctly.
62 * OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the memory partition after you
63 * called OSSafetyCriticalStart().
64 * OS_ERR_MEM_INVALID_BLKS user specified an invalid number of blocks (must be >= 2)
65 * OS_ERR_MEM_INVALID_P_ADDR if you are specifying an invalid address for the memory
66 * storage of the partition or, the block does not align on a
67 * pointer boundary
68 * OS_ERR_MEM_INVALID_SIZE user specified an invalid block size
69 * - must be greater than the size of a pointer
70 * - must be able to hold an integral number of pointers
71 * Returns : none
72 ************************************************************************************************************************
73 */
74 
75 void OSMemCreate (OS_MEM *p_mem,
76  CPU_CHAR *p_name,
77  void *p_addr,
78  OS_MEM_QTY n_blks,
79  OS_MEM_SIZE blk_size,
80  OS_ERR *p_err)
81 {
82 #if OS_CFG_ARG_CHK_EN > 0u
83  CPU_DATA align_msk;
84 #endif
85  OS_MEM_QTY i;
86  OS_MEM_QTY loops;
87  CPU_INT08U *p_blk;
88  void **p_link;
89  CPU_SR_ALLOC();
90 
91 
92 
93 #ifdef OS_SAFETY_CRITICAL
94  if (p_err == (OS_ERR *)0) {
95  OS_SAFETY_CRITICAL_EXCEPTION();
96  return;
97  }
98 #endif
99 
100 #ifdef OS_SAFETY_CRITICAL_IEC61508
101  if (OSSafetyCriticalStartFlag == DEF_TRUE) {
103  return;
104  }
105 #endif
106 
107 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
108  if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
109  *p_err = OS_ERR_MEM_CREATE_ISR;
110  return;
111  }
112 #endif
113 
114 #if OS_CFG_ARG_CHK_EN > 0u
115  if (p_addr == (void *)0) { /* Must pass a valid address for the memory part. */
116  *p_err = OS_ERR_MEM_INVALID_P_ADDR;
117  return;
118  }
119  if (n_blks < (OS_MEM_QTY)2) { /* Must have at least 2 blocks per partition */
120  *p_err = OS_ERR_MEM_INVALID_BLKS;
121  return;
122  }
123  if (blk_size < sizeof(void *)) { /* Must contain space for at least a pointer */
124  *p_err = OS_ERR_MEM_INVALID_SIZE;
125  return;
126  }
127  align_msk = sizeof(void *) - 1u;
128  if (align_msk > 0) {
129  if (((CPU_ADDR)p_addr & align_msk) != 0u){ /* Must be pointer size aligned */
130  *p_err = OS_ERR_MEM_INVALID_P_ADDR;
131  return;
132  }
133  if ((blk_size & align_msk) != 0u) { /* Block size must be a multiple address size */
134  *p_err = OS_ERR_MEM_INVALID_SIZE;
135  return;
136  }
137  }
138 #endif
139 
140  p_link = (void **)p_addr; /* Create linked list of free memory blocks */
141  p_blk = (CPU_INT08U *)p_addr;
142  loops = n_blks - 1u;
143  for (i = 0u; i < loops; i++) {
144  p_blk += blk_size;
145  *p_link = (void *)p_blk; /* Save pointer to NEXT block in CURRENT block */
146  p_link = (void **)(void *)p_blk; /* Position to NEXT block */
147  }
148  *p_link = (void *)0; /* Last memory block points to NULL */
149 
151  p_mem->Type = OS_OBJ_TYPE_MEM; /* Set the type of object */
152  p_mem->NamePtr = p_name; /* Save name of memory partition */
153  p_mem->AddrPtr = p_addr; /* Store start address of memory partition */
154  p_mem->FreeListPtr = p_addr; /* Initialize pointer to pool of free blocks */
155  p_mem->NbrFree = n_blks; /* Store number of free blocks in MCB */
156  p_mem->NbrMax = n_blks;
157  p_mem->BlkSize = blk_size; /* Store block size of each memory blocks */
158 
159 #if OS_CFG_DBG_EN > 0u
160  OS_MemDbgListAdd(p_mem);
161 #endif
162 
163  OSMemQty++;
164 
166  *p_err = OS_ERR_NONE;
167 }
168 
169 /*$PAGE*/
170 /*
171 ************************************************************************************************************************
172 * GET A MEMORY BLOCK
173 *
174 * Description : Get a memory block from a partition
175 *
176 * Arguments : p_mem is a pointer to the memory partition control block
177 *
178 * p_err is a pointer to a variable containing an error message which will be set by this function to
179 * either:
180 *
181 * OS_ERR_NONE if the memory partition has been created correctly.
182 * OS_ERR_MEM_INVALID_P_MEM if you passed a NULL pointer for 'p_mem'
183 * OS_ERR_MEM_NO_FREE_BLKS if there are no more free memory blocks to allocate to the caller
184 *
185 * Returns : A pointer to a memory block if no error is detected
186 * A pointer to NULL if an error is detected
187 ************************************************************************************************************************
188 */
189 
190 void *OSMemGet (OS_MEM *p_mem,
191  OS_ERR *p_err)
192 {
193  void *p_blk;
194  CPU_SR_ALLOC();
195 
196 
197 
198 #ifdef OS_SAFETY_CRITICAL
199  if (p_err == (OS_ERR *)0) {
200  OS_SAFETY_CRITICAL_EXCEPTION();
201  return ((void *)0);
202  }
203 #endif
204 
205 #if OS_CFG_ARG_CHK_EN > 0u
206  if (p_mem == (OS_MEM *)0) { /* Must point to a valid memory partition */
207  *p_err = OS_ERR_MEM_INVALID_P_MEM;
208  return ((void *)0);
209  }
210 #endif
211 
213  if (p_mem->NbrFree == (OS_MEM_QTY)0) { /* See if there are any free memory blocks */
215  *p_err = OS_ERR_MEM_NO_FREE_BLKS; /* No, Notify caller of empty memory partition */
216  return ((void *)0); /* Return NULL pointer to caller */
217  }
218  p_blk = p_mem->FreeListPtr; /* Yes, point to next free memory block */
219  p_mem->FreeListPtr = *(void **)p_blk; /* Adjust pointer to new free list */
220  p_mem->NbrFree--; /* One less memory block in this partition */
222  *p_err = OS_ERR_NONE; /* No error */
223  return (p_blk); /* Return memory block to caller */
224 }
225 
226 /*$PAGE*/
227 /*
228 ************************************************************************************************************************
229 * RELEASE A MEMORY BLOCK
230 *
231 * Description : Returns a memory block to a partition
232 *
233 * Arguments : p_mem is a pointer to the memory partition control block
234 *
235 * p_blk is a pointer to the memory block being released.
236 *
237 * p_err is a pointer to a variable that will contain an error code returned by this function.
238 *
239 * OS_ERR_NONE if the memory block was inserted into the partition
240 * OS_ERR_MEM_FULL if you are returning a memory block to an already FULL memory
241 * partition (You freed more blocks than you allocated!)
242 * OS_ERR_MEM_INVALID_P_BLK if you passed a NULL pointer for the block to release.
243 * OS_ERR_MEM_INVALID_P_MEM if you passed a NULL pointer for 'p_mem'
244 ************************************************************************************************************************
245 */
246 
247 void OSMemPut (OS_MEM *p_mem,
248  void *p_blk,
249  OS_ERR *p_err)
250 {
251  CPU_SR_ALLOC();
252 
253 
254 
255 #ifdef OS_SAFETY_CRITICAL
256  if (p_err == (OS_ERR *)0) {
257  OS_SAFETY_CRITICAL_EXCEPTION();
258  return;
259  }
260 #endif
261 
262 #if OS_CFG_ARG_CHK_EN > 0u
263  if (p_mem == (OS_MEM *)0) { /* Must point to a valid memory partition */
264  *p_err = OS_ERR_MEM_INVALID_P_MEM;
265  return;
266  }
267  if (p_blk == (void *)0) { /* Must release a valid block */
268  *p_err = OS_ERR_MEM_INVALID_P_BLK;
269  return;
270  }
271 #endif
272 
274  if (p_mem->NbrFree >= p_mem->NbrMax) { /* Make sure all blocks not already returned */
276  *p_err = OS_ERR_MEM_FULL;
277  return;
278  }
279  *(void **)p_blk = p_mem->FreeListPtr; /* Insert released block into free block list */
280  p_mem->FreeListPtr = p_blk;
281  p_mem->NbrFree++; /* One more memory block in this partition */
283  *p_err = OS_ERR_NONE; /* Notify caller that memory block was released */
284 }
285 
286 /*$PAGE*/
287 /*
288 ************************************************************************************************************************
289 * ADD MEMORY PARTITION TO DEBUG LIST
290 *
291 * Description : This function is called by OSMemCreate() to add the memory partition to the debug table.
292 *
293 * Arguments : p_mem Is a pointer to the memory partition
294 *
295 * Returns : none
296 *
297 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
298 ************************************************************************************************************************
299 */
300 
301 #if OS_CFG_DBG_EN > 0u
302 void OS_MemDbgListAdd (OS_MEM *p_mem)
303 {
304  p_mem->DbgPrevPtr = (OS_MEM *)0;
305  if (OSMemDbgListPtr == (OS_MEM *)0) {
306  p_mem->DbgNextPtr = (OS_MEM *)0;
307  } else {
308  p_mem->DbgNextPtr = OSMemDbgListPtr;
309  OSMemDbgListPtr->DbgPrevPtr = p_mem;
310  }
311  OSMemDbgListPtr = p_mem;
312 }
313 #endif
314 
315 /*$PAGE*/
316 /*
317 ************************************************************************************************************************
318 * INITIALIZE MEMORY PARTITION MANAGER
319 *
320 * Description : This function is called by uC/OS-III to initialize the memory partition manager. Your
321 * application MUST NOT call this function.
322 *
323 * Arguments : none
324 *
325 * Returns : none
326 *
327 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
328 ************************************************************************************************************************
329 */
330 
331 void OS_MemInit (OS_ERR *p_err)
332 {
333 #ifdef OS_SAFETY_CRITICAL
334  if (p_err == (OS_ERR *)0) {
335  OS_SAFETY_CRITICAL_EXCEPTION();
336  return;
337  }
338 #endif
339 
340 #if OS_CFG_DBG_EN > 0u
341  OSMemDbgListPtr = (OS_MEM *)0;
342 #endif
343 
344  OSMemQty = (OS_OBJ_QTY)0;
345  *p_err = OS_ERR_NONE;
346 }
347 #endif