'키패드 인터럽트 프로그래밍 예'에 해당되는 글 1건

여기서는 인터럽트를 사용하는 응용으로써 키패드 디바이스 드라이버를 설명한다. 키패드는 내부에 디코더를 가지고 있어 눌려진 키에 대한 4비트 BCD 데이터를 출력하며 이출력은 4비트 래치를 거쳐 프로세서의 데이터 버스에 입력된다. 4비트를 위해 사용되는 데이터 버스의 비트 위치는 비트 15 ~ 비트 12로 가정하였다.


키패드 회로에서는 주소 0x0C00 0000에서 래치 동작신호를 발생시키기 위하여 주소 디코더에 칩 선택 신호 CS3를 사용하고있다. 또 키패드에서 발생하는 인터럽트를 처리하기 위해 인터럽트 요청 신호가 PXA 프로세서의 GPIO핀에 연결되어 있다.


key-drv.h 소스 


#include "linux/kernel.h"
#include "linux/module.h"
#include "linux/init.h"
#include "linux/types.h"
#include "linux/ioport.h"
#inlcude "unistd.h"
#include "linux/slab.h"
#include "linux/mm.h"
......


#define KEY_ADDR 0xF3000000

#define KEY_IRQ IRQ_GPIO(19)

static int KEY_MAJOR = 67;

static DECLARE_WAIT_QUEUE_HEAD(key_queue);

key_drv.h의 처음 부분에는 디바이스 드라이버 구현에 필요한 각종 헤더파일들과 인터럽트 사용에 필요한 헤더파일들이 있다.


키패드 디바이스 파일의 주번호로 67이 정의되어 있다.


다음문에서는 인터럽트가 발생할 때까지 프로세스를 대기상태로 두는 대기큐를 선언한다.


DECLARE_WAIT_QUEUE_HEAD(key_queue);


다음 문은 리눅스 커널 소스에서 해당 임베디드 보드에 대한 물리주소와 가상주소를 서로 연결해주기 위한 것이다.


#define KEY_ADDR 0xF3000000



다음은 디바이스 드라이버 실제 구현 부분인 key-drv.c 부분이다.




#include "key-drv.h"

static unsigned short *key;
static int key_data =0;

static void key_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
  key_data = (*(key) & 0xf000) >> 12;

  printk("Interrupt Service : Input Data from Keypad : %d \n",key_data);

 wake_up_interruptible(&key_queue);
}

static ssize_t key_read(struct file *filp, char *buf,size_t count,loff_t *l)
{
  int tmp;

 tmp = key_data;

  intteruptible_sleep_on(&key_queue);

 copy_to_user(buf,&key_data,sizeof(tmp));
 return 0;
}

static int key_open(struct inode *inode, struct file *filp)
{
  MOD_INC_USE_COUNT;
  printk("keypad Device Open\n");
  return 0;
}

static int key_release(Struct inode *inode, struct file *filp)
{
 MOD_DEC_USE_COUNT;
 printk("Keypad Device Released\n");
 return 0;
}
 
static struct file_operations key_fops = {
 open : key_open,
 read : key_read,
 release : key_release,


};


static int __init key_init(void)
{
  int res, result;

   if((result = register_chrdev(KEY_MAJOR,"key",&key_fops))<0){
     printk(" register_chrdev() FAIL! \n");
     return result;
   }

   if(!check_region(KEY_ADDR,2))
    request_region(KEY_ADDR, 2, "key");

  key = (unsigned short *)KEY_ADDR;

  if((res = request_irq(KEY_IRQ, &key_interrupt, SA_INTERRUPT, "key", NULL))<0)
     printk(KERN_ERR, "request_irq() FAIL!\n");

  set_GPIO_IRQ_edge(IRQ_TO_GPIO_2_80(KEY_IRQ), GPIO_FALLING_EDGE);

  return 0;
}

void __exit key_exit(void)
{
   disable_irq(KEY_IRQ);
         free_irq(KEY_IRQ,NULL);

   release_region(KEY_ADDR, 2);
   unregister_chrdev(KEY_MAJOR,"key");
}

module_init(key_init);
module_exit(key_exit);

}


블로그 이미지

종환 Revolutionist-JongHwan

github.com/alciakng 항상 겸손하자.