问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