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