Widora-neo GPIO中断试验

最近想在widora-neo上装个红外接收头,以此来控制音乐播放等软件。第一步设想用GPIO脚电平变化产生中断来唤醒红外信号解码,但在mt7688手册上找了半天也没有发现GPIO对应的中断号,"必应“中搜索了一阵子,发现有个gpio_to_irq()函数可以获得对应的中断号,不知道widora中能不能用,试验了一下,发现居然OK! 将发现和大家分享一下:

1. 内核模块模板
继续采用"编制第一个widora-neo驱动" 中的模板。

2.  mt7688 GPIO中断相关寄存器
用GPIO 17 脚上的上升沿来触发中断,主要用到如下的寄存器。
volatile unsigned long *GPIO_CTRL_0;   //--- GPIO0 to GPIO31 direction control register  0-input 1-output
volatile unsigned long *GINT_REDGE_0;  //--GPIO0 to GPIO31 rising edge interrupt enable register
volatile unsigned long *GINT_FEDGE_0;  //--GPIO0 to GPIO31 falling edge interrupt enable register
volatile unsigned long *GINT_STAT_0;  //---GPIO0 to GPIO31 interrupt status register 1-int  0 -no int
volatile unsigned long *GINT_EDGE_0;  //---GPIO0 to GPIO31 interrupt edge status register 1-rising 0-falling
volatile unsigned long *GPIO1_MODE; // GPIO1 purpose selection register,for SPIS or GPIO14-17 mode selection
volatile unsigned long *AGPIO_CFG; // analog GPIO configuartion,GPIO14-17 purpose

3. 申请和注册GPIO中断
3.1  用gpio_to_irq()函数取得GPIO中断号
调用函数 gpio_to_irq(GPIO_PIN_NUM) 来获得中断号,需要包含相关头文件#include <linux/gpio.h>

3.2  申请注册中断
调用函数request_irq(GPIO_INT_NUM,gpio_int_handler,IRQF_DISABLED,"GPIO_INT_midas",NULL)  申请注册中断,相关要素可查阅网上资料。 IRQF_TRIGGER_RISING 标志应该也可以用,没有试过。   申请注册成功后,可以用   cat /proc/interrupts 命令看到对应的中断号。

4.  模块程序
4.1  主要自定函数功能
static void Init_GPIO(void)     /* 映射并设定相关寄存器功能 /
static void GPIO_unmap(void)   /
释放内存映射 /
static void get_gpio_INT_num(void)   /
获得GPIO映射的中断号 */
static irqreturn_t gpio_int_handler(int irq,void *dev_id,struct pt_regs regs)  / 中断处理函数 /
static int register_gpio_IRQ(void)   /
向内核申请注册中断 */
4.2  在设备打开时进行中断的初始化和注册(黑体部分)。
//---OPEN
static int gpio_int_open(struct inode *inode, struct file *file)
{
int ret_v=0;
printk("gpio_int driver open........ \n");

    //------------    init GPIO interrupt   ----------
    Init_GPIO();
    get_gpio_INT_num();
    ret_v=register_gpio_IRQ();  //---register GPIO interrup

return ret_v;
}

4.3 在读取设备时返回中断状态,并重使能中断(黑体部分)。
//---READ
static ssize_t gpio_int_read(struct file *file, char __user *buffer,
size_t len, loff_t *pos)
{
int ret_v = 0;
printk("gpio_int drive read...\n");

 copy_to_user(buffer,&INT_STATUS,4);
 INT_STATUS=0; //----reset interrupt token
 msleep(100);  //------------ deter re-enabling irq to avoid key-jitter
  if(DISABLE_IRQ_TOKEN)
     {
           enable_irq(GPIO_INT_NUM);   
          DISABLE_IRQ_TOKEN=0;
     }

ret_v=4;
return ret_v;
}
4.4  在设备关闭的时候注销和清理中断资源(黑体部分)。
//---CLOSE
static int gpio_int_close(struct inode *inode , struct file *file)
{
printk("gpio_int drive close...\n");

    //------------free irq resource----------------------------
    GPIO_unmap();  //-----free GPIO map
    free_irq(GPIO_INT_NUM,NULL); //----free irq NON-SHARED**

return 0;
}

5.  用户程序
写一个用户程序来测试,当中断被触发时会在串口终端输出"GPIO Interrupt Triggered! "信息。

 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <sys/ioctl.h>

 char str_dev[]="/dev/gpio_int_dev";

 int main(int argc, char **argv)
 {
     int fd;
     unsigned int INT_STATUS = 0;
     //------- open driver--------
     fd = open(str_dev, O_RDWR | O_NONBLOCK);
     if (fd < 0)
      {
     printf("can't open %s\n",str_dev);
     return -1;
         }
       //------------- read INT_STATUS -------
     while(1)
     {
     read(fd, &INT_STATUS, sizeof(INT_STATUS));
         if(INT_STATUS==1)
               printf("GPIO Interrupt Triggered!\n");
         usleep(200000);  
      }
     close(fd);

     return 0;
 }

6.  接线试验
由于这里用的是上升沿触发,需要将GPIO17脚通过一个几k的电阻(3.9k etc.)拉低。


可以在这里获得完整的源码: https://github.com/midaszhou/openwrt_widora/tree/midas/package/kernel/gpio-int


本文章由作者:佐须之男 整理编辑,原文地址: Widora-neo GPIO中断试验
本站的文章和资源来自互联网或者站长的原创,按照 CC BY -NC -SA 3.0 CN协议发布和共享,转载或引用本站文章应遵循相同协议。如果有侵犯版权的资 源请尽快联系站长,我们会在24h内删除有争议的资源。欢迎大家多多交流,期待共同学习进步。

相关推荐