在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

您好,歡迎來電子發燒友網! ,新用戶?[免費注冊]

您的位置:電子發燒友網>電子百科>語音視頻>安防監控>

海思HI3515按鍵中斷驅動程序

2017年12月26日 18:08 網絡整理 作者:佚名 用戶評論(0

  海思HI3515開發板的按鍵中斷程序分享,hi3515的核心芯片與網上例子較多的s3c之類的有一些區別,管腳配置方式不一樣,中斷的使用情況也不一樣。

  第一步,編寫按鍵驅動程序,button.c代碼如下:

  /*所有模塊都需要的頭文件*/

  #include《linux/module.h》

  /*聲明printk()這個內核態的函數*/

  #include《linux/kernel.h》

  /*文件系統有關的,結構體file_operations也在fs頭文件定義*/

  #include《linux/fs.h》

  /*init和exit相關宏*/

  #include《linux/init.h》

  #include《linux/delay.h》

  #include《linux/poll.h》

  /*linux中斷定義*/

  #include《linux/irq.h》

  /**/

  #include《asm/irq.h》

  /*包含與中斷相關的大部分宏及結構體的定義,request_irq()等*/

  #include《linux/interrupt.h》

  /*linux中的用戶態內存交互函數,copy_from_user(),copy_to_user()等*/

  #include《asm/uaccess.h》

  //#include《mach/regs-gpio.h》

  //#include《mach/hardware.h》

  #include《linux/platform_device.h》

  #include《linux/cdev.h》

  /*misc混合設備注冊與注銷*/

  #include《linux/miscdevice.h》

  #include 《asm/io.h》

  #include 《asm/system.h》

  #define BUTTON_READ 0x01

  #define DEVICE_NAME “BUTTON_irq”

  #define REG_WRITE(addr,value) ((*(volatile unsigned int *)(addr)) = (value))

  #define REG_READ(Addr) (*(volatile unsigned int *)(Addr))

  static unsigned int gpio3_virtual_addr = 0;

  static unsigned int reg_virtual_addr = 0;

  /*數組中是否有數據標志,0表示無數據可讀,1表示有數字可讀*/

  static volatile char key;

  /*定義和初始化一個等待隊列頭*/

  static DECLARE_WAIT_QUEUE_HEAD(button_waitq);

  /*定義一個整形變量,判斷按鍵是否按下*/

  static volatile int ev_press = 0;

  /*

  *定義結構體類型,由它把按鈕中斷的信息綜合起來

  */

  struct button_irq_desc {

  int irq;/*中斷號*/

  int pin;/*中斷標志寄存器,有中斷產生時為1,無中斷時為0*/

  int number;/*編號*/

  char *name;/*名稱*/

  };

  static struct button_irq_desc button_irqs[]={

  {8,2,1,“KEY1”},

  };

  static void hi3515_button_pin_cfg(void)

  {

  /*配置作為普通輸入*/

  REG_WRITE(reg_virtual_addr + 0x08,0x1);/*reg2管腳復用配置gpio3_0,按鍵1*/

  REG_WRITE(reg_virtual_addr + 0x0c,0x1);/*reg3管腳復用配置gpio3_1,按鍵1*/

  REG_WRITE(reg_virtual_addr + 0x10,0x1);/*reg4管腳復用配置gpio3_2,按鍵1*/

  REG_WRITE(reg_virtual_addr + 0x14,0x1);/*reg5管腳復用配置gpio3_3,按鍵2*/

  /*管腳中斷配置*/

  REG_WRITE(gpio3_virtual_addr + 0x0400,0x3);/*dir設置管腳為0-1:輸出,2-3:輸入*/

  REG_WRITE(gpio3_virtual_addr + 0x0404,0xc);/*is邊沿觸發中斷*/

  REG_WRITE(gpio3_virtual_addr + 0x040c,0x0);/*iev低電平觸發*/

  REG_WRITE(gpio3_virtual_addr + 0x041c,0xff);/*ic清除中斷*/

  REG_WRITE(gpio3_virtual_addr + 0x0410,0x04);/*ie啟用中斷*/

  }

  /*

  *gpio地址映射

  */

  static int virtual_addr_map(void)

  {

  reg_virtual_addr = (unsigned int)ioremap_nocache(0x200f0000,0x4000);

  if(!reg_virtual_addr)

  {

  printk(“0x200f0000 ioremap addr failed !\n”);

  return -1;

  }

  gpio3_virtual_addr = (unsigned int)ioremap_nocache(0x20180000,0x4000);

  if(!gpio3_virtual_addr)

  {

  printk(“0x20180000 ioremap addr failed !\n”);

  return -1;

  }

  }

  /*取消地址映射*/

  static void virtual_addr_unmap(void)

  {

  iounmap((void*)gpio3_virtual_addr);

  iounmap((void*)reg_virtual_addr);

  }

  /*

  *read調用的具體函數,由它讀取鍵盤輸入的結果,

  *實質上就是讀取key_values數組的值

  *完成鍵盤輸入設備的核心功能,根據標志位ev_press判斷是否可讀

  *如果可讀,則讀取數據到用戶buffer中,如果不可讀,

  *則進程進入等待隊列等待,直到數組可讀為止

  *等待隊列機制,所中斷管理中常用的機制。

  */

  static int button_irq_read(struct file *filp,

  char __user *buff,

  size_t count,loff_t *offp)

  {

  unsigned long err;

  #if 1

  if(!ev_press) /*ev_press=0,則表示沒有數據可讀*/

  {

  if(filp-》f_flags & O_NONBLOCK)

  return -EAGAIN;

  else /*無數據可讀時,進程休眠,放進button_waitq等待隊列*/

  wait_event_interruptible(button_waitq,ev_press);

  /*

  *wait_event_interruptible()函數將進程置為可中斷的掛起狀態

  *反復檢查ev_press=1是否成立,如果不成立,則繼續休眠。

  *條件滿足后,即把本程序置為運行態,

  */

  }

  /*ev_press=1之后,進程退出等待隊列。從此處開始運行*/

  ev_press = 0;/*置0標志位,表明本次中斷已經處理*/

  err = copy_to_user(buff,&key,sizeof(key));

  /*把按鍵值傳會用戶空間*/

  #endif

  return 0;

  }

  static irqreturn_t irq_interrupt(int irq,void *dev_id)

  {

  #if 1

  /*對傳入的中斷資源進行處理,獲得中斷控制寄存器的值(即是否有數據)

  取反后賦值給down,為0時說明有數據,

  注意按下依次按鈕有兩次中斷,

  對數組可讀標志位進行設置,ev_press=1表示數組已經可以讀了*/

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

  int down;

  down = 0x0c & REG_READ(gpio3_virtual_addr + 0x0414);

  REG_WRITE(gpio3_virtual_addr + 0x041c,0xff);/*ic清除按鍵中斷*/

  mdelay(5);/**/

  if(down != 0x0c )

  {

  key = (char)down;

  ev_press = 1; /*置1標志位,喚醒等待隊列進程,在read函數中使用*/

  /*

  *喚醒休眠的進程,用戶空間程序使用調用read函數時,

  *如果沒有產生中斷,進程就會進入休眠狀態,一直等待,直到產生中斷

  *中斷產生后,通過wake_up_interruptible()函數喚醒休眠進程

  */

  wake_up_interruptible(&button_waitq);

  }

  #endif

  REG_WRITE(gpio3_virtual_addr + 0x0410,0x0c);/*ie啟用按鍵中斷*/

  return IRQ_HANDLED; //IRQ_HANDLED=1

  }

  /*

  *poll調用的具體函數,poll實質上是select的調用函數

  *如果有按鍵數據,則select會立刻返回

  *如果沒有按鍵數據,則等待

  *實質上這是鍵盤等待輸入的機制

  *poll_wait()會監測進程隊列button_waitq里的進程

  *例如button_irq_read所在的進程的標志ev_press置為1了

  *那么就不再等待,這實質上就所select函數的運行機制

  */

  static unsigned int button_irq_poll(struct file *file, struct poll_table_struct *wait)

  {

  #if 1

  /*

  *poll調用的具體函數,poll實質上是select的調用函數

  *如果有按鍵數據,則select會立刻返回

  *如果沒有按鍵數據,則等待

  *實質上這是鍵盤等待輸入的機制。

  *select調用是用戶程序里面使用的。

  */

  unsigned int mask = 0;

  poll_wait(file,&button_waitq,wait);

  /*poll_wait會檢測button_waitq里的進程*/

  if(ev_press)

  mask |=POLLIN | POLLRDNORM;

  return mask;

  #endif

  }

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

  {

  #if 1

  int err;/*中斷注冊返回值*/

  virtual_addr_map(); /*地址映射*/

  hi3515_button_pin_cfg();/*管腳配置,要先進行地址映射*/

  /*注冊中斷*/

  err = request_irq(8,irq_interrupt,IRQF_SHARED,\

  “KEY”,(void *)&button_irqs);

  if(err)/*如果注冊中斷失敗,則釋放已經成功注冊的中斷*/

  {

  return -EBUSY;

  }

  ev_press = 1;

  #endif

  return 0;

  }

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

  {

  free_irq(8,(void *)&button_irqs);

  virtual_addr_unmap();/*取消地址映射*/

  return 0;

  }

  int button_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)

  {

  unsigned int __user *argp = (unsigned int __user *)arg;

  int value;

  value = *(unsigned int *)arg;

  switch (cmd)

  {

  case 1:

  if(value == 0) /*led1亮*/

  REG_WRITE(gpio3_virtual_addr +0x4,0);

  else if(value == 1) /*led1滅*/

  REG_WRITE(gpio3_virtual_addr +0x4,1);

  break;

  case 2:

  if(value == 0) /*led2亮*/

  REG_WRITE(gpio3_virtual_addr +0x8,0);

  else if(value == 1) /*led2滅*/

  REG_WRITE(gpio3_virtual_addr +0x8,2);

  break;

  default:

  return -1;

  }

  return 0;

  }

  static struct file_operations dev_fops = {

  .owner = THIS_MODULE,

  .open = button_irq_open,

  .release = button_irq_close,

  .ioctl = button_ioctl,

  .read = button_irq_read,

  .poll = button_irq_poll,/*用戶程序使用select調用的時候才會用到poll*/

  };

  /*

  *misc混合設備注冊和注銷

  */

  static struct miscdevice misc = {

  .minor = MISC_DYNAMIC_MINOR,/*次設備號*/

  .name = DEVICE_NAME,/*設備名*/

  .fops = &dev_fops,/*設備文件操作結構體*/

  };

  static int __init button_init(void)

  {

  int ret;

  ret = misc_register(&misc);

  if(0 != ret)

  {

  printk(“register device failed! !\n”);

  return -1;

  }

  printk(“register device success !\n”);

  return 0;

  }

  static void __exit button_exit(void)

  {

  misc_deregister(&misc);

  printk(“unregister device success !\n”);

  }

  module_init(button_init);

  module_exit(button_exit);

  MODULE_LICENSE(“GPL”);

  MODULE_AUTHOR(“Dong”);

  第二步。,編寫測試程序,test_button.c代碼如下

  /*

  *按鍵中斷測試程序

  *按鍵被按下時,產生中斷

  *打印按下信息,切換led顯示狀態

  */

  #include 《stdio.h》

  #include 《ctype.h》

  #include 《sys/ioctl.h》

  #include 《sys/types.h》

  #include 《sys/stat.h》

  #include 《fcntl.h》

  #include《linux/delay.h》

  int main(int argc , char* argv[])

  {

  int fd = -1;

  unsigned int led1;

  unsigned int led2; ;

  char key;

  fd = open(“/dev/BUTTON_irq”, 0);

  if (fd《0)

  {

  printf(“Open BUTTON_irq dev error!\n”);

  return -1;

  }

  for(;;)

  {

  int ret;

  ret = read(fd,&key,sizeof(key));

  if(ret《 0)

  {

  perror(“read button:”);

  return -1;

  }

  if(key == 4)/*按鍵1被按下*/

  {

  printf(“K1 is press!\n”);

  led1 = (~led1)&0x1;

  ioctl(fd, 0x01, &led1); /*切換led1的狀態*/

  }

  if(key == 8)/*按鍵2被按下*/

  {

  printf(“K2 is press!\n”);

  led2 = (~led2)&0x1;

  ioctl(fd, 0x02, &led2); /*切換led2的狀態*/

  }

  //printf(“\n”);

  }

  close(fd);

  return 0;

  }

  第三步,makefile文件,代碼如下:

  LINUXROOT = /opt/Hi3515_SDK_V1.0.5.1/source/os/linux-2.6.24

  #這是放內核的路徑

  CC = arm-hismall-linux-gcc

  obj-m := button.o

  default:

  $(CC) -g -Wall -o test_button test_button.c

  @make -C $(LINUXROOT) M=$(PWD) modules

  rm -rf *.o *.mod.c *.symvers

  clean:

  @make -C $(LINUXROOT) M=$(PWD) clean

非常好我支持^.^

(0) 0%

不好我反對

(0) 0%

( 發表人:steve )

      發表評論

      用戶評論
      評價:好評中評差評

      發表評論,獲取積分! 請遵守相關規定!

      ?
      主站蜘蛛池模板: 114毛片免费观看网站 | 夜色福利久久久久久777777 | 失禁h啪肉尿出来高h男男 | 手机看片国产免费久久网 | 免费大秀视频在线播放 | 最近2018中文字幕免费看在线 | 观看在线人视频 | 欧美一级黄色片 | 99久久99久久精品免费看子伦 | 国产在线永久视频 | 亚洲a级毛片 | 美国一级大黄香蕉片 | 种子 在线播放 | 色姑娘天天干 | 久久国产精品自在自线 | 久久国产精品自在自线 | 这里只有精品在线 | 免费人成在线观看网站品爱网 | 失禁h啪肉尿出来高h男男 | 一二三四日本视频社区 | 日本黄色大片网站 | 色婷婷社区| 天天操天天舔天天射 | 天堂网在线最新版官网 | 国产精品综合色区在线观看 | 奇米在线 | 免费被视频网站在线观看 | 男女激情做爰叫床声视频偷拍 | 六月丁香婷婷激情国产 | 日韩免费毛片全部不收费 | 中文字幕人成不卡一区 | 最近的中文字幕免费动漫视频 | 午夜片在线 | 久久精品成人免费网站 | 黄网站色视频免费看无下截 | 精品国产免费久久久久久婷婷 | 天天综合视频网 | 99香蕉精品视频在线观看 | 午夜爽爽爽 | 欧美激情片网站 | 国产精品午夜自在在线精品 |