我爱编程

RT5350开发笔记(一)

2014-12-30  本文已影响0人  fengz0108

背景:采用RT5350开发板做做主控器,配合声音采集模块实现声音采集,混声,组网传输等功能的系统。已有了声音采集模I2C配置程序(stm32),I2S配置程序(有问题)。

RT5350##

rt5350其实就是一个路由器,上面加在的是一个Linux内核的小系统,外置的接口有UART、SPI、I2C、I2S等可用于Linux开发,本次系统需要用到的只是I2C、I2S两部分,另外下载调试还需要用到ttyS1串口与LAN或WAN接口。具体信息请参考文档YG -WIFI-132开发版说明

首先要阅读文档资料,其中重要的是前三部分SDK开发指南,应仔细阅读,会了解到Uboot的编译、内核配置/编译、以及下载文件到自己的板子上等具体操作。

然后按照文档中的方法编译烧写内核,原封不动的编译烧写后发现上电后搜索不到路由器的无线网信号,后来我先选取Save Configuration to an Alternate File然后再按照文档中的配置,编译烧写上电后找到了信号。缺省的AP为RT5350_AP

I2C##

配置GPIO为I2C模式###

在文档资料中的第九部分提到GPIO的配置说明,但是里面只是提到GPIO7~GPIO14。根据 datasheet1.3 PinSharing Scheme中提到I2C是GPIO1和GPIO2,所以如何配置还需从Datasheet中找。在内核配置->Devices Driver->Character devices下我们看到有一个Ralink RT2880 I2C Support很显然这是一个厂商提供的I2C设备例程,当然这也是我们最终参考的程序。

在主函数i2cdrv_init中有一行代码,就是将GPIO配制成I2C模式

/* configure i2c to normal mode */ 
RT2880_RGE (RALINK_SYSCTL_BASE + 0x60) &= ~1;

在Datasheet中3.4 System Control中找到GPIO Purpose Select中提到该寄存器b[1]=1为I2C模式,b[1]=0则为GPIO模式。

开发板I2C控制器初始化###

这部分代码在i2c_drv.c

void i2c_master_init (void)

Ps:这部分代码主要是参考Datasheet中的 3.10 I2C Controller,通过寄存器的配置实现基本的参数设置和收发数据得实现,而非调用Linux系统的i2c控制器驱动,应该仔细阅读!!!

只修改设备地址i2cdrv_addr即可

unsigned long i2cdrv_addr = FM34_ADDR;
#define FM34_ADDR   (0xC0>>1)

i2c_write###

根据俊哥的程序,需要这个函数完成一个连续8byte的连续写入,结合Datesheet和i2c_drv.c的写函数修改如下

int i2c_write(u8* data,u8 len)
{
    int i,j;

    RT2880_REG(RT2880_I2C_BYTECNT_REG) = len-1;

    RT2880_REG(RT2880_I2C_DATAOUT_REG) = data[0];

    RT2880_REG(RT2880_I2C_STARTXFR_REG) = WRITE_CMD;

    for(i=1;i<len;i++)
        {
    //  printk("%d ",i);
    udelay(170);
        j = 0;
        do{
            if(IS_SDOEMPTY){
                RT2880_REG(RT2880_I2C_DATAOUT_REG) = data[i];
                }
            break;
          }while (++j<max_ee_busy_loop);
        }
        i = 0;
        while(IS_BUSY && i<i2c_busy_loop){
        i++;
            }
    return true;
}

在调试过程中有很多问题需要注意:

  1. 调试工具可以使用建议逻辑分析仪看I2C输出。可以看到是否有数据写出,根据协议首先写出的是设备地址,查看是否有应答信号,有应答信号再继续。工具为SALEAE
  2. 在调试过程中要注意延时,谨慎使用printk函数 因为该函数会造成延时,导致输出结果不可预测。开始没有正确数据出来,加上printk ("%d",i);后可以看到数据正常传出但是从第二个开始就有一小段延时,没法解释,后来才是知道就是打印字符的时间。
  3. 结合逻辑分析仪软件读出一个字节数据传出需要150ms的时间,于是加入延时udelay (170);后数据连续传出很漂亮。

写设备控制命令串###

unsigned char fm_WriteMem(unsigned char AdrHi,unsigned char AdrLo,unsigned char DataHi,unsigned char DataLo)
{
    unsigned char wBuf[7];
    wBuf[0] = 0xfc;
    wBuf[1] = 0xf3;
    wBuf[2] = 0x3b;
    wBuf[3] = AdrHi;
    wBuf[4] = AdrLo;
    wBuf[5] = DataHi;
    wBuf[6] = DataLo;
    return i2c_write(wBuf,7);
}

设备命令字符串的结构在FM34-500B Datasheet V1.42.6 SHI (Serial Host Interface)中有详细的解释与说明。

读设备控制命令###

unsigned int fm_ReadMem(unsigned char AdrHi,unsigned char AdrLo,int* data)
{
    unsigned char hi_byte,low_byte;
    unsigned char write_buf[5];
    write_buf[0] = 0xfc;
    write_buf[1] = 0xf3;
    write_buf[2] = 0x37;
    write_buf[3] = AdrHi;
    write_buf[4] = AdrLo;

    if(!i2c_write(write_buf,5))
    {
        return false;
    }
    if(i2c_write(read_buf1,4))
    {
        i2c_read(&hi_byte,1);
    }
    if(i2c_write(read_buf2,4))
    {
        i2c_read(&low_byte,1);
    }
    *data = ((unsigned int)hi_byte<<8)+(unsigned int)low_byte;
    return true;
}

实现流程在FM34-500B Datasheet V1.4中由详尽说明。

测试函数###

static int test(void)
{
    int data = 0xffff;
    printk("i2c_master_init\n");
    i2c_master_init();
    fm_WriteMem(0x23,0x6f,0xab,0xcd);
    fm_ReadMem(0x23,0x6f,&data);
    printk("the 0x236f result is :%d \r\n",data);
    fm_WriteMem(0x23,0x6f,0x0b,0x05);
    fm_ReadMem(0x23,0x6f,&data);
    printk("result is :%d\r\n",data);
}

测试写函数与读函数是否可行。

设备初始化函数###

int fm_int(void)
{
    int i;
    int data = 0xffff;
    printk("init fm34\r\n");
    mdelay(1000);
    printk("i2c_master_init\n");
    i2c_master_init();
    for(i = 0; i<37;i++)
    {
        while(!fm_WriteMem(*(*(init_farameter2+i)+0),*(*(init_farameter2+i)+1),*(*(init_farameter2+i)+2),*(*(init_farameter2+i)+3)));
    }
    mdelay(10);
    for(i = 37; i<75;i++)
    {
        while(!fm_WriteMem(*(*(init_farameter2+i)+0),*(*(init_farameter2+i)+1),*(*(init_farameter2+i)+2),*(*(init_farameter2+i)+3)));
    }
    mdelay(10);
    while(!fm_WriteMem(0x22,0xfb,0x00,0x00));
    mdelay(10);
    while(data != 0x5a5a)
    {
        while(!fm_ReadMem(0x22, 0xfb , &data))//(0x8000: before parameter configure, 0x0 means finish configure, 0x5A5A means DSP running)
        {
            mdelay(20);
        }
        printk("the 0x22fb result is : %d \r\n",data);
    }
}

这个过程是初始化I2C设备的全过程,所有的命令串写在数组unsigned char init_farameter2中,一次完成所有寄存器配置后,发送开始配置命令并等待设备响应,会返回0x5a5a
注意:

  1. 由于控制命令串有75条在发送过程中会出错,所以我试着将它分为两次发送;
  2. 即便是这样还是总是不能通过,于是在每一次读写操作前加上了一个小延时mdelay(10);得以解决;
  3. 函数设计缺陷,在没有得到正确应答的情况下会无限响应下去,只能重启。

后记###

到此FM34配置工作的已结束,下一步要看I2S的驱动。

调试方法还是编译模块fm_drv.ko,通过insmod命令加载测试。

上一篇下一篇

猜你喜欢

热点阅读