在内核模块IOCTLs中使用GPIOs

问题描述 投票:0回答:1

我在我的内核模块中使用GPIO,当我从IOCTL中设置或重置GPIO时,我在 "dmesg "日志中得到以下警告。

[11115.549204] WARNING: CPU: 1 PID: 5199 at drivers/gpio/gpiolib.c:2415 gpiod_get_raw_value+0x7c/0xb8
[11115.558267] Modules linked in: ariodrv(O) [last unloaded: ariodrv]
[11115.564570] CPU: 1 PID: 5199 Comm: ARIO_RMG Tainted: G        W  O    4.9.166.RMG.-00002-gcbd9807b6c03-dirty #13
[11115.574776] Hardware name: Freescale i.MX6 Quad/DualLite (Device Tree)
[11115.581320] Backtrace: 
[11115.583816] [<8010b150>] (dump_backtrace) from [<8010b3fc>] (show_stack+0x18/0x1c)
[11115.591426]  r7:00000009 r6:600b0013 r5:80c1ae70 r4:00000000
[11115.597119] [<8010b3e4>] (show_stack) from [<803f51d4>] (dump_stack+0x9c/0xb0)
[11115.604380] [<803f5138>] (dump_stack) from [<80124878>] (__warn+0xec/0x104)
[11115.611367]  r7:00000009 r6:80a39e28 r5:00000000 r4:00000000
[11115.617050] [<8012478c>] (__warn) from [<80124948>] (warn_slowpath_null+0x28/0x30)
[11115.624653]  r9:8d696000 r8:7ea8cfa0 r7:0000000e r6:8d26e600 r5:8c1f9c54 r4:8c207f10
[11115.632434] [<80124920>] (warn_slowpath_null) from [<8042fbb8>] (gpiod_get_raw_value+0x7c/0xb8)
[11115.641177] [<8042fb3c>] (gpiod_get_raw_value) from [<7f00cd78>] (device_ioctl+0x334/0x9f8 [ariodrv])
[11115.650428]  r5:8004d282 r4:7ea8cfa0
[11115.654034] [<7f00ca44>] (device_ioctl [ariodrv]) from [<80219c58>] (do_vfs_ioctl+0xa8/0x914)
[11115.662595]  r7:0000000e r6:8d26e600 r5:8ccc5bc0 r4:7ea8cfa0
[11115.668278] [<80219bb0>] (do_vfs_ioctl) from [<8021a500>] (SyS_ioctl+0x3c/0x64)
[11115.675618]  r10:00000036 r9:8d696000 r8:7ea8cfa0 r7:8004d282 r6:8d26e600 r5:0000000e
[11115.683477]  r4:8d26e601
[11115.686035] [<8021a4c4>] (SyS_ioctl) from [<80107960>] (ret_fast_syscall+0x0/0x48)
[11115.693645]  r9:8d696000 r8:80107b44 r7:00000036 r6:00000000 r5:768c611c r4:7ea8cf98
[11115.701504] ---[ end trace 7be84f1e05fd36af ]---

但是如果我在其他函数中设置或获取GPIO引脚的值,比如我的模块的init函数,我就不会收到这些警告......

所以问题是我应该如何在IOCTL调用中使用GPIO引脚?

这是我的GPIO设置IOCTL代码的一部分。

IOCTL_FUNC(...) {

....

case IOCTL_RMG_GPIO_SET:
            {
                ....
                //I have initialized the GPIO pin as output before, and assume my gpio pin number is 4.
                //int gpioNumber = 4;
                //int value = 1;
                gpio_set_value(gpioNumber, value);

                break;
            }
 ....
}

不管是获取还是设置一个值都是无所谓的 如果我在IOCTL调用中使用这些GPIO,我得到了警告。但是在其他内部函数中,比如 init_module()module_release() 函数,我可以在没有警告的情况下设置和获取这些值。

EDIT 1.我的问题是在我的IOexpander(MCP23xxx系列)的GPIO上。

我的问题出在我的IOexpander(MCP23xxx系列)上的GPIO上,这个IOexpander在i2c总线上工作,我在使用我的处理器(iMX6DL)上的GPIO时没有任何问题或警告。

EDIT 2.我在使用我的处理器(iMX6DL)上的GPIO时没有任何问题或警告。

@Tsyvarev 和 @0andriy 谢谢你们, From 这个环节 我想明白了 gpiod_get_raw_value_cansleep() 函数不是我所需要的,因为这个函数需要一个GPIO描述符来工作,我的内核错误就是因为这个。但是这个函数 gpio_get_value_cansleep()gpio_set_value_cansleep() 函数是适合i2c IO扩展器的函数。

所以谢谢你的帮助,现在是工作代码。

IOCTL_FUNC(...) {

....

case IOCTL_RMG_GPIO_SET:
            {
                ....
                //I have initialized the GPIO pin as output before, and assume my gpio pin number is 4.
                //int gpioNumber = 4;
                //int value = 1;
                gpio_set_value_cansleep(gpioNumber, value);

                break;
            }
case IOCTL_RMG_GPIO_GET:
            {
                ....
                //I have initialized the GPIO pin as output before, and assume my gpio pin number is 4.
                //int gpioNumber = 4;
                value = gpio_get_value_cansleep(gpioNumber);

                break;
            }
 ....
}
linux linux-kernel kernel-module gpio
1个回答
1
投票

如果你读了警告处的linux源代码,它会告诉你。

* This function should be called from contexts where we cannot sleep, and will
* complain if the GPIO chip functions potentially sleep.
WARN_ON(desc->gdev->chip->can_sleep);

你应该调用gpio_get_value_cansleep。

© www.soinside.com 2019 - 2024. All rights reserved.