Chinaunix首页 | 论坛 | 博客
  • 博客访问: 203347
  • 博文数量: 93
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 978
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-10 15:46
个人简介

青春无悔

文章分类

全部博文(93)

文章存档

2015年(16)

2014年(77)

我的朋友

分类: 嵌入式

2014-11-10 16:41:57

需求:算法移动数据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!");
    }

}

阅读(718) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~