Spidev不使用ioctl同时写/读

我希望找到一些帮助,即使这个问题可能是硬件而不是软件相关(我们会看到)。 我正在开发基于Freescales P1021处理器(ppc,e500v2核心)的定制电路板。 外部PCB将连接并可由SPI配置。 该外部PCB的规格读取为全双工模式下的2字节命令,并且只有最后一个字节用于在MISO上传输数据。

知道这一点,我目前正在准备一些软件来测试这个设备。 所以我从众所周知的spi_test程序开始。

root@p1021rdb:~# ./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 root@p1021rdb:~# 

PIC1

信号显示608个时钟,似乎上半年只有数据。 我决定用loopback调查和测试它 – 切割MOSI-MISO将数据循环回rx缓冲区。 结果:

 root@p1021rdb:~# ./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 root@p1021rdb:~# 

PIC2

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

此外,我操作将在此程序中发送的模式减少到2个字节(以模拟我想要的命令格式),如下所示:

 #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 []的两个字节,而对于其他2个字节,它是低/ 0。 以下是控制台输出和信号的结果:

 root@p1021rdb:~# ./spi_test_2bytes -D /dev/spidev32766.3 spi mode: 0 bits per word: 8 max speed: 500000 Hz (500 KHz) 00 00 root@p1021rdb:~# 

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输出显示没有收到的数据和信号是预期的:

 root@p1021rdb:~# ./spi_test_2bytes -D /dev/spidev32766.3 spi mode: 0 bits per word: 8 max speed: 500000 Hz (500 KHz) 00 00 root@p1021rdb:~# 

PIC5

图像pic6

实际上在我看来,不是做2字节全双工传输,而是进行N字节发送,然后进行N字节接收。

实际上有两个问题:

  1. 为什么传输0xAA,0x81和0x00,0x00?
  2. 为什么(使用环回)原始代码能够将数据恢复到rx缓冲区中,但如果减少到2个字节则不会收到数据?

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

我知道这是一个非常老的线程,但我一直在运行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