Linux内核6.6.37-v8+下I2C驱动初始化指针类型不兼容错误排查
I2C驱动编译报错:函数签名不匹配问题
我在编写I2C设备驱动时陷入僵局,连续几天谷歌搜索都没解决问题。为了定位错误,我把代码简化到了最小程度:
#include <linux/i2c.h> #include <linux/module.h> static int my_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { pr_info("Probe function called\n"); // Add your probe implementation here return 0; // Return 0 on success } static int my_i2c_remove(struct i2c_client *client) { pr_info("Remove function called\n"); // Add your remove implementation here return 0; // Return 0 on success } static const struct i2c_device_id my_id_table[] = { { "my_i2c_device", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, my_id_table); static struct i2c_driver my_i2c_driver = { .driver = { .name = "my_i2c_driver", .owner = THIS_MODULE, }, .probe = my_i2c_probe, .remove = my_i2c_remove, .id_table = my_id_table, }; static int __init my_init(void) { return i2c_add_driver(&my_i2c_driver); } static void __exit my_exit(void) { i2c_del_driver(&my_i2c_driver); } module_init(my_init); module_exit(my_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Sample I2C Driver");
编译错误信息
编译时持续出现以下错误:
sudo make make -C /lib/modules/6.6.37-v8+/build M=/home/pi/ForestBox/driver modules make[1]: Entering directory '/home/pi/linux-4251c6ff2aa870ca9782abc0ecdf60eac3ba22ab' CC [M] /home/pi/ForestBox/driver/RTC_PCF_Driver.o /home/pi/ForestBox/driver/RTC_PCF_Driver.c:29:14: error: initialization of ‘int (*)(struct i2c_client *)’ from incompatible pointer type ‘int (*)(struct i2c_client *, const struct i2c_device_id *)’ [-Werror=incompatible-pointer-types] 29 | .probe = my_i2c_probe, | ^~~~~~~~~~~~ /home/pi/ForestBox/driver/RTC_PCF_Driver.c:29:14: note: (near initialization for ‘my_i2c_driver.probe’) /home/pi/ForestBox/driver/RTC_PCF_Driver.c:30:15: error: initialization of ‘void (*)(struct i2c_client *)’ from incompatible pointer type ‘int (*)(struct i2c_client *)’ [-Werror=incompatible-pointer-types] 30 | .remove = my_i2c_remove, | ^~~~~~~~~~~~~ /home/pi/ForestBox/driver/RTC_PCF_Driver.c:30:15: note: (near initialization for ‘my_i2c_driver.remove’) cc1: some warnings being treated as errors make[3]: *** [scripts/Makefile.build:243: /home/pi/ForestBox/driver/RTC_PCF_Driver.o] Error 1 make[2]: *** [/home/pi/linux-4251c6ff2aa870ca9782abc0ecdf60eac3ba22ab/Makefile:1921: /home/pi/ForestBox/driver] Error 2 make[1]: *** [Makefile:234: __sub-make] Error 2 make[1]: Leaving directory '/home/pi/linux-4251c6ff2aa870ca9782abc0ecdf60eac3ba22ab' make: *** [Makefile:5: all] Error 2
环境信息
- 内核版本:
$ uname -r 6.6.37-v8+
- GCC版本:
$ gcc --version gcc (Debian 12.2.0-14) 12.2.0 Copyright (C) 2022 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
我知道错误是函数签名不匹配,但我觉得自己的签名是正确的。在另一台同设备的全新系统测试,还是一样的错误。怀疑是版本问题,但不知道怎么验证。
问题根源
你的内核版本是6.6.37,属于较新的Linux内核,I2C驱动的probe和remove函数签名已经发生了变化:
- probe函数:旧版本内核支持带
const struct i2c_device_id *id参数的签名,但新内核已经废弃该形式,要求probe只接收struct i2c_client *client一个参数。 - remove函数:旧版本返回
int,新内核要求返回void,不再需要返回值。
修改后的代码
#include <linux/i2c.h> #include <linux/module.h> static int my_i2c_probe(struct i2c_client *client) { pr_info("Probe function called\n"); // Add your probe implementation here return 0; // Return 0 on success } static void my_i2c_remove(struct i2c_client *client) { pr_info("Remove function called\n"); // Add your remove implementation here } static const struct i2c_device_id my_id_table[] = { { "my_i2c_device", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, my_id_table); static struct i2c_driver my_i2c_driver = { .driver = { .name = "my_i2c_driver", .owner = THIS_MODULE, }, .probe = my_i2c_probe, .remove = my_i2c_remove, .id_table = my_id_table, }; static int __init my_init(void) { return i2c_add_driver(&my_i2c_driver); } static void __exit my_exit(void) { i2c_del_driver(&my_i2c_driver); } module_init(my_init); module_exit(my_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Your Name"); MODULE_DESCRIPTION("Sample I2C Driver");
验证版本兼容性的方法
你可以直接查看当前内核的i2c.h头文件,确认struct i2c_driver的定义:
cat /usr/src/linux-headers-$(uname -r)/include/linux/i2c.h | grep -A 10 "struct i2c_driver"
在6.6版本的内核中,i2c_driver的probe和remove定义如下:
struct i2c_driver { ... int (*probe)(struct i2c_client *client); void (*remove)(struct i2c_client *client); ... };
内容的提问来源于stack exchange,提问作者Mykola Grodskyi
相关产品推荐
相关产品推荐

