⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zl5011xmm.c

📁 Zalink50114----TDMoIP芯片驱动源码
💻 C
📖 第 1 页 / 共 3 页
字号:
    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 + -