美文网首页我爱编程
RT5350开发笔记(一)

RT5350开发笔记(一)

作者: fengz0108 | 来源:发表于2014-12-30 22:45 被阅读0次

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

    RT5350##

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

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

    • 使用到的开发环境是厂商提供好的虚拟机镜像Fedora6+4.12,里面有配置好的开发环境;
    • tftp下载文件到开发板
    • 超级终端打印log和发送控制命令

    然后按照文档中的方法编译烧写内核,原封不动的编译烧写后发现上电后搜索不到路由器的无线网信号,后来我先选取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命令加载测试。

    相关文章

      网友评论

        本文标题:RT5350开发笔记(一)

        本文链接:https://www.haomeiwen.com/subject/ihlztttx.html