| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

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
100 CPU_INT08U Mem_Heap[LIB_MEM_CFG_HEAP_SIZE]; /* Mem heap. */
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 ------------- */
190 Mem_PoolTbl = &Mem_PoolHeap;
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;
477 CPU_BOOLEAN mem_cmp;
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)
592 void *Mem_HeapAlloc (CPU_SIZE_T size,
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) {
622 *perr = LIB_MEM_ERR_INVALID_MEM_SIZE;
623 return ((void *)0);
624 }
625
626 if (align < 1) {
627 *perr = LIB_MEM_ERR_INVALID_MEM_ALIGN;
628 return ((void *)0);
629 }
630 #endif
631
632 /* -------------- ALLOC HEAP MEM BLK -------------- */
633 pmem_pool_heap = &Mem_PoolHeap;
634
635 CPU_CRITICAL_ENTER();
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, ... */
645 CPU_CRITICAL_EXIT();
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, ... */
653 CPU_CRITICAL_EXIT();
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, ... */
661 CPU_CRITICAL_EXIT();
662 *poctets_reqd = size_req; /* ... rtn add'l heap size needed. */
663 *perr = LIB_MEM_ERR_HEAP_EMPTY;
664 return ((void *)0);
665 }
666
667 CPU_CRITICAL_EXIT();
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) {
958 *perr = LIB_MEM_ERR_INVALID_SEG_SIZE;
959 return;
960 }
961 }
962
963 if (blk_nbr < 1) {
964 *perr = LIB_MEM_ERR_INVALID_BLK_NBR;
965 return;
966 }
967
968 if (blk_size < 1) {
969 *perr = LIB_MEM_ERR_INVALID_BLK_SIZE;
970 return;
971 }
972
973 if (blk_align < 1) {
974 *perr = LIB_MEM_ERR_INVALID_BLK_ALIGN;
975 return;
976 }
977 #endif
978
979
980 /* ------------ VALIDATE MEM POOL TBL ------------- */
981 if (Mem_PoolTbl == (MEM_POOL *)0) {
982 *perr = LIB_MEM_ERR_HEAP_NOT_FOUND;
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
993 CPU_CRITICAL_ENTER();
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, ... */
1009 CPU_CRITICAL_EXIT();
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, ... */
1022 CPU_CRITICAL_EXIT();
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)) {
1033 CPU_CRITICAL_EXIT();
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, ... */
1041 CPU_CRITICAL_EXIT();
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. */
1055 CPU_CRITICAL_EXIT();
1056 *perr = LIB_MEM_ERR_INVALID_BLK_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 ))) {
1089 CPU_CRITICAL_EXIT();
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, ... */
1117 CPU_CRITICAL_EXIT();
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, ... */
1125 CPU_CRITICAL_EXIT();
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, ... */
1139 CPU_CRITICAL_EXIT();
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, ... */
1147 CPU_CRITICAL_EXIT();
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;
1164 CPU_CRITICAL_EXIT();
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;
1188 CPU_CRITICAL_EXIT();
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
1248 CPU_CRITICAL_EXIT();
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. */
1309 *perr = LIB_MEM_ERR_INVALID_BLK_SIZE;
1310 return ((void *)0);
1311 }
1312 #endif
1313
1314 CPU_CRITICAL_ENTER();
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. */
1318 CPU_CRITICAL_EXIT();
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. */
1324 CPU_CRITICAL_EXIT();
1325 *perr = LIB_MEM_ERR_INVALID_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. */
1333 CPU_CRITICAL_EXIT();
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. */
1339 CPU_CRITICAL_EXIT();
1340 *perr = LIB_MEM_ERR_INVALID_BLK_IX;
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
1348 CPU_CRITICAL_EXIT();
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
1420 CPU_CRITICAL_ENTER();
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. */
1424 CPU_CRITICAL_EXIT();
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) {
1431 CPU_CRITICAL_EXIT();
1432 *perr = LIB_MEM_ERR_INVALID_BLK_ADDR;
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]) {
1438 CPU_CRITICAL_EXIT();
1439 *perr = LIB_MEM_ERR_INVALID_BLK_ADDR_IN_POOL;
1440 return;
1441 }
1442 }
1443 #endif
1444
1445 if (pmem_pool->BlkIx >= pmem_pool->BlkNbr) { /* Validate mem pool NOT already full. */
1446 CPU_CRITICAL_EXIT();
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
1455 CPU_CRITICAL_EXIT();
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