OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5031|回复: 17

使用i2c_new_device注册设备失败

[复制链接]

1

主题

9

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2020-6-1
在线时间
5 小时
发表于 2021-7-16 20:32:02 | 显示全部楼层 |阅读模式
使用i2c_new_device注册设备失败,错误提示为:probe of 0-001a failed with error 26,请问有遇到过这样的问题的吗?
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2020-6-1
在线时间
5 小时
 楼主| 发表于 2021-7-17 20:07:55 来自手机 | 显示全部楼层
原子哥,帮忙解决下啊
回复 支持 反对

使用道具 举报

5

主题

123

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1820
金钱
1820
注册时间
2019-7-23
在线时间
281 小时
发表于 2021-7-19 09:26:01 | 显示全部楼层
这个提示你已经有 0-001a这个设备了,所以你无法再次创建0-001a这个i2c设备。  设备树中估计已经创建了,你把设备树的这个设备节点注销掉,在调用创建i2c设备节点函数应该就行了
回复 支持 反对

使用道具 举报

5

主题

123

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1820
金钱
1820
注册时间
2019-7-23
在线时间
281 小时
发表于 2021-7-19 09:28:49 | 显示全部楼层
0-001a对应的是i2c0这个总线,在设备树种应该是 i2c1   因为在dtsi文件中,aliases这个节点属性中有一条 i2c0 = &i2c1
回复 支持 反对

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2020-6-1
在线时间
5 小时
 楼主| 发表于 2021-7-19 10:51:38 来自手机 | 显示全部楼层
tw1157727586 发表于 2021-7-19 09:28
0-001a对应的是i2c0这个总线,在设备树种应该是 i2c1   因为在dtsi文件中,aliases这个节点属性中有一条 i2 ...

感谢回复,地址我改成了42,这个地址没有地方使用,还是提示一样的问题,我主要是想在驱动里手动添加设备
回复 支持 反对

使用道具 举报

5

主题

123

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1820
金钱
1820
注册时间
2019-7-23
在线时间
281 小时
发表于 2021-7-19 13:48:09 | 显示全部楼层
你注册i2c设备的代码发一下
回复 支持 反对

使用道具 举报

5

主题

123

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1820
金钱
1820
注册时间
2019-7-23
在线时间
281 小时
发表于 2021-7-19 13:52:03 | 显示全部楼层
static int __init i2c_client_ap3216c_init(void)
{
        struct i2c_adapter *adapter;

        static struct i2c_board_info board_info = {
          I2C_BOARD_INFO("ap3216c", 0x1e),
        };

       
        printk("%s %s %d\n", __FILE__, __FUNCTION__, __LINE__);
        /* register I2C device */
        adapter = i2c_get_adapter(0);
        ap3216c_client = i2c_new_device(adapter, &board_info);
        i2c_put_adapter(adapter);
        return 0;
}

享受技术
回复 支持 反对

使用道具 举报

5

主题

123

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1820
金钱
1820
注册时间
2019-7-23
在线时间
281 小时
发表于 2021-7-19 13:53:04 | 显示全部楼层
重新做个驱动,这样注册一下就行了
回复 支持 反对

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2020-6-1
在线时间
5 小时
 楼主| 发表于 2021-7-19 15:10:41 | 显示全部楼层
tw1157727586 发表于 2021-7-19 13:53
重新做个驱动,这样注册一下就行了

我使用的platform模型,写了2个驱动,platform device里面注册i2c设备,然后platform driver注册后在probe里面注册i2c驱动,再在i2c的probe里面开启一个定时器,每隔300ms读取一次ps数据并打印
回复 支持 反对

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2020-6-1
在线时间
5 小时
 楼主| 发表于 2021-7-19 15:11:07 | 显示全部楼层
a5086397 发表于 2021-7-19 15:10
我使用的platform模型,写了2个驱动,platform device里面注册i2c设备,然后platform driver注册后在prob ...

platform device :

#define MY_PLATFORM_DEV_NAME     "i2c_3216"

void dev_release(struct device *dev)
{

}

struct platform_device my_platform_dev = {
    .name = MY_PLATFORM_DEV_NAME,
    .id = -1,
    .dev = {
        .release = dev_release,
    },
};

struct i2c_board_info i2c_3216_client_info = {
    I2C_BOARD_INFO("i2c_3216_dev", 0x1e),
};
struct i2c_client *my_i2c_client = NULL;

static int __init my_platform_dev_init(void)
{
    platform_device_register(&my_platform_dev);
    struct i2c_adapter *p = NULL;
    //注册client
    p = i2c_get_adapter(0);
    my_i2c_client = i2c_new_device(p, &i2c_3216_client_info);

    if( !my_i2c_client )
    {
        printk("i2c new device failed \r\n");
    }
    else
    {
        printk("i2c new device sucessful \r\n");
    }

        return 0;
}

static void __exit my_platform_dev_exit(void)
{
    platform_device_unregister(&my_platform_dev);
    if( my_i2c_client )
    {
        i2c_unregister_device(my_i2c_client);
    }
   
    printk("my_platform_dev_exit \r\n");
}

module_init(my_platform_dev_init);
module_exit(my_platform_dev_exit);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION(" my platform device");
回复 支持 反对

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2020-6-1
在线时间
5 小时
 楼主| 发表于 2021-7-19 15:11:54 | 显示全部楼层
a5086397 发表于 2021-7-19 15:11
platform device :

#define MY_PLATFORM_DEV_NAME     "i2c_3216"

platform driver:

#define DEV_NAME          "i2c_3216"

struct my_i2c_3216{
    struct timer_list timer;
    struct i2c_client *my_i2c_client;
};

struct my_i2c_3216 i2c_3216_device;

void i2c_3216_read_reg(int reg, uint8_t *buf)
{
    struct i2c_msg msg[2] = {0};

    msg[0].addr = i2c_3216_device.my_i2c_client->addr;
    msg[0].len = 1;
    msg[0].buf = ®
    msg[0].flags = 0;

    msg[1].addr = i2c_3216_device.my_i2c_client->addr;
    msg[1].len = 1;
    msg[1].buf = buf;
    msg[1].flags = I2C_M_RD;

    i2c_transfer(i2c_3216_device.my_i2c_client->adapter, msg, 2);
}

void i2c_3216_write_reg(int reg, uint8_t *buf)
{
    struct i2c_msg msg[2] = {0};

    msg[0].addr = i2c_3216_device.my_i2c_client->addr;
    msg[0].len = 1;
    msg[0].buf = ®
    msg[0].flags = 0;

    msg[1].addr = i2c_3216_device.my_i2c_client->addr;
    msg[1].len = 1;
    msg[1].buf = buf;
    msg[1].flags = 0;

    i2c_transfer(i2c_3216_device.my_i2c_client->adapter, msg, 2);
}

//定时器中断函数,用于按键消除抖动
void timer_handler(unsigned long param)
{
    uint8_t data[2] = {0};
    uint16_t ps = 0;
    struct my_i2c_3216 *dev = (struct my_i2c_3216 *)param;
    mod_timer(&dev->timer, jiffies + msecs_to_jiffies(300));
    i2c_3216_read_reg(0x0e, &data[0]);
    i2c_3216_read_reg(0x0e, &data[1]);
    ps = data[0] | (data[1] << 8);
    printk("3216 ps data : %d \r\n", ps);
}


int i2c_3216_probe(struct i2c_client *client, const struct i2c_device_id *id )
{
    uint8_t data = 0;
    //保存设备信息,用于获取设备地址
    i2c_3216_device.my_i2c_client = client;
    if( client )
    {
        printk("client addr : %02x \r\n", client->addr);
    }
    //初始化定时器, 定时器中断中读取ps数据并输出
    init_timer(&i2c_3216_device.timer);
    i2c_3216_device.timer.function = timer_handler;
    i2c_3216_device.timer.data = (unsigned long)&i2c_3216_device;
    mod_timer(&i2c_3216_device.timer, jiffies + msecs_to_jiffies(300));

    //初始化3216
    data = 0x04;
    i2c_3216_write_reg(0x00, &data);
    mdelay(50);
    data = 0x03;
    i2c_3216_write_reg(0x00, &data);
}

int i2c_3216_remove(struct i2c_client *client)
{
    del_timer(&i2c_3216_device.timer);
}

struct i2c_device_id _3216_id_table[] = {
    {.name = "i2c_3216_dev"},
};

struct i2c_driver i2c_3216_driver = {
    .probe = i2c_3216_probe,
    .remove = i2c_3216_remove,
    .id_table = _3216_id_table,
    .driver = {
        .owner = THIS_MODULE,
        .name = "i2c_3216_dev",
    },
};

int my_platform_probe(struct platform_device *dev)
{
    //注册3216驱动
    i2c_register_driver(THIS_MODULE, &i2c_3216_driver);
    return 0;
}

int my_platform_remove(struct platform_device *dev)
{
    i2c_del_driver(&i2c_3216_driver);
    printk("my_platform_remove\r\n");
}



struct platform_driver my_platform_driver = {
    .driver = {
        .name = "i2c_3216",
        .owner = THIS_MODULE,
    },

    .probe = my_platform_probe,
    .remove = my_platform_remove,
};


module_platform_driver(my_platform_driver);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("i2c 3216 driver");

回复 支持 反对

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2020-6-1
在线时间
5 小时
 楼主| 发表于 2021-7-19 15:12:48 | 显示全部楼层
a5086397 发表于 2021-7-19 15:11
platform driver:

#define DEV_NAME          "i2c_3216"

挂载驱动后,错误类型变成了02:
/ # depmod
/ # modprobe my_platform_device.ko
[   21.745615] i2c new device sucessful
/ # modprobe i2c_no_dts_driver.ko
[   28.158811] client addr : 1e
[   28.219151] i2c_3216_dev: probe of 0-001e failed with error 2
回复 支持 反对

使用道具 举报

5

主题

123

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1820
金钱
1820
注册时间
2019-7-23
在线时间
281 小时
发表于 2021-7-19 17:14:33 | 显示全部楼层
本帖最后由 tw1157727586 于 2021-7-19 17:19 编辑

你没有释放 adapter,可能会导致你无法卸载此驱动
享受技术
回复 支持 反对

使用道具 举报

5

主题

123

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1820
金钱
1820
注册时间
2019-7-23
在线时间
281 小时
发表于 2021-7-19 17:15:39 | 显示全部楼层
struct i2c_adapter *i2c_get_adapter(int nr)
{
        struct i2c_adapter *adapter;

        mutex_lock(&core_lock);
        adapter = idr_find(&i2c_adapter_idr, nr);
        if (adapter && !try_module_get(adapter->owner))
                adapter = NULL;

        mutex_unlock(&core_lock);
        return adapter;
}
EXPORT_SYMBOL(i2c_get_adapter);

void i2c_put_adapter(struct i2c_adapter *adap)
{
        if (adap)
                module_put(adap->owner);
}
EXPORT_SYMBOL(i2c_put_adapter);


i2c_get_adapter和i2c_put_adapter是成对出现的




享受技术
回复 支持 反对

使用道具 举报

5

主题

123

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1820
金钱
1820
注册时间
2019-7-23
在线时间
281 小时
发表于 2021-7-19 17:16:46 | 显示全部楼层
请参考我发的代码,和你的代码还有差别的
回复 支持 反对

使用道具 举报

5

主题

123

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1820
金钱
1820
注册时间
2019-7-23
在线时间
281 小时
发表于 2021-7-19 17:25:30 | 显示全部楼层
你想要使用i2c设备没必要注册platform设备。
回复 支持 反对

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2020-6-1
在线时间
5 小时
 楼主| 发表于 2021-7-19 19:51:23 来自手机 | 显示全部楼层
tw1157727586 发表于 2021-7-19 17:25
你想要使用i2c设备没必要注册platform设备。

再次感谢!问题找到了,除了设备树里面注释设备节点外,还需要配置下内核,取消编译自带的驱动
回复 支持 反对

使用道具 举报

1

主题

9

帖子

0

精华

新手上路

积分
25
金钱
25
注册时间
2020-6-1
在线时间
5 小时
 楼主| 发表于 2021-7-19 19:55:12 来自手机 | 显示全部楼层
tw1157727586 发表于 2021-7-19 17:14
你没有释放 adapter,可能会导致你无法卸载此驱动

我之前试过释放adapter,还是会报错
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-25 18:36

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表