【问题标题】:Reading/writing SPI devices读/写 SPI 设备
【发布时间】:2017-01-24 12:31:12
【问题描述】:

(我真的不确定要应用哪些标签,所以如果我选择了错误的标签,请提前道歉。)

我希望这不是一个太愚蠢的问题,但我真的迷路了。

一位客户借给我一个Atmel SAMA5D2 Xplained board with Linux4SAM 来玩。我正在尝试在其上连接 SPI 接口,但我不知道从哪里开始。

为了清楚起见,我使用了类似的板(不是这个特定的)裸机。我也使用 Linux 多年,并在几年前编写了一些简单的设备驱动程序。我还是迷路了。

dmesg | grep spi 给我以下输出:

[    1.840000] atmel_spi f8000000.spi: version: 0x311
[    1.840000] atmel_spi f8000000.spi: Using dma0chan0 (tx) and dma0chan1 (rx) for DMA transfers
[    1.850000] atmel_spi f8000000.spi: Using FIFO (16 data)
[    1.860000] atmel_spi f8000000.spi: Atmel SPI Controller at 0xf8000000 (irq 32)
[    1.860000] m25p80 spi32766.0: at25df321a (4096 Kbytes)

据此,我推断驱动程序已加载并且已配置为使用 DMA。然而,查看 /dev/ 并没有任何东西看起来像 SPI 设备(我期待找到类似 /dev/spidev/dev/spi32766.0 或类似的东西。)

这是否意味着没有加载实际的设备驱动程序?我必须写一个才能使用 SPI 吗?

如果我查看Makefile in the Linux4SAM source tree,我会在第 1171 行看到内核不支持加载模块。这是否意味着我必须重新编译内核以包含我的新驱动程序?这似乎是一种愚蠢的方法;如果我无法访问硬件,为什么还要提供 Linux 发行版?

我在这里缺少什么? (我觉得挺傻的……)

编辑要明确:我想访问将连接到某个外部设备的外部 SPI 接口。我认为 m25p80 是一些内部闪存;我没有兴趣在那里读/写。

【问题讨论】:

  • kernel.org/doc/Documentation/spi/spidev 并且您必须在内核配置和设备树等资源提供程序中启用 spidev。
  • “如果我查看 Makefile ...内核不支持加载模块。” -- 您不会在 Makefile 中找到配置细节。 “我认为 m25p80 是一些内部闪存” -- 错误,即通过 SPI 连接的外部闪存。研究内核Documentation/spi/spi-summary。 SPI(从)设备通常具有源自其功能的设备节点名称,而不是其使用的接口。 Spidev 是个例外,因为它是一个用户空间组合。
  • @0andriy:在内核配置中启用了 spidev。我可以加载模块(modprobe),但没有出现新设备。我没想到必须在设备树中指定其他内容……我是此类平台上的 Linux 新手。
  • @sawdust:我措辞错误。内核确实支持加载模块,但 Makefile 告诉我无法使用源代码树 (make -C <path_to_lib/modules> modules) 编译新模块。我确实阅读了您所指的文档,但如果我不知道我在寻找什么信息,就很难将这些点联系起来。
  • 检查这里列出的spidevice cat /proc/devices,如果是并且看不到设备节点(/dev/spidev*),我怀疑你的驱动程序没有创建设备节点,需要使用mknod手动创建。

标签: linux-device-driver embedded-linux atmel


【解决方案1】:

spidev 是一个标准的 Linux 设备驱动程序,它只是通过 /dev 接口将低级 API 导出到用户空间

如果你想访问特定的 SPI 客户端(从)你应该写你的驱动程序 根据Linux SPI驱动模型:

static const struct of_device_id myspi_dt_ids[] = {
{ .compatible = "xxxx,yyyyy" },
{},

static struct spi_driver xxx_spi_driver = {
.driver = {
    .name =     "myspi",
    .owner =    THIS_MODULE,
    .of_match_table = of_match_ptr(myspi_dt_ids),
},
.probe =    myspi_probe,
.remove =   myspi_remove,

例如定义 spi_driver struct、of_device_id struct、callbacks(hooks),并注册它。 您应该使用兼容的属性字符串将其绑定到您的 DT 节点。

            myspi@0 {
            compatible = "xxxx,yyyyy";
            spi-max-frequency = <5000000>;
            reg = <0>;
        };

秒,

兼容 = "linux,spidev";

Linux 不鼓励使用此兼容属性,因为节点应该 描述真实的硬件设备而不是用户空间抽象

【讨论】:

  • 最初的问题是让一个测试程序工作,我希望用 spidev 来完成它,但我从来没有让它工作。为了开发除快速测试之外我需要的功能,我完全按照您在此处描述的方式进行了操作。
【解决方案2】:

@0andriy 让我走上了正轨。我必须将 SPI 资源添加到设备树并将编译的设备树 Blob 闪存到板上。 (因为我根本不知道设备树,所以这个信息真的很难找到......)。

我现在有一个/dev/spidev32765.0。我将此添加到设备树中:

        spi1: spi@fc000000 {
            pinctrl-names = "default";
            pinctrl-0 = <&pinctrl_spi1_default>;
            status = "okay";

            spidev@0 {
                compatible = "linux,spidev";
                spi-max-frequency = <83000000>;
                reg = <0>;
            };
        };

        pinctrl@fc038000 {
            pinctrl_spi1_default: spi1_default {
                pinmux = <PIN_PD25__SPI1_SPCK>,
                     <PIN_PD26__SPI1_MOSI>,
                     <PIN_PD27__SPI1_MISO>,
                     <PIN_PD28__SPI1_NPCS0>;
                bias-disable;
            };
        };

虽然我读到添加spidev@0 并不是真正正确的做法(我确实在dmesg 中看到输出“spidev spi32765.0: buggy DT: spidev listed directly in DT”)。

现在,如果我运行 spidev_test,它仍然不起作用(它会超时),但我想这是另一个问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-07
    • 2012-05-28
    • 1970-01-01
    • 2020-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多