我正在尝试编写一个将安装在Linux MCU(Raspberry Pi)上的程序,该程序将读取从另一个MCU(我自己建立的本土产品)的串行数据。
我已经研究过如何做到这一点,并认为我有“大局”,但仍然缺少一些东西。首先,我需要启用内核模块并让自己访问设备:
sudo modprobe spi_bcm2708
sudo chown `id -u`.`id -g` /dev/spidev0.*
从那里我可以使用this famous C file来测试SPI连接。
所以现在连接就在那里,但我仍然需要从中读取串行数据。根据{{3}}的答案,我只需要:
...打开相关端口进行阅读,并使用
read()
获取数据。
然而,该答案中的代码片段似乎是通过设备驱动程序打开一个端口,而不是通过SPI。
我的理解是我可以使用SPI从连接的MCU设备读取数据,而我不需要为该设备编写我自己的设备驱动程序。这是真的?如果是这样,我将如何从SPI连接读取,以及该代码与上述链接问题的答案中的代码有何不同?
如果我的理解不正确,并且我确实读过“通过”设备驱动程序,为什么我首先需要驱动程序?这不是SPI希望规避的吗?提前谢谢。
答案 0 :(得分:5)
我正在尝试编写一个将安装在Linux MCU(Raspberry Pi)上的程序,该程序将读取从另一个MCU(我自己建立的本土产品)的串行数据。
[ MCU 不适合使用。 Raspberry Pi使用SoC(片上系统)。微控制器将更便宜和更便宜。比SoC更简单的设备。如果您想使用TLA,请使用SBC,单板计算机。]
[您滥用术语“串行端口”和“串行数据”。今天,由于PC无处不在,“串口”已经专门用于指EIA / RS-232异步串行连接。 SPI。 USB。 I2C,TWI,SATA 等等不应被称为“串行”连接,除非您要解释它们是如何工作的。]
在Linux中,SPI设备驱动程序通常实现为*平台驱动程序而不是字符驱动程序。因此,此类驱动程序不具有文件操作,或 fops ,执行 open(), read(), write()或 close()。这样的操作是对于目标设备,平台设备连接到系统。因此,平台设备在/dev
中没有像目标设备那样的设备节点.SPI与USB和PCI属于同一类别;它们都是总线并且通常作为平台驱动程序实现。
我的理解是我可以使用SPI从连接的MCU设备读取数据,而且我不需要为该设备编写自己的设备驱动程序。这是真的吗?
答案取决于您使用的内核是否为您的用户程序公开了一个SPI字符设备。但如果SPI驱动程序是平台驱动程序,则必须实现自定义SBC的设备驱动程序。此目标设备需要/dev
中的节点,分配的主要和次要编号以及与这些编号关联的驱动程序。该驱动程序将利用SPI驱动程序提供的平台操作或使用Linux SPI API执行传输。 SPI及其驱动程序仅仅是用于在此处理器和目标设备之间传输数据的管道。使用SATA和PCI,用户很少知道将外围设备连接到计算机的这些(内部)总线。
linux/drivers/spi/spi_bcm2708.c
是一个平台驱动程序。它没有 fops 来支持/执行 open(), read(), write()或 close()操作。它将自身注册为SPI主控制器,因此其他(目标)驱动程序可以使用SPI API来实现其服务。
IMO你最好在RPI和你的自定义SBC之间实现EIA / RS-232链接。如果使用非规范(原始)传输,那么如果/当您转换/升级到SPI连接时,您编写的代码中可能有99%将是可重用的。没有流量控制的3线串行连接类似于SPI连接,但没有施加主/从层次结构,更简单的HW接口和更长的电缆长度。
请注意,使用您安装的任何电缆,您可能无法在长SPI距离内实现快速传输速率。 SPI的10 Mbps速率通常在具有接地层和短迹线的多层板上实现。
答案 1 :(得分:4)
在Unix上,一切都是文件
如果正确安装了spi_bcm2708
驱动程序,那么该设备应该有一个/dev/whatever
文件(或者有几个用于以不同方式访问设备的文件)。
如果未自动创建一个,您可以使用mknod
进行输入用户空间代码只需打开/dev/whatever
文件,就好像它是任何其他常规文件并从中读取/写入数据一样。这就是Unix的重点。
编辑:这正是链接问题中的代码正在做的事情,它正在打开终端/dev/ttyS0
作为带有open()和读/写的文件。
答案 2 :(得分:1)
您找到了Linux documentation of SPI吗?
有几个好的文件:spi-summary和spidev。
文件spidev_fdx.c中也有示例,其中read()
用于SPI设备。
但通常从SPI读取由ioctl()
函数处理。