2013-04-09 170 views
6

我希望找到一些帮助,即使此问题可能比软件相关的硬件更多(我们将会看到)。我正在开发基于Freescales P1021处理器(ppc,e500v2核心)的定制板。外部PCB将被连接并可通过SPI进行配置。这个外部PCB的规格读取,因为它期望在全双工模式下的2字节命令,并且只有最后一个字节用于在MISO上传回数据。Spidev不会使用ioctl同时写入/读取

了解到这一点,我目前正在准备一些软件来测试此设备。所以我从众所周知的spi_test计划开始。

[email protected]:~# ./spi_test -D /dev/spidev32766.3 
spi mode: 0 
bits per word: 8 
max speed: 500000 Hz (500 KHz) 

00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 00 00 00 00 
00 00 
[email protected]:~# 

Pic1

的信号示出了608个时钟,它似乎有仅在第一半数据。我决定用loopback进行调查和测试 - 将MOSI-MISO循环切回数据到rx缓冲区。结果:

[email protected]:~# ./spi_test -D /dev/spidev32766.3 
spi mode: 0 
bits per word: 8 
max speed: 500000 Hz (500 KHz) 

FF FF FF FF FF FF 
40 00 00 00 00 95 
FF FF FF FF FF FF 
FF FF FF FF FF FF 
FF FF FF FF FF FF 
DE AD BE EF BA AD 
F0 0D 
[email protected]:~# 

Pic2

这个信号显示,整个电报重复任何原因(我不知道为什么)。但是,程序正确显示了控制台中接收到的数据,因此可能是spi_test预期的。

另外我操纵,这将在该程序被向下发送到2个字节的模式(模拟请求的命令格式I瞄准)所示:

#ifdef ORIG 
    uint8_t tx[] = { 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 
     0xF0, 0x0D, 
    }; 
#else 
    uint8_t tx[] = { 
     0xAA, 0x81, 
    }; 
#endif 

但作为没想到32位被移位输出到SPI总线 - 而不是16个。在前两个字节中,MOSI提供来自tx []的两个字节,而另外两个字节则为低/ 0。下面是控制台输出的结果和信号:

[email protected]:~# ./spi_test_2bytes -D /dev/spidev32766.3 
spi mode: 0 
bits per word: 8 
max speed: 500000 Hz (500 KHz) 

00 00 
[email protected]:~# 

Pic3

即使我回环MOSI到MISO没有数据被接收(控制台输出仍是相同的接收“00 00”):

(仅发送)

Pic4

我周围的所有参数有点玩,并决定改变测试程序使用半双工模式:

#ifdef ORIG 
    uint8_t tx[] = { 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0x40, 0x00, 0x00, 0x00, 0x00, 0x95, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
     0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD, 
     0xF0, 0x0D, 
    }; 
#else 
    uint8_t tx[] = { 
     0xAA, 0x81, 
    }; 
#endif 
    uint8_t rx[ARRAY_SIZE(tx)] = {0, }; 
    struct spi_ioc_transfer tr = { 
     .tx_buf = (unsigned long)tx, 
#ifdef ORIG  
     .rx_buf = (unsigned long)rx, 
#else 
     .rx_buf = 0, 
#endif 

因为这是编译和执行的东西是像预期的那样。 SPI_CLK为16位循环16次,MOSI按预期提供数据。 Cosole输出没有显示出接收到的数据和信号都像预期:

[email protected]:~# ./spi_test_2bytes -D /dev/spidev32766.3 
spi mode: 0 
bits per word: 8 
max speed: 500000 Hz (500 KHz) 

00 00 
[email protected]:~# 

Pic5

Pic6

其实在我看来,与其做2个字节的全双工传输我做了N字节,发送随后由一个N字节接收。

其实有两个问题:

  1. 为什么和0xAA,0x81表示和0×00,0×00传输?
  2. 为什么(使用回送)原始代码能够将数据返回到rx缓冲区,但是如果减少到2个字节,则不会接收到数据?
+0

邮政别处的图像和链接添加到他们的答案 - 那么高代表用户可以编辑您的答案,包括他们 – 2013-04-09 16:51:42

+0

我会检查今天,如果spidev与SPI_MASTER_HALF_DUPLEX标志编译启用,强制spi设备半双工。 – stede 2013-04-11 05:47:09

+0

SPI_MASTER_HALF_DUPLEX未设置。 – stede 2013-04-11 14:47:31

回答

1

那么,这个帖子是安静的压倒性的。我只读了几个部分,最近在Linux上与SPI联系。但是,如 https://www.kernel.org/doc/Documentation/spi/spidev 中所述,异步读/写在用户空间中不可用。 AFAIK读/写只是fcntl的一个包装。因此,您需要编写自己的内核模块来实现异步I/O。

+0

这个答案看起来不对。 https://www.kernel.org/doc/Documentation/spi/spidev文章特别指出:“使用ioctl()请求,全双工传输......都可用”。并且spi-test(例如https://github.com/KnCMiner/spi-test/blob/master/spi-test.c#L97)使用该ioctl()。 – 2017-06-18 11:36:03

0

我知道这是一个非常老的线程,但我一直在运行OpenWRT的RT5350上使用spidev。我得到和你一样的结果;我只是无法获得全双工传输。读取RT5350数据表时,似乎硬件只能进行半双工SPI传输。每次传输都是写入(MOSI上的输出字节,不读取任何内容)或读取(MOSI上的输出零,读取MISO)。

我无法获得P1021芯片的数据表,但考虑到我们结果的相似性,我会说它的硬件SPI是以类似的方式实现的。

这意味着内核模块不是答案(无论如何,ioctl SPI_IOC_MESSAGE最终会调用spi_async())。做全双工SPI的唯一方法是使用软件中的GPIO。

RT5350参考: http://forum.vocore.io/viewtopic.php?f=3&t=72#p233