Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1223061
  • 博文数量: 322
  • 博客积分: 10010
  • 博客等级: 上将
  • 技术积分: 3276
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-17 09:21
文章分类

全部博文(322)

文章存档

2010年(155)

2009年(167)

我的朋友

分类: 嵌入式

2010-04-05 10:48:20

  首先按键设备相关的数据结构的定义如下所示:

  /* butt_drv.h */

  ……

  typedef struct _st_key_info_matrix       /* 按键数据结构 */

  {

  unsigned char key_id;                /* 按键ID */

  unsigned int irq_no;                 /* 对应的中断号 */

  unsigned int irq_gpio_port;          /* 对应的中断线的输入端口地址*/

  unsigned int kscan_gpio_port;        /* 对应的KSCAN端口地址 */

  } st_key_info_matrix;

  typedef struct _st_key_buffer             /* 按键缓冲数据结构 */

  {

  unsigned long jiffy[MAX_KEY_COUNT];   /* 按键时间, 5秒钟以前的铵键作废*/

  unsigned char buf[MAX_KEY_COUNT];     /* 按键缓冲区 */

  unsigned int head,tail;               /* 按键缓冲区头和尾 */

  } st_key_buffer;

  ……

  下面是矩阵按键数组的定义,数组元素的信息(一个按键信息)按照0行0列,0行1列,…,3行2列,3行3列的顺序逐行排列。

  static st_key_info_matrix key_info_matrix[MAX_COLUMN][MAX_ROW] =

  {

  {{10, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE11},     /* 0行0列 */

  {11, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG6},

  {12, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPE13},

  {16, IRQ_EINT0, S3C2410_GPF0, S3C2410_GPG2}},

  {{7, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE11},     /* 1行0列 */

  {8, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG6},

  {9, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPE13},

  {15, IRQ_EINT2, S3C2410_GPF2, S3C2410_GPG2}},

  {{4, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE11},     /* 2行0列 */

  {5, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG6},

  {6, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPE13},

  {14, IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG2}},

  {{1, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE11},     /* 3行0列 */

  {2, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG6},

  {3, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPE13},

  {13, IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG2}},

  };

  下面是与按键相关的端口的初始化函数。这些函数已经在简单的GPIO字符设备驱动程序里被使用过。此外,set_irq_type()函数用于设定中断线的类型,在本实例中通过该函数将4个中断线的类型配置为下降沿触发式。

  static void init_gpio(void)

  {

  s3c2410_gpio_cfgpin(S3C2410_GPE11, S3C2410_GPE11_OUTP);     /* GPE11 */

  s3c2410_gpio_setpin(S3C2410_GPE11, 0);

  s3c2410_gpio_cfgpin(S3C2410_GPE13, S3C2410_GPE13_OUTP);     /* GPE13 */

  s3c2410_gpio_setpin(S3C2410_GPE13, 0);

  s3c2410_gpio_cfgpin(S3C2410_GPG2, S3C2410_GPG2_OUTP);     /* GPG2 */

  s3c2410_gpio_setpin(S3C2410_GPG2, 0);

  s3c2410_gpio_cfgpin(S3C2410_GPG6, S3C2410_GPG6_OUTP);     /* GPG6 */

  s3c2410_gpio_setpin(S3C2410_GPG6, 0);

  s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_EINT0);     /* GPF0 */

  s3c2410_gpio_cfgpin(S3C2410_GPF2, S3C2410_GPF2_EINT2);     /* GPF2 */

  s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPG3_EINT11);     /* GPG3 */

  s3c2410_gpio_cfgpin(S3C2410_GPG11, S3C2410_GPG11_EINT19);     /* GPG11 */

  set_irq_type(IRQ_EINT0, IRQT_FALLING);

  set_irq_type(IRQ_EINT2, IRQT_FALLING);

  set_irq_type(IRQ_EINT11, IRQT_FALLING);

  set_irq_type(IRQ_EINT19, IRQT_FALLING);

  }

  现在讨论按键驱动的主要接口,以下为驱动模块的入口和卸载函数。

  /* 初始化并添加struct cdev结构到系统之中 */

  static void button_setup_cdev(struct cdev *dev,

  int minor, struct file_operations *fops)

  {

  int err;

  int devno = MKDEV(button_major,minor);

  cdev_init(dev, fops); /* 初始化结构体struct cdev */

  dev->owner = THIS_MODULE;

  dev->ops = fops; /* 关联到设备的file_operations结构 */

  err = cdev_add(dev, devno, 1); /* 将struct cdev结构添加到系统之中 */

  if (err)

  {

  printk(KERN_INFO"Error %d adding button %d\n",err, minor);

  }

  }

  ……

  /* 驱动初始化 */

  static int button_init(void)

  {

  int ret;

  /* 将主设备号和次设备号定义到一个dev_t数据类型的结构体之中 */

  dev_t dev = MKDEV(button_major, 0);

  if (button_major)

  {/* 静态注册一个设备,设备号先前指定好,并设定设备名,用cat /proc/devices来查看 */

  ret = register_chrdev_region(dev, 1, BUTT*_DEVICE_NAME);

  }

  else

  { /*由系统动态分配主设备号 */

  ret = alloc_chrdev_region(&dev, 0, 1, BUTT*_DEVICE_NAME);

  button_major = MAJOR(dev); /* 获得主设备号 */

  }

  if (ret < 0)

  {

  printk(KERN_WARNING"Button:unable to get major %d\n",button_major);

  return ret;

  }

  /* 初始化和添加结构体struct cdev到系统之中 */

  button_setup_cdev(&button_dev, 0, &button_fops);

  printk("Button driver initialized.\n");

  return 0;

  }

  /* 驱动卸载 */

  static void __exit button_exit(void)

  {

  cdev_del(&button_dev); /* 删除结构体struct cdev */

  /* 卸载设备驱动所占有的资源 */

  unregister_chrdev_region(MKDEV(button_major, 0), 1);

  printk("Button driver uninstalled\n");

  }

  module_init(button_init); /* 初始化设备驱动程序的入口 */

  module_exit(button_exit); /* 卸载设备驱动程序的入口 */

  MODULE_AUTHOR("David");

  MODULE_LICENSE("Dual BSD/GPL");

阅读(659) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~