[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 メーリングリストの案内