panda.jpg


안녕하세요 판다 이우영입니다.


저번 시간에 이어 디바이스 드라이버를 작성하고


poll의 동작을 눈으로 확인해 보겠습니다.


1. 디바이스 드라이버 작성




 

 polldev1.c



#include <linux/init.h>

#include <linux/module.h>

#include <linux/kernel.h>

 

#include <linux/version.h>

#include <linux/fs.h>

#include <linux/sched.h>

 

#include <linux/interrupt.h>

#include <linux/wait.h>

#include <linux/irq.h>

 

#include <linux/ioport.h>

#include <linux/slab.h>

#include <linux/poll.h>

#include <linux/proc_fs.h>

#include <linux/workqueue.h>

 

#include <linux/time.h>

#include <linux/timer.h>

 

#include <linux/poll.h>

 

#include <asm/system.h>

#include <asm/uaccess.h>

#include <asm/ioctl.h>

#include <asm/unistd.h>

#include <asm/io.h>

#include <asm/irq.h>

#include <asm/gpio.h>

#include <asm/mach/arch.h>

 

#include <plat/gpio-cfg.h>

 

#define POLL_DEV_NAME              "polldev1"

#define POLL_DEV_MAJOR             240

 

#define IRQT_FALLING               IRQ_TYPE_EDGE_FALLING

 

#define DATA_SIZE                  0x1000

 

DECLARE_WAIT_QUEUE_HEAD(WaitQueue_Read_int);

 

static unsigned int     ReadQCount = 0;

u32         irq;

 

irqreturn_t poll_dev1_interrupt(int irq, void *dev_id, struct pt_regs *regs)

{

      unsigned long flags;

    

      local_save_flags(flags);

      local_irq_disable();

      ReadQCount++;

      local_irq_restore(flags);

 

      wake_up_interruptible(&WaitQueue_Read_int);

    

      return IRQ_HANDLED;

}

 

int poll_dev1_open(struct inode *inode, struct file *filp)

{

      u32 gpio;

 

      gpio = S3C64XX_GPN(6);

      s3c_gpio_setpull( gpio, S3C_GPIO_PULL_UP );

      irq = IRQ_EINT(6);

      set_irq_type( irq, IRQT_FALLING );

 

      if( !request_irq( irq, poll_dev1_interrupt, IRQF_DISABLED, POLL_DEV_NAME, NULL ));

 

      return 0;

}

 

ssize_t poll_dev1_read( struct file *filp, char *buf, size_t count, loff_t *f_pos )

{

      unsigned long flags;

      int retstate = 0;

 

      retstate = wait_event_interruptible(WaitQueue_Read_int,ReadQCount);

 

      if(retstate) return retstate;

 

      copy_to_user(buf,"poll_dev1_read",count);

      local_save_flags(flags);

      local_irq_disable();

      ReadQCount = 0;

      local_irq_restore(flags);

 

      return 0;

}

 

unsigned int poll_dev1_poll( struct file *filp, poll_table *wait)

{

      unsigned int mask = 0;

 

      poll_wait(filp, &WaitQueue_Read_int, wait);

 

      if(ReadQCount > 0)

            mask |= POLLIN | POLLRDNORM;

    

      return mask;

}

 

int poll_dev1_release(struct inode *inode, struct file *filp)

{

      free_irq( irq, NULL );

 

      return 0;

}

 

struct file_operations poll_fops =

{

            .owner      = THIS_MODULE,

            .read       = poll_dev1_read,

            .poll       = poll_dev1_poll,

            .open       = poll_dev1_open,

            .release    = poll_dev1_release,

};

 

int poll_dev1_init( void )

{

      int result;

 

      result = register_chrdev(POLL_DEV_MAJOR,POLL_DEV_NAME,&poll_fops);

 

      if( result < 0)

            return result;

 

      return 0;

}

 

void poll_dev1_exit( void )

{

      unregister_chrdev(POLL_DEV_MAJOR, POLL_DEV_NAME);

}

module_init( poll_dev1_init );

module_exit( poll_dev1_exit );

 

MODULE_LICENSE("Dual BSD/GPL");

 


만드셨나요?


de1을  dev2로 바꾸어서 하나더 만들어 보겠습니다.


인터럽트 번호변경해주시구요(전 5로 하겠습니다.)



 polldev2.c

 

 

#include <linux/init.h>

#include <linux/module.h>

#include <linux/kernel.h>

 

#include <linux/version.h>

#include <linux/fs.h>

#include <linux/sched.h>

 

#include <linux/interrupt.h>

#include <linux/wait.h>

#include <linux/irq.h>

 

#include <linux/ioport.h>

#include <linux/slab.h>

#include <linux/poll.h>

#include <linux/proc_fs.h>

#include <linux/workqueue.h>

 

#include <linux/time.h>

#include <linux/timer.h>

 

#include <linux/poll.h>

 

#include <asm/system.h>

#include <asm/uaccess.h>

#include <asm/ioctl.h>

#include <asm/unistd.h>

#include <asm/io.h>

#include <asm/irq.h>

#include <asm/gpio.h>

#include <asm/mach/arch.h>

 

#include <plat/gpio-cfg.h>

 

#define POLL_DEV_NAME              "polldev2"

#define POLL_DEV_MAJOR             241

 

#define IRQT_FALLING               IRQ_TYPE_EDGE_FALLING

 

#define DATA_SIZE                  0x1000

 

DECLARE_WAIT_QUEUE_HEAD(WaitQueue_Read_int);

 

static unsigned int     ReadQCount = 0;

u32         irq;

 

irqreturn_t poll_dev2_interrupt(int irq, void *dev_id, struct pt_regs *regs)

{

      unsigned long flags;

    

      local_save_flags(flags);

      local_irq_disable();

      ReadQCount++;

      local_irq_restore(flags);

 

      wake_up_interruptible(&WaitQueue_Read_int);

    

      return IRQ_HANDLED;

}

 

int poll_dev2_open(struct inode *inode, struct file *filp)

{

      u32 gpio;

 

      gpio = S3C64XX_GPN(5);

      s3c_gpio_setpull( gpio, S3C_GPIO_PULL_UP );

      irq = IRQ_EINT(5);

      set_irq_type( irq, IRQT_FALLING );

 

      if( !request_irq( irq, poll_dev2_interrupt, IRQF_DISABLED, POLL_DEV_NAME, NULL ));

 

      return 0;

}

 

ssize_t poll_dev2_read( struct file *filp, char *buf, size_t count, loff_t *f_pos )

{

      unsigned long flags;

      int retstate = 0;

 

      retstate = wait_event_interruptible(WaitQueue_Read_int,ReadQCount);

 

      if(retstate) return retstate;

 

      copy_to_user(buf,"poll_dev2_read",count);

      local_save_flags(flags);

      local_irq_disable();

      ReadQCount = 0;

      local_irq_restore(flags);

 

      return 0;

}

 

unsigned int poll_dev2_poll( struct file *filp, poll_table *wait)

{

      unsigned int mask = 0;

 

      poll_wait(filp, &WaitQueue_Read_int, wait);

 

      if(ReadQCount > 0)

            mask |= POLLIN | POLLRDNORM;

    

      return mask;

}

 

int poll_dev2_release(struct inode *inode, struct file *filp)

{

      free_irq( irq, NULL );

 

      return 0;

}

 

struct file_operations poll_fops =

{

            .owner      = THIS_MODULE,

            .read       = poll_dev2_read,

            .poll       = poll_dev2_poll,

            .open       = poll_dev2_open,

            .release    = poll_dev2_release,

};

 

int poll_dev2_init( void )

{

      int result;

 

      result = register_chrdev(POLL_DEV_MAJOR,POLL_DEV_NAME,&poll_fops);

 

      if( result < 0)

            return result;

 

      return 0;

}

 

void poll_dev2_exit( void )

{

      unregister_chrdev(POLL_DEV_MAJOR, POLL_DEV_NAME);

}

module_init( poll_dev2_init );

module_exit( poll_dev2_exit );

 

MODULE_LICENSE("Dual BSD/GPL");



그럼 프로그램을 동작 시켜 보겠습니다.


2. 테스트




다음 그림과 같이 동작 시키겠습니다.


01.PNG


mknod 명령을 이용해 디바이스 파일을 만들어주고


insmod 명령을 통해 디바이스드라이버를 등록합니다.


./poll_app 를 실행 시키면 다음과 같이 동작 합니다.


02.PNG


정해진 시간동안 인터럽트가 발생 안하면 NO POLL EVENT!!! 메시지가 출력되고


직접 등록시킨 GPIO 핀에 인터럽트를 발생시키면

(전 바늘같은걸로 쇼트냈습니다 ㅎㅎ)


등록한 디바이스 드라이버의 메시지를 읽어 화면에 출력합니다.


이상으로 POLL 에 대해 알아보았습니다.


직접 다른방식으로 만들어 보시고 꼭 자기것으로 만드시길 바랍니다.


그럼 다음시간에 만나요~~