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

📄 xsdma.c

📁 优龙YLP270开发板 光盘自带的BIOS和实验例程源码 强烈推荐
💻 C
📖 第 1 页 / 共 4 页
字号:
    
    //
    // Build the command register for a memory to memory transfer. Note
    // that the reserved width field is used for memory to memory transfers.
 
    dmaCommandRegister = ( descInfoP->transferLength << DCMD_LEN_SHIFT 
                            | DCMD_WIDTH_RSVD    // mem to mem transfer 
                            | DCMD_SIZE_32       // 32 byte bursts
                            | DCMD_INCTRGADDR    // increment target address
                            | DCMD_INCSRCADDR    // increment source address
                            );

    descInfoP->commandRegister = dmaCommandRegister;

    XsDmaFillDescriptorStructure (descInfoP);
 
} // XsDmaSetupMem2MemDescriptor ()


/*
*******************************************************************************
*
* FUNCTION:         XsDmaSetupMem2PeriphDescriptor
*
* DESCRIPTION:      Fills in a descriptor in memory that will do a memory to 
*                   peripheral transfer.
*
* INPUT PARAMETERS: 
*            XsDmaDescriptorParamsT* descInfoP: 
*                   Pointer to the descriptor information structure that 
*                   carries the address of a DMA descriptor and all information
*                   necessary to fill it in.  
*
* RETURNS:          None
*
* GLOBAL EFFECTS:   None
*
* ASSUMPTIONS:      None
*
* CALLS:            XsDmaFillDescriptorStructure
*
* CALLED BY:        XsDmaCreateDescriptorFromChan
*
* PROTOTYPE:        static void SetupMem2PeriphDescriptor 
*                                           (XsDmaDescriptorParamsT*);
*
* DETAILS:          Adds the contents of the command register member and then
*                   invokes XsDmaFillDescriptorStructure().  These contents are
*                   mainly constructed from the specified buffer length and a 
*                   set of entries in the DmaDeviceTable.
*
*******************************************************************************
*/

static
void XsDmaSetupMem2PeriphDescriptor (XsDmaDescriptorParamsT* descInfoP)
{
    XsDmaChannelConfigEntryT*  channelConfigP;
    UINT32 dmaCommandRegister;

    channelConfigP =  &XsDmaChannelConfigTable[descInfoP->channel];


    //
    // Build the command register for a memory to peripheral transfer. Note
    // that the reserved width field is used for memory to memory transfers.
    //

    // construct a word fragment depending on the peripheral device we are
    // dealing with.

    dmaCommandRegister = 0x0; // clear the command register
    
    // note that the source address is incremented but the target address is 
    // not incremented.
        
    dmaCommandRegister |= descInfoP->transferLength << DCMD_LEN_SHIFT;
    dmaCommandRegister |= DmaDeviceTable[channelConfigP->targetDeviceName]
                                                                   .data_width;
    dmaCommandRegister |= DmaDeviceTable[channelConfigP->targetDeviceName]
                                                                   .best_burst;
    dmaCommandRegister |= DCMD_INCSRCADDR;  // increment the source address
    dmaCommandRegister |= DCMD_FLOWTRG;     // flow control the target

    descInfoP->commandRegister = dmaCommandRegister;

    descInfoP->targetPhysicalAddr = DmaDeviceTable
                                [channelConfigP->targetDeviceName].trans_addr;

    descInfoP->targetVirtualAddr = (PVOID)descInfoP->targetPhysicalAddr; // Identity mapped.

    XsDmaFillDescriptorStructure (descInfoP);

} // XsDmaSetupMem2PeriphDescriptor ()

/*
*******************************************************************************
*
* FUNCTION:         XsDmaSetupPeriph2MemDescriptor
*
* DESCRIPTION:      Fills in a descriptor in memory that will do a peripheral  
*                   to memory transfer.
*
* INPUT PARAMETERS: 
*            XsDmaDescriptorParamsT* descInfoP: 
*                   Pointer to the descriptor information structure that 
*                   carries the address of a DMA descriptor and all information
*                   necessary to fill it in.  
*
* RETURNS:          None
*
* GLOBAL EFFECTS:   None
*
* ASSUMPTIONS:      None
*
* CALLS:            XsDmaFillDescriptorStructure
*
* CALLED BY:        XsDmaCreateDescriptorFromChan
*
* PROTOTYPE:        static void SetupPeriph2MemoryDescriptor
*                                           (XsDmaDescriptorParamsT*);
*
* DETAILS:          Adds the contents of the command register member and then
*                   invokes XsDmaFillDescriptorStructure().  These contents are
*                   mainly constructed from the specified buffer length and a 
*                   set of entries in the DmaDeviceTable.
*
*******************************************************************************
*/

static
void XsDmaSetupPeriph2MemDescriptor(XsDmaDescriptorParamsT* descInfoP)
{
    XsDmaChannelConfigEntryT*  channelConfigP;
    UINT32 dmaCommandRegister;

    channelConfigP =  &XsDmaChannelConfigTable[descInfoP->channel];

    //
    // Build the command register for a memory to peripheral transfer. Note
    // that the reserved width field is used for memory to memory transfers.
    //

    dmaCommandRegister = 0x0; // clear the command register
    
    // note that the target address is incremented but the source address is 
    // not incremented.
    
    dmaCommandRegister |= DmaDeviceTable[channelConfigP->sourceDeviceName]
                                                                   .data_width;
    dmaCommandRegister |= descInfoP->transferLength << DCMD_LEN_SHIFT;
    dmaCommandRegister |= DmaDeviceTable[channelConfigP->sourceDeviceName]
                                                                   .best_burst;
    dmaCommandRegister |= DCMD_FLOWSRC;     // flow control the source
    dmaCommandRegister |= DCMD_INCTRGADDR;  // increment the target address
  
    descInfoP->commandRegister = dmaCommandRegister;

    descInfoP->sourcePhysicalAddr 
                = DmaDeviceTable[channelConfigP->sourceDeviceName].rec_addr;

    descInfoP->sourceVirtualAddr = (PVOID)descInfoP->sourcePhysicalAddr; //Identity mapped.

    XsDmaFillDescriptorStructure (descInfoP);

} // XsDmaSetupPeriph2MemDescriptor ()


/*
*******************************************************************************
*
* FUNCTION:         XsDmaLoadFirstDescriptorAddr
*
* DESCRIPTION:      Loads the physical address of the descriptor, whose virtual
*                   address is received as a pointer, into the DDADR register
*                   for the specified DMA channel.  This makes the values in 
*                   its members available for loading when the channel is 
*                   started.
*
* INPUT PARAMETERS: UINT32 channel
*                   XsDmaDescriptorElementsTPT firstDescriptorP
*
* RETURNS:          UINT32 - 0 (ERR_NONE) means no error
*                            ERR_T_ILLPARAM: Pointer to invalid descriptor
*
* GLOBAL EFFECTS:   None
*
* ASSUMPTIONS:      Assumes that the DMA has already been setup
*                   Operating in Descriptor Fetch Mode.
*
* CALLS:            -
*
* CALLED BY:        Anyone
*
* PROTOTYPE:        UINT32 XsDmaLoadFirstDescriptorAddr (UINT32, 
*                                                 XsDmaDescriptorElementsTPT);
*
*******************************************************************************
*/

UINT32 XsDmaLoadFirstDescriptorAddr (INT channel, 
                                 XsDmaDescriptorElementsTPT firstDescriptorP)
{
    UINT32 returnValue = ERR_NONE;

    // Assume valid channel #.
    // But verify that we actually have a descriptor: minimal sanity check.
    if (firstDescriptorP->signature != XSDMA_DESC_SIGNATURE)
    {
        // There is an error
        LOGERROR(returnValue, ERR_L_XSDMA, 0, ERR_T_ILLPARAM, (UINT32) firstDescriptorP, 0, 0);  
    }
    else
    {
        // Load the physical address of the first descriptor into the channel group. The rest of 
        // the registers are loaded when the the channel is started.

        XsDmaControlRegsP->DDG[channel].DDADR = firstDescriptorP->currentPhysicalAddr;
    }

    return (returnValue); 

} // XsDmaLoadFirstDescriptorAddr ()


/*
*******************************************************************************
*
* FUNCTION:         XsDmaStart
*
* DESCRIPTION:      Starts the DMA channel.  Always sets the channel's 
*                   DCSR_RUN bit.  For non-memory devices, also places 
*                   the channel number, ORed with the  DRCMR_MAPVLD bit,
*                   into the device's DRCMR.  (For some non-memory devices, 
*                   DMA is activated as soon as the channel mapping is done; 
*                   therefore, channel mapping is performed here.)
*
* INPUT PARAMETERS: INT channel:  Channel which is to be started.
*
* RETURNS:          UINT32
*           Success: ERR_NONE (0)
*           Failure: ERR_T_ALREADY_IN_USE: DMA transfer involves a non-memory 
*                                           device that is already mapped to 
*                                           a different active channel.
*
* GLOBAL EFFECTS:   None
*
* ASSUMPTIONS:      
*            o  XsDmaGetFreeChannel has provided this channel to this client.  
*                In the process, the device type was specified.
*            o  Channel number has been validated elsewhere. 
*
* CALLS:            None
*
* CALLED BY:        Anyone
*
* PROTOTYPE:        UINT32 XsDmaStart (INT);
*
*******************************************************************************
*/

UINT32 XsDmaStart (INT channel)
{
    // Assume that the channel # has been validated elsewhere.
    // Operate under interrupt protection 
    UINT32 status = ERR_NONE;
    UINT32 previousIntState;
    UINT32 drcmrCur;
    XsDmaDrcmrIdT thisDrcmrId;
    XsDmaChannelConfigEntryT* channelConfigP;
    VUINT temp;

    channelConfigP = &XsDmaChannelConfigTable [channel];
    thisDrcmrId = channelConfigP->drcmrId;
    
    
    previousIntState = IRQ_DisableInterrupts(CPSR_I_Bit|CPSR_F_Bit);

    if (XSDMA_DRCMR_ID_MEMORY != thisDrcmrId)
    {
        drcmrCur = XsDmaControlRegsP->DRCMR[thisDrcmrId];

        // Make sure the device has no other channel already active.
        if ((drcmrCur & DRCMR_MAPVLD) && ((drcmrCur & DRCMR_CHLNUM_MSK) != channel))
        {
            LOGERROR(status, ERR_L_XSDMA, ERR_S_DMA_START, ERR_T_DMA_NOCHAN, 
                    ERR_T_ALREADY_IN_USE, 0, 0);  
        }
        else
        {

        // For non-memory devices, write the channel # to the device's DRCMR 
        //  register with the MAPVLD bit set.
            XsDmaControlRegsP->DRCMR[thisDrcmrId] = channel | DRCMR_MAPVLD;
        }
    } // if (non-memory device)

    temp = XsDmaControlRegsP->DRCMR[thisDrcmrId];
    DM_CwDbgPrintf(DM_CW_DMA_0, "DRCMR %d: %x Index: %d \r\n", (UINT)channel, (UINT)temp, (UINT)thisDrcmrId);

    // Always set the DCSR_RUN bit for the channel. 
    XsDmaControlRegsP->DCSR[channel] |=  DCSR_RUN;

    IRQ_EnableInterrupts (previousIntState);

    return (status);
    
} // XsDmaStart ()


/*
*******************************************************************************
*
* FUNCTION:         XsDmaStop
*
* DESCRIPTION:      Clears the Run bit in the DCSR of the appropriate DMA 
*                   channel.  This causes the channel to stop, but any current
*                   burst will complete.  See Notes immediately below.  
*                   Interrupt protection is provided.
*
* INPUT PARAMETERS: UINT32 channel
*
* RETURNS:          UINT32 - ERR_NONE
*
* GLOBAL EFFECTS:   None
*
* ASSUMPTIONS:      Channel number has been validated elsewhere.
*
* CALLS:            None
*
* CALLED BY:        Anyone
*
* PROTOTYPE:        UINT32 XsDmaStop (UINT32);
*
*   Notes: - "After the channel stops, the DCSR.StopIntr bit is set to 

⌨️ 快捷键说明

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