📄 lib_mem.c
字号:
* | | | | | | | | | P | | |
* | | | | | | | | | | | |
* | ------- ------- | ------- ------- -------
* | | ^ | | ^
* | | | SegPrevPtr | |
* | v | (see Note #2b2) v |
* | ------- -------
* | | | |
* Memory Pools | | | |
* (see Note #2a2) | | | |
* | | | |
* | | | | |
* | ------- -------
* | | ^
* | PoolNextPtr ---> | | <--- PoolPrevPtr
* | (see Note #2b3) v | (see Note #2b3)
* | -------
* | | |
* | | |
* | | |
* | | |
* v | |
* --- -------
*
*$PAGE*
* Argument(s) : pmem_pool Pointer to a memory pool structure to create (see Note #3).
*
* pmem_base_addr Memory pool base address :
*
* (a) Null address Memory pool allocated from general-purpose heap.
* (b) Non-null address Memory pool allocated from dedicated memory
* specified by its base address.
*
* mem_size Size of memory pool segment (in octets).
*
* blk_nbr Number of memory pool blocks to create.
*
* blk_size Size of memory pool blocks to create (in octets).
*
* blk_align Alignment of memory pool blocks to specific word boundary (in octets).
*
* poctets_reqd Optional pointer to a variable to ... :
*
* (a) Return the number of octets required to successfully
* allocate the memory pool, if any error(s);
* (b) Return 0, otherwise.
*
* perr Pointer to variable that will receive the return error code from this function :
*
* LIB_MEM_ERR_NONE Memory pool successfully created.
*
* LIB_MEM_ERR_HEAP_NOT_FOUND Heap segment NOT found.
* LIB_MEM_ERR_HEAP_EMPTY Heap segment empty; NOT enough available
* memory from heap.
* LIB_MEM_ERR_HEAP_OVF Requested memory overflows heap memory.
* LIB_MEM_ERR_SEG_EMPTY Memory segment empty; NOT enough available
* memory from segment for memory pools.
* LIB_MEM_ERR_SEG_OVF Requested memory overflows segment memory.
*
* LIB_MEM_ERR_INVALID_SEG_SIZE Invalid memory segment size.
* LIB_MEM_ERR_INVALID_SEG_OVERLAP Memory segment overlaps other memory
* segment(s) in memory pool table.
* LIB_MEM_ERR_INVALID_BLK_NBR Invalid memory pool number of blocks.
* LIB_MEM_ERR_INVALID_BLK_SIZE Invalid memory pool block size.
* LIB_MEM_ERR_INVALID_BLK_ALIGN Invalid memory pool block alignment.
*
* ------- RETURNED BY Mem_PoolClr() : -------
* LIB_MEM_ERR_NULL_PTR Argument 'pmem_pool' passed a NULL pointer.
*
* Return(s) : none.
*
* Caller(s) : Application.
*
* Note(s) : (3) Assumes 'pmem_pool' points to a valid memory pool (if non-NULL).
*
* (4) Pointers to variables that return values MUST be initialized PRIOR to all other
* validation or function handling in case of any error(s).
*
* (5) 'pmem_pool' variables MUST ALWAYS be accessed exclusively in critical sections.
*********************************************************************************************************
*/
/*$PAGE*/
#if (LIB_MEM_CFG_ALLOC_EN == DEF_ENABLED)
void Mem_PoolCreate (MEM_POOL *pmem_pool,
void *pmem_base_addr,
CPU_SIZE_T mem_size,
CPU_SIZE_T blk_nbr,
CPU_SIZE_T blk_size,
CPU_SIZE_T blk_align,
CPU_SIZE_T *poctets_reqd,
LIB_ERR *perr)
{
MEM_POOL *pmem_pool_heap;
MEM_POOL *pmem_pool_prev;
MEM_POOL *pmem_pool_next;
MEM_POOL *pmem_pool_blk;
void **ppool_ptr;
void *pmem_blk;
CPU_INT08U *pmem_addr_ptrs;
CPU_INT08U *pmem_addr_pool;
CPU_INT08U *pmem_base_addr_start;
CPU_INT08U *pmem_base_addr_end;
CPU_INT08U *pmem_seg_addr_start;
CPU_INT08U *pmem_seg_addr_end;
CPU_SIZE_T octets_reqd_unused;
CPU_SIZE_T size_tot;
CPU_SIZE_T size_tot_ptrs;
CPU_SIZE_T size_tot_pool;
CPU_SIZE_T size_rem;
CPU_SIZE_T size_pool_ptrs;
CPU_SIZE_T blk_rem;
CPU_SIZE_T i;
CPU_SR_ALLOC();
#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED) /* ------------- VALIDATE RTN ERR PTR ------------- */
if (perr == (LIB_ERR *)0) {
CPU_SW_EXCEPTION(;);
}
#endif
/* ------------ VALIDATE RTN OCTETS PTR ----------- */
if (poctets_reqd == (CPU_SIZE_T *) 0) { /* If NOT avail, ... */
poctets_reqd = (CPU_SIZE_T *)&octets_reqd_unused; /* ... re-cfg NULL rtn ptr to unused local var. */
(void)&octets_reqd_unused; /* Prevent possible 'variable unused' warning. */
}
*poctets_reqd = 0u; /* Init octets req'd for err (see Note #4). */
Mem_PoolClr(pmem_pool, perr); /* Init mem pool for err (see Note #4). */
if (*perr != LIB_MEM_ERR_NONE) {
return;
}
/* ----------- VALIDATE MEM POOL CREATE ----------- */
#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
if (pmem_base_addr != (void *)0) {
if (mem_size < 1) {
*perr = LIB_MEM_ERR_INVALID_SEG_SIZE;
return;
}
}
if (blk_nbr < 1) {
*perr = LIB_MEM_ERR_INVALID_BLK_NBR;
return;
}
if (blk_size < 1) {
*perr = LIB_MEM_ERR_INVALID_BLK_SIZE;
return;
}
if (blk_align < 1) {
*perr = LIB_MEM_ERR_INVALID_BLK_ALIGN;
return;
}
#endif
/* ------------ VALIDATE MEM POOL TBL ------------- */
if (Mem_PoolTbl == (MEM_POOL *)0) {
*perr = LIB_MEM_ERR_HEAP_NOT_FOUND;
return;
}
/*$PAGE*/
/* ---------------- CREATE MEM POOL --------------- */
pmem_pool_heap = (MEM_POOL *)&Mem_PoolHeap;
size_tot = (CPU_SIZE_T) 0u;
CPU_CRITICAL_ENTER();
if (pmem_base_addr == (void *)0) { /* If no base addr, cfg mem pool from heap. */
pmem_pool_blk = pmem_pool_heap;
pmem_pool_prev = pmem_pool_heap;
pmem_pool_next = pmem_pool_heap;
/* --------------- VALIDATE MEM SEG --------------- */
/* Calc tot mem size for mem pool ptrs. */
pmem_addr_ptrs = (CPU_INT08U *)pmem_pool_heap->SegAddrNextAvail;
size_tot_ptrs = Mem_PoolSegCalcTotSize((void *)pmem_addr_ptrs,
(CPU_SIZE_T)blk_nbr,
(CPU_SIZE_T)sizeof(void *),
(CPU_SIZE_T)sizeof(void *));
#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
if (size_tot_ptrs < 1) { /* If heap ovf, ... */
CPU_CRITICAL_EXIT();
*perr = LIB_MEM_ERR_HEAP_OVF; /* ... rtn err but add'l heap size NOT avail. */
return;
}
#endif
/* Calc tot mem size for mem blks. */
pmem_addr_pool = pmem_addr_ptrs + size_tot_ptrs; /* Adj next avail addr for mem pool blks. */
size_tot_pool = Mem_PoolSegCalcTotSize((void *)pmem_addr_pool,
(CPU_SIZE_T)blk_nbr,
(CPU_SIZE_T)blk_size,
(CPU_SIZE_T)blk_align);
#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
if (size_tot_pool < 1) { /* If heap ovf, ... */
CPU_CRITICAL_EXIT();
*perr = LIB_MEM_ERR_HEAP_OVF; /* ... rtn err but add'l heap size NOT avail. */
return;
}
#endif
size_tot = size_tot_ptrs + size_tot_pool;
#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
if ((size_tot < size_tot_ptrs) || /* If heap ovf, ... */
(size_tot < size_tot_pool)) {
CPU_CRITICAL_EXIT();
*perr = LIB_MEM_ERR_HEAP_OVF; /* ... rtn err but add'l heap size NOT avail. */
return;
}
#endif
size_rem = pmem_pool_heap->SegSizeRem;
if (size_tot > size_rem) { /* If tot size > rem size, ... */
CPU_CRITICAL_EXIT();
*poctets_reqd = size_tot - size_rem; /* ... rtn add'l heap size needed. */
*perr = LIB_MEM_ERR_HEAP_EMPTY;
return;
}
/*$PAGE*/
} else { /* Else cfg mem pool from dedicated mem. */
/* -------- SRCH ALL MEM SEGS FOR MEM POOL -------- */
pmem_base_addr_start = (CPU_INT08U *)pmem_base_addr;
pmem_base_addr_end = (CPU_INT08U *)pmem_base_addr + mem_size - 1;
#if (LIB_MEM_CFG_ARG_CHK_EXT_EN == DEF_ENABLED)
if (pmem_base_addr_end < pmem_base_addr_start) { /* Chk ovf of end addr. */
CPU_CRITICAL_EXIT();
*perr = LIB_MEM_ERR_INVALID_BLK_ADDR;
return;
}
#endif
pmem_pool_blk = (MEM_POOL *)0;
pmem_pool_prev = (MEM_POOL *)0;
pmem_pool_next = Mem_PoolTbl;
while (pmem_pool_next != (MEM_POOL *)0) { /* Srch tbl for mem seg with same base addr/size. */
if ((pmem_base_addr == pmem_pool_next->SegAddr) && /* If same base addr/size found, ... */
(mem_size == pmem_pool_next->SegSizeTot)) {
pmem_pool_blk = pmem_pool_next;
pmem_pool_prev = pmem_pool_next;
break; /* ... prev mem seg found in tbl. */
} else {
pmem_seg_addr_start = (CPU_INT08U *)pmem_pool_next->SegAddr;
pmem_seg_addr_end = (CPU_INT08U *)pmem_pool_next->SegAddr + pmem_pool_next->SegSizeTot - 1;
if (pmem_base_addr_end < pmem_seg_addr_start) { /* If mem seg addr/size prior to next mem seg, ... */
break; /* ... new mem seg NOT avail in tbl. */
/* If mem seg overlaps prev mem seg(s) in tbl, ... */
} else if (((pmem_base_addr_start <= pmem_seg_addr_start) &&
(pmem_base_addr_end >= pmem_seg_addr_start)) ||
((pmem_base_addr_start >= pmem_seg_addr_start) &&
(pmem_base_addr_end <= pmem_seg_addr_end )) ||
((pmem_base_addr_start <= pmem_seg_addr_end ) &&
(pmem_base_addr_end >= pmem_seg_addr_end ))) {
CPU_CRITICAL_EXIT();
*perr = LIB_MEM_ERR_INVALID_SEG_OVERLAP; /* ... rtn err. */
return;
}
}
/* If mem seg NOT found, adv to next mem seg. */
pmem_pool_prev = pmem_pool_next;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -