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

📄 xdma_multi_sg.c

📁 linux嵌入式系统的dma方式的实现代码
💻 C
📖 第 1 页 / 共 3 页
字号:
** @param InstancePtr contains a pointer to the multichannel DMA to operate on.*        The DMA channel should be configured to use scatter gather in order*        for this function to be called.** @param Channel is the particular channel of interest.** @return* - XTRUE if the scatter gather list is empty, otherwise a value of*   XFALSE.** @note** None.*******************************************************************************/Xboolean XDmaMulti_IsSgListEmpty(XDmaMulti *InstancePtr, unsigned Channel){    /* Assert to verify valid input arguments. */    XASSERT_NONVOID(InstancePtr != XNULL);    XASSERT_NONVOID(InstancePtr->ChannelCount > Channel);    XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);    /*     * If the number of descriptors which are being used in the list is zero     * then the list is empty.     */    return (CHANNEL_DATA.ActiveDescriptorCount == 0);}/*****************************************************************************//**** This function puts a buffer descriptor into the DMA channel scatter* gather list. A DMA channel maintains a list of buffer descriptors which are* to be processed.  This function puts the specified buffer descriptor* at the next location in the list.  Note that since the list is already intact,* the information in the parameter is copied into the list (rather than modify* list pointers on the fly).** After buffer descriptors are put into the list, they must also be committed* by calling another function.  This allows multiple buffer descriptors which* span a single packet to be put into the list while preventing the hardware* from starting the first buffer descriptor of the packet.** @param InstancePtr contains a pointer to the multichannel DMA to operate on.*        The DMA channel should be configured to use scatter gather in order*        for this function to be called.** @param Channel is the particular channel of interest.** @param BufferDescriptorPtr is a pointer to the buffer descriptor to be put into*        the next available location of the scatter gather list.** @return* - XST_SUCCESS if the buffer descriptor was*   successfully put into the scatter gather list.*   <br><br>* - XST_DMA_SG_NO_LIST indicates the scatter gather list has not*   been created.*   <br><br>* - XST_DMA_SG_LIST_FULL indicates the buffer descriptor was not*   put into the list because the list was full.*   <br><br>* - XST_DMA_SG_BD_LOCKED indicates the buffer descriptor was not*   put into the list because the buffer descriptor in the list which is to*   be overwritten was locked.  A locked buffer descriptor indicates the higher*   layered software is still using the buffer descriptor.** @note** It is necessary to create a scatter gather list for a DMA channel before* putting buffer descriptors into it.*******************************************************************************/XStatus XDmaMulti_PutDescriptor(XDmaMulti *InstancePtr, unsigned Channel,                                XBufDescriptor *BufferDescriptorPtr){    Xuint32 Control;    /*     * Assert to verify valid input arguments and alignment for those     * arguments that have alignment restrictions.     */    XASSERT_NONVOID(InstancePtr != XNULL);    XASSERT_NONVOID(InstancePtr->ChannelCount > Channel);    XASSERT_NONVOID(BufferDescriptorPtr != XNULL);    XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);    /* If a scatter gather list has not been created yet, return a status. */    if (CHANNEL_DATA.TotalDescriptorCount == 0)    {        return XST_DMA_SG_NO_LIST;    }    /*     * If the list is full because all descriptors are pointing to valid     * buffers, then indicate an error, this code assumes no list or an     * empty list is detected above.     */    if (CHANNEL_DATA.ActiveDescriptorCount ==        CHANNEL_DATA.TotalDescriptorCount)    {         return XST_DMA_SG_LIST_FULL;    }    /*     * If the buffer descriptor in the list which is to be overwritten is     * locked, then don't overwrite it and return a status.     */    if ((XBufDescriptor_IsLocked(CHANNEL_DATA.PutPtr)) != 0)    {        return XST_DMA_SG_BD_LOCKED;    }    /*     * Set the scatter gather stop bit in the control word of the descriptor     * to cause the hw to stop after it processes this descriptor since it     * will be the last in the list.     */    Control = XBufDescriptor_GetControl(BufferDescriptorPtr);    XBufDescriptor_SetControl(BufferDescriptorPtr,                              Control | XDM_DMACR_SG_STOP_MASK);    /*     * Set both statuses in the descriptor so we tell if they are updated with     * the status of the transfer, the hardware should change the busy in the     * DMA status to be false when it completes.     */    XBufDescriptor_SetStatus(BufferDescriptorPtr, XDM_DMASR_BUSY_MASK);    XBufDescriptor_SetDeviceStatus(BufferDescriptorPtr, 0);    /*     * Copy the descriptor into the next position in the list so it's ready to     * be used by the hw, this assumes the descriptor in the list prior to this     * one still has the stop bit in the control word set such that the hw     * use this one yet.     */    CopyBufferDescriptor(BufferDescriptorPtr,                         CHANNEL_DATA.PutPtr);    /*     * Only the last in the list and the one to be committed have scatter gather     * disabled in the control word, a commit requires only one descriptor     * to be changed, when # of descriptors to commit > 2 all others except the     * 1st and last have scatter gather enabled.     */    if ((CHANNEL_DATA.CommitPtr !=         CHANNEL_DATA.LastPtr) &&        (CHANNEL_DATA.CommitPtr != XNULL))    {        Control = XBufDescriptor_GetControl(CHANNEL_DATA.LastPtr);        XBufDescriptor_SetControl(CHANNEL_DATA.LastPtr,                                  Control & ~XDM_DMACR_SG_STOP_MASK);    }    /*     * Update the list data based upon putting a descriptor into the list,     * these operations must be last.     */    CHANNEL_DATA.ActiveDescriptorCount++;    /*     * Only update the commit pointer if it is not already active, this allows     * it to be deactivated after every commit such that a single descriptor     * which is committed does not appear to be waiting to be committed     */    if (CHANNEL_DATA.CommitPtr == XNULL)    {        CHANNEL_DATA.CommitPtr = CHANNEL_DATA.LastPtr;    }    /*     * These updates MUST BE LAST after the commit pointer update in order for     * the commit pointer to track the correct descriptor to be committed.     */    CHANNEL_DATA.LastPtr = CHANNEL_DATA.PutPtr;    CHANNEL_DATA.PutPtr = XBufDescriptor_GetNextPtr(CHANNEL_DATA.PutPtr);    return XST_SUCCESS;}/*****************************************************************************//**** This function commits the buffer descriptors which have been put into the* scatter list for a DMA channel since the last commit operation was* performed.  This enables the calling functions to put several buffer* descriptors into the list (e.g.,a packet's worth) before allowing the scatter* gather operations to start.  This prevents the DMA channel hardware from* starting to use the buffer descriptors in the list before they are ready* to be used (multiple buffer descriptors for a single packet).** @param InstancePtr contains a pointer to the multichannel DMA to operate on.*        The DMA channel should be configured to use scatter gather in order*        for this function to be called.** @param Channel is the particular channel of interest.** @return* - XST_SUCCESS if the buffer descriptors of the list were*   successfully committed.*   <br><br>* - XST_DMA_SG_NOTHING_TO_COMMIT indicates that the buffer descriptors*   were not committed because there was nothing to commit in the list.  All the*   buffer descriptors which are in the list are committed.** @note** None.*******************************************************************************/XStatus XDmaMulti_CommitPuts(XDmaMulti *InstancePtr, unsigned Channel){    /* Assert to verify input arguments. */    XASSERT_NONVOID(InstancePtr != XNULL);    XASSERT_NONVOID(InstancePtr->ChannelCount > Channel);    XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);    /*     * If the buffer descriptor to be committed is already committed or     * the list is empty (none have been put in), then indicate an error.     */    if ((CHANNEL_DATA.CommitPtr == XNULL) ||         XDmaMulti_IsSgListEmpty(InstancePtr, Channel) == XTRUE)    {        return XST_DMA_SG_NOTHING_TO_COMMIT;    }    /*     * Last descriptor in the list must have scatter gather disabled so the end     * of the list is hit by hw, if descriptor to commit is not last in list,     * commit descriptors by enabling scatter gather in the descriptor.     */    if (CHANNEL_DATA.CommitPtr != CHANNEL_DATA.LastPtr)    {        Xuint32 Control;        Control = XBufDescriptor_GetControl(CHANNEL_DATA.CommitPtr);        XBufDescriptor_SetControl(CHANNEL_DATA .CommitPtr,                                  Control & ~XDM_DMACR_SG_STOP_MASK);    }    /*     * Update the commit pointer to indicate that there is nothing to be     * committed, this state is used by start processing to know that the     * buffer descriptor to start is not waiting to be committed.     */    CHANNEL_DATA.CommitPtr = XNULL;    return XST_SUCCESS;}/*****************************************************************************//**** This function gets a buffer descriptor from the scatter gather list of the* DMA channel. The buffer descriptor is retrieved from the scatter gather* list and the scatter gather list is updated to not include the retrieved buffer* descriptor.  This is typically done after a scatter gather operation* completes indicating that a data buffer has been successfully sent or data* has been received into the data buffer. The purpose of this function is to* allow the device using the scatter gather operation to get the results of the* operation.** @param InstancePtr contains a pointer to the multichannel DMA to operate on.*        The DMA channel should be configured to use scatter gather in order*        for this function to be called.** @param Channel is the particular channel of interest.** @param BufDescriptorPtr is a pointer to a pointer to the buffer descriptor*        which was retrieved from the list.  The buffer descriptor is not*        really removed from the list, but it is changed to a state such that*        the hardware will not use it again until it is put into the scatter*        gather list of a DMA channel.** @return* - XST_SUCCESS if a buffer descriptor was retrieved*   <br><br>* - XST_DMA_SG_NO_LIST indicates the scatter gather list has not been created.*   <br><br>* - XST_DMA_SG_LIST_EMPTY indicates no buffer descriptor was*   retrieved from the list because there are no buffer descriptors to be*   processed in the list.*   <br><br>* - BufDescriptorPtr is updated to point to the buffer descriptor which was*   retrieved from the list if the status indicates success.** @note** None.*******************************************************************************/XStatus XDmaMulti_GetDescriptor(XDmaMulti *InstancePtr, unsigned Channel,                                XBufDescriptor** BufDescriptorPtr){    Xuint32 Control;    /* Assert to verify input arguments. */    XASSERT_NONVOID(InstancePtr != XNULL);    XASSERT_NONVOID(InstancePtr->ChannelCount > Channel);    XASSERT_NONVOID(BufDescriptorPtr != XNULL);    XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);    /* If a scatter gather list has not been created yet, return a status. */    if (CHANNEL_DATA.TotalDescriptorCount == 0)    {        return XST_DMA_SG_NO_LIST;    }    /* If the buffer descriptor list is empty, then indicate an error. */    if (XDmaMulti_IsSgListEmpty(InstancePtr, Channel) == XTRUE)    {        return XST_DMA_SG_LIST_EMPTY;    }    /*     * Retrieve the next buffer descriptor which is ready to be processed from     * the buffer descriptor list for a DMA channel, set the control word     * such that hardware will stop after the descriptor has been processed.     */    Control = XBufDescriptor_GetControl(CHANNEL_DATA.GetPtr);    XBufDescriptor_SetControl(CHANNEL_DATA.GetPtr,                              Control | XDM_DMACR_SG_STOP_MASK);    /*     * Set the input argument, which is also an output, to point to the     * buffer descriptor which is to be retrieved from the list.     */    *BufDescriptorPtr = CHANNEL_DATA.GetPtr;    /*     * Update the pointer of a DMA channel to reflect the buffer descriptor     * was retrieved from the list by setting it to the next buffer descriptor     * in the list and indicate one less descriptor in the list now.     */    CHANNEL_DATA.GetPtr = XBufDescriptor_GetNextPtr(CHANNEL_DATA.GetPtr);    CHANNEL_DATA.ActiveDescriptorCount--;    return XST_SUCCESS;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -