[Suzaku:00549] Re: module内でpoll_wait使用について

三浦浩二 email@hidden
2006年 6月 20日 (火) 17:19:55 JST


いつもお世話になります。
 (株)デザインテックの三浦です。

> 【方法2】 ... Makefile にスペシャルファイルを追加
>
> dist/vendors/AtmarkTechno/SUZAKU/Makefile (SUZAKU-Sの場合)
> dist/vendors/AtmarkTechno/SUZAKU-V/Makefile (SUZAKU-Vの場合)
>
> の DEVICES に
>   usertimer,c,60,0
> を追加して、image を再作成してもらえば可能です。
=>
        アドバイス有難う御座いました。
        早速、poll動作を見たのですが期待した動作になりません。
        期待動作としましては
            (1)openにてusertimer_waitの初期化
            (2)selectにてusertimer_waitの休眠
                 タイムアウトが1秒ですのでコンソールに","が表示されるのでは
            (3)割り込みにてusertimer_waitの起床
            (4)LEDが3秒毎に点滅する
        また、割り込みは3秒に設定していまして
        cat /proc/interruptsにて3秒毎のカウントアップしていることは確認して
います。
        WindowsのDDKでいいますと
        ユーザ内のWaitForSingleObject関数でプロセスの休眠、
        デバイスドライバ内の割り込み発生(KeSetEvent関数)でプロセスの起床
        を期待しています。
        module、ユーザ、実行結果は以下の通りです。
        poll(select)関数が理解できていないからだと思いますが
        何かよいアドバイスはないでしょうか?

------------------------timermod.c-------------------------------------
#define MODULE
#define __KERNEL__
#define __linux__
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/wait.h>
#include <linux/fs.h>
#include <linux/poll.h>
#include <linux/sched.h>

#define DEV_NAME "UserTimer"
#define IRQ 3
#define OPB_TIMER_0_BASEADDR 0xFFFF4000
#define OPB_TIMER_UDT0 0x2
#define OPB_TIMER_ARHT0 0x10
#define OPB_TIMER_LOAD0 0x20
#define OPB_TIMER_EINT0 0x40
#define OPB_TIMER_ENT0 0x80
#define OPB_TIMER_TINIT0 0x100

static wait_queue_head_t usertimer_wait;

static int usertimer_open(struct inode *inode, struct file *file)
{
 init_waitqueue_head(&usertimer_wait);
 return 0;
}

static int usertimer_close(struct inode *inode, struct file *file)
{
 return 0;
}

static unsigned int usertimer_poll(struct file *file, poll_table *wait)
{
 poll_wait(file, &usertimer_wait, wait);
 return POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM;
}

static struct file_operations usertimer_fops =
{
 THIS_MODULE,
 NULL,
 NULL,
 NULL,
 NULL,
 usertimer_poll,
 NULL,
 NULL,
 usertimer_open,
 NULL,
 usertimer_close,
 NULL,
 NULL,
 NULL,
 NULL,
 NULL
};

static void usertimer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{

 if ( ((*(volatile unsigned long
*)(OPB_TIMER_0_BASEADDR+0x00))&OPB_TIMER_TINIT0)==0 )
  return;

 *(volatile unsigned long *)(OPB_TIMER_0_BASEADDR+0x00) =
  OPB_TIMER_UDT0 |
  OPB_TIMER_ARHT0 |
  OPB_TIMER_EINT0 |
  OPB_TIMER_ENT0 |
  OPB_TIMER_TINIT0;
 wake_up_interruptible(&usertimer_wait);

}

int init_module(void)
{
 if ( register_chrdev( 60, "usertimer", &usertimer_fops )!= 0 )
 {
  printk("error:register_chrdev()\n");
  return 1;
 }

 if (request_irq(IRQ, usertimer_interrupt, SA_INTERRUPT,
   DEV_NAME, NULL))
  return 1;

 *(volatile unsigned long *)(OPB_TIMER_0_BASEADDR+0x04) =
  1500*103219; // TLR0 (103219=2ms)
 *(volatile unsigned long *)(OPB_TIMER_0_BASEADDR+0x00) =
  OPB_TIMER_LOAD0;

 *(volatile unsigned long *)(OPB_TIMER_0_BASEADDR+0x00) =
  OPB_TIMER_UDT0 |
  OPB_TIMER_ARHT0 |
  OPB_TIMER_EINT0 |
  OPB_TIMER_ENT0 ;

 init_waitqueue_head(&usertimer_wait);

 return 0;
}

void cleanup_module(void)
{
 unregister_chrdev( 60, "usertimer");
 free_irq(IRQ, NULL);
}
------------------------timermod.c-------------------------------------

------------------------timer.c-------------------------------------
#include <fcntl.h>
#include <stdio.h>
#include <sys/time.h>

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

 int fd, i, r;
 int led = 0;
 fd_set fds;
 struct timeval tv;

 printf("timer.c test\n");

 if ( (fd=open("/dev/usertimer", O_RDWR))<0 )
 {
  printf("error:can not open device diver\n");
  return(-1);
 }

 for(i=0;i<10;i++)
 {
  FD_ZERO(&fds);
  FD_SET(fd, &fds);
  tv.tv_sec = 1; tv.tv_usec = 0; // timeout 1sec
  r=select(fd+1, &fds, NULL, NULL, &tv);
  if ( r<0 )
   printf("error:select\n");
  if ( r==0 )
  {
   putchar('.');
   fflush(stdout);
  }
  if ( (r==1)&&(FD_ISSET(fd, &fds)) )
  {
   printf("interrupt\n");
   *(volatile unsigned long *)0x90000000 = led;
   led = 1-led;
  }
 }

 close(fd);
 return 0;
}
------------------------timer.c-------------------------------------

------------------------実行結果-------------------------------------

# ./timer
timer.c test
interrupt
interrupt
interrupt
interrupt
interrupt
interrupt
interrupt
interrupt
interrupt
interrupt
#
(ほぼ一瞬で実行します。LEDも点滅しないで一瞬点灯して消灯します)
------------------------実行結果-------------------------------------




suzaku メーリングリストの案内