需求:算法移动数据memcpy耗时过长,考虑DMA方式。
1.MDMA
要点:
1)源和目的通道都需要使能
2)源DMAx_CONFIG先于目的DMAx_CONFIG的配置
工作模式:
1)Register-Based DMA Operation
1.1)Stop Mode
1.2)Autobuffer Mode
2)Two-Dimensional DMA Operation
3)Descriptor-Based DMA Operation
3.1)Descriptor List Mode
3.2)Descriptor Array Mode
3.3)Variable Descriptor Size
3.4)Mixing Flow Modes
MDMA调试成功的代码
// DMA Manager data (base memory + memory for 2 DMA channels, since memory DMA requires 2)
static u8 DMAMgrData[ADI_DMA_BASE_MEMORY + (ADI_DMA_CHANNEL_MEMORY * 2)];
static ADI_DMA_MANAGER_HANDLE DMAManagerHandle; // handle for the whole DMA manager
static ADI_DMA_STREAM_HANDLE DMAStreamHandle;
volatile u32 DmaDoneFlag = 0; // flag between callback and main
/*********************************************************************
*
* Function: callback
*
*********************************************************************/
static void Callback( // callback function called by DCB
void *AppHandle,
u32 Event,
void *pArg)
{
// if (0x12345678 != *(u32 *)pArg) return;
switch(Event) {
case ADI_DMA_EVENT_DESCRIPTOR_PROCESSED:
DmaDoneFlag = 1; // Tell main() that the DMA is done.
break;
case ADI_DMA_EVENT_INNER_LOOP_PROCESSED: // this is only used with 2-D DMA
break;
case ADI_DMA_EVENT_OUTER_LOOP_PROCESSED: // we're not using this feature of DMA
break;
case ADI_DMA_EVENT_ERROR_INTERRUPT: // this is a common error when debugging DMA applications
break;
default: // unexpected events
break;
}
}
#pragma section("sdram0_bank1")
static int pArray_src[100];
static int pArray_des[100];
int dma_memcpy(
void *pDest,
void *pSrc,
u16 ElementWidth,
u16 ElementCount)
{
ADI_DMA_RESULT result;
result = adi_dma_MemoryCopy(
DMAStreamHandle,
pDest,
pSrc,
ElementWidth,
ElementCount,
Callback
);
if (ADI_DMA_RESULT_SUCCESS != result)
{
AIO_printf("\r\n>>adi_dma_MemoryCopy error!");
return -1;
}
else
{
AIO_printf("\r\n>>adi_dma_MemoryCopy OK!");
return 0;
}
}
static void buffer_init(void)
{
int i;
for (i = 0; i < 100; i++)
{
if (i & 0x01 == 0) pArray_src[i] = 0xA5A5A5A5;
else pArray_src[i] = 0x5a5a5a5a;
}
}
static void buffer_check(void)
{
int i;
for (i = 0; i < 100; i++)
{
if (pArray_src[i] != pArray_des[i])
{
AIO_printf("\r\n>>buffer_check error");
return;
}
}
AIO_printf("\r\n>>buffer_check OK");
}
void sys_dma_init(void)
{
ADI_DMA_RESULT result;
ADI_INT_RESULT res;
u32 u32MaxChannels;
u32 value = 0;
buffer_init();
// get the IVG level to which the RTC is mapped, parameters are
// interrupt ID
// address where the IVG level will be stored
res = adi_int_SICSetIVG( ADI_INT_MDMA0, ISR_LEVEL_MDMA);
if (ADI_INT_RESULT_SUCCESS != res)
{
AIO_printf("\r\n>>sys_dma_init adi_int_SICSetIVG error!");
return;
}
//init server
result = adi_dma_Init( DMAMgrData,
sizeof(DMAMgrData),
&u32MaxChannels,
&DMAManagerHandle,
NULL);
if (ADI_DMA_RESULT_SUCCESS != result)
{
AIO_printf("\r\n>>sys_dma_init error!");
return;
}
else
{
AIO_printf("\r\n>>sys_dma_init ok! u32MaxChannels =%d",u32MaxChannels);
}
// open the source DMA channel
result = adi_dma_MemoryOpen(
DMAManagerHandle,
ADI_DMA_MDMA_0,
(void *)0x12345678,
&DMAStreamHandle,
NULL
);
if (ADI_DMA_RESULT_SUCCESS != result)
{
AIO_printf("\r\n>>adi_dma_MemoryOpen error!");
return;
}
else
{
AIO_printf("\r\n>>adi_dma_MemoryOpen OK!");
}
dma_memcpy(pArray_des, pArray_src, sizeof(int), 100);
// adi_dma_MemoryCopy2D();
do {
result = adi_dma_Control(
DMAStreamHandle,
ADI_DMA_CMD_GET_TRANSFER_STATUS,
(void *)&value);
if (ADI_DMA_RESULT_SUCCESS != result)
{
AIO_printf("\r\n>>adi_dma_Control error!");
}
else
{
AIO_printf("\r\n>>adi_dma_Control OK!");
}
} while(value); // TRUE(1) - inprogress, FALSE(0) -not in progess.
// if (!DmaDoneFlag) while(1);
buffer_check();
//should wait for a flag ti indicate before closing the channel.
result = adi_dma_MemoryClose( DMAStreamHandle, 1);
if (ADI_DMA_RESULT_SUCCESS != result)
{
AIO_printf("\r\n>>adi_dma_MemoryClose error!");
return;
}
else
{
AIO_printf("\r\n>>adi_dma_MemoryClose OK!");
}
result = adi_dma_Terminate(DMAManagerHandle);//In many embedded systems, the DMA manager is never terminated.
if (ADI_DMA_RESULT_SUCCESS != result)
{
AIO_printf("\r\n>>adi_dma_Terminate error!");
return;
}
else
{
AIO_printf("\r\n>>adi_dma_Terminate OK!");
}
}
阅读(748) | 评论(0) | 转发(0) |