• TMS320C64X+ 中使用EDMA3中断


      关于EDMA3,TI的文档有详细的介绍。园子里的文章 http://www.cnblogs.com/fpga/archive/2009/10/13/1582516.html,http://www.cnblogs.com/fpga/archive/2009/09/25/1574127.html 对其有详细的介绍,下面主要介绍一下如何注册和捕获EDMA事件完成中断。代码是裸奔的,没有用到CSL。

      首先,要了解一下DSP的中断系统,可以参考文章:http://blog.csdn.net/ruby97/article/details/7538125 。

      CPU系统级的中断事件一共有128个,涵盖了各种外设的系统级中断事件(每个事件的编号都是固定的)。详细见c6455的综述文档。然后查看《TMS320C64x+ DSP Megamodule Reference Guide》文档,里面对中断系统有详细描述。

      

      这128个中断,被分成4种:

    1. Reset中断
    2. EXCEP(异常中断)
    3. NMI(不可屏蔽中断)
    4. INT[15:4]普通中断 

      我们正常情况下,都是只使用普通中断来处理事件。那么,128中断是如何被当做这四类中断处理的呢?

      我们可以看到,中断控制器中有个叫做 Interrupt Selector的单元。这个单元会把128个中断进行一次筛选,送入DSP来处理。实际上是一个 128-->12的映射,实际上DSP系统级中断处理个数非常有限。

      

      为了解决这个问题,可以将不同中断事件进行一个组合,再交给DSP处理。其中EVT[3:0]是一个组合事件,可以任意组合128个事件。

      

      

      所以,整个DSP中断系统的架构可以用下面的图形来展示:

      

      不同的事件,通过组合和筛选,最终被映射到16个系统级中断里来处理。

      

      其次,让我们来看看如何编写 ISR(中断服务)。

      与中断相关的必须设定的寄存器主要有

    •   ISTP 寄存器(设置中断向量表的首地址),必须为128字节对齐。
    •   EVTCLRn   (中断事件清除寄存器)
    •   EVTMASKn(中断事件屏蔽寄存器)
    •   EVTFLAGn (中断事件标识寄存器)
    •   INTMUX     (中断事件筛选寄存器)

      此外还有,ICR(中断控制寄存器),EVTSETn(中断事件使能寄存器),INTXSTAT(中断异常状态寄存器),INTXCLR(中断异常清除寄存器)等等。

      下面举例说明:

      1:编写GPIO1的上升沿触发EDMA3进行EDMA数据传输完成中断服务例程

      首先,设置ISTP,将中断向量表放到L2SRAM的某个地方(确保安全)。设置ICR,使能必要的中断。EVTCLRn设置,把所有事件都清除掉。EVTMASKn使能要用到的中断,INTMUXn筛选出需要的中断事件。

      这里,我们把 GPIO1触发的EDMA3中断,安排在EDMA3_INT2中,对应128个CPU的系统级中断标号为:73 = 0x49,同时我们把EDMA3_INT2 中断安排在 INT5的位置(优先级比较高)

        ICR = 0x0000FFF0;
        ISTP = 0x00922000; // interruput vector table location
    
        EVTCLR0 = 0xFFFFFFFF;
        EVTCLR1 = 0xFFFFFFFF;
        EVTCLR2 = 0xFFFFFFFF;
        EVTCLR3 = 0xFFFFFFFF;
    
        EVTMASK0 = 0xFFFFFFFF;
        EVTMASK1 = 0xFFFFFFFF;
        EVTMASK2 = 0xFFFFFFFF;
        EVTMASK3 = 0xFFFFFFFF;
    
        INTMUX1   = 0x4700492A;        // enable INT4 to RINT1, INT5 to EDMA3CC_INT2,  INT7 to EDMA3CC_INT0,
        INTMUX2   = 0x00004548;        // enable INT8 to EDMA3CC_INT1  //enable INT9 to TINT1
        INTMUX3   = 0x00000000;        //
        
    
        IER     |=    0x2;            // ENABLE NMI
        IER     |=    0x7f0;          // ENABLE INT4   INT7   INT8  INT9 INT10
    
        CSR    |=    0x1;                // enable intertuput

      接着,千万别玩了配置GPIO1的工作模式,设置为上升沿触发

      

        GP_BINTEN |= 0x1 ;           //enable gpio as souce of interruput
        GP_DIR  &= (0xffffffaf);     //set GP[4] GP[6] output
        GP_DIR  |= (0xa2);           //set GP[5] GP[7] GP[1] as input 
        GP_SET_RIS_TRIG |= 0xa2 ;    //the rising edge of gpio1 and gpio5 gpio7 trige the interruput or event

      然后,我们要配置EDMA3的GPIO对应的中断,查看6455综述文档,我们发现EDMA3相关的事件共有64个

      

      其中GPIO1,对应为事件EVT:49(注意不要跟系统级中断事件混淆),EDMA初始化代码如下:

      这里,我们从EMIFA_CE2_BASE_ADDR(源地址)搬移数据到目的地址(0x009fb880),使用二维数据传输,每次传输32bit,不使用Chain模式(我们只传输一次)。

      在OPT参数中,我们打开了传输完成中断(TCINTEN = 1),LINK = NULL,并且设置 TCC(Transfer Complete Code) = 49(传输完成码)

      这里非常容易混淆,TCC的值该如何设定? 文档中的表述说明,其实TCC的值可以随意设定(0-63)假设为:n,一旦该传输完成,EDMA3内部通道:n,产生一个事件(注意这是EDMA内部事件)

      IPTRn对应的某个位置变成:1。表明触发了该事件!!!不同的EDMA通道,可以设定相同的TCC(但是我不建议这么做,除非你有一个理由!)

      这样一来,我搞了好久才发现,EDMA3的触发事件(外设触发EDMA传输) 和 EDMA3 通道传输完成事件(TCC=n)并一毛钱的关系!!!

      那么EDMA3 的内部事件如何捕获呢?

      我们发现,EDMA3 传输完成事件,总共有64个,然而EDMA3在CPU系统级中断对应的只有 8个事件

      

       64个事件,怎么当做8个事件来处理呢???这里就要看到EDMA3内部有个DRAE(DMA Region Access Enable Register),这几组寄存器来对EDMA3的64个事件进行筛选(MASK),映射到8个系统级中断中去。

       

      总结一下:

      对于要使用中断的通道而言,要确保对应的Parameter Set中的OPT位置上 TCINTEN = 1, TCC = n(n随意,是对应EDMA3内部完成事件标号),使能该事件 EESR = n,使能该事件中断 IESR = n,配置 DRAE = n

      对于不使用传输完成中断的通道而言,OPT中设置 TCINTEN = 0即可

        EDMA3CC_DRAE2  = 0x00000004;
        EDMA3CC_DRAEH2 = 0x00000000;
        
        EDMA3CC_DCHMAP49 = 0x000000A0; // map channel 49(tied to gpio1 event) to PaRAM set 5
        EDMA3CC_EESRH |= 0x00020000;   // enable the event/channel 49
        EDMA3CC_IESR  |= 0x00000000;   // enable the TCC=49 interrupt
        EDMA3CC_IESRH |= 0x00020000;
        EDMA3CC_DMAQNUM6 |= 0x00000020; //Event 49 is queued on Q2
        pEDMA3CC_PaRAM = EDMA3CC_PaRAM5;
        pEDMA3CC_PaRAM->OPT = 0x0013120C; //TCINTEN=1;TCC=49;SYNCDIM=1(AB);32-bit mode,static=1
        pEDMA3CC_PaRAM->SRC = EMIFA_CE2_BASE_ADDR;//EMIFA_CE2_BASE_ADDR
        pEDMA3CC_PaRAM->BCNT_ACNT = 0x05000004; //ACNT=32;BCNT=4576;
        pEDMA3CC_PaRAM->DST = (volatile long*)(0x009fb880);//
        pEDMA3CC_PaRAM->DSTBIDX_SRCBIDX = 0x00040004; //DSTBIDX=8;SRCBIDX=8;
        pEDMA3CC_PaRAM->BCNTRLD_LINK = 0x0000FFFF;     //LINK=NULL
        pEDMA3CC_PaRAM->DSTCIDX_SRCCIDX = 0x0;
        pEDMA3CC_PaRAM->RSVD_CCNT = 0x00000001;
        
        EDMA3CC_EMCR = 0xFFFFFFFF;
        EDMA3CC_EMCRH = 0xFFFFFFFF;
        EDMA3CC_ICR = 0xFFFFFFFF;
        EDMA3CC_ICRH = 0xFFFFFFFF;

      然后,配置中断向量表

      

    .ref    _EDMA3CC_INT2   
    INT5:
        STW.D2      B0,*B15--
        NOP         4
        MVKL.S2     _EDMA3CC_INT2,B0
        MVKH.S2        _EDMA3CC_INT2,B0
        b.S2        B0
        LDW.D2      *++B15,B0
        NOP         4
        nop

      最后,编写对应的中断服务例程

      

    void interrupt EDMA3CC_INT2()
    {
        EDMA3CC_EMCR = 0xFFFFFFFF;
        EDMA3CC_EMCRH = 0xFFFFFFFF;
        EDMA3CC_ICR = 0xFFFFFFFF;
        EDMA3CC_ICRH = 0xFFFFFFFF;
      // do something
    }

      

  • 相关阅读:
    Java多线程初学者指南(5):join方法的使用
    Java多线程初学者指南(4):线程的生命周期
    使用Runnable接口创建线程-3
    用Thread类创建线程-2
    线程简介-1
    Struts, Namespace用法
    多线程编程
    算法实例
    java 堆与栈的区别
    Spring AOP EXPRESSION
  • 原文地址:https://www.cnblogs.com/fangying7/p/3783898.html
Copyright © 2020-2023  润新知