DM8168平台中完成gv7601的spi总线驱动笔记

问1: 首先测试spi驱动自发自收,对应8168哪些管脚,如何配置spi功能?
答1:
    SPI_D0
    SPI_D1
    SPI_SCLK
    SPI_SCS0
    SPI_SCS1
    SPI_SCS2
    SPI_SCS3
    
    
arch\arm\mach-omap2\Board-ti8168evm.c

内核启动打印信息
[    0.340000] omap2_mcspi omap2_mcspi.1: registered master spi1
[    0.340000] spi spi1.0: setup: speed 48000000, sample leading edge, clk normal
[    0.340000] spi spi1.0: setup mode 0, 8 bits/w, 75000000 Hz max --> 0
[    0.340000] omap2_mcspi omap2_mcspi.1: registered child spi1.0

[    0.340000] omap2_mcspi omap2_mcspi.1: chipselect 0 already in use
[    0.340000] omap2_mcspi omap2_mcspi.1: can't create new device for spidev



改写后:
[    0.340000] omap2_mcspi omap2_mcspi.1: registered master spi1
[    0.340000] spi spi1.0: setup: speed 48000000, sample leading edge, clk normal
[    0.340000] spi spi1.0: setup mode 0, 8 bits/w, 75000000 Hz max --> 0
[    0.340000] omap2_mcspi omap2_mcspi.1: registered child spi1.0

[    0.340000] spi spi1.1: setup: speed 48000000, sample leading edge, clk normal
[    0.340000] spi spi1.1: setup mode 0, 8 bits/w, 75000000 Hz max --> 0
[    0.340000] omap2_mcspi omap2_mcspi.1: registered child spi1.1






//////////////////////////////////////////////////////////////////
注意:SPI_D[0]和SPI_D[1]好像要配置input和output,但是在这里没有配置
    一样可以自发自收
SPI Data IO. Can be configured as either MISO or MOSI
SPI_D[0]---PINCTRL171    0x4814 0AA8
SPI_D[1]---PINCTRL172    0x4814 0AAC


SPI 4803 0000h 4803 0FFFh 4KB Peripheral Registers
    4803 1000h 4803 1FFFh 4KB Support Registers

124h MCSPI_SYST McSPI system test register Section 16.3.10

9 SPIDATDIR1 Sets the direction of the SPI_D[1].
0 Output
1 Input

8 SPIDATDIR0 Sets the direction of the SPI_D[0].
0 Output
1 Input

SPI_D0-R76输入
SPI_D1-R77输出


问2:在做自发自收的时候,如果断开mosi和miso脚,用自带的spidev测试程序会打印发送的数据,
     如果把mosi和miso脚连接,就会接收全是0x00的数据,
     如果断开mosi和miso 打印的全是发送数据, 请问怎么回事?
     理论上应该是断开全是0x00,连接才是发送的数据 
     同时用示波器测量mosi和miso脚都有数据波形  
答2:其实这个问题是因为spi总线上负载gv7601引起的,如果去掉spi总线上的gv7601芯片
     短接mosi和miso,       miso就会收到mosi发送的数据
     如果断开mosi和miso,   miso就不会接收数据
     当时这个问题困扰我好几天,其实断开的话,miso接收到发送的数据也可以验证spi总线是正常的,
     因为gv7601的datasheet上说写数据的话
     During the write sequence, all Command and following Data Words input at the SDIN
     pin are output at the SDOUT pin unchanged
    
     
     
     

问3:omap2_mcspi_txrx_pio如何接收数据推送到应用层?
答3:  



////////////////////////////////////
16.3.11 McSPI Module Control Register (MCSPI_MODULCTRL)参考p1623

1 PIN34     Pin mode selection. This register is used to configure the SPI pin mode, in master or slave mode. If
            asserted, the controller only use SPI_D[0], SPI_D[1], and SPI_SCLK clock pin for SPI transfers.
            0 SPI_SCS[n] is used as a chip select.
            1 SPI_SCS[n] is not used. In this mode all related option to chip select have no meaning
            
            
注意把BTMODE2短接就可以从sd卡启动  


McSPI System Test Register (MCSPI_SYST) p1621
SPI Registers p1608  




问4:8bit和16bit在示波器波形图上不一样,为什么接收脚检测到数据是一样的?
    8bit时序图好理解,16bit如何理解?
spi mode: 0
bits per word: 16
max speed: 4000 Hz (4 KHz)
mydatabuffer[0]=0x6
mydatabuffer[1]=0x80
gv7601_read(1,0x06)=0x8006

mosi波形图bit7在前bit0在后
0x80  0x06


spi mode: 0
bits per word: 8
max speed: 4000 Hz (4 KHz)
mydatabuffer[0]=0x6
mydatabuffer[1]=0x80
gv7601_read(1,0x06)=0x8006

mosi波形图
0x06  0x80

答4:其实这就是数据按8bit和16bit发送的格式不同而已,
     本质上发送的内容还是一样的





//---------------------------------------------------------------
参考源代码:
///////////////////////////////////////////////////////
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

static uint8_t  mode;
static uint8_t  bits = 8;
static uint32_t speed = 2*1000;         //32*100*1000; //500000;
static uint16_t delay=0;





#if 0
//read operating
static int transfer_r(int fd,unsigned short addr)
{
	int ret;
    unsigned char  cmd[2];
    unsigned char  databuffer[4];
    unsigned char  mydatabuffer[2];
	struct spi_ioc_transfer	xfer[2];
	
	

    
    cmd[0] = addr & 0x00ff; 
    cmd[1] = 0x80 | (addr >> 8); 
    memset(xfer,0,2*sizeof(struct spi_ioc_transfer));
    memset(databuffer,0x00,2);
    xfer[0].tx_buf          = (unsigned long)cmd;
    xfer[0].rx_buf          = NULL;
    xfer[0].len             = 2;
    xfer[0].delay_usecs     = delay;
    xfer[0].bits_per_word   = bits;	
    xfer[0].speed_hz        = speed;
        
    
    
    xfer[1].rx_buf          = (unsigned long)databuffer;
    xfer[1].tx_buf          = NULL;
    xfer[1].len             = 4;
    xfer[1].delay_usecs     = delay;
    xfer[1].bits_per_word   = bits;	
    xfer[1].speed_hz        = speed;
    


    ret = ioctl(fd, SPI_IOC_MESSAGE(2), &xfer);
	if (ret == -1 )
	    printf("can't transfer");

	printf("databuffer[0]=0x%x\n",databuffer[0]);
	printf("databuffer[1]=0x%x\n",databuffer[1]);
	printf("databuffer[2]=0x%x\n",databuffer[2]);
	printf("databuffer[3]=0x%x\n",databuffer[3]);

	return ((databuffer[1] << 8) + databuffer[0]);
}
#else
static int transfer_r(int fd,unsigned short addr)
{
	int ret;
    unsigned char  cmd[2];
    unsigned char  databuffer[4];
    unsigned char  mydatabuffer[2];
	struct spi_ioc_transfer	xfer[2];
	
	

    
    cmd[0] = addr & 0x00ff; 
    cmd[1] = 0x80 | (addr >> 8); 
    memset(xfer,0,2*sizeof(struct spi_ioc_transfer));
    memset(databuffer,0x00,2);
    xfer[0].tx_buf          = (unsigned long)cmd;
    xfer[0].rx_buf      = (unsigned long)databuffer;
    xfer[0].len             = 2;
    xfer[0].delay_usecs     = delay;
    xfer[0].bits_per_word   = bits;	
    xfer[0].speed_hz        = speed;
        

	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &xfer);
	if (ret == -1 )
	    printf("can't transfer");

	printf("databuffer[0]=0x%x\n",databuffer[0]);
	printf("databuffer[1]=0x%x\n",databuffer[1]);
	printf("databuffer[2]=0x%x\n",databuffer[2]);
	printf("databuffer[3]=0x%x\n",databuffer[3]);

	return ((databuffer[1] << 8) + databuffer[0]);
	
}
#endif












int gv7601_read(unsigned char chip_id,unsigned short addr)
{
	int fd;
	int ret ;
    char device[1024];
	
    memset(device,0x00,1024);
    sprintf(device,"/dev/spidev1.%d",chip_id);
    fd = open(device,O_RDWR);
    if (fd < 0)
        printf("can't open device");

	/*
	 * spi mode
	 */
	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
	if (ret == -1)
		printf("can't set spi mode");

	ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
	if (ret == -1)
		printf("can't get spi mode");

	/*
	 * bits per word
	 */
	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
	if (ret == -1)
		printf("can't set bits per word");

	ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
	if (ret == -1)
		printf("can't get bits per word");

	/*
	 * max speed hz
	 */
	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
	if (ret == -1)
		printf("can't set max speed hz");

	ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
	if (ret == -1)
		printf("can't get max speed hz");

	printf("spi mode: %d\n", mode);
	printf("bits per word: %d\n", bits);
	printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);	
		 		

    ret = transfer_r(fd,addr);
    close(fd);
	return ret;

}





int main(int argc, char *argv[])
{
    int tmp;

    while(1)
    {
        tmp = gv7601_read(3,0x06);
        printf("gv7601_read(1,0x06)=0x%x\n",tmp);
        sleep(1);
        
    
    }

    
    return 0;
    

}

问5:在spi应用中SPI_IOC_MESSAGE(1)和SPI_IOC_MESSAGE(2),其中SPI_IOC_MESSAGE(2)为什么接收不到数据?
	//声明并初始化spi_ioc_transfer结构体
	struct spi_ioc_transfer tr = {
		.tx_buf = (unsigned long)tx,
		.rx_buf = (unsigned long)rx,
		.len = ARRAY_SIZE(tx),
		.delay_usecs = delay,
		.speed_hz = speed,
		.bits_per_word = bits,
	};

	//SPI_IOC_MESSAGE(1)的1表示spi_ioc_transfer的数量 
	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);		//ioctl默认操作,传输数据
	///////////////////////////////
    xfer[0].tx_buf          = (unsigned long)cmd;
    xfer[0].rx_buf          = NULL;
    xfer[0].len             = 2;
    xfer[0].delay_usecs     = delay;
    xfer[0].bits_per_word   = bits;	
    xfer[0].speed_hz        = speed;
        
    
    
    xfer[1].rx_buf          = (unsigned long)databuffer;
    xfer[1].tx_buf          = NULL;
    xfer[1].len             = 2;
    xfer[1].delay_usecs     = delay;
    xfer[1].bits_per_word   = bits;	
    xfer[1].speed_hz        = speed;
    
    //xfer[0].rx_buf      = (unsigned long)mydatabuffer;

    ret = ioctl(fd, SPI_IOC_MESSAGE(2), &xfer);	
    为什么databuffer接收的数据全是0x00,用示波器测试接收脚有数据,如果通过ioctl(fd, SPI_IOC_MESSAGE(1)可以打印接收到数据
答5:其实相当于全双工和半双工通信方式,最好参考Timing获取答案    
    
    
	
    



////////////////////////////////////////////////////////////
问6:测试gv7601芯片的时候,如果是读寄存器,读的数据是0,如果是写寄存器,写什么就输出什么,
     现在的问题是为什么读寄存器读的数据是0呢?
     如果把standy引脚接地的话,有时候可以读出数据?
     
     比如datasheet中默认是非0数据,可是采用半双工方式读取的数据全是0呢?
006h FF_CRC_V   15      EDH Full Field CRC Validity bit.        R 0
     AP_CRC_V   14      EDH Active Picture CRC Validity bit.    R 0
     VD_STD     13-8    Detected Video Standard.                R 29
     RSVD       7-0     Reserved.                               R 255  
     
     mosi发送的16bit数据    0x80 0x06
     miso接收的数据应该是   0x80 0x06  寄存器值(非0)
     
     排查问题?p26
     1.字节顺序ok
     2.clk频率    不超过60MHZ ok
     3.Data Setup Time 和Data Hold Time  大于1.5ns ok
     
答6:这个问题困扰我一个多星期,后来发现是硬件引起的,因为你通过示波器检查读时序正常都没有问题
     应该把芯片的standby引脚接地,同时连接VCO_VDD上的一个电阻应该焊接100欧,可是错焊接成100K,
     电流太小,里面的模块工作有时不正常,所以表现为有时候可以读出数据,有时候不能读出数据

 
注意:     
4个gv7601并联在spi总线上,如果应用层读a-gv7601(CS为低电平)其中寄存器,但是b-gv7601(CS为高电平)的输出脚,会把输入数据照样输出
这样的话会冲掉读寄存器的值,所以datasheet建议采用串联方式菊花链 


/////////////////////////
如果频率为20000hz  两个spi数据包间隔也是100ms,现在make menuconfig中去掉spi的debug功能就没有占用很长时间了
因为打印下列debug信息占用很长时间  
[  182.960000] spidev spi1.3: setup: speed 11718, sample leading edge, clk normal
[  183.050000] spidev spi1.3: setup: speed 11718, sample leading edge, clk normal
[  183.140000] spidev spi1.3: setup: speed 11718, sample leading edge, clk normal
[  184.230000] spidev spi1.3: setup: speed 11718, sample leading edge, clk normal

DM8168平台中完成gv7601的spi总线驱动笔记_第1张图片


DM8168平台中完成gv7601的spi总线驱动笔记_第2张图片

你可能感兴趣的:(linux底层驱动)