<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 基于S3C2440的linux驅(qū)動

          基于S3C2440的linux驅(qū)動

          作者: 時間:2016-11-20 來源:網(wǎng)絡(luò) 收藏

          MINI2440_BUTTON.C

          #include

          本文引用地址:http://www.ex-cimer.com/article/201611/318871.htm

          #include

          #include

          #include

          #include

          #include

          #include

          #include interrupt.h>

          #include

          #include

          #include

          #define DEVICE_NAME "buttons"

          #define BUTTON_MAJOR 232

          struct button_irq_desc {

          int irq;

          int pin;

          int pin_setting;

          int number;

          char *name;

          };

          static struct button_irq_desc button_irqs [] = {

          {IRQ_EINT8, S3C2410_GPG0, S3C2410_GPG0_EINT8, 0, "KEY1"},

          {IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG3_EINT11, 1, "KEY2"},

          {IRQ_EINT13, S3C2410_GPG5, S3C2410_GPG5_EINT13, 2, "KEY3"},

          {IRQ_EINT14, S3C2410_GPG6, S3C2410_GPG6_EINT14, 3, "KEY4"},

          {IRQ_EINT15, S3C2410_GPG7, S3C2410_GPG7_EINT15, 4, "KEY5"},

          {IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 5, "KEY6"},

          };

          static volatile int key_values [] = {0, 0, 0, 0, 0, 0};

          static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

          static volatile int ev_press = 0;

          static irqreturn_t buttons_interrupt(int irq, void *dev_id)

          {

          struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;

          int up = s3c2410_gpio_getpin(button_irqs->pin);

          if (up)

          key_values[button_irqs->number] = (button_irqs->number + 1) + 0x80;

          else

          key_values[button_irqs->number] = (button_irqs->number + 1);

          ev_press = 1;

          wake_up_interruptible(&button_waitq);

          return IRQ_RETVAL(IRQ_HANDLED);

          }

          static int mini2440_buttons_open(struct inode *inode, struct file *file)

          {

          int i;

          int err;

          for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {

          // 注冊中斷處理函數(shù)

          s3c2410_gpio_cfgpin(button_irqs[i].pin,button_irqs[i].pin_setting);

          err = request_irq(button_irqs[i].irq, buttons_interrupt, NULL,

          button_irqs[i].name, (void *)&button_irqs[i]);

          set_irq_type(button_irqs[i].irq, IRQT_BOTHEDGE);

          if (err)

          break;

          }

          if (err) {

          // 釋放已經(jīng)注冊的中斷

          i--;

          for (; i >= 0; i--) {

          disable_irq(button_irqs[i].irq);

          free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);

          }

          return -EBUSY;

          }

          return 0;

          }

          static int mini2440_buttons_close(struct inode *inode, struct file *file)

          {

          int i;

          for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) {

          // 釋放已經(jīng)注冊的中斷

          disable_irq(button_irqs[i].irq);

          free_irq(button_irqs[i].irq, (void *)&button_irqs[i]);

          }

          return 0;

          }

          static int mini2440_buttons_read(struct file *filp, char __user *buff,

          size_t count, loff_t *offp)

          {

          unsigned long err;

          if (!ev_press) {

          if (filp->f_flags & O_NONBLOCK)

          return -EAGAIN;

          else

          wait_event_interruptible(button_waitq, ev_press);

          }

          ev_press = 0;

          err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count));

          memset((void *)key_values, 0, sizeof(key_values));

          return err ? -EFAULT : min(sizeof(key_values), count);

          }

          static unsigned int mini2440_buttons_poll(

          struct file *file,

          struct poll_table_struct *wait)

          {

          unsigned int mask = 0;

          poll_wait(file, &button_waitq, wait);

          if (ev_press)

          mask |= POLLIN | POLLRDNORM;

          return mask;

          }

          static struct file_operations mini2440_buttons_fops = {

          .owner = THIS_MODULE,

          .open = mini2440_buttons_open,

          .release = mini2440_buttons_close,

          .read = mini2440_buttons_read,

          .poll = mini2440_buttons_poll,

          };

          static int __init mini2440_buttons_init(void)

          {

          int ret;

          ret = register_chrdev(BUTTON_MAJOR, DEVICE_NAME, &mini2440_buttons_fops);

          if (ret < 0) {

          printk(DEVICE_NAME " cant register major numbern");

          return ret;

          }

          devfs_mk_cdev(MKDEV(BUTTON_MAJOR, 0), S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, DEVICE_NAME);

          printk(DEVICE_NAME " initializedn");

          return 0;

          }

          static void __exit mini2440_buttons_exit(void)

          {

          devfs_remove(DEVICE_NAME);

          unregister_chrdev(BUTTON_MAJOR, DEVICE_NAME);

          }

          module_init(mini2440_buttons_init);

          module_exit(mini2440_buttons_exit);

          MODULE_AUTHOR("http://www.arm9.net"); // 驅(qū)動程序的作者

          MODULE_DESCRIPTION("S3C2410/S3C2440 BUTTON Driver"); // 一些描述信息

          MODULE_LICENSE("GPL"); // 遵循的協(xié)議

          總結(jié)一下,程序框架。

          按鍵的驅(qū)動主要是多了中斷的處理,關(guān)于中斷主要的處理函數(shù)是

          request_irq(button_irqs[i].irq, buttons_interrupt, NULL,

          button_irqs[i].name, (void *)&button_irqs[i]);

          第二個參數(shù)是主要的中斷處理函數(shù)。

          static irqreturn_t buttons_interrupt(int irq, void *dev_id)

          {

          struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id;

          int up = s3c2410_gpio_getpin(button_irqs->pin);

          if (up)

          key_values[button_irqs->number] = (button_irqs->number + 1) + 0x80;

          else

          key_values[button_irqs->number] = (button_irqs->number + 1);

          ev_press = 1;

          wake_up_interruptible(&button_waitq);

          return IRQ_RETVAL(IRQ_HANDLED);

          }

          另外還用到了兩個重要的結(jié)構(gòu)體:

          static struct button_irq_desc button_irqs [] = {

          {IRQ_EINT8, S3C2410_GPG0, S3C2410_GPG0_EINT8, 0, "KEY1"},

          {IRQ_EINT11, S3C2410_GPG3, S3C2410_GPG3_EINT11, 1, "KEY2"},

          {IRQ_EINT13, S3C2410_GPG5, S3C2410_GPG5_EINT13, 2, "KEY3"},

          {IRQ_EINT14, S3C2410_GPG6, S3C2410_GPG6_EINT14, 3, "KEY4"},

          {IRQ_EINT15, S3C2410_GPG7, S3C2410_GPG7_EINT15, 4, "KEY5"},

          {IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 5, "KEY6"},

          };

          struct button_irq_desc {

          int irq;

          int pin;

          int pin_setting;

          int number;

          char *name;

          };

          而驅(qū)動程序中的最重要的部分,file_operations為

          static struct file_operations mini2440_buttons_fops = {

          .owner = THIS_MODULE,

          .open = mini2440_buttons_open,

          .release = mini2440_buttons_close,

          .read = mini2440_buttons_read,

          .poll = mini2440_buttons_poll,

          };

          程序中其他的任務(wù)就是豐滿這個機(jī)構(gòu)體,使得應(yīng)用程序在調(diào)用open,close等的時候可以在

          驅(qū)動中找到對應(yīng)的項。

          這里的request_irq在open函數(shù)里調(diào)用的。

          至于注冊的部分跟LEDS那些是一樣的,就不多說啦。

          再附個應(yīng)用程序供參考:

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          #include

          int main(void)

          {

          int i;

          int buttons_fd;

          int key_value[4];

          buttons_fd = open("/dev/buttons", 0);

          if (buttons_fd < 0) {

          perror("open device buttons");

          exit(1);

          }

          for (;;) {

          fd_set rds;

          int ret;

          FD_ZERO(&rds);

          FD_SET(buttons_fd, &rds);

          ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);

          if (ret < 0) {

          perror("select");

          exit(1);

          }

          if (ret == 0) {

          printf("Timeout.n");

          }

          else if (FD_ISSET(buttons_fd, &rds)) {

          int ret = read(buttons_fd, key_value, sizeof key_value);

          if (ret != sizeof key_value) {

          if (errno != EAGAIN)

          perror("read buttonsn");

          continue;

          } else {

          for (i = 0;i < sizeof(key_value)/sizeof(key_value[0]); i++)

          printf("K%d %s, key value = 0x%02xn", i+1, (key_value[i] & 0x80) ? "released" :

          key_value[i] ? "pressed down" : "",

          key_value[i]);

          }

          }

          }

          close(buttons_fd);

          return 0;

          }



          關(guān)鍵詞: S3C2440linux驅(qū)

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();