【问题标题】:Including Drivers in User Space Programs/ SPI Application在用户空间程序/ SPI 应用程序中包含驱动程序
【发布时间】:2018-04-18 20:59:25
【问题描述】:

现在我正在寻找使用 Cadence SPI 驱动程序在 Linux 上执行一些基本的读写操作。我刚刚使用了 I2C 驱动程序,但对于所有这些驱动程序如何组合在一起以及是否存在它们都符合的通用接口,我仍然有些困惑。

这是我编写的使用 I2C 驱动程序的代码

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <inttypes.h>

#include <errno.h>
#include <string.h>

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>

#define I2C_ADAPTER                 "/dev/i2c-0"
#define I2C_SWITHC_MUX_ADDRESS      0x74
#define DEVICE_ADDRESS              0x54


int main (int argc, char *argv[])
{
    int file;

    uint8_t reg, value;

    char *end;

    /* Take a value to write */

    printf("The device address on the bus: %d", DEVICE_ADDRESS);

    if(argc == 2) {
        value = strtol(argv[1], &end, 16);
        printf("value to write is: %d\n", value);
    }
    else {
        printf("arg failed\n\n.");
    }


    if((file = open(I2C_ADAPTER, O_RDWR)) < 0) {
        printf("Failed to open the bus\n");
        return -1;
    }

    if(ioctl(file, I2C_SLAVE_FORCE, I2C_SWITHC_MUX_ADDRESS) < 0) {
        printf("Unable to open device as slave \n%s\n", strerror(errno));
        return -1;
    }

    char buf[10];

    reg = DEVICE_ADDRESS;

    buf[0] = reg;
    buf[1] = value;

    if(write(file, buf, 2) != 2) {
        printf("Failed to write to bus %s.\n\n", strerror(errno));
    }
    else {
        printf("Successful write\n");
        printf(buf);
        printf("\n\n");
    }

    if(read(file, buf, 1) != 1) {
        printf("Failed to read from the i2c bus.\n %s\n\n", strerror(errno));
    }
    else {
        printf("Successful read\n");
        printf("Buf = [%02u]\n", buf[0]);
        printf("\n\n");
    }

    return 0;
}

我对实际调用驱动程序的位置感到困惑。现在我在这里阅读 SPI 驱动程序文档:

https://www.kernel.org/doc/html/v4.11/driver-api/spi.html

I2C 驱动的相应文档在这里:

https://www.kernel.org/doc/html/v4.11/driver-api/i2c.html

I2C 文档中定义的第一个结构是 i2c_driver。我不认为我在编写 I2C 程序时使用了 I2C 驱动程序文档中定义的任何结构。我真的使用过 I2C Cadence 驱动程序吗?如果没有,如何重写我的程序以使用 I2C Cadence 驱动程序,以便了解如何在用户空间中使用驱动程序,以便使用 SPI 驱动程序。

【问题讨论】:

  • 您通过“i2c-dev”驱动程序间接使用了 I2C Cadance 驱动程序。每当从系统中添加或删除 I2C 适配器(I2C 主总线控制器)时,该驱动程序都会收到通知,并创建或销毁“/dev/i2c-n”设备作为响应。这允许用户空间应用程序向 I2C 总线上的任何从设备发送消息(有可能混淆绑定到设备驱动程序的任何从设备)。
  • 使用 SPI,您可以使用“spidev”驱动程序从用户空间访问 SPI 从设备,但与 I2C 不同,SPI 从设备需要在系统中定义(例如在设备树或板配置代码)并绑定到“spidev”驱动程序。
  • 我知道如何将它添加到设备树中。但是如何将它绑定到驱动程序?我想添加一个eeprom。
  • 这些“开发”驱动程序是什么?它们是合法的还是我应该通过其他协议来访问系统?
  • 最后,当您在用户空间使用驱动程序时,正常流程是 1. 定义与硬件相关的宏 2. 使用宏文件驱动程序结构 3. 调用驱动程序例程以作用于硬件?

标签: c linux linux-device-driver userspace


【解决方案1】:

这是调用堆栈从用户空间通过内核 I2C 框架到 Cadence I2C 驱动程序的样子(类似于read()/write()):

  1. 用户空间驱动程序ioctl()i2c-dev.c 中调用compat_i2cdev_ioctl()
  2. i2cdev_ioctl_rdwr()i2c-core-case.c 中调用i2c_transfer()
  3. __i2c_transfer() 致电adap-&gt;algo-&gt;master_xfer()

当你注册I2C驱动时,这个函数指针.master_xfer是用i2c-cadence.c中定义的回调初始化的,在probe()函数中:

id->adap.algo = &cdns_i2c_algo;

struct i2c_algorithm cdns_i2c_algo = {
.master_xfer    = cdns_i2c_master_xfer,

希望对你有帮助。

【讨论】:

    【解决方案2】:

    把我的两分钱放进去,你也可以使用 i2c-tools 实用程序。这使得使用 linux 处理 i2c 设备变得非常容易。参考如何使用它。 https://elinux.org/Interfacing_with_I2C_Devices

    【讨论】:

    • 对于我的实际实现,这正是我所做的。只是不确定它会如何扩展以及是否是首选方式
    • 一个澄清。您提供的代码是用户应用程序(具有主要功能)。内核驱动程序代码将创建。 /dev 中的 i2c-* 设备节点。现在你有两个选择。从您编写的用户空间使用 i2c-* 。并在初始化时交叉编译并启动(编写一些初始化脚本)。或编写内核驱动程序检查一些 rtc 驱动程序以从内核执行相同的请求。自己决定你想做什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-04
    • 1970-01-01
    • 1970-01-01
    • 2013-02-23
    • 2018-02-27
    相关资源
    最近更新 更多