现在的位置: 首页 > 综合 > 正文

DM642基于CSL的EDMA配置方法

2018年04月11日 ⁄ 综合 ⁄ 共 9192字 ⁄ 字号 评论关闭

 

目录

前言

.创建一个EDMA事件句柄

.PRAM(参数RAM区域)中分配事件的重载/连接参数

.EDMA事件分配传输结束代码,一般分配的结束代码等于EDMA事件通道号

.配置EDMA事件的参数RAM6个寄存器值

4.1.配置过程中需要禁止EDMA传输中断

4. 2.参数RAM配置

4.3.寄存器配置接口:

.配置EDMA相关中断以及ISR

5.1. 安装EDMA向量中断号(物理中断号)

5.2. 是否允许一次传输结束后产生中断(使能传输结束中断)

5.3. 挂接传输结束中断的中断服务程序(ISR)

5.4. 使能EDMA事件号的EDMA传输

.示例程序

6.1.示例程序1

6.2.示例程序2

前言

    本文以DM642VP口为例,描述了基于CSLEDMA的使用方法,包括EDMA的创建,初始化等.本文中是通过VPFIFO的阀值设置,触发(启动)EDMA的传输.FIFO的接收到的数据或者需要发送的数据达到自己设定的阀值,将启动一次EDMA的传输,修改相应的EMDA参数RAM的寄存器值.关于阀值的设置详细见文档“采集功能的配置步骤”。

.创建一个EDMA事件句柄

调用接口函数EDMA_Handle EDMA_open(int chaNum, Uint32 flags);

在使用EDMA之前,都必须先调用这个函数.

示例:

如果需要打开VP0的通道AY,U,V的传输,对应的事件号EDMA_CHA_VP0EVTYA=16, EDMA_CHA_VP0EVTUA=17,EDMA_CHA_VP0EVTVA=18

EDMA_Handle EDMA_VPAY_handle, EDMA_VPAu_handle, EDMA_VPAV_handle;

EDMA_VPAY_handle = EDMA_open(EDMA_CHA_VP0EVTYA, EDMA_OPEN_RESET);

EDMA_VPAU_handle = EDMA_open(EDMA_CHA_VP0EVTUA, EDMA_OPEN_RESET);

EDMA_VPAV_handle = EDMA_open(EDMA_CHA_VP0EVTVA, EDMA_OPEN_RESET);

参数flags-----EDMA_OPEN_RESET,表示复位EDMA通道,禁止中断,清除中断标志.

具体示例见示例程序1

.PRAM(参数RAM区域)中分配事件的重载/连接参数

函数接口:EDMA_Handle EDMA_allocTable(int tableNum);

此函数是为了实现复杂的数据传输方式,在传输BT656模式中,设置两帧数据,每一帧数据分为两场:顶场和底场,第一帧的顶场传输完成连接到底场,底场数据传输完成连接到第二帧的顶场,顶场数据传输完成连接到底场数据,底场数据传输完成再连接到第一帧的顶场数据传输,用四个RLD形成一个循环,每次底场数据传输完成产生中断,通过中断函数,把这一帧的顶场和底场数据入队列,DSP进行后续处理,

由于BT656由一个亮度分量和两个色度分量组成,因此,需要3*4个重载/连接参数 

具体示例见示例程序1

.EDMA事件分配传输结束代码,一般分配的结束代码等于EDMA事件通道号

函数接口:int EDMA_intAlloc(int tcc);

具体示例见示例程序1

.配置EDMA事件的参数RAM6个寄存器值

4.1.配置过程中需要禁止EDMA传输中断

EDMA_intDisable(chan->tcc[0]);

EDMA_intDisable(chan->tcc[1]);

4. 2.参数RAM配置

函数接口:void EDMA_config(EDMA_Handle hEdma, EDMA_Config *config);

    typedef struct {

  Uint32 opt;     //通道选择

  Uint32 src;     //源地址

  Uint32 cnt;     //阵列(二维)/(一维)计数

  Uint32 dst;     //目的地址

  Uint32 idx;     //阵列/帧索引

  Uint32 rld;     //重载地址参数

} EDMA_Config;

EDMA_config(chan->hEdma[i], &cfgEdma);//配置EDMA通道事件RAM

EDMA_config(chan->hRld[4 * i], &cfgEdma); //配置对应通道事件的传输事件RAM

4.3.寄存器配置接口:

EDMA_OPT_RMK(pri,esize,ds2,sum,dd2,dum,tcint,tcc,tccm,atcint,atcc,pdts,pdtd,link,fs);

EDMA_SRC_RMK(src)

EDMA_CNT_RMK(frmcnt,elecnt);

EDMA_DST_RMK(dst);

EDMA_IDX_RMK(frmidx,eleidx);

EDMA_RLD_RMK(elerld,link);

术语陈述:

对于传704*576大小的Y数据

EDMA_CNT_RMK(frmcnt,elecnt);

如果配置了EDMA传输的数据宽度为32.一帧为704个数据,那么frmcnt=576,elecnt=704/4(字节)

这里的帧表示对数据的打包形式或者是说一种数据组织结构的总称,上面的例子表示704个数据为一帧.

EDMA_IDX_RMK(frmidx,eleidx);采用帧索引的话,eleidx=0,frmidx=704(一帧的数据个数).

具体示例见程序示例2

.配置EDMA相关中断以及ISR

5.1. 安装EDMA向量中断号(物理中断号)

    EDMA的中断号为8,为固定的

函数接口:Void IRQ_map(Uint32 eventId,, int intNumber);

IRQ_map(IRQ_EVT_EDMAINT, irqId);

具体示例见程序示例2

5.2. 是否允许一次传输结束后产生中断(使能传输结束中断)

     函数接口: void   EDMA_intEnable(Uint32 tccIntNum);

void   EDMA_intDisable(Uint32 tccIntNum);

void   EDMA_intClear(Uint32 tccIntNum)

 EDMA_intClear(chan->tcc[0]);  

 EDMA_intEnable(chan->tcc[0]);

  EDMA_intClear(chan->tcc[1]);   

   EDMA_intEnable(chan->tcc[1]);

具体示例见程序示例2 

5.3. 挂接传输结束中断的中断服务程序(ISR)

函数接口: EDMA_IntHandler EDMA_intHook(int tccNum, EDMA_IntHandler funcAddr);

EDMA_intHook(chan->tcc[0], captureEdmaISR);      

 EDMA_intHook(chan->tcc[1], captureEdmaISR);

具体示例见程序示例2

5.4. 使能EDMA事件号的EDMA传输 

     函数接口: void   EDMA_enableChannel(EDMA_Handle hEdma);

     for(i = 0; i < numEdmaChans; i ++)

         {

 

            EDMA_disableChannel(chan->hEdma[i]);

            EDMA_clearChannel(chan->hEdma[i]);

            EDMA_enableChannel(chan->hEdma[i]);

        }   

 

        IRQ_enable(IRQ_EVT_EDMAINT);

    具体示例见程序示例2

.示例程序

6.1.示例程序1

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

for(j = 0; j <( _VPORT_NUM_EDMA_CHANS)&& retVal == IOM_COMPLETED; j ++)

{

    if( (chan->hEdma[j] = EDMA_open(chan->edmaChanNum[j], EDMA_OPEN_RESET))==EDMA_HINV //分配一个事件的重载或连接参数RAM(6个字)    

         ||  (chan->hRld[4 * j] = EDMA_allocTable(-1))==EDMA_HINV

         ||  (chan->hRld[4 * j + 1] = EDMA_allocTable(-1))==EDMA_HINV

         ||  (chan->hRld[4 * j + 2] = EDMA_allocTable(-1))==EDMA_HINV

         ||  (chan->hRld[4 * j + 3] = EDMA_allocTable(-1))==EDMA_HINV

                                   /*分配传输结束代码==EDMA事件号*/

         ||  (chan->tcc[j] = EDMA_intAlloc(chan->edmaChanNum[j])) == -1)

{

           retVal = IOM_EALLOC;

         msg_print("entrymdCreateChan ---retVal=%d----------jinx",retVal);

       }/* if((port->...*/

     msg_print("entry mdCreateChan ---retVal=%d--------------------jinx",retVal);

}

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

6.2.示例程序2

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

EDMA_Config  cfgEdma;

for(i = 0; i < numEdmaChans; i ++)

{

 

   Int optFld1 = EDMA_OPT_RMK(//YEVT通道事件参数RAM

                edmaPri,                // 1,EDMA传输具有最高优先级

                EDMA_OPT_ESIZE_32BIT,

                EDMA_OPT_2DS_NO,   //0,表示一维源

                EDMA_OPT_SUM_NONE, //0,表示固定源地址

                EDMA_OPT_2DD_YES,  // 1,表示二维目的

              EDMA_OPT_DUM_INC,  // 1,目的地址根据2DSFS位增加

                EDMA_OPT_TCINT_NO, // 0,禁止传输结束中断

                EDMA_OPT_TCC_OF(0), // 0,传输结束代码为0

                EDMA_OPT_TCCM_OF(0),//0,传输事件结束代码最大设置

                EDMA_OPT_ATCINT_NO,   // 0,禁止将要结束事件中断

                EDMA_OPT_ATCC_DEFAULT,

                EDMA_OPT_PDTS_DISABLE,//源地址为片内外设传输方式0,禁止片内外设读

                EDMA_OPT_PDTD_DISABLE,//目的地址为片内外设传输方式0,禁止片内外设写

                EDMA_OPT_LINK_YES,      // 1,事件参数连接使能

                EDMA_OPT_FS_NO          //0,数据或者阵列同步

            );

 

   

 

            Int optFld2a = EDMA_OPT_RMK( 

                edmaPri,

                EDMA_OPT_ESIZE_32BIT, 

                EDMA_OPT_2DS_NO,

                EDMA_OPT_SUM_NONE,

                EDMA_OPT_2DD_YES,

              EDMA_OPT_DUM_INC,  // 1,目的地址根据2DSFS位增加

                (i == 0 ? EDMA_OPT_TCINT_YES:EDMA_OPT_TCINT_NO),

                EDMA_OPT_TCC_OF(i == 0 ? chan->tcc[0] & 0x0f : 0),

                EDMA_OPT_TCCM_OF(i == 0 ? chan->tcc[0] >> 4 : 0),

                EDMA_OPT_ATCINT_NO,   

                EDMA_OPT_ATCC_DEFAULT,

                EDMA_OPT_PDTS_DISABLE,

                EDMA_OPT_PDTD_DISABLE,

                EDMA_OPT_LINK_YES,

                EDMA_OPT_FS_NO

            );

 

            Int optFld2b = EDMA_OPT_RMK(

                edmaPri,

                EDMA_OPT_ESIZE_32BIT,

                EDMA_OPT_2DS_NO,

                EDMA_OPT_SUM_NONE,

                EDMA_OPT_2DD_YES,

              EDMA_OPT_DUM_INC,  // 1,目的地址根据2DSFS位增加

                (i == 0 ? EDMA_OPT_TCINT_YES:EDMA_OPT_TCINT_NO),

                EDMA_OPT_TCC_OF(i == 0 ? chan->tcc[1] & 0x0f : 0),

                EDMA_OPT_TCCM_OF(i == 0 ? chan->tcc[1] >> 4 : 0),

                EDMA_OPT_ATCINT_NO,   

                EDMA_OPT_ATCC_DEFAULT,

                EDMA_OPT_PDTS_DISABLE,

                EDMA_OPT_PDTD_DISABLE,

                EDMA_OPT_LINK_YES,

                EDMA_OPT_FS_NO

            );

            thrld = (i == 0) ? chan->yThrld : chan->cThrld;

            cfgEdma.src = EDMA_SRC_RMK(chan->edmaAddr[i]);

            if(chan->interlaced) //隔行扫描模式 noted by jinx 2008.06.23

            {

                   if(!(params->cmode & _VPORT_MASK_RAW))//BT.656

                   { 

                     /* to merge the two fields together */

                     /* EDMA is configured to transfer only field 1 initially */

                     /* line pitch is twice the line size */

                     /* this requires that the threlhold is the same as line size */              

                     /* first field */

                       //#define EDMA_CNT_RMK(frmcnt,elecnt)

                       //阵列数为288-1;数据计数=704/4,

                       //因为设置为32位数据宽度,thrld表示2字的个数,

                       //因此转换为数据计数的时候需要把thrld*2,(thrld << 1)

                       //noted by jinx 2008.06.12

                     cfgEdma.cnt =

                       EDMA_CNT_RMK((chan->numEventsFld1) - 1, (thrld << 1));

                     if(chan->mergeFlds) {

                       //#define EDMA_IDX_RMK(frmidx,eleidx)

                       //thrld << 4表示隔行存放数据,留出存放场2或者场1的一行数据存储空间,

                       //thrld << 3表示连续存储,即存放完此场的一行数据后,接着还是存放此场的下一行数据

                         cfgEdma.idx = EDMA_IDX_RMK(thrld << 4, 0);

                     } else {

                         cfgEdma.idx = EDMA_IDX_RMK(thrld << 3, 0);               

                     }

                     /* hard code the first two frames as current and reload buffers */               

                     /* first field */

                     cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i + 1]);

                     cfgEdma.opt = optFld1;

                     cfgEdma.dst =

                       EDMA_DST_RMK(*((Int *)(&chan->viops[0].frame.iFrm.y1) + i));

                     EDMA_config(chan->hEdma[i], &cfgEdma);//配置EDMA通道事件RAM

                     EDMA_config(chan->hRld[4 * i], &cfgEdma); //配置对应通道事件的传输事件RAM

                     cfgEdma.dst =

                       EDMA_DST_RMK(*((Int *)(&chan->viops[1].frame.iFrm.y1) + i));

                     cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i + 3]);

                     EDMA_config(chan->hRld[4 * i + 2], &cfgEdma);

                     /* second field */

                     cfgEdma.opt = optFld2a;

                     cfgEdma.cnt =

                       EDMA_CNT_RMK((chan->numEvents-chan->numEventsFld1) - 1,

                        (thrld << 1));

                     cfgEdma.dst =

                       EDMA_DST_RMK(*((Int *)(&chan->viops[0].frame.iFrm.y2) + i));

                     cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i + 2]);

                     EDMA_config(chan->hRld[4 * i + 1], &cfgEdma);

                     cfgEdma.opt = optFld2b;

                     cfgEdma.dst =

                       EDMA_DST_RMK(*((Int *)(&chan->viops[1].frame.iFrm.y2) + i));

                     cfgEdma.rld = EDMA_RLD_RMK(0, chan->hRld[4 * i]);

                     EDMA_config(chan->hRld[4 * i + 3], &cfgEdma);                 

                 }

 

       }

 

}

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

抱歉!评论已关闭.