📄 wmxscaledmatest.c
字号:
v_pDmaReg->DCSR[channel] |= DCSR_DMA_INT_MASK;
}
/* Now work out how long it all took */
endTime = GetMillisecondTimestamp( hDevice );
duration = endTime - startTime;
WMTEST_TRACE(( "%d buffers of %d samples took %dms (expected %dms)\n",
repeats,
samplesPerBuffer,
duration,
expectedDuration
));
# if VERIFY_DMA_TIMING
/* Make sure it's reasonably close to what we expect */
WMTEST_GREATER( duration, expectedDuration - TEST_MILLISECOND_SLOP );
WMTEST_LESS( duration, expectedDuration + TEST_MILLISECOND_SLOP );
# endif /* VERIFY_DMA_TIMING */
}
while ( loopForever );
/*
* Stop, mute, disable and power down the Voice DAC Interface.
*/
WMVoiceStop( hDevice );
WMTEST_CALL( WMAudioMuteAllOutputs( hDevice, TRUE ) );
WMTEST_CALL( WMAudioEnableOutputPaths( hDevice, WM_STREAM_VOICE_OUT, FALSE ) );
WMTEST_CALL( WMAudioPowerDown( hDevice,WM_POWER_AUDIO_PLAYBACK ) );
/*
* Clean up the DMA now that the test is finished.
*/
private_CleanupDMA( hDevice, channel, channelId );
#else /* WM_VOICE */
WMTEST_SKIP();
#endif /* WM_VOICE */
}
WMTEST_END
/*-----------------------------------------------------------------------------
* Function: private_InitDMA
*
* Initialise the DMA.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* channel The DMA channel to stop.
* channelId The DMA DRCMR channel ID.
*
* Returns: void
*---------------------------------------------------------------------------*/
void private_InitDMA( WM_DEVICE_HANDLE hDevice, int channel, int channelId )
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT *) hDevice;
VOLATILE_DMAC_T *v_pDmaReg = pDeviceContext->v_pDmaReg;
/*
* Disable the DMA Interrupts until we have finished.
* NOTE: At this point the DMA IST may already be running.
* If it is, it will interfere with this function
* as we need to be able to poll the dcsr to see
* if any DMA interrupts have occured.
*/
WMAudioDisableDMAInterrupts( hDevice );
/*
* Set up the DMA so it's ready to run on this channel.
*/
v_pDmaReg->DDG[channel].DDADR = (unsigned int)v_pAudioXmitA_Physical;
v_pDmaReg->DRCMR1[channelId] = DMA_MAP_VALID_MASK | channel;
}
/*-----------------------------------------------------------------------------
* Function: private_CleanupDMA
*
* Clean up the DMA descriptors and buffers.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* channel The DMA channel to stop.
* channelId The DMA DRCMR channel ID.
*
* Returns: void
*---------------------------------------------------------------------------*/
void private_CleanupDMA( WM_DEVICE_HANDLE hDevice, int channel, int channelId )
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext =
(WM_XSCALE_DEVICE_CONTEXT *) hDevice;
VOLATILE_DMAC_T *v_pDmaReg = pDeviceContext->v_pDmaReg;
/* Fill the DMA buffers with silence */
private_ClearDMABuffers();
/* Stop the DMA from running */
v_pDmaReg->DCSR[channel] &= ~DCSR_RUN; /* clear the RUN bit */
/* Clear the DRCMR */
v_pDmaReg->DRCMR1[channelId] = 0;
/* Clear the descriptors */
private_ClearDescriptors();
/* Free the virtual memory */
private_ReleaseDMAMemory();
/*
* Enable the DMA Interrupts now we have finished.
*/
WMAudioEnableDMAInterrupts( hDevice );
}
/*-----------------------------------------------------------------------------
* Function: private_MapDMAMemory
*
* Maps the DMA descriptors and buffers in to virtual memory.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
*
* Returns: TRUE on success, FALSE on error
*---------------------------------------------------------------------------*/
WM_BOOL private_MapDMAMemory( WM_DEVICE_HANDLE hDevice )
{
/* Don't map in twice */
if ( s_Initialised )
{
goto done;
}
/*
* The DMA descriptors
*/
v_pAudioXmitA_Virtual = ALLOC_OR_MAP_BUFFER( hDevice,
volatile XLLP_DMAC_DESCRIPTOR_T,
WMDMA_DESCRIPTOR_BASE_PHYSICAL,
WMAUDIO_DMA_DESC_SIZE * WMDMA_DESCRIPTORS_PER_CHANNEL,
&v_pAudioXmitA_Physical,
"private_MapDMAMemory: ALLOC_OR_MAP_BUFFER failed to allocate DMA descriptors"
);
if ( !v_pAudioXmitA_Virtual )
{
v_pAudioXmitA_Physical = NULL;
WM_TRACE( hDevice, ( "private_MapDMAMemory: ALLOC_OR_MAP_BUFFER failed to allocate DMA descriptors" ) );
goto error;
}
v_pAudioXmitB_Virtual = (volatile XLLP_DMAC_DESCRIPTOR_T *)((unsigned long)v_pAudioXmitA_Virtual + WMAUDIO_DMA_DESC_SIZE);
v_pAudioXmitB_Physical = (volatile XLLP_DMAC_DESCRIPTOR_T *)((unsigned long)v_pAudioXmitA_Physical + WMAUDIO_DMA_DESC_SIZE);
/*
* The DMA buffers
*/
v_pDMABufXmitA_Virtual = ALLOC_OR_MAP_BUFFER( hDevice,
WM_AUDIO_STEREO_SAMPLE,
WMDMA_BUFFER_BASE_PHYSICAL,
WMAUDIO_MAX_BUFFER_SIZE * WMDMA_BUFFERS_PER_CHANNEL,
&v_pDMABufXmitA_Physical,
"private_MapDMAMemory: ALLOC_OR_MAP_BUFFER failed to allocate DMA buffers"
);
if ( !v_pDMABufXmitA_Virtual )
{
v_pDMABufXmitA_Physical = NULL;
WM_TRACE( hDevice, ( "private_MapDMAMemory: ALLOC_OR_MAP_BUFFER failed to allocate DMA buffers" ) );
goto error;
}
v_pDMABufXmitB_Virtual = (WM_AUDIO_STEREO_SAMPLE *)((unsigned long)v_pDMABufXmitA_Virtual + WMAUDIO_MAX_BUFFER_SIZE);
v_pDMABufXmitB_Physical = (WM_AUDIO_STEREO_SAMPLE *)((unsigned long)v_pDMABufXmitA_Physical + WMAUDIO_MAX_BUFFER_SIZE);
/*
* All well and good.
*/
done:
s_Initialised = TRUE;
return TRUE;
/*
* Clean up on error
*/
error:
private_ReleaseDMAMemory();
return FALSE;
}
/*-----------------------------------------------------------------------------
* Function: private_ReleaseDMAMemory
*
* Releases the virtual memory used by the DMA descriptors and buffers.
*
* Parameters:
* none
*
* Returns: void
*---------------------------------------------------------------------------*/
void private_ReleaseDMAMemory()
{
if ( v_pAudioXmitA_Virtual )
{
FREE_BUFFER_MEMORY( v_pAudioXmitA_Virtual,
v_pAudioXmitA_Physical,
WMAUDIO_DMA_DESC_SIZE * WMDMA_DESCRIPTORS_PER_CHANNEL
);
v_pAudioXmitA_Virtual = NULL;
v_pAudioXmitA_Physical = NULL;
v_pAudioXmitB_Virtual = NULL;
v_pAudioXmitB_Physical = NULL;
}
if ( v_pDMABufXmitA_Virtual )
{
FREE_BUFFER_MEMORY( v_pDMABufXmitA_Virtual,
v_pDMABufXmitA_Physical,
WMAUDIO_MAX_BUFFER_SIZE * WMDMA_BUFFERS_PER_CHANNEL
);
v_pDMABufXmitA_Virtual = NULL;
v_pDMABufXmitA_Physical = NULL;
v_pDMABufXmitB_Virtual = NULL;
v_pDMABufXmitB_Physical = NULL;
}
s_Initialised = FALSE;
}
/*-----------------------------------------------------------------------------
* Function: private_ClearDescriptors
*
* Clears the DMA descriptors.
*
* Parameters:
* none
*
* Returns: void
*---------------------------------------------------------------------------*/
void private_ClearDescriptors( void )
{
union DmaCmdReg CmdBuff = {0};
/*
* Clear XmitA Descriptor
*/
v_pAudioXmitA_Virtual->DDADR = (DMAC_DESC_FIELD_T)NULL; /* address of the next (XmitB) descriptor */
v_pAudioXmitA_Virtual->DTADR = (DMAC_DESC_FIELD_T)NULL; /* source address of the AC97 XmitA buffer */
v_pAudioXmitA_Virtual->DSADR = (DMAC_DESC_FIELD_T)NULL; /* destination address of the XmitA buffer */
v_pAudioXmitA_Virtual->DCMD = CmdBuff.DcmdDword; /* size and cmd values of the XmitA buffer */
/*
* Clear XmitB Descriptor
*/
v_pAudioXmitB_Virtual->DDADR = (DMAC_DESC_FIELD_T)NULL; /* address of the next (XmitA) descriptor */
v_pAudioXmitB_Virtual->DTADR = (DMAC_DESC_FIELD_T)NULL; /* source address of the AC97 XmitB buffer */
v_pAudioXmitB_Virtual->DSADR = (DMAC_DESC_FIELD_T)NULL; /* destination address of the XmitB buffer */
v_pAudioXmitB_Virtual->DCMD = CmdBuff.DcmdDword; /* size and cmd values of the XmitB buffer */
}
/*-----------------------------------------------------------------------------
* Function: private_ClearDMABuffers
*
* Fill the DMA buffers with silence.
*
* Parameters:
* none
*
* Returns: void
*---------------------------------------------------------------------------*/
void private_ClearDMABuffers( void )
{
/*
* Set the the whole of the DMA buffers to zero.
*/
memset( v_pDMABufXmitA_Virtual, 0, WMAUDIO_MAX_BUFFER_SIZE );
memset( v_pDMABufXmitB_Virtual, 0, WMAUDIO_MAX_BUFFER_SIZE );
}
/*-----------------------------------------------------------------------------
* Function: private_FillDescriptors
*
* Sets up the DMA descriptors.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* channel the channel to set the descriptors up for.
*
* Returns: void
*---------------------------------------------------------------------------*/
void private_FillDescriptors( WM_DEVICE_HANDLE hDevice, int channel )
{
union DmaCmdReg CmdBuff = {0};
unsigned long channelAddr;
switch ( channel )
{
case WMDMA_STEREO_OUT:
# if WM_AC97
if ( WM_IS_AC97( hDevice ) )
{
channelAddr = DMAC_AC97_AUDIO_XMIT_FIFO;
}
# endif
# if WM_I2S
if ( WM_IS_I2S( hDevice ) )
{
channelAddr = DMAC_I2S_AUDIO_XMIT_FIFO;
}
# endif
break;
case WMDMA_MONO_OUT:
channelAddr = DMAC_AC97_MONO_XMIT_FIFO;
break;
case WMDMA_VOICE_OUT:
channelAddr = DMAC_SSP2_AUDIO_XMIT_FIFO;
break;
}
/* set values with bit fields */
CmdBuff.DcmdReg.len = WMAUDIO_MAX_BUFFER_SIZE; /*length of memory buffer */
CmdBuff.DcmdReg.width = 0x3; /* 4 bytes per sample */
CmdBuff.DcmdReg.size = 0x3; /* 32 byte burst size */
CmdBuff.DcmdReg.endian = 0; /* little endian */
CmdBuff.DcmdReg.flybyt = 0; /* Flowthrough */
CmdBuff.DcmdReg.flybys = 0; /* Flowthrough */
CmdBuff.DcmdReg.endirqen = 1; /* 1 means Interrupt when decrement length = 0; */
CmdBuff.DcmdReg.startirqen = 0; /* 1 means Interrupt when the desc is loaded */
CmdBuff.DcmdReg.flowtrg = 1; /* 1 means the target is an external peripheral */
CmdBuff.DcmdReg.flowsrc = 0; /* 1 means the source is an external peripheral (and needs flow con */
CmdBuff.DcmdReg.inctrgadd = 0; /* 1 means increment the target address (since it's memory) */
CmdBuff.DcmdReg.incsrcadd = 1; /* 1 means increment the source address (since it's a peripheral) */
/*
* set up XmitA Descriptor
*/
v_pAudioXmitA_Virtual->DDADR = (DMAC_DESC_FIELD_T)v_pAudioXmitB_Physical; /* address of the next (XmitB) descriptor */
v_pAudioXmitA_Virtual->DTADR = channelAddr; /* source address of the XmitA buffer */
v_pAudioXmitA_Virtual->DSADR = (DMAC_DESC_FIELD_T)v_pDMABufXmitA_Physical;/* destination address of the XmitA buffer */
v_pAudioXmitA_Virtual->DCMD = CmdBuff.DcmdDword; /* size and cmd values of the XmitA buffer */
/*
* set up XmitB Descriptor
*/
v_pAudioXmitB_Virtual->DDADR = (DMAC_DESC_FIELD_T)v_pAudioXmitA_Physical; /* address of the next (XmitA) descriptor */
v_pAudioXmitB_Virtual->DTADR = channelAddr; /* source address of the XmitB buffer */
v_pAudioXmitB_Virtual->DSADR = (DMAC_DESC_FIELD_T)v_pDMABufXmitB_Physical;/* destination address of the XmitB buffer */
v_pAudioXmitB_Virtual->DCMD = CmdBuff.DcmdDword; /* size and cmd values of the XmitB buffer */
}
/*-----------------------------------------------------------------------------
* Function: private_WaitForBuffer
*
* Waits for the DMA buffer to finish.
*
* Parameters:
* hDevice handle to the device (from WMOpenDevice)
* channel DMA channel to wait for
*
* Returns: WM_STATUS
* WMS_SUCCESS - succeeded
* WMS_DATA_TIMED_OUT - couldn't do write
*---------------------------------------------------------------------------*/
static WM_STATUS private_WaitForBuffer( WM_DEVICE_HANDLE hDevice,
unsigned int channel
)
{
WM_XSCALE_DEVICE_CONTEXT *pDeviceContext = (WM_XSCALE_DEVICE_CONTEXT*) hDevice;
VOLATILE_DMAC_T *v_pDmaReg = pDeviceContext->v_pDmaReg;
unsigned int startTime = GetMillisecondTimestamp( hDevice );
unsigned int endTime;
while ( !(v_pDmaReg->DCSR[channel] & DCSR_DMA_INT_MASK) )
{
MilliSleep( hDevice, 1 );
endTime = GetMillisecondTimestamp( hDevice );
if ( ( endTime - startTime ) >= MAX_PATIENCE )
return WMS_DATA_TIMED_OUT;
}
return WMS_SUCCESS;
}
#endif /* WM_AUDIO_STREAM && WM_TESTING */
/*------------------------------ END OF FILE ---------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -