我正在研究并行端口驱动程序。现在我已经看到了从并行端口获取中断的方法。
其中一人,
首先制作控制寄存器1(IRQ)的第4针。 然后降低nACK。
所以我在数据引脚8和nACK之间切换。所以,如果我写了一些有msb 1的数据,那么如果该开关打开,它将被中断。现在我有一个问题。如果我断开了那个开关并再次连接,那么它就不会给我中断。
那么,我怎样才能通过交换机获得中断的连接与否。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/parport.h>
#include <asm/uaccess.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/errno.h>
#include <asm/irq.h>
#include <linux/kthread.h>
#define DEVICE_NAME "parlelport"
struct pardevice *pdev;
static int dummy;
int ret;
static irqreturn_t recv_handler(int irq, void *dev_id)
{
printk("we inside if isr");
return 0;
}
int led_open(struct inode *inode, struct file *file)
{
printk("1\n");
printk("Device File Opened\n");
char byte1;
byte1=inb(0x37A);
printk("%d \n",byte1);
return 0;
}
ssize_t led_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
printk("2\n");
char byte=inb(0x37A);
printk("%d",byte);
byte = byte | 0x10; // 0x10= 00010000, 4th pin of CTRL reg
outb(byte, 0x37A); //which enable IRQ
char kbuf;
copy_from_user(&kbuf, buf, 1);
parport_claim_or_block(pdev); /* Claim the port */
parport_write_data(pdev->port, kbuf); /* Write to the device */
//parport_release (pdev);
return count;
}
int led_release(struct inode *inode, struct file *file)
{
printk("3\n");
printk("Device File Released\n");
char byte;
byte=inb(0x37A);
printk("%d", byte);
return 0;
}
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
.release = led_release,
};
static int led_preempt(void *handle)
{
printk("4\n");
return 1;
}
static void led_attach(struct parport *port)
{
printk("5\n");
pdev = parport_register_device(port, DEVICE_NAME, led_preempt, NULL, NULL, 0, NULL);
printk("Port attached\n");
char byte1;
byte1=inb(0x37A);
printk("%d \n",byte1);
}
static void led_detach(struct parport *port)
{
printk("6\n");
parport_unregister_device (pdev);
printk("Port Deattached\n");
}
static struct parport_driver led_driver = {
.name= "led",
.attach = led_attach,
.detach = led_detach,
};
int __init led_init(void)
{
printk("7\n");
if (register_chrdev(89, DEVICE_NAME, &led_fops))
{
printk("Can't register device\n");
return -1;
}
char byte=inb(0x37A);
printk("%d",byte);
byte = byte | 0x10;
outb(byte, 0x37A);
char byte1;
byte1=inb(0x37A);
printk("%d %d \n",byte,byte1);
parport_register_driver(&led_driver);
ret= request_irq(7, recv_handler, IRQF_SHARED, "parlelport", &dummy);
printk("%d",ret);
return 0;
}
void __exit led_cleanup(void)
{
printk("8\n");
unregister_chrdev(89, DEVICE_NAME);
if(!ret)
free_irq(7, &dummy);
parport_unregister_driver(&led_driver);
printk("LED Driver unregistered.\n");
return;
}
module_init(led_init);
module_exit(led_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vikrant Patel");
Test.c文件
int main()
{
int fd=open("/dev/parlelport",O_RDWR);
char byte;
printf("Enter Value to send on parallel port");
scanf("%c",&byte);
printf("Byte value is %c\n",byte);
if(write(fd,&byte,sizeof(char)))
{
printf("\nSuccessfully written on port");
}
getchar();
getchar();
close(fd);
}
答案 0 :(得分:1)
我明白了。
首先制作一个帖子 将Enable IRQ代码放在该线程中 所以它会不断执行它 每当我在我的硬件上连接引脚时,它就会被中断。
检查您的参考代码。
#include <linux/module.h>
#include <linux/parport.h>
#include <asm/io.h>
#include <linux/interrupt.h>
#include <linux/kthread.h>
#define DEVICE_NAME "parlelport"
#define DATA 0x378
#define STATUS 0x379
#define CONTROL 0x37A
struct pardevice *pdev;
struct task_struct *ts1, *ts2;
int dummy;
char buf1='1',buf2='2';
char byte='0';
int thread1(void *data)
{
while(1)
{
outb(byte, CONTROL); /* 0x30 = 0011 0000 , makes IRQ pin(5th bit) enable */
printk("Thread1\n");
parport_claim_or_block(pdev); /* Claim the port */
parport_write_data(pdev->port, buf1); /* Write to the device */
parport_release(pdev); /* Release the port */
msleep(4000);
if (kthread_should_stop())
break;
}
return 0;
}
int thread2(void *data)
{
while(1)
{
outb(byte,CONTROL); /* 0x30 = 0011 0000 , makes IRQ pin(5th bit) enable */
printk("Thread2\n");
parport_claim_or_block(pdev); /* Claim the port */
parport_write_data(pdev->port, buf2); /* Write to the device */
parport_release(pdev); /* Release the port */
msleep(4000);
if (kthread_should_stop())
break;
}
return 0;
}
int led_open(struct inode *inode, struct file *file)
{
printk("Device File Opened\n");
ts1=kthread_run(thread1,NULL,"kthread"); /* Initiation of thread 1 */
msleep(2000);
ts2=kthread_run(thread2,NULL,"kthread"); /* Initiation of thread 2 */
return 0;
}
ssize_t led_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
{
return count;
}
int led_release(struct inode *inode, struct file *file)
{
printk("Device File Released\n");
kthread_stop(ts1);
kthread_stop(ts2);
buf1='1';
buf2='2';
outb_p(0x00,DATA);
return 0;
}
static irqreturn_t recv_handler(int irq, void *unused)
{
printk("we inside of isr");
buf1= buf1 ^ 0x7F;
buf2= buf2 ^ 0x7F;
return 0;
}
static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open,
.write = led_write,
.release = led_release,
};
static int led_preempt(void *handle)
{
return 1;
}
static void led_attach(struct parport *port)
{
pdev = parport_register_device(port, DEVICE_NAME, led_preempt, NULL, NULL, 0, NULL);
printk("Port attached\n");
}
static void led_detach(struct parport *port)
{
parport_unregister_device (pdev);
printk("Port Deattached\n");
}
static struct parport_driver led_driver = {
.name= "led",
.attach = led_attach,
.detach = led_detach,
};
int __init led_init(void)
{
/*Register our ISR with the kernel for PARALLEL_IRQ */
if (request_irq(7, recv_handler, IRQF_SHARED, DEVICE_NAME ,&dummy))
{
printk("Registering ISR failed\n");
return -ENODEV;
}
/*Register Character Device Driver at 89 Major number*/
if (register_chrdev(89, DEVICE_NAME, &led_fops))
{
printk("Can't register device\n");
return -1;
}
/*Register parallel port driver with parport structure led_driver*/
parport_register_driver(&led_driver);
return 0;
}
void __exit led_cleanup(void)
{
unregister_chrdev(89, DEVICE_NAME); /* Unregister char driver */
free_irq(7, &dummy); /* Free the ISR from IRQ7 */
parport_unregister_driver(&led_driver); /* Unregister the parallel port driver */
printk("LED Driver unregistered.\n");
return;
}
module_init(led_init);
module_exit(led_cleanup);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Vikrant Patel");