?? zl5011xmm.c
字號:
zl5011xMmAlloc
Description:
A memory area is allocated from the heap. A table in the device structure
is used to track these memory allocations. The size of the table is fixed (to
avoid dynamic allocation).
A very simple algorithm is used, which just allocates from the start of the heap.
A list in the structure is used to track the allocations, and to track memory
being free抎 and released.
Array in structure contains
pBlockStart
pBlockEnd
iNextBlock
iPrevBlock
the last block in chain is 'labelled' with iNextBlock = zero.
Inputs:
zl5011xParams Pointer to the structure for this device instance
allocSize size of the memory to allocate
Outputs:
pMemory address of allocated block.
Returns:
zlStatusE
Remarks:
see also zl5011xMmFree()
Memory is allocated in 8 byte chunks and an allocation will be aligned to
an 8 byte boundary. The allocation size is rounded up to the next 8 bytes.
*******************************************************************************/
extern zlStatusE zl5011xMmAlloc(zl5011xParamsS *zl5011xParams, Uint32T allocSize, Uint32T *pMemory)
{
zlStatusE status = ZL5011X_OK;
Uint32T size = 0;
/* index variables for accessing the allocation table */
Uint32T iNew = 0, iExisting, iNext;
Uint32T temp;
ZL5011X_TRACE(ZL5011X_MM_FN_ID, "zl5011xMmAlloc: size %08X", allocSize, 0, 0, 0, 0, 0);
if ((zl5011xParams->packetMemory.heapStartAddress == (Uint32T)ZL5011X_NOT_INITIALISED) ||
(zl5011xParams->packetMemory.heapEndAddress == (Uint32T)ZL5011X_NOT_INITIALISED))
{
status = ZL5011X_ERROR;
}
if (status == ZL5011X_OK)
{
/* round up the requested alloc size to a multiple of 8 bytes */
size = (allocSize + ZL5011X_MM_GRANULARITY_MASK) & ~ZL5011X_MM_GRANULARITY_MASK;
iNew = 0;
/* find free item in array by looking for pStart = zero */
while(iNew < ZL5011X_MEMORY_NUM_HEAP_ALLOCS)
{
if (zl5011xParams->packetMemory.allocTable[iNew].pBlockStart == 0)
{
break;
}
iNew++;
}
if (iNew == ZL5011X_MEMORY_NUM_HEAP_ALLOCS)
{
/* we reached the end */
status = ZL5011X_PACKET_MEMORY_FAIL;
}
}
/* find free area in memory */
iExisting = 0;
while((status == ZL5011X_OK) && (iExisting < ZL5011X_MEMORY_NUM_HEAP_ALLOCS))
{
iNext = zl5011xParams->packetMemory.allocTable[iExisting].iNextBlock;
/* detect last block to be allocated with iNext = zero */
if (iNext == 0)
{
/* see if there is room for New block */
temp = zl5011xParams->packetMemory.heapEndAddress -
zl5011xParams->packetMemory.allocTable[iExisting].pBlockEnd;
if (temp < size)
{
status = ZL5011X_PACKET_MEMORY_FAIL;
}
break;
}
/* detect if there is room between this existing block and next */
if ((zl5011xParams->packetMemory.allocTable[zl5011xParams->packetMemory.allocTable[iExisting].iNextBlock].pBlockStart -
zl5011xParams->packetMemory.allocTable[iExisting].pBlockEnd) > size)
{
break;
}
/* try the next block in the chain */
iExisting = iNext;
}
/* check for end of existing blocks but no room found */
if (status == ZL5011X_OK)
{
if (iExisting == ZL5011X_MEMORY_NUM_HEAP_ALLOCS)
{
status = ZL5011X_PACKET_MEMORY_FAIL;
}
}
/* place new block */
if (status == ZL5011X_OK)
{
/* place new block above existing block */
zl5011xParams->packetMemory.allocTable[iNew].pBlockStart = zl5011xParams->packetMemory.allocTable[iExisting].pBlockEnd + 1;
zl5011xParams->packetMemory.allocTable[iNew].pBlockEnd = zl5011xParams->packetMemory.allocTable[iExisting].pBlockEnd + size;
zl5011xParams->packetMemory.allocTable[iNew].iNextBlock = zl5011xParams->packetMemory.allocTable[iExisting].iNextBlock;
zl5011xParams->packetMemory.allocTable[iNew].iPrevBlock = iExisting;
zl5011xParams->packetMemory.allocTable[zl5011xParams->packetMemory.allocTable[iExisting].iNextBlock].iPrevBlock = iNew;
zl5011xParams->packetMemory.allocTable[iExisting].iNextBlock = iNew;
/* output pointer to allocated block */
*pMemory = zl5011xParams->packetMemory.allocTable[iNew].pBlockStart;
ZL5011X_TRACE(ZL5011X_MM_FN_ID, "zl5011xMmAlloc: size %08x, address %08x",
size, *pMemory, 0, 0, 0, 0);
}
return(status);
}
/*******************************************************************************
Function:
zl5011xMmFree
Description:
The memory is released back into the heap by MmFree.
A list in the structure is used to track the allocations and frees.
Normally clear start & end pointers and copy next & prev to their appropriate
positions in prev & next blocks.
Special behaviour for first item in array. Don't really free it, but leave next
etc alone. leave start at zl5011xParams->packetMemory.heapStartAddress and 'zero' the block
length (but maintain word alignment). Index is wasted but too bad.
Inputs:
zl5011xParams Pointer to the structure for this device instance
start address pointer to start of block being freed.
size
Outputs:
Returns:
zlStatusE
Remarks:
see also zl5011xMmAlloc()
*******************************************************************************/
extern zlStatusE zl5011xMmFree(zl5011xParamsS *zl5011xParams, Uint32T pMemory)
{
zlStatusE status = ZL5011X_OK;
Uint32T index = 0;
ZL5011X_TRACE(ZL5011X_MM_FN_ID, "zl5011xMmFree: address 0x%08x ", pMemory, 0, 0, 0, 0, 0);
/* find item in array with this value of pStart */
while(index < ZL5011X_MEMORY_NUM_HEAP_ALLOCS)
{
if (zl5011xParams->packetMemory.allocTable[index].pBlockStart == pMemory)
{
break;
}
index++;
}
if (index == ZL5011X_MEMORY_NUM_HEAP_ALLOCS)
{
/* we reached the end */
status = ZL5011X_PARAMETER_INVALID;
}
/* remove the block */
if (status == ZL5011X_OK)
{
if (index == 0)
{ /* special behaviour for first item - cannot be removed */
status = ZL5011X_PARAMETER_INVALID;
}
else if (zl5011xParams->packetMemory.allocTable[index].iNextBlock == 0)
{
/* special behaviour for last block in chain
* no change for iPrevBlock[iNextBlock[index]]
*/
zl5011xParams->packetMemory.allocTable[zl5011xParams->packetMemory.allocTable[index].iPrevBlock].iNextBlock = 0;
zl5011xParams->packetMemory.allocTable[index].pBlockStart = 0;
zl5011xParams->packetMemory.allocTable[index].pBlockEnd = 0;
zl5011xParams->packetMemory.allocTable[index].iNextBlock = 0;
zl5011xParams->packetMemory.allocTable[index].iPrevBlock = 0;
}
else
{ /* normal behaviour: removal of block */
zl5011xParams->packetMemory.allocTable[zl5011xParams->packetMemory.allocTable[index].iNextBlock].iPrevBlock = zl5011xParams->packetMemory.allocTable[index].iPrevBlock;
zl5011xParams->packetMemory.allocTable[zl5011xParams->packetMemory.allocTable[index].iPrevBlock].iNextBlock = zl5011xParams->packetMemory.allocTable[index].iNextBlock;
zl5011xParams->packetMemory.allocTable[index].pBlockStart = 0;
zl5011xParams->packetMemory.allocTable[index].pBlockEnd = 0;
zl5011xParams->packetMemory.allocTable[index].iNextBlock = 0;
zl5011xParams->packetMemory.allocTable[index].iPrevBlock = 0;
}
}
return(status);
}
/*******************************************************************************
Function:
zl5011xMmSetHeap
Description:
This defines the location of a packet memory heap. The alloc and free
functions are used to access the heap.
Inputs:
zl5011xParams Pointer to the structure for this device instance
startHeap start address for the memory heap
endHeap end address of the memory heap
Outputs:
Returns:
zlStatusE
Remarks:
Addresses should be 8 byte aligned, since that is the minimum size that can
be allocated.
*******************************************************************************/
extern zlStatusE zl5011xMmSetHeap(zl5011xParamsS *zl5011xParams, Uint32T startHeap, Uint32T endHeap)
{
zlStatusE status = ZL5011X_OK;
Sint32T heapSize;
ZL5011X_TRACE(ZL5011X_MM_FN_ID, "zl5011xMmSetHeap: start %08x, end %08x", startHeap, endHeap, 0, 0, 0, 0);
/* the device uses 8 byte words, so round down / up the bottom 3 bits
of the address as required */
startHeap = startHeap & ~ZL5011X_MM_GRANULARITY_MASK;
endHeap = endHeap | ZL5011X_MM_GRANULARITY_MASK;
/* if the heap is requested to start at 0, actually make it start one
location in, to help with the allocation function */
if (startHeap == 0)
{
startHeap += ZL5011X_MM_GRANULARITY_MASK + 1;
}
/* if the start of the heap is in external memory, then check the end of the
heap is also in the external memory */
if ((startHeap > ZL5011X_EXT_MEM_BASE) &&
(startHeap < (ZL5011X_EXT_MEM_BASE + zl5011xParams->packetMemory.extMemSizeBytes)))
{
if ((endHeap < ZL5011X_EXT_MEM_BASE) ||
(endHeap > (ZL5011X_EXT_MEM_BASE + zl5011xParams->packetMemory.extMemSizeBytes)))
{
status = ZL5011X_PARAMETER_INVALID;
}
}
if (status == ZL5011X_OK)
{
/* if the end of the heap is in internal memory, then check the end of the
heap is also in the internal memory */
if ((startHeap > ZL5011X_INT_MEM_BASE) &&
(startHeap < (ZL5011X_INT_MEM_BASE + ZL5011X_INT_MEMORY_SIZE_IN_BYTES)))
{
if ((endHeap < ZL5011X_INT_MEM_BASE) ||
(endHeap > (ZL5011X_INT_MEM_BASE + ZL5011X_INT_MEMORY_SIZE_IN_BYTES)))
{
status = ZL5011X_PARAMETER_INVALID;
}
}
}
if (status == ZL5011X_OK)
{
heapSize = endHeap - startHeap + 1; /* +1 because both startHeap and endHeap are inclusive */
if (heapSize < ZL5011X_MM_MIN_HEAP_SIZE)
{
status = ZL5011X_PARAMETER_INVALID;
}
}
if (status == ZL5011X_OK)
{
zl5011xParams->packetMemory.heapStartAddress = startHeap;
zl5011xParams->packetMemory.heapEndAddress = endHeap;
/* the heap is now set up, so zero out the structure */
(void)memset(zl5011xParams->packetMemory.allocTable, 0,
sizeof(zl5011xParams->packetMemory.allocTable));
/* initialise the first block for the allocation function. The first block
is special, and must always be present */
zl5011xParams->packetMemory.allocTable[0].pBlockStart = startHeap;
zl5011xParams->packetMemory.allocTable[0].pBlockEnd = startHeap + ZL5011X_MM_GRANULARITY_MASK;
}
return(status);
}
/***************** END ****************************************************/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -