📄 xsdma.c
字号:
//
// 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 + -