This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

OMAPL138 DSP MCASP接口 输出数据问题

Other Parts Discussed in Thread: TLV320AIC3104

大家好,目前我遇到了一个棘手的问题,希望大家帮助。

1.运行环境:IDE: CCSV5  仿真器:XDS100-V2   操作系统:windows XP

2.主芯片:OMAPL138   TLV320AIC3104

3.设计概况:TLV320AIC3104与OMAPL138的MCASP接口连接,配置时,3104为主设备,OMAPL138  DSP为从设备。MCASP的AFSX、ACLKX、AXR7、           AXR15 分别于3104的WCLK、BCLK、DOUT、DIN连接。

     (a).配置3104的采样率为16K,时钟源来自12.288M的外部晶振,使用内部的PLL(具体配置为R=1,P=1,J=8,D=0),Page 0 register 2 为0x44

     (b).配置3104为master  mode ,I2S ,16 bit ,slot 0  1, 0 bit delay(详细配置见附件中源文件)

    3104调试结果:用示波器测量WCLK 为15.9999KHZ(理论值应该是16KHZ),BCLK为511.996KHZ(理论值为应该是512KHZ),DOUT接口有输出信号。

                                BCLK=32*WCLK。

  (c)配置MCASP AFSX 、ACLKX为外部时钟,ASYNC=0,收发同步。(详细配置见附件中的源文件)

4.目前遇到的问题:采用CPU轮询的方式可以读到3104送出的数据(尚未验证接收到的数据是否正确),往发送缓冲区写数据(对应的为XBUF15),用示波器     测量其外部引脚无信号。
请大家帮忙解决下,手册我已经读了N遍了,个人感觉是按照手册严格配置的,但就是得不到想要的结果。

MCASP&3104配置源文件.zip
  • 是否有自己先参考比较BSL包里的例子程序?

  • BSL包里面有个3106的程序,貌似3106是从,MCASP是主,我这块板子上AHCLKX/R没有外接时钟,AUXCLK从系统时钟过来为24M,若MCASP为主的话,我感觉不能准确分频,得到3104   16K采样率所需的时钟频率。(这点我不知道我理解的是否正确)。

    还有个问题,3104为主的情况下,得到BCLK为512KHZ,WCLK为16KHZ,采样率为16K,用示波器观察,字时钟的上升沿和下降沿都对应着位时钟的下降沿,请问产生的时钟是否正确 ?

  • 怎么读写BUFFER,我是这样操作的,您看对吗?谢谢!

    for(sec=0;sec<5;sec++)
       {
        for(msec=0;msec<1000;msec++)
        {
         for(sample=0;sample<16;sample++)
         {
          while(!(MCASP->SRCTL7&0x20));
          sample_data=MCASP->RBUF7;
          while(!(MCASP->SRCTL15&0x10));
          MCASP->XBUF15=sample_data;
          while(!(MCASP->SRCTL7&0x20));
          sample_data=MCASP->RBUF7;
          while(!(MCASP->SRCTL15&0x10));
          MCASP->XBUF15=sample_data;
         }
        }
       }

    写的时候,XDATA中有underrun错误。

  • TI专家:

    这个问题可能是一些细节上的问题,尝试了很多方法,现在依然不行,有种黔驴技穷的感觉,求调试思路。多谢了。

    ZV138_APP_V1.0_3104_driver_v1.0.zip
  • 注意这个例子在收发数之前,在使能McASP之后,先发送一个空数,因为使能后,发送寄存器是空的,如果等到收到数才发送,肯定就underrun了。

       // wait for transmit ready and send a dummy byte.
       while(!CHKBIT(MCASP->SRCTL11, XRDY)) {}
       MCASP->XBUF11 = 0;

  • 要不把整个测试工程贴上来看看,从两个配置文件看不出什么来。

  • TI专家:

          您好!我已经把整个工程都贴上去了,麻烦您帮我看下,谢谢。

     

  • RSTAT中也有overrun的错误。

  • 从你的代码流程来看是先配置McASP, 再配AIC3104,然后收发数。

    比较BSL的例子的流程是有区别的,例子里是在收发数之前才把McASP使能。

    不清楚AIC3104是在哪一步开始往外送时钟,这么做的风险是当McASP配置完后,AIC提供时钟,而此时代码还没有到收发数据阶段,如果这个时间差过长,那么必然会导致underrun, overrun。

    建议对比一下BSL的例子的流程以。先配置好AIC,McASP的基本配置,最后使能McASP的收发模块,再收发数据。

    另外,建议改成EDMA的方式以提高效率。

  • wei lee1 说:

    for(sec=0;sec<5;sec++)
       {
        for(msec=0;msec<1000;msec++)
        {
         for(sample=0;sample<16;sample++)
         {
          while(!(MCASP->SRCTL7&0x20));
          sample_data=MCASP->RBUF7;
          while(!(MCASP->SRCTL15&0x10));
          MCASP->XBUF15=sample_data;
          while(!(MCASP->SRCTL7&0x20));
          sample_data=MCASP->RBUF7;
          while(!(MCASP->SRCTL15&0x10));
          MCASP->XBUF15=sample_data;
         }
        }
       }

    下面是BSL例子的代码,如果是同一个时钟源,那就先发后收,收的时候也必要检查状态,肯定数据是ready的。关键还是配置的顺序,另外清除underrun与overrun,程序也是应该可以往下跑的。


       // wait for transmit ready and send a dummy byte.
       while(!CHKBIT(MCASP->SRCTL11, XRDY)) {}
       MCASP->XBUF11 = 0;

       // loop audio
       for (sec = 0; sec < 15; sec++)
       {
          for (msec = 0; msec < 1000; msec++)
          {
             for (sample = 0; sample < 48; sample++)
             {
                // wait for recv ready and send a sample to the left channel.
                while (!CHKBIT(MCASP->SRCTL11, XRDY)) {}
                MCASP->XBUF11 = dat;
                dat = MCASP->XBUF12;

                // wait for recv ready and send a sample to the right channel.
                while (!CHKBIT(MCASP->SRCTL11, XRDY)) {}
                MCASP->XBUF11 = dat;
                dat = MCASP->XBUF12;
             }
          }
       }
       return (rtn);
    }

  • 我修改了配置顺序,先配置3104,由于3104工作在master模式,3104配置结束时,就产生了WCLK和BCLK。然后配置MCASP,复位帧同步发生器后,运行的是参照的你给BSL中的代码,先发后接收。调试结果:程序能往下跑,但MCASP依然没有输出。程序运行结束时,查看XSTAT和RSTAT寄存器,仍然存在underrun与overrun。

    疑问#1:先配置3104产生的时钟对MCASP会有影响吗?MCASP都是最后复位,我感觉影响不大。这样理解正确吗?

    疑问#2:3104配置的是0 bit delay,MCASP的接收和发送配置的也都是 0 bit delay。这正确吗?

    疑问#3: 当AFSX选择外部时,ACLKXCTL寄存器的CLKXP配置成0或1是不是一样的,XCLK不连接到AFSX模块。这正确吗?

  • 疑问#4:用示波器观察3104的WCLK和BCLK,WCLK的上升沿和下降沿都对应着BCLK的下降沿,MCASP的AFSX和ACLKX的时钟边沿该如何配置呢?

  • 疑问#5:如果不采用CPU轮询的方式,改用EDMA,是否可以规避underrun和overrun的错误呢?(EDMA还没看该怎么配置,等下我实验下)

  • 疑问#1:先配置3104产生的时钟对MCASP会有影响吗?MCASP都是最后复位,我感觉影响不大。这样理解正确吗?

    【TT】没有影响,McASP解复位前是不会工作的。

    疑问#2:3104配置的是0 bit delay,MCASP的接收和发送配置的也都是 0 bit delay。这正确吗?

    【TT】发送与接收方配置一致,正确。

    疑问#3: 当AFSX选择外部时,ACLKXCTL寄存器的CLKXP配置成0或1是不是一样的,XCLK不连接到AFSX模块。这正确吗

    【TT】不一样,发送方要根据接收方的要求配置,比如配置发送方上升沿发送,则接收方要配置为下降沿采数。反之亦然。否则采数不正常。

     

  • 时钟是AIC3104送出来的,且是0bit delay,那说明AIC3104是下降沿送数,MCASP则要上升沿采数。

    对McASP做为发送方来说,也是下降沿送数,AIC3104应该是上升沿采数。

  • $5. 在真正的系统中用CPU轮询肯定不现实,这样CPU就没时钟干别的事了,不过这里用哪种方法与underrun,overrun没有关系。

    前面提到程序能往下跑,说明中间没有出现过underrun,overrun,否则中间在等待条件时会卡死的,等不到状态,一定要清除underrun,overrun才可以继续往下运行的。是最后没有disable AIC或MCASP,而时钟一直在提供,而McASP退出循环,不再读写数,所以出现underrun,overrun。

    数据不正确可能与极性配置有关,同时RX上有数据吗?也可以参考例子的beep部分,先验证发送部分。

  •  问题早就解决了,但一直没有时间结贴,感谢Tony Tang给予的帮助。

    在这个工程中犯了一个说起来让人脸红的错误,MCASP的引脚复用搞错了,吸取这次的经验教训,以后在调试类似问题的时候首先保证引脚复用,时钟,引脚输入输出方向是正确,然后再去调试其他。

    附件中我给出了我的工程,采用CPU轮询的方式实现了AIC3104的直通。分享给大家,希望大家做类似东西的时候能够给予一点帮助。

    ZV138_APP_V1.0_3104_driver_v1.0.zip
  • 各位前辈:

    我也碰到了类似的问题,求各位高手指点!使用环境如下:

    (1)采用C6727B的mcasp接收AIC23B的音频采样数据;

    (2)Mcasp工作与同步模式、时钟信号由内部产生;对应AXCLK、AFSX接入到Aic23的BCLK、LRCIN和LRCOUT;

    (3)Mcasp工作于突发模式,2slot,但只传输一个slot0,故RTDM和XTDM均为1;

    结果:接收数据正常,但发送数据始终发不出来;查询对应SRCTLn中XRDY状态,始终为0.该问题已困扰10个深夜了,也黔驴技穷,求高手指点!

    相关寄存器配置如下:

    /************************复位***************************/

     #define GBLCTL0   (*(unsigned int*)(McASP0_BASE + 0x44))
      #define DLBCTL0   (*(unsigned int*)(McASP0_BASE + 0x4c))
     #define RGBLCTL0   (*(unsigned int*)(McASP0_BASE + 0x60))
     #define XGBLCTL0   (*(unsigned int*)(McASP0_BASE + 0xA0))
     GBLCTL0=0;
     flag=GBLCTL0;    while(flag!=0){flag=GBLCTL0;};

     DLBCTL0=0;
     flag=DLBCTL0;    while(flag!=0){flag=DLBCTL0;};

    /************************接收端口配置***************************/

        #define RMASK0   (*(unsigned int*)(McASP0_BASE + 0x64))
      #define RFMT0   (*(unsigned int*)(McASP0_BASE + 0x68))
      #define AFSRCTL0   (*(unsigned int*)(McASP0_BASE + 0x6c))
      #define RTDM0   (*(unsigned int*)(McASP0_BASE + 0x78))
         RMASK0=0xFFFFFFFF;
         RFMT0=0x0000180f8;     ////1bit delay;MSB first;32bit;peripherial bus
         AFSRCTL0=0x00000113; ////2-slot,1word width;internal FS;falling edge begin a frame--1;rising edge----0
         RTDM0=1;              // slot 0 is active; CSL_MCASP_RTDM_RTDMS_MASK; //all slot is active
        
       

    /************************发送端口配置***************************/

      #define XMASK0   (*(unsigned int*)(McASP0_BASE + 0xA4))
      #define XFMT0   (*(unsigned int*)(McASP0_BASE + 0xA8))
      #define AFSXCTL0   (*(unsigned int*)(McASP0_BASE + 0xAc))
      #define XTDM0   (*(unsigned int*)(McASP0_BASE + 0xB8))
         XMASK0=0xFFFFFFFF;

         XFMT0=0x000180f8;     ////1bit delay;MSB first;32bit;peripherial bus
         flag=XFMT0;  while(flag!=0x000180f8){flag=XFMT0;};
     
         AFSXCTL0=0x00000113; ////2-slot,1word width;internal FS;falling edge begin a frame--1;rising edge----0
        flag=AFSXCTL0;  while(flag!=0x00000113){flag=AFSXCTL0;};

         XTDM0=1;              // slot 0 is active; CSL_MCASP_RTDM_RTDMS_MASK; //all slot is active
       flag=XTDM0;  while(flag!=1){flag=XTDM0;};

    /************************发送时钟配置***************************/

       #define ACLKXCTL0   (*(unsigned int*)(McASP0_BASE + 0xB0))
       #define AHCLKXCTL0   (*(unsigned int*)(McASP0_BASE + 0xB4))
       #define XCLKCHK0   (*(unsigned int*)(McASP0_BASE + 0xC8))
       ACLKXCTL0=0x00000020;
       XCLKCHK0=0xFF000F;
       AHCLKXCTL0=0x00008003;

     

    /************************接收时钟配置***************************/


       #define ACLKRCTL0   (*(unsigned int*)(McASP0_BASE + 0x70))
       #define AHCLKRCTL0   (*(unsigned int*)(McASP0_BASE + 0x74))
       #define RCLKCHK0   (*(unsigned int*)(McASP0_BASE + 0x88))
       ACLKRCTL0=0x000000a0;
       RCLKCHK0=0xFF000F;
       AHCLKRCTL0=0x00008003;

     

       SRCTL01=2;//mcasp01为接收器
       flag=SRCTL01;    while(flag & 0x03!=2){flag=SRCTL01;};

       SRCTL00=1;//mcasp00为发送器
       flag=SRCTL00;   
       flag=flag & 0x03;
       while(flag !=1){flag=SRCTL00;};

    /************************中断与DMAX event26关联的配置(此处验证无问题)***************************/

      RINTCTL=RINTCTL|0x20;//RINTCTL & 0xFFFFFFEF;//
       flag=RINTCTL;    while(flag & 0x20==0){flag=RINTCTL;};

       XINTCTL=XINTCTL|0x20;
       flag=XINTCTL;    while(flag & 0x20==0){flag=XINTCTL;};

       AMUTE=AMUTE & 0xFFFFFFF3;
       flag=AMUTE;    while(flag & 0x0C!=0){flag=AMUTE;};

    /************************传输端口配置***************************/

    //set PFUNC;PDIR;DITCTRL;AMUTE.
     PFUNC0= ~(B28_MSK | B26_MSK | B1_MSK | B0_MSK); //McASP AFSX,ACLKX,AXR[01],AXR[00]

     PDIR0 = (B28_MSK | B26_MSK | B0_MSK);// |   //Output AFSX,ACLKX,AXR[00]

      /************reset AHCLK **************/
       RGBLCTL0=RGBLCTL0|0x02;// RHCLKRST XHCLKRST置1
       flag=RGBLCTL0;    while(flag & 0x02==0){flag=RGBLCTL0;};

       XGBLCTL0=XGBLCTL0|0x200;// RHCLKRST XHCLKRST置1
       flag=XGBLCTL0;    while(flag & 0x200==0){flag=XGBLCTL0;};

        /************reset ACLK **************/
       RGBLCTL0=RGBLCTL0|0x01;// XCLKRST RCLKRST置1
       flag=RGBLCTL0;    while(flag & 0x01==00){flag=RGBLCTL0;};
       XGBLCTL0=XGBLCTL0|0x100;// XCLKRST RCLKRST置1
       flag=XGBLCTL0;    while(flag & 0x100==0){flag=XGBLCTL0;};

       //激活串行器
       XSTAT=0xFFFF;
       RSTAT=0xFFFF;
       XGBLCTL0=XGBLCTL0|0x400;// RSRCLR XSRCLR1
       flag=XGBLCTL0;    while(flag & 0x400==0){flag=XGBLCTL0;};

       RGBLCTL0=RGBLCTL0|0x04;// RSRCLR XSRCLR1
       flag=RGBLCTL0;    while(flag & 0x04==0){flag=RGBLCTL0;};

       XBUF00=0;
       RBUF01=0;

       //状态机退出复位
        RGBLCTL0=RGBLCTL0|0x08;// RSMRST XSMRST
     flag=RGBLCTL0;    while(flag & 0x08==0){flag=RGBLCTL0;};

     XGBLCTL0=XGBLCTL0|0x800;// RSMRST XSMRST
     flag=XGBLCTL0;    while(flag & 0x800==0){flag=XGBLCTL0;};

     //帧同步信息退出复位
         RGBLCTL0=RGBLCTL0|0x10;// XFST RFRST
       flag=RGBLCTL0;    while(flag & 0x10==0){flag=RGBLCTL0;};
      XGBLCTL0=XGBLCTL0|0x1000;// XFST RFRST
       flag=XGBLCTL0;    while(flag & 0x1000==0){flag=XGBLCTL0;};

     

  • RTDM0和XTDM0都应该配成3吧。

    另外总体的配置步骤没有按按照C6727 McASP的user guide来做。

  • Tony Tang:

    不知这么理解对不对:

    (1)RTDM0和XTDM0都应该配成3:

    TDM模式下,2个slot,但我只接收slot0的数据,故为1.

    (2)另外总体的配置步骤没有按按照C6727 McASP的user guide来做

    我是参考《TMS320C672x DSP Multichannel Audio Serial Port (McASP) Reference Guide (Rev. B)》进行的,具体哪个位置的顺序不对,还请专家指点啊。

     

     

     

  • 您好,请问一下例子程序包在哪里下载??

  • 你好  我下了你的工程。但是运行的时候任然卡在标志位那里  while(!(MCASP->SRCTL15&0x10));  就在这里死循环了。  本身有找过网上其他的测试代码,但是都是以axr11  axr12作为DIN DOUT     而我的是用合众达的  看原理图是以axr15  axr7作为DIN DOUT 。         跟你的程序应该对应的,不知道有什么问题,求解答,谢谢。PS 我是新手。

  • 您好!我也碰到类似的问题。

    当前我用AM335x的MCASP0的TDM模式读取codec音频数据,使用引脚为FX,ALCK,AXR0(收),AXR1(发),工作在主模式,现在能正常收到codec的音频数据,但转发出去的时候,引脚无信号,检查了下引脚配置,没查出问题所在。感觉也是引脚配置问题,其他三个脚都ok。

    请问您能否具体讲下你的引脚配置呢,比如方向模式等。谢谢!