인터럽트 함수와 디바이스 드라이버간에 데이터 공유
1. 전역 변수를 이용해 데이터를 공유
static unsigned long int_count = 0;
irqreturn_t count_interrup(int irq, void *dev_id, struct pt_regs *regs)
{
int_count++;
return IRQ_HANDLED;
}
int int_open(struct inode *inode, struct file *filp)
{
if(!request_irq(XXX_IRQ, count_interrupt, SA_INTERRUPT, "test", NULL))
{
// 하드웨어 인터럽트 허가 처리 루틴
:
int_count = 0;
}
return 0;
}
int int_release(struct inode *inode, struct fiel *filp)
{
// 하드웨어 인터럽트 금지 처리 루틴
:
free_irq(XXX_IRQ, NULL);
printk("int count %d\n", int_count);
return 0;
}
인터럽트 서비스 함수 하나가 동작하는 경우에 사용하지만, 동일한 인터럽트 서비스 함수로 여러 디바이스를 제어 할 경우에는 사용 할 수 없다.
/////////////////////////////////////////////////////////////////
2. dev_id를 이용하여 데이터를 공유 하는 경우
이 방식은 디바이스의 다른 정보를 전달하는 가장 보편적인 방법으로 다중 프로세스 환경에 매우 적합하다.
typedef struct
{
unsigned long ioaddress;
unsigned long count;
} __attribute__ ((packed)) R_INT_INFO;
irqreturn_t count_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
R_INT_INFO *ptrInfo;
ptrInfo = (R_INT_INFO *) dev_id;
printk("INT READ I/O %02X\n", inb(ptrInfo->ioaddress));
ptrInfo->count++;
return IRQ_HANDLED;
}
int int_open(struct inode *inode, struct file *filp)
{
R_INT_INFO *ptrInfo;
ptrInfo = kmalloc(sizeof(R_INT_INFO), GFP_KERNEL);
filp->private_data = ptrInfo;
switch(MINOR(inode->i_rdev))
{
case 0: ptrInfo->ioaddress = 0x378; break;
case 1: ptrInfo->ioaddress = 0x278; break;
}
if(!request_irq(XXX_IRQ, count_interrupt, SA_INTERRUPT, "test", ptrInfo))
{
enable_handware_int(ptrInfo); // 실제함수 아님.. 가상의 함수.
}
return 0;
}
int int_release(struct inode *inode, struct file *filp)
{
R_INT_INFO *ptrInfo = (R_INT_INFO *)filp->private_data;
disable_hardware_int(ptrInfo); // 실제함수 아님.. 가상의 함수.
free_irq(XXX_IRQ, ptrInfo);
kfree(ptrInfo);
return 0;
}
1. 전역 변수를 이용해 데이터를 공유
static unsigned long int_count = 0;
irqreturn_t count_interrup(int irq, void *dev_id, struct pt_regs *regs)
{
int_count++;
return IRQ_HANDLED;
}
int int_open(struct inode *inode, struct file *filp)
{
if(!request_irq(XXX_IRQ, count_interrupt, SA_INTERRUPT, "test", NULL))
{
// 하드웨어 인터럽트 허가 처리 루틴
:
int_count = 0;
}
return 0;
}
int int_release(struct inode *inode, struct fiel *filp)
{
// 하드웨어 인터럽트 금지 처리 루틴
:
free_irq(XXX_IRQ, NULL);
printk("int count %d\n", int_count);
return 0;
}
인터럽트 서비스 함수 하나가 동작하는 경우에 사용하지만, 동일한 인터럽트 서비스 함수로 여러 디바이스를 제어 할 경우에는 사용 할 수 없다.
/////////////////////////////////////////////////////////////////
2. dev_id를 이용하여 데이터를 공유 하는 경우
이 방식은 디바이스의 다른 정보를 전달하는 가장 보편적인 방법으로 다중 프로세스 환경에 매우 적합하다.
typedef struct
{
unsigned long ioaddress;
unsigned long count;
} __attribute__ ((packed)) R_INT_INFO;
irqreturn_t count_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
R_INT_INFO *ptrInfo;
ptrInfo = (R_INT_INFO *) dev_id;
printk("INT READ I/O %02X\n", inb(ptrInfo->ioaddress));
ptrInfo->count++;
return IRQ_HANDLED;
}
int int_open(struct inode *inode, struct file *filp)
{
R_INT_INFO *ptrInfo;
ptrInfo = kmalloc(sizeof(R_INT_INFO), GFP_KERNEL);
filp->private_data = ptrInfo;
switch(MINOR(inode->i_rdev))
{
case 0: ptrInfo->ioaddress = 0x378; break;
case 1: ptrInfo->ioaddress = 0x278; break;
}
if(!request_irq(XXX_IRQ, count_interrupt, SA_INTERRUPT, "test", ptrInfo))
{
enable_handware_int(ptrInfo); // 실제함수 아님.. 가상의 함수.
}
return 0;
}
int int_release(struct inode *inode, struct file *filp)
{
R_INT_INFO *ptrInfo = (R_INT_INFO *)filp->private_data;
disable_hardware_int(ptrInfo); // 실제함수 아님.. 가상의 함수.
free_irq(XXX_IRQ, ptrInfo);
kfree(ptrInfo);
return 0;
}
'Linux > Device Driver' 카테고리의 다른 글
인터럽트 발생금지 (0) | 2013.09.26 |
---|---|
인터럽트 공유 (0) | 2013.09.26 |
시간 처리와 커널 타이머 함수 (0) | 2013.09.26 |
kmalloc, vmalloc (0) | 2013.09.26 |
print port address (프린트 포트 주소) (0) | 2013.09.26 |