UCOS_TI_LM3S_Keil
 全部 结构体 文件 函数 变量 类型定义 宏定义 
lib_mem.c
浏览该文件的文档.
1 /*
2 *********************************************************************************************************
3 * uC/LIB
4 * CUSTOM LIBRARY MODULES
5 *
6 * (c) Copyright 2004-2009; Micrium, Inc.; Weston, FL
7 *
8 * All rights reserved. Protected by international copyright laws.
9 *
10 * uC/LIB is provided in source form for FREE evaluation, for educational
11 * use or peaceful research. If you plan on using uC/LIB in a commercial
12 * product you need to contact Micrium to properly license its use in your
13 * product. We provide ALL the source code for your convenience and to
14 * help you experience uC/LIB. The fact that the source code is provided
15 * does NOT mean that you can use it without paying a licensing fee.
16 *
17 * Knowledge of the source code may NOT be used to develop a similar product.
18 *
19 * Please help us continue to provide the Embedded community with the finest
20 * software available. Your honesty is greatly appreciated.
21 *********************************************************************************************************
22 */
23 
24 /*
25 *********************************************************************************************************
26 *
27 * STANDARD MEMORY OPERATIONS
28 *
29 * Filename : lib_mem.c
30 * Version : V1.30
31 * Programmer(s) : ITJ
32 * FGK
33 *********************************************************************************************************
34 * Note(s) : (1) NO compiler-supplied standard library functions are used in library or product software.
35 *
36 * (a) ALL standard library functions are implemented in the custom library modules :
37 *
38 * (1) <Custom Library Directory>\lib*.*
39 *
40 * (2) <Custom Library Directory>\Ports<cpu><compiler>\lib*_a.*
41 *
42 * where
43 * <Custom Library Directory> directory path for custom library software
44 * <cpu> directory name for specific processor (CPU)
45 * <compiler> directory name for specific compiler
46 *
47 * (b) Product-specific library functions are implemented in individual products.
48 *********************************************************************************************************
49 */
50 
51 
52 /*
53 *********************************************************************************************************
54 * INCLUDE FILES
55 *********************************************************************************************************
56 */
57 
58 #define LIB_MEM_MODULE
59 #include <lib_mem.h>
60 
61 
62 /*$PAGE*/
63 /*
64 *********************************************************************************************************
65 * LOCAL DEFINES
66 *********************************************************************************************************
67 */
68 
69 
70 /*
71 *********************************************************************************************************
72 * LOCAL CONSTANTS
73 *********************************************************************************************************
74 */
75 
76 
77 /*
78 *********************************************************************************************************
79 * LOCAL DATA TYPES
80 *********************************************************************************************************
81 */
82 
83 
84 /*
85 *********************************************************************************************************
86 * LOCAL TABLES
87 *********************************************************************************************************
88 */
89 
90 
91 /*
92 *********************************************************************************************************
93 * LOCAL GLOBAL VARIABLES
94 *********************************************************************************************************
95 */
96 
97 #if (LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED)
98 MEM_POOL *Mem_PoolTbl; /* Mem pool/seg tbl. */
99 MEM_POOL Mem_PoolHeap; /* Mem heap pool/seg. */
100 
101 #ifndef LIB_MEM_CFG_HEAP_BASE_ADDR
103 #endif
104 #endif
105 
106 
107 /*
108 *********************************************************************************************************
109 * LOCAL FUNCTION PROTOTYPES
110 *********************************************************************************************************
111 */
112 
113 #if (LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED) /* -------------- MEM POOL FNCTS -------------- */
114 
115 #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
116 static CPU_BOOLEAN Mem_PoolBlkIsValidAddr(MEM_POOL *pmem_pool,
117  void *pmem_blk);
118 #endif
119 
120 
121 static CPU_SIZE_T Mem_PoolSegCalcTotSize(void *pmem_addr,
122  CPU_SIZE_T blk_nbr,
123  CPU_SIZE_T blk_size,
124  CPU_SIZE_T blk_align);
125 
126 static void *Mem_PoolSegAlloc (MEM_POOL *pmem_pool,
127  CPU_SIZE_T size,
128  CPU_SIZE_T align);
129 
130 #endif
131 
132 
133 /*
134 *********************************************************************************************************
135 * LOCAL CONFIGURATION ERRORS
136 *********************************************************************************************************
137 */
138 
139 
140 /*$PAGE*/
141 /*
142 *********************************************************************************************************
143 * Mem_Init()
144 *
145 * Description : (1) Initialize Memory Management Module :
146 *
147 * (a) Initialize heap memory pool
148 * (b) Initialize memory pool table
149 *
150 *
151 * Argument(s) : none.
152 *
153 * Return(s) : none.
154 *
155 * Caller(s) : Application.
156 *
157 * Note(s) : none.
158 *********************************************************************************************************
159 */
160 
161 void Mem_Init (void)
162 {
163 #if (LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED)
164  MEM_POOL *pmem_pool;
165 
166  /* --------- INIT MEM HEAP SEG / POOL --------- */
167  pmem_pool = (MEM_POOL *)&Mem_PoolHeap;
168  pmem_pool->Type = (LIB_MEM_TYPE) LIB_MEM_TYPE_HEAP;
169  pmem_pool->SegPrevPtr = (MEM_POOL *) 0;
170  pmem_pool->SegNextPtr = (MEM_POOL *) 0;
171  pmem_pool->PoolPrevPtr = (MEM_POOL *) 0;
172  pmem_pool->PoolNextPtr = (MEM_POOL *) 0;
173  pmem_pool->PoolAddrStart = (void *) 0;
174  pmem_pool->PoolAddrEnd = (void *) 0;
175  pmem_pool->PoolPtrs = (void **) 0;
176  pmem_pool->BlkSize = (CPU_SIZE_T ) 0;
177  pmem_pool->BlkNbr = (CPU_SIZE_T ) 0;
178  pmem_pool->BlkIx = (MEM_POOL_IX ) 0;
179 
180 #ifdef LIB_MEM_CFG_HEAP_BASE_ADDR
181  pmem_pool->SegAddr = (void *) LIB_MEM_CFG_HEAP_BASE_ADDR;
182  pmem_pool->SegAddrNextAvail = (void *) LIB_MEM_CFG_HEAP_BASE_ADDR;
183 #else
184  pmem_pool->SegAddr = (void *)&Mem_Heap[0];
185  pmem_pool->SegAddrNextAvail = (void *)&Mem_Heap[0];
186 #endif
187 
188  pmem_pool->SegSizeTot = (CPU_SIZE_T ) LIB_MEM_CFG_HEAP_SIZE;
189  pmem_pool->SegSizeRem = (CPU_SIZE_T ) LIB_MEM_CFG_HEAP_SIZE;
190 
191  /* ------------ INIT MEM POOL TBL ------------- */
193 #endif
194 }
195 
196 
197 /*$PAGE*/
198 /*
199 *********************************************************************************************************
200 * Mem_Clr()
201 *
202 * Description : Clear data buffer (see Note #2).
203 *
204 * Argument(s) : pmem Pointer to memory buffer to clear.
205 *
206 * size Number of data buffer octets to clear.
207 *
208 * Return(s) : none.
209 *
210 * Caller(s) : Application.
211 *
212 * Note(s) : (1) Null clears allowed (i.e. 0-octet size).
213 *
214 * See also 'Mem_Set() Note #1'.
215 *
216 * (2) Clear data by setting each data octet to 0.
217 *********************************************************************************************************
218 */
219 
220 void Mem_Clr (void *pmem,
221  CPU_SIZE_T size)
222 {
223  Mem_Set((void *)pmem,
224  (CPU_INT08U)0, /* See Note #2. */
225  (CPU_SIZE_T)size);
226 }
227 
228 
229 /*$PAGE*/
230 /*
231 *********************************************************************************************************
232 * Mem_Set()
233 *
234 * Description : Fill data buffer with specified data octet.
235 *
236 * Argument(s) : pmem Pointer to memory buffer to fill with specified data octet.
237 *
238 * data_val Data fill octet value.
239 *
240 * size Number of data buffer octets to fill.
241 *
242 * Return(s) : none.
243 *
244 * Caller(s) : Application.
245 *
246 * Note(s) : (1) Null sets allowed (i.e. 0-octet size).
247 *
248 * (2) For best CPU performance, optimized to fill data buffer using 'CPU_ALIGN'-sized data
249 * words.
250 *
251 * (a) Since many word-aligned processors REQUIRE that multi-octet words be accessed on
252 * word-aligned addresses, 'CPU_ALIGN'-sized words MUST be accessed on 'CPU_ALIGN'd
253 * addresses.
254 *
255 * (3) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
256 * address boundary.
257 *
258 * Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values. Thus,
259 * address values MUST be cast to an appropriately-sized integer value PRIOR to any
260 * mem_align_modulo arithmetic operation.
261 *********************************************************************************************************
262 */
263 
264 void Mem_Set (void *pmem,
265  CPU_INT08U data_val,
266  CPU_SIZE_T size)
267 {
268  CPU_SIZE_T size_rem;
269  CPU_ALIGN data_align;
270  CPU_ALIGN *pmem_align;
271  CPU_INT08U *pmem_08;
272  CPU_INT08U mem_align_modulo;
273  CPU_INT08U i;
274 
275 
276  if (size < 1) { /* See Note #1. */
277  return;
278  }
279  if (pmem == (void *)0) {
280  return;
281  }
282 
283 
284  data_align = 0;
285  for (i = 0; i < sizeof(CPU_ALIGN); i++) { /* Fill each data_align octet with data val. */
286  data_align <<= DEF_OCTET_NBR_BITS;
287  data_align |= (CPU_ALIGN)data_val;
288  }
289 
290  size_rem = (CPU_SIZE_T)size;
291  mem_align_modulo = (CPU_INT08U)((CPU_ADDR)pmem % sizeof(CPU_ALIGN)); /* See Note #3. */
292 
293  pmem_08 = (CPU_INT08U *)pmem;
294  if (mem_align_modulo != 0) { /* If leading octets avail, ... */
295  i = mem_align_modulo;
296  while ((size_rem > 0) && /* ... start mem buf fill with leading octets ... */
297  (i < sizeof(CPU_ALIGN ))) { /* ... until next CPU_ALIGN word boundary. */
298  *pmem_08++ = data_val;
299  size_rem -= sizeof(CPU_INT08U);
300  i++;
301  }
302  }
303 
304  pmem_align = (CPU_ALIGN *)pmem_08; /* See Note #2a. */
305  while (size_rem >= sizeof(CPU_ALIGN)) { /* While mem buf aligned on CPU_ALIGN word boundaries, */
306  *pmem_align++ = data_align; /* ... fill mem buf with CPU_ALIGN-sized data. */
307  size_rem -= sizeof(CPU_ALIGN);
308  }
309 
310  pmem_08 = (CPU_INT08U *)pmem_align;
311  while (size_rem > 0) { /* Finish mem buf fill with trailing octets. */
312  *pmem_08++ = data_val;
313  size_rem -= sizeof(CPU_INT08U);
314  }
315 }
316 
317 
318 /*$PAGE*/
319 /*
320 *********************************************************************************************************
321 * Mem_Copy()
322 *
323 * Description : Copy data octets from one memory buffer to another memory buffer.
324 *
325 * Argument(s) : pdest Pointer to destination memory buffer.
326 *
327 * psrc Pointer to source memory buffer.
328 *
329 * size Number of data buffer octets to copy.
330 *
331 * Return(s) : none.
332 *
333 * Caller(s) : Application.
334 *
335 * Note(s) : (1) Null copies allowed (i.e. 0-octet size).
336 *
337 * (2) Memory buffers NOT checked for overlapping.
338 *
339 * (3) For best CPU performance, optimized to copy data buffer using 'CPU_ALIGN'-sized data
340 * words.
341 *
342 * (a) Since many word-aligned processors REQUIRE that multi-octet words be accessed on
343 * word-aligned addresses, 'CPU_ALIGN'-sized words MUST be accessed on 'CPU_ALIGN'd
344 * addresses.
345 *
346 * (4) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
347 * address boundary.
348 *
349 * Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values. Thus,
350 * address values MUST be cast to an appropriately-sized integer value PRIOR to any
351 * mem_align_modulo arithmetic operation.
352 *********************************************************************************************************
353 */
354 /*$PAGE*/
355 #if (LIB_MEM_CFG_OPTIMIZE_ASM_EN != DEF_ENABLED)
356 void Mem_Copy (void *pdest,
357  void *psrc,
358  CPU_SIZE_T size)
359 {
360  CPU_SIZE_T size_rem;
361  CPU_ALIGN *pmem_align_dest;
362  CPU_ALIGN *pmem_align_src;
363  CPU_INT08U *pmem_08_dest;
364  CPU_INT08U *pmem_08_src;
365  CPU_INT08U i;
366  CPU_INT08U mem_align_modulo_dest;
367  CPU_INT08U mem_align_modulo_src;
368  CPU_BOOLEAN mem_aligned;
369 
370 
371  if (size < 1) { /* See Note #1. */
372  return;
373  }
374  if (pdest == (void *)0) {
375  return;
376  }
377  if (psrc == (void *)0) {
378  return;
379  }
380 
381 
382  size_rem = (CPU_SIZE_T )size;
383 
384  pmem_08_dest = (CPU_INT08U *)pdest;
385  pmem_08_src = (CPU_INT08U *)psrc;
386  /* See Note #4. */
387  mem_align_modulo_dest = (CPU_INT08U )((CPU_ADDR)pmem_08_dest % sizeof(CPU_ALIGN));
388  mem_align_modulo_src = (CPU_INT08U )((CPU_ADDR)pmem_08_src % sizeof(CPU_ALIGN));
389 
390  mem_aligned = (mem_align_modulo_dest == mem_align_modulo_src) ? DEF_YES : DEF_NO;
391 
392  if (mem_aligned == DEF_YES) { /* If mem bufs' alignment offset equal, ... */
393  /* ... optimize copy for mem buf alignment. */
394  if (mem_align_modulo_dest != 0) { /* If leading octets avail, ... */
395  i = mem_align_modulo_dest;
396  while ((size_rem > 0) && /* ... start mem buf copy with leading octets ... */
397  (i < sizeof(CPU_ALIGN ))) { /* ... until next CPU_ALIGN word boundary. */
398  *pmem_08_dest++ = *pmem_08_src++;
399  size_rem -= sizeof(CPU_INT08U);
400  i++;
401  }
402  }
403 
404  pmem_align_dest = (CPU_ALIGN *)pmem_08_dest; /* See Note #3a. */
405  pmem_align_src = (CPU_ALIGN *)pmem_08_src;
406  while (size_rem >= sizeof(CPU_ALIGN)) { /* While mem bufs aligned on CPU_ALIGN word boundaries, */
407  *pmem_align_dest++ = *pmem_align_src++; /* ... copy psrc to pdest with CPU_ALIGN-sized words. */
408  size_rem -= sizeof(CPU_ALIGN);
409  }
410 
411  pmem_08_dest = (CPU_INT08U *)pmem_align_dest;
412  pmem_08_src = (CPU_INT08U *)pmem_align_src;
413  }
414 
415  while (size_rem > 0) { /* For unaligned mem bufs or trailing octets, ... */
416  *pmem_08_dest++ = *pmem_08_src++; /* ... copy psrc to pdest by octets. */
417  size_rem -= sizeof(CPU_INT08U);
418  }
419 }
420 #endif
421 
422 
423 /*$PAGE*/
424 /*
425 *********************************************************************************************************
426 * Mem_Cmp()
427 *
428 * Description : Verify that ALL data octets in two memory buffers are identical in sequence.
429 *
430 * Argument(s) : p1_mem Pointer to first memory buffer.
431 *
432 * p2_mem Pointer to second memory buffer.
433 *
434 * size Number of data buffer octets to compare.
435 *
436 * Return(s) : DEF_YES, if 'size' number of data octets are identical in both memory buffers.
437 *
438 * DEF_NO, otherwise.
439 *
440 * Caller(s) : Application.
441 *
442 * Note(s) : (1) Null compares allowed (i.e. 0-octet size); 'DEF_YES' returned to indicate identical
443 * null compare.
444 *
445 * (2) Many memory buffer comparisons vary ONLY in the least significant octets -- e.g.
446 * network address buffers. Consequently, memory buffer comparison is more efficient
447 * if the comparison starts from the end of the memory buffers which will abort sooner
448 * on dissimilar memory buffers that vary only in the least significant octets.
449 *
450 * (3) For best CPU performance, optimized to compare data buffers using 'CPU_ALIGN'-sized
451 * data words.
452 *
453 * (a) Since many word-aligned processors REQUIRE that multi-octet words be accessed on
454 * word-aligned addresses, 'CPU_ALIGN'-sized words MUST be accessed on 'CPU_ALIGN'd
455 * addresses.
456 *
457 * (4) Modulo arithmetic is used to determine whether a memory buffer starts on a 'CPU_ALIGN'
458 * address boundary.
459 *
460 * Modulo arithmetic in ANSI-C REQUIREs operations performed on integer values. Thus,
461 * address values MUST be cast to an appropriately-sized integer value PRIOR to any
462 * mem_align_modulo arithmetic operation.
463 ********************************************************************************************************
464 */
465 /*$PAGE*/
466 CPU_BOOLEAN Mem_Cmp (void *p1_mem,
467  void *p2_mem,
468  CPU_SIZE_T size)
469 {
470  CPU_SIZE_T size_rem;
471  CPU_ALIGN *p1_mem_align;
472  CPU_ALIGN *p2_mem_align;
473  CPU_INT08U *p1_mem_08;
474  CPU_INT08U *p2_mem_08;
475  CPU_INT08U i;
476  CPU_INT08U mem_align_modulo_1;
477  CPU_INT08U mem_align_modulo_2;
478  CPU_BOOLEAN mem_aligned;
479  CPU_BOOLEAN mem_cmp;
480 
481 
482  if (size < 1) { /* See Note #1. */
483  return (DEF_YES);
484  }
485  if (p1_mem == (void *)0) {
486  return (DEF_NO);
487  }
488  if (p2_mem == (void *)0) {
489  return (DEF_NO);
490  }
491 
492 
493  mem_cmp = DEF_YES; /* Assume mem bufs are identical until cmp fails. */
494  size_rem = size;
495  /* Start @ end of mem bufs (see Note #2). */
496  p1_mem_08 = (CPU_INT08U *)p1_mem + size;
497  p2_mem_08 = (CPU_INT08U *)p2_mem + size;
498  /* See Note #4. */
499  mem_align_modulo_1 = (CPU_INT08U )((CPU_ADDR)p1_mem_08 % sizeof(CPU_ALIGN));
500  mem_align_modulo_2 = (CPU_INT08U )((CPU_ADDR)p2_mem_08 % sizeof(CPU_ALIGN));
501 
502  mem_aligned = (mem_align_modulo_1 == mem_align_modulo_2) ? DEF_YES : DEF_NO;
503 
504  if (mem_aligned == DEF_YES) { /* If mem bufs' alignment offset equal, ... */
505  /* ... optimize cmp for mem buf alignment. */
506  if (mem_align_modulo_1 != 0) { /* If trailing octets avail, ... */
507  i = mem_align_modulo_1;
508  while ((mem_cmp == DEF_YES) && /* ... cmp mem bufs while identical & ... */
509  (size_rem > 0) && /* ... start mem buf cmp with trailing octets ... */
510  (i > 0)) { /* ... until next CPU_ALIGN word boundary. */
511  p1_mem_08--;
512  p2_mem_08--;
513  if (*p1_mem_08 != *p2_mem_08) { /* If ANY data octet(s) NOT identical, cmp fails. */
514  mem_cmp = DEF_NO;
515  }
516  size_rem -= sizeof(CPU_INT08U);
517  i--;
518  }
519  }
520 
521  if (mem_cmp == DEF_YES) { /* If cmp still identical, cmp aligned mem bufs. */
522  p1_mem_align = (CPU_ALIGN *)p1_mem_08; /* See Note #3a. */
523  p2_mem_align = (CPU_ALIGN *)p2_mem_08;
524 
525  while ((mem_cmp == DEF_YES) && /* Cmp mem bufs while identical & ... */
526  (size_rem >= sizeof(CPU_ALIGN))) { /* ... mem bufs aligned on CPU_ALIGN word boundaries. */
527  p1_mem_align--;
528  p2_mem_align--;
529  if (*p1_mem_align != *p2_mem_align) { /* If ANY data octet(s) NOT identical, cmp fails. */
530  mem_cmp = DEF_NO;
531  }
532  size_rem -= sizeof(CPU_ALIGN);
533  }
534 
535  p1_mem_08 = (CPU_INT08U *)p1_mem_align;
536  p2_mem_08 = (CPU_INT08U *)p2_mem_align;
537  }
538  }
539 
540  while ((mem_cmp == DEF_YES) && /* Cmp mem bufs while identical ... */
541  (size_rem > 0)) { /* ... for unaligned mem bufs or trailing octets. */
542  p1_mem_08--;
543  p2_mem_08--;
544  if (*p1_mem_08 != *p2_mem_08) { /* If ANY data octet(s) NOT identical, cmp fails. */
545  mem_cmp = DEF_NO;
546  }
547  size_rem -= sizeof(CPU_INT08U);
548  }
549 
550  return (mem_cmp);
551 }
552 
553 
554 /*$PAGE*/
555 /*
556 *********************************************************************************************************
557 * Mem_HeapAlloc()
558 *
559 * Description : Allocate a memory block from the heap memory pool.
560 *
561 * Argument(s) : size Size of memory block to allocate (in octets).
562 *
563 * align Alignment of memory block to allocate (in octets).
564 *
565 * poctets_reqd Pointer to a variable to ... :
566 *
567 * (a) Return the number of octets required to successfully
568 * allocate the memory block, if any errors;
569 * (b) Return 0, otherwise.
570 *
571 * perr Pointer to variable that will receive the return error code from this function :
572 *
573 * LIB_MEM_ERR_NONE Memory block successfully returned.
574 * LIB_MEM_ERR_INVALID_MEM_SIZE Invalid memory size.
575 * LIB_MEM_ERR_HEAP_EMPTY Heap segment empty; NO available memory
576 * from heap.
577 *
578 * Return(s) : Pointer to memory block, if NO errors.
579 *
580 * Pointer to NULL, otherwise.
581 *
582 * Caller(s) : Application.
583 *
584 * Note(s) : (1) Pointers to variables that return values MUST be initialized PRIOR to all other
585 * validation or function handling in case of any error(s).
586 *
587 * (2) 'pmem_pool' variables MUST ALWAYS be accessed exclusively in critical sections.
588 *********************************************************************************************************
589 */
590 /*$PAGE*/
591 #if (LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED)
593  CPU_SIZE_T align,
594  CPU_SIZE_T *poctets_reqd,
595  LIB_ERR *perr)
596 {
597  MEM_POOL *pmem_pool_heap;
598  void *pmem_addr;
599  void *pmem_blk;
600  CPU_SIZE_T size_rem;
601  CPU_SIZE_T size_req;
602  CPU_SR_ALLOC();
603 
604  /* Init octets req'd for err (see Note #1). */
605  if (poctets_reqd != (CPU_SIZE_T *)0) {
606  *poctets_reqd = (CPU_SIZE_T )0;
607  }
608 
609  /* ------------ VALIDATE HEAP MEM ALLOC ----------- */
610 #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
611  if (size < 1) {
613  return ((void *)0);
614  }
615 #endif
616  if (align < 1) {
617  align = 1;
618  }
619 
620  /* -------------- ALLOC HEAP MEM BLK -------------- */
621  pmem_pool_heap = &Mem_PoolHeap;
622 
624 
625  pmem_addr = pmem_pool_heap->SegAddrNextAvail;
626  size_rem = pmem_pool_heap->SegSizeRem;
627  size_req = Mem_PoolSegCalcTotSize((void *)pmem_addr,
628  (CPU_SIZE_T)1, /* Alloc for single mem blk from heap. */
629  (CPU_SIZE_T)size,
630  (CPU_SIZE_T)align);
631  if (size_req > size_rem) { /* If req'd size > rem heap size, ... */
633  *perr = LIB_MEM_ERR_HEAP_EMPTY;
634  if (poctets_reqd != (CPU_SIZE_T *)0) {
635  *poctets_reqd = size_req - size_rem; /* ... rtn add'l heap size needed. */
636  }
637  return ((void *)0);
638  }
639 
640  pmem_blk = Mem_PoolSegAlloc(pmem_pool_heap, size, align);
641  if (pmem_blk == (void *)0) { /* If mem blk NOT avail from heap, ... */
643  *perr = LIB_MEM_ERR_HEAP_EMPTY;
644  if (poctets_reqd != (CPU_SIZE_T *)0) {
645  *poctets_reqd = size_req; /* ... rtn add'l heap size needed. */
646  }
647  return ((void *)0);
648  }
649 
651 
652  *perr = LIB_MEM_ERR_NONE;
653 
654  return (pmem_blk);
655 }
656 #endif
657 
658 
659 /*$PAGE*/
660 /*
661 *********************************************************************************************************
662 * Mem_PoolClr()
663 *
664 * Description : Clear a memory pool.
665 *
666 * Argument(s) : pmem_pool Pointer to a memory pool structure to clear (see Note #1).
667 *
668 * perr Pointer to variable that will receive the return error code from this function :
669 *
670 * LIB_MEM_ERR_NONE Memory pool successfully cleared.
671 * LIB_MEM_ERR_NULL_PTR Argument 'pmem_pool' passed a NULL pointer.
672 *
673 * Return(s) : none.
674 *
675 * Caller(s) : Application,
676 * Mem_PoolCreate().
677 *
678 * Note(s) : (1) Assumes 'pmem_pool' points to a valid memory pool (if non-NULL).
679 *********************************************************************************************************
680 */
681 
682 #if (LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED)
683 void Mem_PoolClr (MEM_POOL *pmem_pool,
684  LIB_ERR *perr)
685 {
686 
687  /* ------------------- VALIDATE PTR ------------------- */
688  if (pmem_pool == (MEM_POOL *)0) {
689  *perr = LIB_MEM_ERR_NULL_PTR;
690  return;
691  }
692 
693 
694  pmem_pool->Type = (LIB_MEM_TYPE)LIB_MEM_TYPE_NONE;
695  pmem_pool->SegPrevPtr = (MEM_POOL *)0;
696  pmem_pool->SegNextPtr = (MEM_POOL *)0;
697  pmem_pool->PoolPrevPtr = (MEM_POOL *)0;
698  pmem_pool->PoolNextPtr = (MEM_POOL *)0;
699  pmem_pool->PoolAddrStart = (void *)0;
700  pmem_pool->PoolAddrEnd = (void *)0;
701  pmem_pool->PoolPtrs = (void **)0;
702  pmem_pool->PoolSize = (CPU_SIZE_T )0;
703  pmem_pool->BlkAlign = (CPU_SIZE_T )0;
704  pmem_pool->BlkSize = (CPU_SIZE_T )0;
705  pmem_pool->BlkNbr = (CPU_SIZE_T )0;
706  pmem_pool->BlkIx = (MEM_POOL_IX )0;
707  pmem_pool->SegAddr = (void *)0;
708  pmem_pool->SegAddrNextAvail = (void *)0;
709  pmem_pool->SegSizeTot = (CPU_SIZE_T )0;
710  pmem_pool->SegSizeRem = (CPU_SIZE_T )0;
711 
712 
713  *perr = LIB_MEM_ERR_NONE;
714 }
715 #endif
716 
717 
718 /*$PAGE*/
719 /*
720 *********************************************************************************************************
721 * Mem_PoolCreate()
722 *
723 * Description : (1) Create a memory pool :
724 *
725 * (a) Create memory pool from heap or dedicated memory
726 * (b) Allocate memory pool memory blocks
727 * (c) Update memory pool table
728 * (d) Configure memory pool
729 *
730 *
731 * (2) Memory pools are indexed by the Memory Segments they use.
732 *
733 * (a) The memory pool table is composed by a two-dimensional list :
734 *
735 * (1) Memory segments manage the following memory segment/pool information :
736 *
737 * (A) Memory segment base address
738 * (B) Memory segment next available address
739 * (C) Memory segment total size
740 * (D) Memory segment remaining size
741 *
742 * (2) Memory pools share memory from memory segments but do NOT manage any memory
743 * segment information. To access the memory segment information, the head
744 * memory segment must be accessed.
745 *
746 * (b) In the diagram below, memory pools in vertical columns represent they share the same
747 * memory segment for the memory blocks they have. The heads of the memory pool are
748 * linked horizontally to form a memory pool table.
749 *
750 * (1) 'Mem_PoolTbl' points to the head of the Memory Pool table.
751 *
752 * (2) Memory Pools' 'SegPrevPtr' & 'SegNextPtr' doubly-link each memory segment to
753 * form the list of memory segments.
754 *
755 * (3) Memory Pools' 'PoolPrevPtr' & 'PoolNextPtr' doubly-link the memory pools of
756 * each memory segment.
757 *
758 * (c) New memory pools, which do not share a memory segment, are inserted in the Memory
759 * Segments Primary List. The point of insertion is such to keep ascended order by
760 * memory segment base address.
761 *
762 * (d) Memory pool pointers to memory blocks 'PoolPtrs' must be allocated for each created
763 * memory pool. These pointers are stored in the memory pool heap segment 'Mem_PoolHeap'.
764 *
765 * (1) A memory pool can also have its memory blocks allocated from the memory pool heap.
766 * 'pmem_base_addr' must be set to NULL & 'mem_size' must be set to (0) to create the
767 * memory pool.
768 *
769 *
770 * | |
771 * |<----------------------- Memory Segments ----------------------->|
772 * | (see Note #2a1) |
773 *
774 * Lowest Memory Segment Highest Memory Segment
775 * Base Address Base Address
776 * (see Note #2c) (see Note #2c)
777 *
778 * | SegNextPtr Heap Memory Pool |
779 * | (see Note #2b2) (see Note #2d) |
780 * | | |
781 * v | | v
782 * | v
783 * --- Head of Memory ------- ------- v ------- ------- -------
784 * ^ Pool Table --->| |------->| |------->| |------->| |------->| |
785 * | (see Note #2b1) | | | | | | | H | | |
786 * | | |<-------| |<-------| |<-------| E |<-------| |
787 * | | | | | ^ | | | A | | |
788 * | | | | | | | | | P | | |
789 * | | | | | | | | | | | |
790 * | ------- ------- | ------- ------- -------
791 * | | ^ | | ^
792 * | | | SegPrevPtr | |
793 * | v | (see Note #2b2) v |
794 * | ------- -------
795 * | | | |
796 * Memory Pools | | | |
797 * (see Note #2a2) | | | |
798 * | | | |
799 * | | | | |
800 * | ------- -------
801 * | | ^
802 * | PoolNextPtr ---> | | <--- PoolPrevPtr
803 * | (see Note #2b3) v | (see Note #2b3)
804 * | -------
805 * | | |
806 * | | |
807 * | | |
808 * | | |
809 * v | |
810 * --- -------
811 *
812 *$PAGE*
813 * Argument(s) : pmem_pool Pointer to a memory pool structure to create (see Note #3).
814 *
815 * pmem_base_addr Memory pool base address :
816 *
817 * (a) Null address Memory pool allocated from general-purpose heap.
818 * (b) Non-null address Memory pool allocated from dedicated memory
819 * specified by its base address.
820 *
821 * mem_size Size of memory pool segment (in octets).
822 *
823 * blk_nbr Number of memory pool blocks to create.
824 *
825 * blk_size Size of memory pool blocks to create (in octets).
826 *
827 * blk_align Alignment of memory pool blocks to create (in octets).
828 *
829 * poctets_reqd Pointer to a variable to ... :
830 *
831 * (a) Return the number of octets required to successfully
832 * allocate the memory pool, if any errors;
833 * (b) Return 0, otherwise.
834 *
835 * perr Pointer to variable that will receive the return error code from this function :
836 *
837 * LIB_MEM_ERR_NONE Memory pool successfully created.
838 *
839 * LIB_MEM_ERR_HEAP_NOT_FOUND Heap segment NOT found.
840 * LIB_MEM_ERR_HEAP_EMPTY Heap segment empty; NO available memory
841 * from heap.
842 * LIB_MEM_ERR_SEG_EMPTY Memory segment empty; NO available memory
843 * from segment for memory pools.
844 *
845 * LIB_MEM_ERR_INVALID_SEG_SIZE Invalid memory segment size.
846 * LIB_MEM_ERR_INVALID_SEG_OVERLAP Memory segment overlaps other memory
847 * segment(s) in memory pool table.
848 * LIB_MEM_ERR_INVALID_BLK_NBR Invalid memory pool number of blocks.
849 * LIB_MEM_ERR_INVALID_BLK_SIZE Invalid memory pool block size.
850 *
851 * ------- RETURNED BY Mem_PoolClr() : -------
852 * LIB_MEM_ERR_NULL_PTR Argument 'pmem_pool' passed a NULL pointer.
853 *
854 * Return(s) : none.
855 *
856 * Caller(s) : Application.
857 *
858 * Note(s) : (3) Assumes 'pmem_pool' points to a valid memory pool (if non-NULL).
859 *
860 * (4) Pointers to variables that return values MUST be initialized PRIOR to all other
861 * validation or function handling in case of any error(s).
862 *
863 * (5) 'pmem_pool' variables MUST ALWAYS be accessed exclusively in critical sections.
864 *********************************************************************************************************
865 */
866 
867 #if (LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED)
868 void Mem_PoolCreate (MEM_POOL *pmem_pool,
869  void *pmem_base_addr,
870  CPU_SIZE_T mem_size,
871  CPU_SIZE_T blk_nbr,
872  CPU_SIZE_T blk_size,
873  CPU_SIZE_T blk_align,
874  CPU_SIZE_T *poctets_reqd,
875  LIB_ERR *perr)
876 {
877  MEM_POOL *pmem_pool_heap;
878  MEM_POOL *pmem_pool_prev;
879  MEM_POOL *pmem_pool_next;
880  MEM_POOL *pmem_pool_blk;
881  void **ppool_ptr;
882  void *pmem_blk;
883  CPU_INT08U *pmem_addr_ptrs;
884  CPU_INT08U *pmem_addr_pool;
885  CPU_INT08U *pmem_base_addr_start;
886  CPU_INT08U *pmem_base_addr_end;
887  CPU_INT08U *pmem_seg_addr_start;
888  CPU_INT08U *pmem_seg_addr_end;
889  CPU_SIZE_T size_tot;
890  CPU_SIZE_T size_tot_ptrs;
891  CPU_SIZE_T size_tot_pool;
892  CPU_SIZE_T size_rem;
893  CPU_SIZE_T size_pool_ptrs;
894  CPU_SIZE_T blk_rem;
895  CPU_SIZE_T i;
896  CPU_SR_ALLOC();
897 
898 
899 /*$PAGE*/
900  /* Init octets req'd for err (see Note #4). */
901  if (poctets_reqd != (CPU_SIZE_T *)0) {
902  *poctets_reqd = (CPU_SIZE_T )0;
903  }
904 
905 
906  Mem_PoolClr(pmem_pool, perr); /* Init mem pool for err (see Note #4). */
907  if (*perr != LIB_MEM_ERR_NONE) {
908  return;
909  }
910 
911 
912  /* ----------- VALIDATE MEM POOL CREATE ----------- */
913 #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
914  if (pmem_base_addr != (void *)0) {
915  if (mem_size < 1) {
917  return;
918  }
919  }
920 
921  if (blk_nbr < 1) {
923  return;
924  }
925 
926  if (blk_size < 1) {
928  return;
929  }
930 #endif
931 
932  if (blk_align < 1) {
933  blk_align = 1;
934  }
935 
936  /* ------------ VALIDATE MEM POOL TBL ------------- */
937  if (Mem_PoolTbl == (MEM_POOL *)0) {
939  return;
940  }
941 
942 
943 
944 /*$PAGE*/
945  /* ---------------- CREATE MEM POOL --------------- */
946  pmem_pool_heap = (MEM_POOL *)&Mem_PoolHeap;
947 
949 
950  if (pmem_base_addr == (void *)0) { /* If no base addr, cfg mem pool from heap. */
951  pmem_pool_blk = pmem_pool_heap;
952  pmem_pool_prev = pmem_pool_heap;
953  pmem_pool_next = pmem_pool_heap;
954 
955  /* --------------- VALIDATE MEM SEG --------------- */
956  /* Calc tot mem size for mem pool ptrs. */
957  pmem_addr_ptrs = (CPU_INT08U *)pmem_pool_heap->SegAddrNextAvail;
958  size_tot_ptrs = Mem_PoolSegCalcTotSize((void *)pmem_addr_ptrs,
959  (CPU_SIZE_T)blk_nbr,
960  (CPU_SIZE_T)sizeof(void *),
961  (CPU_SIZE_T)sizeof(void *));
962  /* Calc tot mem size for mem blks. */
963  pmem_addr_pool = pmem_addr_ptrs + size_tot_ptrs; /* Adj next avail addr for mem pool blks. */
964  size_tot_pool = Mem_PoolSegCalcTotSize((void *)pmem_addr_pool,
965  (CPU_SIZE_T)blk_nbr,
966  (CPU_SIZE_T)blk_size,
967  (CPU_SIZE_T)blk_align);
968 
969  size_tot = size_tot_ptrs + size_tot_pool;
970  size_rem = pmem_pool_heap->SegSizeRem;
971 
972  if (size_tot > size_rem) { /* If tot size > rem size, ... */
974  *perr = LIB_MEM_ERR_HEAP_EMPTY;
975  if (poctets_reqd != (CPU_SIZE_T *)0) {
976  *poctets_reqd = size_tot - size_rem; /* ... rtn add'l heap size needed. */
977  }
978  return;
979  }
980 
981 
982  } else { /* Else cfg mem pool from dedicated mem. */
983  /* -------- SRCH ALL MEM SEGS FOR MEM POOL -------- */
984  pmem_base_addr_start = (CPU_INT08U *)pmem_base_addr;
985  pmem_base_addr_end = (CPU_INT08U *)pmem_base_addr + mem_size - 1;
986 
987  pmem_pool_blk = (MEM_POOL *)0;
988  pmem_pool_prev = (MEM_POOL *)0;
989  pmem_pool_next = Mem_PoolTbl;
990 
991  while (pmem_pool_next != (MEM_POOL *)0) { /* Srch tbl for mem seg with same base addr/size. */
992 
993  if ((pmem_base_addr == pmem_pool_next->SegAddr) &&
994  (mem_size == pmem_pool_next->SegSizeTot)) {
995 
996  pmem_pool_blk = pmem_pool_next;
997  pmem_pool_prev = pmem_pool_next;
998  break;
999 
1000  } else {
1001  pmem_seg_addr_start = (CPU_INT08U *)pmem_pool_next->SegAddr;
1002  pmem_seg_addr_end = (CPU_INT08U *)pmem_pool_next->SegAddr + pmem_pool_next->SegSizeTot - 1;
1003 
1004  /* Seg not found. */
1005  if (pmem_base_addr_end < pmem_seg_addr_start) {
1006  break;
1007 
1008  /* New mem seg overlaps cur mem seg. */
1009  } else if (((pmem_base_addr_start <= pmem_seg_addr_start) &&
1010  (pmem_base_addr_end >= pmem_seg_addr_start)) ||
1011  ((pmem_base_addr_start >= pmem_seg_addr_start) &&
1012  (pmem_base_addr_end <= pmem_seg_addr_end )) ||
1013  ((pmem_base_addr_start <= pmem_seg_addr_end ) &&
1014  (pmem_base_addr_end >= pmem_seg_addr_end ))) {
1017  return;
1018  }
1019  }
1020  /* If mem seg NOT found, adv to next mem seg. */
1021  pmem_pool_prev = pmem_pool_next;
1022  pmem_pool_next = pmem_pool_next->SegNextPtr;
1023  }
1024 
1025  if (pmem_pool_blk == (MEM_POOL *)0) { /* If mem seg NOT found, add new mem seg. */
1026  pmem_pool_blk = pmem_pool;
1027  pmem_pool->SegAddr = pmem_base_addr;
1028  pmem_pool->SegAddrNextAvail = pmem_base_addr;
1029  pmem_pool->SegSizeTot = mem_size;
1030  pmem_pool->SegSizeRem = mem_size;
1031  }
1032 
1033 /*$PAGE*/
1034  /* --------------- VALIDATE MEM SEG --------------- */
1035  /* Calc tot mem size for mem pool ptrs. */
1036  pmem_addr_ptrs = (CPU_INT08U *)pmem_pool_heap->SegAddrNextAvail;
1037  size_tot_ptrs = Mem_PoolSegCalcTotSize((void *)pmem_addr_ptrs,
1038  (CPU_SIZE_T)blk_nbr,
1039  (CPU_SIZE_T)sizeof(void *),
1040  (CPU_SIZE_T)sizeof(void *));
1041  size_rem = pmem_pool_heap->SegSizeRem;
1042 
1043  if (size_tot_ptrs > size_rem) { /* If ptr size > rem size, ... */
1045  *perr = LIB_MEM_ERR_HEAP_EMPTY;
1046  if (poctets_reqd != (CPU_SIZE_T *)0) {
1047  *poctets_reqd = size_tot_ptrs - size_rem; /* ... rtn add'l heap size needed. */
1048  }
1049  return;
1050  }
1051 
1052  /* Calc tot mem size for mem blks. */
1053  pmem_addr_pool = (CPU_INT08U *)pmem_pool_blk->SegAddrNextAvail;
1054  size_tot_pool = Mem_PoolSegCalcTotSize((void *)pmem_addr_pool,
1055  (CPU_SIZE_T)blk_nbr,
1056  (CPU_SIZE_T)blk_size,
1057  (CPU_SIZE_T)blk_align);
1058  size_rem = pmem_pool_blk->SegSizeRem;
1059 
1060  if (size_tot_pool > size_rem) { /* If tot size > rem size, ... */
1062  *perr = LIB_MEM_ERR_SEG_EMPTY;
1063  if (poctets_reqd != (CPU_SIZE_T *)0) {
1064  *poctets_reqd = size_tot_pool - size_rem; /* ... rtn add'l seg size needed. */
1065  }
1066  return;
1067  }
1068  }
1069 
1070 
1071  /* ---------------- ALLOC MEM BLKs ---------------- */
1072  size_pool_ptrs = blk_nbr * sizeof(void *);
1073  /* Alloc stk of ptrs for mem blks from heap. */
1074  ppool_ptr = (void **)Mem_PoolSegAlloc((MEM_POOL *)pmem_pool_heap,
1075  (CPU_SIZE_T)size_pool_ptrs,
1076  (CPU_SIZE_T)sizeof(void *));
1077  if (ppool_ptr == (void **)0) { /* If mem pool ptrs alloc failed, ... */
1078  size_rem = pmem_pool_heap->SegSizeRem;
1080  *perr = LIB_MEM_ERR_HEAP_EMPTY;
1081  if (poctets_reqd != (CPU_SIZE_T *)0) { /* ... rtn add'l heap size needed. */
1082  if (pmem_base_addr == (void *)0) {
1083  if (size_tot > size_rem) {
1084  *poctets_reqd = size_tot - size_rem;
1085  } else {
1086  *poctets_reqd = size_tot;
1087  }
1088  } else {
1089  if (size_pool_ptrs > size_rem) {
1090  *poctets_reqd = size_pool_ptrs - size_rem;
1091  } else {
1092  *poctets_reqd = size_pool_ptrs;
1093  }
1094  }
1095  }
1096  return;
1097  }
1098 
1099  for (i = 0; i < blk_nbr; i++) { /* Alloc mem blks from blk seg ptr. */
1100  pmem_blk = (void *)Mem_PoolSegAlloc(pmem_pool_blk, blk_size, blk_align);
1101  if (pmem_blk == (void *)0) { /* If mem blks alloc failed, ... */
1102  pmem_addr_pool = (CPU_INT08U *)pmem_pool_blk->SegAddrNextAvail;
1103  size_rem = (CPU_SIZE_T )pmem_pool_blk->SegSizeRem;
1105  *perr = LIB_MEM_ERR_SEG_EMPTY;
1106  if (poctets_reqd != (CPU_SIZE_T *)0) { /* ... rtn add'l seg size needed. */
1107  blk_rem = blk_nbr - i;
1108  size_tot = Mem_PoolSegCalcTotSize((void *)pmem_addr_pool,
1109  (CPU_SIZE_T)blk_rem,
1110  (CPU_SIZE_T)blk_size,
1111  (CPU_SIZE_T)blk_align);
1112  if (size_tot > size_rem) {
1113  *poctets_reqd = size_tot - size_rem;
1114  } else {
1115  *poctets_reqd = size_tot;
1116  }
1117  }
1118  return;
1119  }
1120  ppool_ptr[i] = pmem_blk;
1121  }
1122 
1123 
1124 /*$PAGE*/
1125  /* ------------- UPDATE MEM POOL TBL -------------- */
1126  if (pmem_pool_prev == pmem_pool_next) { /* Add new mem seg to list. */
1127 
1128  pmem_pool_next = pmem_pool_blk->PoolNextPtr;
1129  pmem_pool->PoolPrevPtr = pmem_pool_blk;
1130  pmem_pool->PoolNextPtr = pmem_pool_next;
1131  pmem_pool_blk->PoolNextPtr = pmem_pool;
1132  if (pmem_pool_next != (MEM_POOL *)0) {
1133  pmem_pool_next->PoolPrevPtr = pmem_pool;
1134  }
1135 
1136  } else { /* Add new mem pool to mem seg. */
1137 
1138  pmem_pool->SegPrevPtr = pmem_pool_prev;
1139  pmem_pool->SegNextPtr = pmem_pool_next;
1140 
1141  if (pmem_pool_prev != (MEM_POOL *)0) { /* Update prev mem pool link. */
1142  pmem_pool_prev->SegNextPtr = pmem_pool;
1143  } else {
1144  Mem_PoolTbl = pmem_pool; /* Update mem pool head. */
1145  }
1146 
1147  if (pmem_pool_next != (MEM_POOL *)0) { /* Update next mem pool link. */
1148  pmem_pool_next->SegPrevPtr = pmem_pool;
1149  }
1150  }
1151 
1152 
1153  /* ----------------- CFG MEM POOL ----------------- */
1154  pmem_pool->Type = (LIB_MEM_TYPE) LIB_MEM_TYPE_POOL;
1155  pmem_pool->PoolAddrStart = (void *) pmem_addr_pool;
1156  pmem_pool->PoolAddrEnd = (void *)(pmem_addr_pool + size_tot_pool - 1);
1157  pmem_pool->PoolPtrs = (void **) ppool_ptr;
1158  pmem_pool->PoolSize = (CPU_SIZE_T ) size_tot_pool;
1159  pmem_pool->BlkAlign = (CPU_SIZE_T ) blk_align;
1160  pmem_pool->BlkSize = (CPU_SIZE_T ) blk_size;
1161  pmem_pool->BlkNbr = (CPU_SIZE_T ) blk_nbr;
1162  pmem_pool->BlkIx = (MEM_POOL_IX ) blk_nbr;
1163 
1164 
1166 
1167  *perr = LIB_MEM_ERR_NONE;
1168 }
1169 #endif
1170 
1171 
1172 /*$PAGE*/
1173 /*
1174 *********************************************************************************************************
1175 * Mem_PoolBlkGet()
1176 *
1177 * Description : Get a memory block from memory pool.
1178 *
1179 * Argument(s) : pmem_pool Pointer to memory pool to get memory block from.
1180 *
1181 * size Size of requested memory (in octets).
1182 *
1183 * perr Pointer to variable that will receive the return error code from this function :
1184 *
1185 * LIB_MEM_ERR_NONE Memory block successfully returned.
1186 * LIB_MEM_ERR_POOL_EMPTY NO memory blocks available in memory pool.
1187 *
1188 * LIB_MEM_ERR_NULL_PTR Argument 'pmem_pool' passed a NULL pointer.
1189 * LIB_MEM_ERR_INVALID_POOL Invalid memory pool type.
1190 * LIB_MEM_ERR_INVALID_BLK_SIZE Invalid memory pool block size requested.
1191 * LIB_MEM_ERR_INVALID_BLK_IX Invalid memory pool block index.
1192 *
1193 * Return(s) : Pointer to memory block, if NO errors.
1194 *
1195 * Pointer to NULL, otherwise.
1196 *
1197 * Caller(s) : Application.
1198 *
1199 * Note(s) : (1) 'pmem_pool' variables MUST ALWAYS be accessed exclusively in critical sections.
1200 *********************************************************************************************************
1201 */
1202 
1203 #if (LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED)
1204 void *Mem_PoolBlkGet (MEM_POOL *pmem_pool,
1205  CPU_SIZE_T size,
1206  LIB_ERR *perr)
1207 {
1208  void *pmem_blk;
1209  CPU_SR_ALLOC();
1210 
1211  /* ------------ VALIDATE MEM POOL GET ------------- */
1212 #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
1213  if (pmem_pool == (MEM_POOL *)0) {
1214  *perr = LIB_MEM_ERR_NULL_PTR;
1215  return ((void *)0);
1216  }
1217 #endif
1218 
1220 
1221 #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
1222  if (pmem_pool->Type != LIB_MEM_TYPE_POOL) {
1224  *perr = LIB_MEM_ERR_INVALID_POOL;
1225  return ((void *)0);
1226  }
1227 
1228  if (size > pmem_pool->BlkSize) {
1231  return ((void *)0);
1232  }
1233 #endif
1234 
1235  if (pmem_pool->BlkIx < 1) {
1237  *perr = LIB_MEM_ERR_POOL_EMPTY;
1238  return ((void *)0);
1239  }
1240 
1241  if (pmem_pool->BlkIx > pmem_pool->BlkNbr) {
1244  return ((void *)0);
1245  }
1246 
1247  /* ------------ GET MEM BLK FROM POOL ------------- */
1248  pmem_pool->BlkIx--;
1249  pmem_blk = pmem_pool->PoolPtrs[pmem_pool->BlkIx];
1250 
1252 
1253  *perr = LIB_MEM_ERR_NONE;
1254 
1255  return (pmem_blk);
1256 }
1257 #endif
1258 
1259 
1260 /*$PAGE*/
1261 /*
1262 *********************************************************************************************************
1263 * Mem_PoolBlkFree()
1264 *
1265 * Description : Free a memory block to memory pool.
1266 *
1267 * Argument(s) : pmem_pool Pointer to memory pool to free memory block.
1268 *
1269 * pmem_blk Pointer to memory block address to free.
1270 *
1271 * perr Pointer to variable that will receive the return error code from this function :
1272 *
1273 * LIB_MEM_ERR_NONE Memory block successfully freed.
1274 * LIB_MEM_ERR_POOL_FULL ALL memory blocks already available in
1275 * memory pool.
1276 *
1277 * LIB_MEM_ERR_NULL_PTR Argument 'pmem_pool'/'pmem_blk' passed
1278 * a NULL pointer.
1279 * LIB_MEM_ERR_INVALID_POOL Invalid memory pool type.
1280 * LIB_MEM_ERR_INVALID_BLK_ADDR Invalid memory block address.
1281 * LIB_MEM_ERR_INVALID_BLK_ADDR_IN_POOL Memory block address already
1282 * in memory pool.
1283 *
1284 * Return(s) : none.
1285 *
1286 * Caller(s) : Application.
1287 *
1288 * Note(s) : (1) 'pmem_pool' variables MUST ALWAYS be accessed exclusively in critical sections.
1289 *********************************************************************************************************
1290 */
1291 /*$PAGE*/
1292 #if (LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED)
1293 void Mem_PoolBlkFree (MEM_POOL *pmem_pool,
1294  void *pmem_blk,
1295  LIB_ERR *perr)
1296 {
1297 #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
1298  CPU_BOOLEAN addr_valid;
1299  MEM_POOL_IX i;
1300 #endif
1301  CPU_SR_ALLOC();
1302 
1303  /* ------------ VALIDATE MEM POOL FREE ------------ */
1304 #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
1305  if (pmem_pool == (MEM_POOL *)0) {
1306  *perr = LIB_MEM_ERR_NULL_PTR;
1307  return;
1308  }
1309 
1310  if (pmem_blk == (void *)0) {
1311  *perr = LIB_MEM_ERR_NULL_PTR;
1312  return;
1313  }
1314 #endif
1315 
1317 
1318 #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
1319  if (pmem_pool->Type != LIB_MEM_TYPE_POOL) {
1321  *perr = LIB_MEM_ERR_INVALID_POOL;
1322  return;
1323  }
1324 #endif
1325 
1326  if (pmem_pool->BlkIx >= pmem_pool->BlkNbr) {
1328  *perr = LIB_MEM_ERR_POOL_FULL;
1329  return;
1330  }
1331 
1332 #if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
1333  addr_valid = Mem_PoolBlkIsValidAddr(pmem_pool, pmem_blk);
1334  if (addr_valid != DEF_OK) {
1337  return;
1338  }
1339 
1340  for (i = 0; i < pmem_pool->BlkIx; i++) {
1341  if (pmem_blk == pmem_pool->PoolPtrs[i]) {
1344  return;
1345  }
1346  }
1347 #endif
1348 
1349  /* ------------- FREE MEM BLK TO POOL ------------- */
1350  pmem_pool->PoolPtrs[pmem_pool->BlkIx] = pmem_blk;
1351  pmem_pool->BlkIx++;
1352 
1354 
1355  *perr = LIB_MEM_ERR_NONE;
1356 }
1357 #endif
1358 
1359 
1360 /*$PAGE*/
1361 /*
1362 *********************************************************************************************************
1363 *********************************************************************************************************
1364 * LOCAL FUNCTIONS
1365 *********************************************************************************************************
1366 *********************************************************************************************************
1367 */
1368 
1369 /*
1370 *********************************************************************************************************
1371 * Mem_PoolBlkIsValidAddr()
1372 *
1373 * Description : Calculates if a given memory block address is valid for the memory pool.
1374 *
1375 * Argument(s) : pmem_pool Pointer to memory pool structure to validate memory block address.
1376 * --------- Argument validated in Mem_PoolBlkFree().
1377 *
1378 * pmem_blk Pointer to memory block address to validate.
1379 * -------- Argument validated in Mem_PoolBlkFree().
1380 *
1381 * Return(s) : DEF_YES, if valid memory pool block address.
1382 *
1383 * DEF_NO, otherwise.
1384 *
1385 * Caller(s) : Mem_PoolBlkFree().
1386 *
1387 * Note(s) : none.
1388 *********************************************************************************************************
1389 */
1390 
1391 #if ((LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED) && \
1392  (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED))
1393 static CPU_BOOLEAN Mem_PoolBlkIsValidAddr (MEM_POOL *pmem_pool,
1394  void *pmem_blk)
1395 {
1396  CPU_INT08U *ppool_addr_first;
1397  void *ppool_addr_start;
1398  void *ppool_addr_end;
1399  CPU_SIZE_T align_offset;
1400  CPU_SIZE_T blk_align;
1401  CPU_SIZE_T blk_align_offset;
1402  CPU_SIZE_T blk_size;
1403  CPU_SIZE_T mem_align;
1404  CPU_SIZE_T mem_align_offset;
1405  CPU_SIZE_T mem_diff;
1406  CPU_BOOLEAN addr_valid;
1407 
1408 
1409  ppool_addr_start = pmem_pool->PoolAddrStart;
1410  ppool_addr_end = pmem_pool->PoolAddrEnd;
1411 
1412  if ((pmem_blk < ppool_addr_start) ||
1413  (pmem_blk > ppool_addr_end)) {
1414  return (DEF_NO);
1415  }
1416 
1417  blk_align = (CPU_SIZE_T)pmem_pool->BlkAlign;
1418  align_offset = (CPU_SIZE_T)((CPU_ADDR)ppool_addr_start % blk_align);
1419  if (align_offset != 0) {
1420  mem_align_offset = blk_align - align_offset;
1421  } else {
1422  mem_align_offset = 0;
1423  }
1424 
1425  blk_size = pmem_pool->BlkSize;
1426  align_offset = blk_size % blk_align;
1427  if (align_offset != 0) {
1428  blk_align_offset = blk_align - align_offset;
1429  } else {
1430  blk_align_offset = 0;
1431  }
1432 
1433  ppool_addr_first = (CPU_INT08U *)((CPU_INT08U *)ppool_addr_start + mem_align_offset);
1434  mem_diff = (CPU_SIZE_T )((CPU_INT08U *)pmem_blk - ppool_addr_first);
1435  mem_align = (CPU_SIZE_T )( blk_size + blk_align_offset);
1436 
1437  addr_valid = ((mem_diff % mem_align) == 0) ? DEF_YES : DEF_NO;
1438 
1439  return (addr_valid);
1440 }
1441 #endif
1442 
1443 
1444 /*$PAGE*/
1445 /*
1446 *********************************************************************************************************
1447 * Mem_PoolSegCalcTotSize()
1448 *
1449 * Description : (1) Calculates total memory segment size for number of blocks with specific size & alignment :
1450 *
1451 *
1452 * ----- ====================== ---
1453 * ^ Mem Addr ---> | / / / / / / | ^
1454 * | (see Note #1a) | / / / / / / /| | Mem Align Offset
1455 * | |/ / / / / / / | | (see Notes #1e & #2a)
1456 * | | / / / / / / | v
1457 * | ====================== ---
1458 * | | | ^
1459 * | | | |
1460 * | | Mem Blk #1 | | Blk Size
1461 * | | | | (see Note #1c)
1462 * | | | v
1463 * | ---------------------- ---
1464 * | | / / / / / / | ^
1465 * | | / / / / / / /| | Blk Align Offset
1466 * | |/ / / / / / / | | (see Notes #1f & #2b)
1467 * | | / / / / / / | v
1468 * | ====================== ---
1469 * | . |
1470 * Total Size | . |
1471 * (see Note #2c) | . |
1472 * ====================== ---
1473 * | | | ^
1474 * | | | |
1475 * | | Mem Blk #N - 1 | | Blk Size
1476 * | | | | (see Note #1c)
1477 * | | | v
1478 * | ---------------------- ---
1479 * | | / / / / / / | ^
1480 * | | / / / / / / /| | Blk Align Offset
1481 * | |/ / / / / / / | | (see Notes #1f & #2b)
1482 * | | / / / / / / | v
1483 * | ====================== ---
1484 * | | | ^
1485 * | | | |
1486 * | | Mem Blk #N | | Blk Size
1487 * | | | | (see Note #1c)
1488 * v | | v
1489 * ----- ====================== ---
1490 *
1491 * where
1492 *
1493 * (a) Mem Addr Memory address of the beginning of the memory block ('pmem_addr')
1494 *
1495 * (b) N Number of memory blocks to allocate ('blk_nbr')
1496 *
1497 * (c) Blk Size Size of memory block to allocate ('blk_size')
1498 *
1499 * (d) Align Required block memory alignment ('blk_align')
1500 *
1501 * (e) Mem Align Offset Offset required to align first memory block
1502 *
1503 * (f) Blk Align Offset Offset required to align every memory block
1504 *
1505 *
1506 * (2) The total size is calculated based on the following equations :
1507 *
1508 * { (1) Align - (Mem Addr % Align) , if memory address is not aligned
1509 * (a) Mem Align Offset = {
1510 * { (2) 0 , if memory address is aligned
1511 *
1512 *
1513 * { (1) Align - (Size % Align) , if memory block is not aligned
1514 * (b) Blk Align Offset = {
1515 * { (2) 0 , if memory block is aligned
1516 *
1517 *
1518 * (c) Total Size = Mem Align Offset
1519 * + ((Blk Size + Blk Align Offset) * (N - 1))
1520 * + Blk Size
1521 *
1522 *$PAGE*
1523 * Argument(s) : pmem_addr Memory address of the beginning of the memory block.
1524 *
1525 * blk_nbr Number of memory blocks to allocate.
1526 *
1527 * blk_size Size of memory block to allocate.
1528 *
1529 * blk_align Required block memory alignment (in octets).
1530 * --------- Argument validated in Mem_HeapAlloc(),
1531 * Mem_PoolCreate().
1532 *
1533 * Return(s) : Total size of memory segment used to allocate the number of blocks.
1534 *
1535 * Caller(s) : Mem_HeapAlloc(),
1536 * Mem_PoolCreate().
1537 *
1538 * Note(s) : none.
1539 *********************************************************************************************************
1540 */
1541 
1542 #if (LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED)
1543 static CPU_SIZE_T Mem_PoolSegCalcTotSize (void *pmem_addr,
1544  CPU_SIZE_T blk_nbr,
1545  CPU_SIZE_T blk_size,
1546  CPU_SIZE_T blk_align)
1547 {
1548  CPU_SIZE_T align_offset;
1549  CPU_SIZE_T mem_align_offset;
1550  CPU_SIZE_T blk_align_offset;
1551  CPU_SIZE_T size_tot;
1552 
1553  /* Calc mem align (see Note #2a). */
1554  align_offset = (CPU_ADDR)pmem_addr % blk_align;
1555  if (align_offset != 0) {
1556  mem_align_offset = blk_align - align_offset;
1557  } else {
1558  mem_align_offset = 0;
1559  }
1560  /* Calc blk align (see Note #2b). */
1561  align_offset = blk_size % blk_align;
1562  if (align_offset != 0) {
1563  blk_align_offset = blk_align - align_offset;
1564  } else {
1565  blk_align_offset = 0;
1566  }
1567  /* Calc tot size (see Note #2c). */
1568  size_tot = mem_align_offset + ((blk_size + blk_align_offset) * (blk_nbr - 1)) + blk_size;
1569 
1570  return (size_tot);
1571 }
1572 #endif
1573 
1574 
1575 /*$PAGE*/
1576 /*
1577 *********************************************************************************************************
1578 * Mem_PoolSegAlloc()
1579 *
1580 * Description : Allocates memory from specific segment.
1581 *
1582 * Argument(s) : pmem_pool Pointer to memory pool structure containing segment information.
1583 * --------- Argument validated in Mem_HeapAlloc(),
1584 * Mem_PoolCreate().
1585 *
1586 * size Size of memory to allocate.
1587 * ---- Argument validated in Mem_HeapAlloc(),
1588 * Mem_PoolCreate().
1589 *
1590 * align Required starting memory alignment (in octets).
1591 * ----- Argument validated in Mem_HeapAlloc(),
1592 * Mem_PoolCreate().
1593 *
1594 * Return(s) : Pointer to allocated memory, if NO errors.
1595 *
1596 * Pointer to NULL, otherwise.
1597 *
1598 * Caller(s) : Mem_HeapAlloc(),
1599 * Mem_PoolCreate().
1600 *
1601 * Note(s) : (1) Allocated memory from the specific segment is NEVER freed after allocation.
1602 *********************************************************************************************************
1603 */
1604 
1605 #if (LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED)
1606 static void *Mem_PoolSegAlloc (MEM_POOL *pmem_pool,
1607  CPU_SIZE_T size,
1608  CPU_SIZE_T align)
1609 {
1610  CPU_INT08U *pmem_addr;
1611  CPU_SIZE_T mem_align;
1612  CPU_SIZE_T align_offset;
1613  CPU_SIZE_T size_tot;
1614  CPU_SIZE_T size_rem;
1615  CPU_SR_ALLOC();
1616 
1617 
1619  pmem_addr = (CPU_INT08U *)pmem_pool->SegAddrNextAvail;
1620 
1621  mem_align = (CPU_SIZE_T )((CPU_ADDR)pmem_addr % align); /* Calc mem align. */
1622 
1623  if (mem_align != 0) {
1624  align_offset = align - mem_align;
1625  } else {
1626  align_offset = 0;
1627  }
1628 
1629  size_tot = align_offset + size;
1630  size_rem = pmem_pool->SegSizeRem;
1631 
1632  if (size_tot > size_rem) { /* If insufficiemt mem seg size rem, ... */
1634  return ((void *)0); /* ... rtn NULL. */
1635  }
1636 
1637  pmem_addr += align_offset; /* Adj mem addr align. */
1638 
1639  pmem_pool->SegAddrNextAvail = pmem_addr + size; /* Adv next avail addr. */
1640  pmem_pool->SegSizeRem -= size_tot; /* Adj rem mem seg size. */
1641 
1643 
1644  return ((void *)pmem_addr);
1645 }
1646 #endif
1647