TI中文支持网
TI专业的中文技术问题搜集分享网站

McAsp采用loopback模式,能够收发数据,但是数据引脚上无法捕捉到任何变化

【芯片型号】TMS320DM8148

【开发环境】软件:linux 驱动 硬件:第三方提供的EVM板,相应的引脚已经引出。

【问题描述】

            实验目的:配置McAsp0为loopback模式,通过cpu轮询发送MCASP0.1,接收MCASP0.0。期望能在RBUF0接收到发送的数据,并在发送引脚MCA0.AXR1测量到发送电平信号。

            实验步骤:编写驱动模块mcasp.ko,加载模块后,配置mcasp引脚复用,时钟选择,工作模式等,用CPU轮询发送,接收数据。

                          1.配置PinMux,将MCASP0相关所有引脚配置为MCASP功能。参考的:tms320dm8172,P153

                          2.配置MCASP0 时钟,采用SYSYCLK22提供AUX_CLK。参考的:SPRUGZ8e ,P458

                          3.配置MCASP0 工作模式,并启动MCASP0开始工作。 参考的:SPRUGZ8e ,P2075

                          4.CPU轮询在XBUF1上发送,在RBUF0上接收。用一个数组recv_array_test存取每一次接收的RBUF0数据。

              实验结果:recv_array_test数组中显示接收到了XBUF1发送的数据。但是在对应的MCASP0.AXR1引脚上并没有测量到任何的电平变化,同时没有帧同步信号引脚MCASP0.AFS也没有任何变化?

              疑问:根据SPRUGZ8e ,P2073页中提到,在loopback模式下应该能够在发送引脚上测量到电平的变化,尝试过去掉loopback配置还是没有任何变化。俺是个新手,对DSP零基础,不知道问题出在哪了。恳请各位前辈,指出问题所在,万分感谢!!!!

【备注】附件中有完整的模块代码,关键操作如下:

static int mcasp_module_init(void)
{
 //enable mcasp 0,1,2
 mcasp_device *mcasp0;
 mcasp_device *mcasp1;
 mcasp_device *mcasp2;
 mcasp_device *mcasp3;
 mcasp_device *mcasp4;
 mcasp_device *mcasp5;
 void __iomem * pll_base;
 void __iomem * mux_base;
 void __iomem * pcrm_base;
 g_mcasp_module.mcasp_group = &g_mcasp_device_group[0];
 kdbg_msg(2,"init mcasp module…..\n");

 mcasp0 = &g_mcasp_device_group[0]; 
 mcasp1 = &g_mcasp_device_group[1]; 
 mcasp2 = &g_mcasp_device_group[2]; 
 mcasp3 = &g_mcasp_device_group[2]; 
 mcasp4 = &g_mcasp_device_group[2]; 
 mcasp5 = &g_mcasp_device_group[2]; 

 mcasp0->ctl_phy_base = MCASP0_PHY_BASE;
 mcasp0->ctl_reg_len = MCASP0_DATA_SIZE;

 mcasp1->ctl_phy_base = MCASP1_PHY_BASE;
 mcasp1->ctl_reg_len = MCASP1_DATA_SIZE;

 mcasp2->ctl_phy_base = MCASP2_PHY_BASE;
 mcasp2->ctl_reg_len = MCASP2_DATA_SIZE;

 mcasp3->ctl_phy_base = MCASP3_PHY_BASE;
 mcasp3->ctl_reg_len = MCASP3_DATA_SIZE;

 mcasp4->ctl_phy_base = MCASP4_PHY_BASE;
 mcasp4->ctl_reg_len = MCASP4_DATA_SIZE;

 mcasp5->ctl_phy_base = MCASP5_PHY_BASE;
 mcasp5->ctl_reg_len = MCASP5_DATA_SIZE;

 mcasp0->enable_reg = ioremap(CM_ALWON_MCASP0_CLKCTRL,4);
 mcasp1->enable_reg = ioremap(CM_ALWON_MCASP1_CLKCTRL,4);
 mcasp2->enable_reg = ioremap(CM_ALWON_MCASP2_CLKCTRL,4);

 if( (NULL == mcasp0->enable_reg) || (NULL == mcasp0->enable_reg ) || (NULL == mcasp0->enable_reg )){
  kdbg_msg(3,"ioremap error!\n");
  return -ERR_MCASP_IOREMAP;
 }
 mcasp_set_reg(mcasp0->enable_reg,0x2);
 mcasp_set_reg(mcasp1->enable_reg,0x2);
 mcasp_set_reg(mcasp2->enable_reg,0x2);
 
 //set pin mux g_mcasp_module.mux_base = ioremap(MUX_MODE_BASE,4*1024);
 mux_base = g_mcasp_module.mux_base;
 mcasp_set_reg((mux_base + PINCNTL17),0x1); //set as mcasp
 mcasp_set_reg((mux_base + PINCNTL18),0x1);
 mcasp_set_reg((mux_base + PINCNTL19),0x1);
 mcasp_set_reg((mux_base + PINCNTL20),0x1);
 mcasp_set_reg((mux_base + PINCNTL21),0x1);
 mcasp_set_reg((mux_base + PINCNTL22),0x1);
 mcasp_set_reg((mux_base + PINCNTL23),0x1);
 mcasp_set_reg((mux_base + PINCNTL24),0x1);
 mcasp_set_reg((mux_base + PINCNTL25),0x1);
 mcasp_set_reg((mux_base + PINCNTL26),0x1);
 mcasp_set_reg((mux_base + PINCNTL27),0x1);
 mcasp_set_reg((mux_base + PINCNTL28),0x1);
 mcasp_set_reg((mux_base + PINCNTL29),0x1);
 mcasp_set_reg((mux_base + PINCNTL30),0x1);
 mcasp_set_reg((mux_base + PINCNTL134),0x20); //set  CLKOUT0
 mcasp_set_reg((mux_base + 0x834),0x4); //set  MCA[0]_AHCLKX
 //set module pll
 g_mcasp_module.module_pll_base = ioremap(TI814X_PLL_BASE,4*1024);
 pll_base = g_mcasp_module.module_pll_base;
 kdbg_msg(2,"ahclk_clksrc org is:%d\n",mcasp_get_reg(pll_base+0x2d4));
 mcasp_set_reg((pll_base + 0x2D4),0x4);
 kdbg_msg(2,"ahclk_clksrc set is:%d\n",mcasp_get_reg(pll_base+0x2d4));
#if 0
 mcasp_set_reg((pll_base + AUDIOPLL_CLKCTRL),0x271B080F);
        mcasp_set_reg((pll_base + AUDIOPLL_M2NDIV),0x10004);
        mcasp_set_reg((pll_base + AUDIOPLL_MN2DIV),0xc);
        mcasp_set_reg((pll_base + AUDIOPLL_TENABLEDIV),0x0);
        mcasp_set_reg((pll_base + AUDIOPLL_TENABLEDIV),0x1);
        mcasp_set_reg((pll_base + AUDIOPLL_TENABLE),0x0);
        mcasp_set_reg((pll_base + AUDIOPLL_TENABLE),0x1);
#endif

 //set pcrm
 g_mcasp_module.pcrm_base = ioremap(TI81XX_PRCM_BASE,4*1024);
 pcrm_base = g_mcasp_module.pcrm_base;

 //set syscllk22 divider as 0x1 [p698]
 kdbg_msg(2,"sysclk22 org is:%x\n",mcasp_get_reg(pcrm_base+0x300+0x58));
 mcasp_set_reg((pcrm_base+0x300+0x58),0x0);
 kdbg_msg(2,"sysclk22 set is:%x\n",mcasp_get_reg(pcrm_base+0x300+0x58));

 //choose sysclk22 as mcasp aux_clk
 mcasp_set_reg((pcrm_base + CM_AUDIOCLK_MCASP0_CLKSEL),0x2); //CM_AUDIOCLK_MCASP0_CLKSEL Select McASP0 audio clock to be SYSCLK22 [p703]
 mcasp_set_reg((pcrm_base + CM_CLKOUT_CTRL),0x80);

 kdbg_msg(2,"init mcasp module ok…..\n");

 return 0; 
}

static int mcasp_open(int mcasp_instance)
{
 mcasp_device *mcasp;
 if(mcasp_instance >= MCASP_INSTANCE_NUM || mcasp_instance < 0){
  kdbg_msg(3,"wrong instance num:%d,which should be %d <= num < %d\n",mcasp_instance,0,MCASP_INSTANCE_NUM);
  return -ERR_MCASP_WRONG_ARG;
 }
 kdbg_msg(2,"start open\n");
 mcasp = &g_mcasp_device_group[mcasp_instance];
 mcasp->ctl_base = ioremap(MCASP0_PHY_BASE,MCASP0_DATA_SIZE);
 if(NULL == mcasp->ctl_base){
  kdbg_msg(3,"ioremap error!\n")
  return -ERR_MCASP_IOREMAP;
 }
 
 kdbg_msg(2,"open end\n");
 return 0;
}

static int mcasp_set_fmt(int mcasp_instance)
{
 void __iomem * mcasp_reg_base;
 mcasp_device *mcasp;

 kdbg_msg(2,"start set fmt\n");
 mcasp = &g_mcasp_device_group[mcasp_instance]; 
 mcasp_reg_base = mcasp->ctl_base;

 kdbg_msg(2,"get virtual base\n");
        mcasp_set_reg((mcasp_reg_base + GBLCTL), 0);       // Reset
        mcasp_set_reg((mcasp_reg_base + RGBLCTL ), 0);       // Reset RX
        mcasp_set_reg((mcasp_reg_base + XGBLCTL ), 0);       // Reset TX

        //RX
 //Rx.set format
        mcasp_set_reg((mcasp_reg_base + RMASK), 0xffffffff); // No padding used
        mcasp_set_reg((mcasp_reg_base + RFMT), 0x000300F8); // MSB 16bit, 3-delay, no pad, CfgBus port
        mcasp_set_reg((mcasp_reg_base + AFSRCTL), 0x0000102); // 2TDM, 1bit Rising edge INTERNAL FS, word
        mcasp_set_reg((mcasp_reg_base + RTDM), 0x0000003); // Slots 0,1
 //Rx.set clock
        mcasp_set_reg((mcasp_reg_base + ACLKRCTL), 0x20); // INTERNAL CLK
        mcasp_set_reg((mcasp_reg_base + AHCLKRCTL), (1<<15)); // INTERNAL CLK        mcasp_set_reg((mcasp_reg_base + XCLKCHK), 0x00FF0008); // 255-MAX 0-MIN, div-by-256
 //Rx.interrupt
        mcasp_set_reg((mcasp_reg_base + RINTCTL), 0x00000000); // Not used

        //TX
 //Tx.set format
        mcasp_set_reg((mcasp_reg_base + XMASK), 0xffffffff); // No padding used
        mcasp_set_reg((mcasp_reg_base + XFMT), 0x000300F8); // MSB 16bit, 3-delay, no pad, CfgBus port
        mcasp_set_reg((mcasp_reg_base + AFSXCTL), 0x0000102); // 2TDM, 1bit Rising edge INTERNAL FS, word
        mcasp_set_reg((mcasp_reg_base + XTDM), 0x0000003); // Slots 0,1
 //Tx.set clock
        mcasp_set_reg((mcasp_reg_base + ACLKXCTL), 0x00000020); //INTERNAL CLK Sync mode
        mcasp_set_reg((mcasp_reg_base + AHCLKXCTL), (1<<15)); // INTERNAL CLK        mcasp_set_reg((mcasp_reg_base + XCLKCHK), 0x00FF0008); // 255-MAX 0-MIN, div-by-256
 //Tx.interrupt
        mcasp_set_reg((mcasp_reg_base + XINTCTL), 0x00000000); // Not used

 //Serializer
        mcasp_set_reg((mcasp_reg_base + SRCTL0), 0x00000002);     // MCASP0.AXR1[2] Recv        mcasp_set_reg((mcasp_reg_base + SRCTL1), 0x00000001);     // MCASP0.AXR1[3] Send

 //Global Register
        mcasp_set_reg((mcasp_reg_base + PFUNC), 0);          // All MCASPs
        mcasp_set_reg((mcasp_reg_base + PDIR), 0x00000002|(0x3f<<26)); // All inputs except AXR0[1], ACLKX1, AFSX1,AHCLKX,AFSR,AHCKLR,ACLKR
        mcasp_set_reg((mcasp_reg_base + DITCTL), 0x00000000); // Not used

 if(loop_back){
  //setting as loop back mode
  mcasp_set_bits((mcasp_reg_base + DLBCTL),0x1); //enable loop back
  mcasp_set_bits((mcasp_reg_base + DLBCTL),(0x1<<2)); //set as loop back mode }else{
  mcasp_set_reg((mcasp_reg_base + DLBCTL),0x0); //Not used
 }
        mcasp_set_reg((mcasp_reg_base + AMUTE), 0x00000000); // Not used

 return 0;
}

static int mcasp_start(int mcasp_instance)
{
 void __iomem * mcasp_reg_base;
 mcasp_device *mcasp;
 int i;
 mcasp = &g_mcasp_device_group[mcasp_instance]; 
 mcasp_reg_base = mcasp->ctl_base;

    mcasp_set_ctl_reg((mcasp_reg_base + RGBLCTL),GBLCTL_RHCLKRST_ON );                  //HS Clk
    mcasp_set_ctl_reg((mcasp_reg_base + XGBLCTL),GBLCTL_XHCLKRST_ON );                  //HS Clk

        mcasp_set_ctl_reg((mcasp_reg_base + RGBLCTL),GBLCTL_RCLKRST_ON);                    //Bit Clk
        mcasp_set_ctl_reg((mcasp_reg_base + XGBLCTL),GBLCTL_XCLKRST_ON);                    //Bit Clk

        mcasp_set_reg((mcasp_reg_base + RSTAT),0x0000ffff );         // Clear all
        mcasp_set_reg((mcasp_reg_base + XSTAT),0x0000ffff );         // Clear all

        mcasp_set_ctl_reg((mcasp_reg_base + RGBLCTL),GBLCTL_RSRCLR_ON);                     //Serialize
        mcasp_set_ctl_reg((mcasp_reg_base + XGBLCTL),GBLCTL_XSRCLR_ON);                     //Serialize

        mcasp_set_reg((mcasp_reg_base + RBUF0),0x456);         //avoid underrun
        mcasp_set_reg((mcasp_reg_base + XBUF1),0x123);         //avoid underrun

        mcasp_set_ctl_reg((mcasp_reg_base + RGBLCTL ),GBLCTL_RSMRST_ON);                    //State Machine
        mcasp_set_ctl_reg((mcasp_reg_base + XGBLCTL ),GBLCTL_XSMRST_ON);                    //State Machine

        mcasp_set_ctl_reg((mcasp_reg_base + RGBLCTL  ),GBLCTL_RFRST_ON);                    //Frame Sync
        mcasp_set_ctl_reg((mcasp_reg_base + XGBLCTL  ),GBLCTL_XFRST_ON);                    //Frame Sync

#if 0
        while(!(mcasp_get_reg(mcasp_reg_base + SRCTL3) & 0x10)){}
        mcasp_set_reg((mcasp_reg_base + XBUF3),0x0);
#endif
 // for test …
#if 1
 for(i=0; i<TEST_ARRAY_SIZE; i++){
  while(!(mcasp_get_reg(mcasp_reg_base + SRCTL1) & 0x10)){}
  mcasp_set_reg((mcasp_reg_base+ XBUF1),0x789);
  x_stat_array[i] = mcasp_get_reg(mcasp_reg_base + XSTAT);
 
  while(!(mcasp_get_reg(mcasp_reg_base + SRCTL0) & 0x20)){}
  recv_array_test[i] = mcasp_get_reg((mcasp_reg_base+ RBUF0));
  r_stat_array[i] = mcasp_get_reg(mcasp_reg_base + RSTAT);
 }
#endif
 
 for(i=0; i<TEST_ARRAY_SIZE; i++){
  printk("%lx ",recv_array_test[i]);
  if((i+1)%10 == 0){
   printk("\n");
  }
 }
 printk("\n");
 
 kdbg_msg(2,"r_stat_array:\n");
 for(i=0; i<TEST_ARRAY_SIZE; i++){
  printk("%lx ",r_stat_array[i]);
  if((i+1)%10 == 0){
   printk("\n");
  }
 }
 printk("\n");

 kdbg_msg(2,"x_stat_array:\n");
 for(i=0; i<TEST_ARRAY_SIZE; i++){
  printk("%lx ",x_stat_array[i]);
  if((i+1)%10 == 0){
   printk("\n");
  }
 }
 printk("\n");

#if 0
 kdbg_msg(2,"srcl0_array:\n");
 for(i=0; i<TEST_ARRAY_SIZE; i++){
  printk("%lx ",srcl0_array[i]);
  if((i+1)%10 == 0){
   printk("\n");
  }
 }
 printk("\n");

 kdbg_msg(2,"srcl1_array:\n");
 for(i=0; i<TEST_ARRAY_SIZE; i++){
  printk("%lx ",srcl1_array[i]);
  if((i+1)%10 == 0){
   printk("\n");
  }
 }
 printk("\n");
#endif

 return 0;
}

static int mcasp_stop(int mcasp_instance)
{
 return 0;
}

static int mcasp_close(int mcasp_instance)
{
 return 0;
}

static int __init  mcasp_init(void)
{
 struct timespec current_time;
 int i;
 //test printk time
 current_time = current_kernel_time();
 kdbg_msg(2,"[%ld:%ld] mcasp start\n",current_time.tv_sec,current_time.tv_nsec);
 current_time = current_kernel_time();
 kdbg_msg(2,"[%ld:%ld] mcasp start\n",current_time.tv_sec,current_time.tv_nsec);

 memset(recv_array_test,0,TEST_ARRAY_SIZE);
 memset(srcl0_array,0,TEST_ARRAY_SIZE);
 memset(srcl1_array,0,TEST_ARRAY_SIZE);
 memset(x_stat_array,0,TEST_ARRAY_SIZE);
 memset(r_stat_array,0,TEST_ARRAY_SIZE);

 for(i=0; i<TEST_ARRAY_SIZE; i++){
  printk("%lx ",recv_array_test[i]);
  if((i+1)%10 == 0){
   printk("\n");
  }
 }
 printk("\n");

 mcasp_module_init();
 mcasp_open(0);
 mcasp_set_fmt(0);
 mcasp_start(0);
 mcasp_stop(0);
 mcasp_close(0);

 kdbg_msg(2,"mcasp end\n");

 return 0; 
}

user151383853:

我觉得是不是引脚复用的设置有问题,是否借助调试器看看设置后的寄存器

liuke liuke:

回复 user151383853:

感谢前辈的指点,测试了一下,MUX的值设置没有错误。但发现MCAP1是可以正常使用,MCASP0,相应的数据引脚始终为高电平状态,帧同步为低电平。先这样凑合用了,还是很感谢!

赞(0)
未经允许不得转载:TI中文支持网 » McAsp采用loopback模式,能够收发数据,但是数据引脚上无法捕捉到任何变化
分享到: 更多 (0)