【问题标题】:Why are i2c_smbus function not available? (I2C – Embedded Linux)为什么 i2c_smbus 功能不可用? (I2C – 嵌入式 Linux)
【发布时间】:2014-08-06 11:22:19
【问题描述】:

在开发嵌入式 Linux 软件以在 I2C 总线上进行通信时,有很多关于使用 i2c_smbus_ 函数的参考资料。当 i2c_smbus 函数如 i2c_smbus_read_word_data 在软件项目中被引用时,ARM8 处理器错误如 'i2c_smbus_read_word_data' 未在此范围内声明 生成于编译。

对以下头文件的调查表明大多数 i2c_smbus 函数定义都不存在。

  • /usr/arm-linux-gnueabi/include/linux/i2c.h
  • /usr/arm-linux-gnueabi/include/linux/i2c-dev.h

同样在下面的参考i2c.h 文件中定义了所有的 i2c_smbus。

如何解决这个问题?

研究参考文献

  1. Using I2C from userspace in Linux
  2. I2C Communication from Linux Userspace – Part II
  3. I2C dev interface

【问题讨论】:

  • 最快的 google 显示你需要包含
  • 我没有看到 i2c-smbus.h 包含在上述任何一个 arm-linux-gnueabi 路径中。
  • 该文件在 2010 年作为 include/linux/i2c-smbus.h 添加到 内核 但是在内核源代码中包含它并不一定意味着它将在您的用户空间中包含给定系统上的目录作为参考,主线提交在这里git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/…
  • 但我没有看到 i2c-smbus.h 中定义的 i2c_smbus_read_byte_data 函数。但是请根据附加链接查看 i2c.h 中定义的这些函数。 cs.fsu.edu/~baker/devices/lxr/http/source/linux/include/linux/…。我想知道如何更新库文件 /usr/arm-linux-gnueabi/include/linux/i2c.h 以包含 i2c_smbus 函数。我不确定是否可能。如果有更新 arm-linux-gnueabi 库的过程,我已经在 ask.ubuntu c 上发布了一个问题。 askubuntu.com/questions/507628/…
  • @MahendraGunawardena 你是在用户空间还是内核空间实现驱动程序?

标签: c++ c arm embedded-linux i2c


【解决方案1】:

因为您的应用程序使用了错误的头文件。

如果您在标头中的函数i2c_smbus_read_word_data() 上看到extern,则它是您的内核 的头文件,而不是您的应用程序 的头文件。 Linux 内核有i2c_smbus_read_word_data() 和其他i2c smbus 函数供其内部使用。但它们是 a) 不是系统调用,或 b) 无法从您的应用程序访问。

相反,获取i2c-tools from Linux Kernel Wiki 并安装它。如果您使用的是 Debian,只需

sudo apt-get install libi2c-dev

并使用i2c_smbus_read_word_data() 或他们提供的任何其他接口。

版本说明

i2c-dev,直到版本 3.x,曾经是一个只有头文件的包,这意味着没有库可以链接。所有函数都是使用ioctl() 定义的内联函数。

例如)

static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
                                     int size, union i2c_smbus_data *data)
{
        struct i2c_smbus_ioctl_data args;

        args.read_write = read_write;
        args.command = command;
        args.size = size;
        args.data = data;
        return ioctl(file,I2C_SMBUS,&args);
}
   :
static inline __s32 i2c_smbus_read_word_data(int file, __u8 command)
{
        union i2c_smbus_data data;
        if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
                             I2C_SMBUS_WORD_DATA,&data))
                return -1;
        else
                return 0x0FFFF & data.word;
}

但从 v4.0 开始,它开始成为标准共享库,带有 libi2c.so.0i2c/smbus.h。您必须在源代码中包含头文件

#include <i2c/smbus.h>

并将libi2c.so.0-li2c 链接

gcc -o a.out main.o -li2c

【讨论】:

【解决方案2】:

我今天遇到了这个。 i2c_smbus_* 函数定义在:

/usr/include/linux/i2c-dev.h

...但是当我尝试在旧版本的 Ubuntu 上为 ARM 进行交叉编译时,我遇到了以下错误:

i2c_smbus_read_block_data was not declared in this scope

原来这些函数没有在等效的 ARM 特定位置定义:

/usr/arm-linux-gnueabi/include/linux/i2c-dev.h

交叉编译时,使用的是第 2 个较旧的头文件。不得不在本地重新声明一些内联 i2c_smbus_... 函数来解决这个问题。

【讨论】:

    【解决方案3】:

    基于https://unix.stackexchange.com/questions/621854/usr-include-linux-i2c-dev-h-does-not-contain-i2c-smbus-read-word-data-functio,我发现这修复了函数未定义错误:

    #include <i2c/smbus.h>
    

    我目前正在处理引用各种 i2c_smbus 函数的遗留代码。它有:

    #include <linux/i2c-dev-user.h>
    

    它无法编译。当然,这个包含曾经可以工作,但似乎 lib 的头文件在某些​​时候发生了变化。我最近确实刷新/重新安装了 libi2c-dev。

    请注意,我添加了上述包含。我无法删除原始包含。还是需要的。

    仅供参考:我还没有尝试过交叉编译。

    【讨论】:

      【解决方案4】:

      来自i2c Linux kernel documentation

      请注意,这里有两个名为“i2c-dev.h”的文件,一个随 Linux 内核分发,旨在包含在内核驱动程序代码中,另一个随 i2c-tools 分发,是意味着包含在用户空间程序中。你显然想要第二个。

      因此,您需要包含来自 i2c-tools 而不是来自 Linux 内核的 i2c-dev.h

      【讨论】:

        猜你喜欢
        • 2019-09-15
        • 2014-01-14
        • 2022-08-09
        • 2022-06-17
        • 1970-01-01
        • 2018-02-15
        • 1970-01-01
        • 2012-09-21
        • 1970-01-01
        相关资源
        最近更新 更多