【MT9669】GPIO IRQ功能在驱动中使用说明

在MT9669的Linux Kernel中,驱动要如何实现中断操作呢?下面是对于非PM GPIO口实现IRQ的相应操作说明:

1.在MT9669中对于GPIO IRQ的对应关系说明如下:

  在bootable/bootloader/mboot-mtk/mboot/sboot/inc/M7642/board/BD_MT167B_10AT_MT5888_M7642.h中有如下内容:

#define PADS_EXTINT0                            DISABLE                 //CONFIG_PADMUX_MODE1: EXT INT0
#define PADS_EXTINT1                            DISABLE                 //CONFIG_PADMUX_MODE1: EXT INT1
                                                                        //CONFIG_PADMUX_MODE2: EXT INT1
#define PADS_EXTINT2                            DISABLE                 //CONFIG_PADMUX_MODE1: EXT INT2
                                                                        //CONFIG_PADMUX_MODE2: EXT INT2
#define PADS_EXTINT3                            DISABLE                 //CONFIG_PADMUX_MODE1: EXT INT3
                                                                        //CONFIG_PADMUX_MODE2
  • 15
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Linux内核GPIO驱动使用消息队列可以解耦原有的功能函数,实现异步处理GPIO断事件。下面是一个简单的示例代码: ```c #include <linux/gpio.h> #include <linux/interrupt.h> #include <linux/module.h> #include <linux/mutex.h> #include <linux/slab.h> #define MAX_QUEUE_LEN 32 struct gpio_event { int gpio; bool value; struct list_head list; }; static struct gpio_event *events; static struct list_head event_list; static DEFINE_MUTEX(event_lock); static DECLARE_WAIT_QUEUE_HEAD(event_waitq); static struct task_struct *event_task; static struct task_struct *queue_task; static int gpio_event_thread(void *data) { while (!kthread_should_stop()) { wait_event_interruptible(event_waitq, !list_empty(&event_list)); mutex_lock(&event_lock); while (!list_empty(&event_list)) { struct gpio_event *event = list_first_entry(&event_list, struct gpio_event, list); list_del(&event->list); mutex_unlock(&event_lock); // 处理 GPIO 断事件 printk(KERN_INFO "GPIO %d value %d\n", event->gpio, event->value); kfree(event); mutex_lock(&event_lock); } mutex_unlock(&event_lock); } return 0; } static irqreturn_t gpio_event_handler(int irq, void *dev_id) { unsigned int gpio = (unsigned int)dev_id; bool value = gpio_get_value(gpio); struct gpio_event *event = kmalloc(sizeof(*event), GFP_KERNEL); if (!event) { printk(KERN_ERR "Failed to allocate gpio event\n"); return IRQ_HANDLED; } event->gpio = gpio; event->value = value; mutex_lock(&event_lock); if (list_empty(&event_list)) { wake_up_interruptible(&event_waitq); } if (list_is_singular(&event_list)) { if (event_task) { wake_up_process(event_task); } } list_add_tail(&event->list, &event_list); if (list_is_full(&event_list)) { if (queue_task) { wake_up_process(queue_task); } } mutex_unlock(&event_lock); return IRQ_HANDLED; } static int gpio_event_queue_thread(void *data) { while (!kthread_should_stop()) { mutex_lock(&event_lock); if (list_is_full(&event_list)) { struct gpio_event *event = list_first_entry(&event_list, struct gpio_event, list); list_del(&event->list); // 处理 GPIO 断事件 printk(KERN_INFO "Discarded GPIO %d value %d\n", event->gpio, event->value); kfree(event); } mutex_unlock(&event_lock); set_current_state(TASK_INTERRUPTIBLE); schedule(); } return 0; } static int __init gpio_event_init(void) { int ret; int i; printk(KERN_INFO "GPIO event module loaded\n"); events = kmalloc_array(MAX_QUEUE_LEN, sizeof(*events), GFP_KERNEL); if (!events) { printk(KERN_ERR "Failed to allocate gpio event array\n"); return -ENOMEM; } INIT_LIST_HEAD(&event_list); event_task = kthread_run(gpio_event_thread, NULL, "gpio_event"); if (!event_task) { printk(KERN_ERR "Failed to create gpio event thread\n"); ret = -ENOMEM; goto err_free_events; } queue_task = kthread_run(gpio_event_queue_thread, NULL, "gpio_queue"); if (!queue_task) { printk(KERN_ERR "Failed to create gpio queue thread\n"); ret = -ENOMEM; goto err_stop_event_thread; } for (i = 0; i < MAX_QUEUE_LEN; i++) { events[i].gpio = -1; } for (i = 0; i < NUM_GPIO_CHIPS; i++) { struct gpio_chip *chip = &gpio_chip[i]; if (chip->base <= chip->ngpio) { int j; for (j = 0; j < chip->ngpio; j++) { int gpio = chip->base + j; if (gpio_is_valid(gpio)) { ret = gpio_request_one(gpio, GPIOF_IN, "gpio_event"); if (ret) { printk(KERN_ERR "Failed to request gpio %d\n", gpio); goto err_free_gpio; } ret = request_irq(gpio_to_irq(gpio), gpio_event_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "gpio_event", (void *)(unsigned long)gpio); if (ret) { printk(KERN_ERR "Failed to request irq for gpio %d\n", gpio); gpio_free(gpio); goto err_free_gpio; } } } } } return 0; err_free_gpio: for (i = 0; i < NUM_GPIO_CHIPS; i++) { struct gpio_chip *chip = &gpio_chip[i]; if (chip->base <= chip->ngpio) { int j; for (j = 0; j < chip->ngpio; j++) { int gpio = chip->base + j; if (gpio_is_valid(gpio)) { free_irq(gpio_to_irq(gpio), (void *)(unsigned long)gpio); gpio_free(gpio); } } } } kthread_stop(queue_task); err_stop_event_thread: kthread_stop(event_task); err_free_events: kfree(events); return ret; } static void __exit gpio_event_exit(void) { int i; printk(KERN_INFO "GPIO event module unloaded\n"); for (i = 0; i < NUM_GPIO_CHIPS; i++) { struct gpio_chip *chip = &gpio_chip[i]; if (chip->base <= chip->ngpio) { int j; for (j = 0; j < chip->ngpio; j++) { int gpio = chip->base + j; if (gpio_is_valid(gpio)) { free_irq(gpio_to_irq(gpio), (void *)(unsigned long)gpio); gpio_free(gpio); } } } } kthread_stop(queue_task); kthread_stop(event_task); kfree(events); } module_init(gpio_event_init); module_exit(gpio_event_exit); MODULE_LICENSE("GPL"); ``` 在上面的示例代码,我们使用了一个事件队列 `event_list`,用于存储 GPIO 断事件。当一个 GPIO 断事件发生时,我们将事件信息保存到队列,并唤醒等待事件的线程 `event_task`。如果队列已满,我们将丢弃最早的事件,并唤醒等待队列空闲的线程 `queue_task`。线程 `event_task` 会从队列取出事件并处理,线程 `queue_task` 则负责丢弃队列最早的事件。这样,我们就实现了 GPIO 断事件的异步处理,并且可以通过消息队列解耦原有的功能函数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stxinu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值