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;
}
我觉得是不是引脚复用的设置有问题,是否借助调试器看看设置后的寄存器
感谢前辈的指点,测试了一下,MUX的值设置没有错误。但发现MCAP1是可以正常使用,MCASP0,相应的数据引脚始终为高电平状态,帧同步为低电平。先这样凑合用了,还是很感谢!