【问题标题】:How to control backlight with a button connect to a gpio?如何通过按钮连接到 gpio 来控制背光?
【发布时间】:2019-09-07 16:27:28
【问题描述】:

我正在尝试使用连接到 gpio 的按钮来增加/减少嵌入式 linux (yocto) 上的背光值

我一步一步地工作,所以,首先,我添加了一个内核模块,每次按下按钮时都会产生一个中断,它的工作就像一个魅力(每次按下按钮时打印k,值也可以访问在 /sys/class/gpio/gpio133/value 的用户空间中)

背光值可在用户空间的 /sys/class/backlight/backlight/brightness 中配置。 我将设备树配置为具有 8 个不同级别的亮度,最大值为 0,这也有效

然后我尝试通过添加 gpio_request 和 gpio_get_value 来获取内核模块中的背光值,但它总是返回值:0。我认为内核模块无法访问 gpio,因为它已被驱动程序使用背光充电,对吗?

由于 gpio 和背光的值可以在用户空间中访问,我编写了一个带有无限循环的 shell 脚本,它读取 gpio 状态,如果它改变了,我得到背光值并减小它。它可以工作,但它使用了超过 10% 的 cpu。我还有一个正在运行的带有声音的 Qt 应用程序,当脚本运行时,声音会噼啪作响。所以我在其中添加了一个 sleep 以减慢 gpio 状态的读取速度,持续时间刚好足以避免爆裂声,但是现在,有时,由于睡眠而错过了按钮按下。

这是工作内核模块,没有任何尝试控制背光:

#include <linux/module.h>
#include <linux/gpio.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Button test management");
MODULE_VERSION("0.1");

static unsigned int GPIO_BUTTON_LUM_PLUS = 133;
static unsigned int irqNumber;

static irq_handler_t ebbgpio_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs);


static int __init ebbgpio_init (void)
{
   int result=0;
   printk(KERN_INFO "GPIO_TEST: Initializing the GPIO_TEST LKM\n");

   if (!gpio_is_valid(GPIO_BUTTON_LUM_PLUS))
   {
      printk(KERN_INFO "GPIO_TEST: invalid Button GPIO LKM\n");
      return -ENODEV;
   }

   gpio_request(GPIO_BUTTON_LUM_PLUS, "sysfs");
   gpio_direction_input(GPIO_BUTTON_LUM_PLUS);
   gpio_set_debounce(GPIO_BUTTON_LUM_PLUS, 200);
   gpio_export(GPIO_BUTTON_LUM_PLUS, false);

   printk(KERN_INFO "GPIO_TEST: the button state is currently: %d\n", gpio_get_value(GPIO_BUTTON_LUM_PLUS));

   irqNumber = gpio_to_irq(GPIO_BUTTON_LUM_PLUS);
   printk(KERN_INFO "GPIO_TEST: the button is mapped to IRQ: %d\n", irqNumber);

   result = request_irq(irqNumber, (irq_handler_t) ebbgpio_irq_handler, IRQF_TRIGGER_RISING, "ebb_gpio_handler", NULL);

   printk(KERN_INFO "GPIO_TEST: The interrupt request result is: %d\n", result);
   return result;
}

static void __exit ebbgpio_exit(void)
{
   printk(KERN_INFO "GPIO_TEST: The button state is currently: %d\n", gpio_get_value(GPIO_BUTTON_LUM_PLUS));
   gpio_unexport(GPIO_BUTTON_LUM_PLUS);
   free_irq(irqNumber, NULL);
   gpio_free(GPIO_BUTTON_LUM_PLUS);
}   

static irq_handler_t ebbgpio_irq_handler(unsigned int irq, void *dev_id, struct pt_regs *regs)
{
   printk(KERN_INFO "GPIO_TEST: Interrupt! (button state is %d)\n", gpio_get_value(GPIO_BUTTON_LUM_PLUS));
   return (irq_handler_t) IRQ_HANDLED;
}


module_init(ebbgpio_init);
module_exit(ebbgpio_exit);

将来我需要读取 2 个 gpio,一个用于降低背光值,另一个用于增加值,所以我正在寻找更好的解决方案 任何帮助将不胜感激

【问题讨论】:

  • 您好,不是一个完整的答案,但您应该查看此类内容:lwn.net/Articles/604686,以便您在文件发生更改时收到通知。
  • 您可以查看gpio-watch 例如。请小心,因为它是 GPL-3 许可的。您还可以查看新的 GPIO API 工具here
  • 感谢您的回答。 YCN:我将 inotify-tools 添加到 yocto 并成功地使用教程中的命令 (inotifywait) 检测到文件夹中的更改。但是当我在 /sys/class/gpio/gpio133 中使用它时,它看不到任何变化。我尝试使用背光,它可以工作,但在这种情况下,我自己更改了值,因为 gpio 被配置为输出。 Nayfe:我明天会试试你的解决方案
  • 最后我设法让 inotifywait 工作,即使 gpio 值文件发生变化,inotify 也需要将 gpio 边缘文件设置为非无值。现在它可以工作了,但是当我按下 gpio 上的按钮时,inotify 检测到 gpio 值文件上的 3 修改事件,这肯定是一个去抖动问题。我还成功地交叉编译了 gpio-watch,它完全符合我的要求。但是我没有实现将它添加到 yocto 中的自定义层,因为我不知道如何添加基于 Makefile 的收据。
  • 您可以使用gpio-keys内核模块和DT或ACPI中的相应记录来执行此操作,无需编写任何代码。

标签: kernel-module yocto gpio backlight


【解决方案1】:

gpio-watch 完全符合我的要求。我创建了一个配方将其添加到我的层中并成功交叉编译了包。但由于它是一个基于 makefile 的包,我很难将它直接安装到我的镜像中。

感谢:https://www.yoctoproject.org/docs/1.8/mega-manual/mega-manual.html#new-recipe-makefile-based-package 我终于设法通过在我的食谱中添加这个来安装包:

 EXTRA_OEMAKE = "'CC=${CC}' 'RANLIB=${RANLIB}' 'AR=${AR}' 'CFLAGS=${CFLAGS} -I${S}/include -DWITHOUT_XATTR' 'BUILDDIR=${S}'"

 do_install () {
         oe_runmake install DESTDIR=${D} SBINDIR=${sbindir} MANDIR=${mandir} INCLUDEDIR=${includedir}
 }

再次感谢您的帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多