Я пытаюсь увеличить / уменьшить значение подсветки на встроенном linux (yocto) с помощью кнопки, подключенной к gpio
Я работал шаг за шагом, поэтому, во-первых, я добавил модуль ядра, который генерирует прерывание при каждом нажатии кнопки, это работает как чудо (printk при каждом нажатии кнопки, значение также доступно в пользовательском пространстве по адресу / sys / class / gpio / gpio133 / value)
Значение подсветки настраивается в пользовательском пространстве по адресу / sys / class / backlight / backlight / Brightness.
Я настроил дерево устройств на 8 различных уровней яркости со значением 0 в качестве максимума, это также работает
Затем я попытался получить значение подсветки в моем модуле ядра, добавив gpio_request и gpio_get_value, но оно всегда возвращает значение: 0. Я думаю, что модуль ядра не может получить доступ к gpio, потому что он уже используется драйвером в зарядка подсветки, я прав?
Поскольку значения gpio и подсветки доступны в пользовательском пространстве, я написал сценарий оболочки с бесконечным циклом, который считывает состояние gpio, и, если оно меняется, я получаю значение подсветки и уменьшаю его. Это работает, но используется более 10% процессорного времени. У меня также есть работающее приложение Qt со звуком, и во время работы скрипта звук потрескивает. Поэтому я добавил режим сна, чтобы замедлить чтение состояния 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, один для уменьшения значения задней подсветки, а другой для увеличения значения, поэтому я ищу лучшее решение
Любая помощь будет признательна