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.

C6727: McASP接口,接收数据正常,但无法发送数据



各位前辈:

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

(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;};

  • 把你的原程序文件,或者工程发上来更方便查看修改些。

  • Tony Tang :

        非常感谢您的帮助,现将工程附上,请专家帮忙诊断。工程已在CCS3.3中调试通过,问题还是出在XBUF写数据后无数据输出,对应的串口控制器的XRDY始终处于0状态。

    在论坛中还看到其他兄弟反应类似的问题,在mcasp的发送端可能大家碰到过同类的困惑,请专家指点迷津。

    程序中的寄存器控制字全部回避使用CLS库,共兄弟们参考,请拍板砖。

    example.zip
  • Dahai,

    #1. 对于配置有个地方我不确定你的系统时钟是多少,以及McASP口的时钟要配置为多少,所以对于    AHCLKXCTL0 = (1<<15 | 3); 后面的divider不能确定,需要你自己计算一下。

    #2. 不对知道你对AIC23配置的数据宽度是多少,需要你自己对XFMT的slot size确定一下。

         XFMT0 = (  1<<16     |  1<<15    |   0x0F <<4  |  1<<3);

    #3. 跑一下修改过的工程,如果有问题再说。

    example.zip
  • 刚注意到只用Slot 0,还是把下面void set_McASP0()里的最后一句(如下)去掉吧,不然怕接收端underrun。

      
       while((XSTAT0 & 0x20)!=0x20);
       XBUF00=0;

  • Tony Tang :

    感谢您的热心支持。程序中问题依旧,现就您比较关注而我未说清楚的问题,回复如下:

    (1)系统时钟为24.576MHz(Mcasp的内部分频时使用AUXCLK,即系统时钟);

    (2)Mcasp收发采用TDM、2slot模式,但仅slot0有效;

    (3)每一个slot为32bit,采样数据率为96KHz(AIC23B中配置),故采样数据由AIC23向McASP传输的速率为2*32*96=6144KHz,也就是Mcasp的移位时钟频率CLK。对高频时钟AHCLKX进行分频、ACLKX进行1分频,由此可计算出高频时钟的分频为24.576MHz/6144KHz=4,由此确定AHCLKXCTL0 的参数值

    系统自运行以来,一直表现的症状为:

    数据接收通道正常:通过采样标准的正玄波,分析器频率可以确定接收通道没有问题;

    发送通道:写数据至XBUF后,对应的SRCTL的Xdata位一直未0、数据也为发送出去(观测D/A通道波形)。

    还请Tony Tang 指点迷津!!!!(下面帖子说的语句去掉后,问题依旧)

  • 检查一下XUNDRN是否置1了?也就是说发送buffer是否 underrun了。

    按说都是用的内部时钟,只是sync mode,没道理只能接收,不能发送。

  • Tongtang:

        您好,根据您的提示和帮助,我查看了STAT在状态,确实发生了XUNDRN。我将程序调整为不断向XBUF写数据并全速运行后,能输出音频(通过耳机收听)。但设置中断一旦程序停下后,再启动运行时,就又无音频输出了,SRCTL&0x10!=0不能通过;查询XSTAT状态(0x151),发生了XUNDRN。

       实际应用中,我的程序并不是一直在往XBUF写数据的,而且,程序调试时,也因设置中断而停止运行,这些情况下,都无法再次输出音频,除非程序复位重新运行。我试着在写XBUF前,通过XSTST&0xFFFFFFFE,对XUNDRN清零,但问题也得不到解决,还请Tongtang大师进一步指点迷津。

  • Dahai,

    这种现像就对了,在C6727的McASP user guide里有下面描述,即underrun之后,需要复位McASP,并重新配置。通常来说,McASP口使能之后是一直运行的,除非将之复位,即将GBLCTL清0.

    3.6.2 Buffer Underrun Error - Transmitter

    In TDM mode, during an underrun case, a long stream of zeros are shifted out causing the DACs to mute. To recover, reset the McASP and start again with the proper initialization.

    下面是一个关闭McASP的函数例程。

    void shutdownAudio(void)
    {
       // close codec.
       AIC3106_writeRegister(AIC3106_REG_PAGESELECT, 0);
       AIC3106_writeRegister(AIC3106_REG_RESET, 0x80);

       // close mcasp.
       MCASP->SRCTL0 = 0;
       MCASP->SRCTL1 = 0;
       MCASP->SRCTL2 = 0;
       MCASP->SRCTL3 = 0;
       MCASP->SRCTL5 = 0;
       MCASP->SRCTL11 = 0;
       MCASP->SRCTL12 = 0;
       MCASP->GBLCTL = 0;
    }

    在实际应用当中:

    #1. 音频数据是连续的,除非人为停止,所以I2S接口的时钟在使能后,就一直有。

    #2. 中断本身不是问题,关键是中断ISR占用的时间不能太长,超出McASP响应的实时要求。

    #3. 实际应用中,不会用轮循的办法去服务McASP,这样效率太低,要用EDMA,CPU只响应EDMA的中断,这样中断的频率就很低了,如果直接用McASP的中断,太频繁,效率太低,不实用。

    #4.在实际应用中,使能McASP的错误中断,这样可以知道什么时候出错了,并做相应的处理,如复位McASP,重新配置等。

     

  • TongTang:

    问题全部解决,我明白了;非常感谢您的热情帮助!!!因我们的需求有点特殊,需要对每一个采样Sample进行处理;所以我们还是优化程序结构、用中断的方式,在XBUF为空时,及时写入合适的数据。

  • @dahai  请问你是怎么解决的?

    我目前也在做am335x上的mcasp, 现在遇到的问题和你之前的问题类似, 时钟和同步信号都量到了,但就是没有量到数据信号?

    数据已经送到XBUF了,还需要注意哪些?

    谢谢

  • Lauffer,

    如果你还有问题,建议你在sitara论坛另启一个贴子,尽量详细描述你的问题,毕竟你的问题是另一个芯片的(虽然都差不多),这样对于你的问题有人跟踪回答更有保障。

  • 别设置中断,全速运行,在测量输出信号试试。

  • 你好,我现在做的是用MCASP发送解调后的音频数据,但是用的是靠mcasp轮询发送的方式,所以每次都是解调出数据后进行发送 ,然后DSP程序继续运行 等下一次解调后继续发送新的数据、这样发送出来的数据断了。不能得到完整的音频波形。没有数据的时候系统正在执行DSP 的其他程序(类似解调数据的计算等等)。如你说说的实际应用#3.用EDMA配合mcasp每次我算出来的解调数据、依靠EDMA进行循环发送。这样我的CPU就能释放出来继续执行DSP的其他程序。应该是一个比较好的解决方案、但是能不能指导一下具体怎么做??

    我现在用的是直接对ASP 寄存器初始化配置,然后发数的方法。谢谢指导