0

我正在研究并行端口驱动程序。现在我已经看到了从并行端口获取中断的方法。

由其中之一,

首先制作控制寄存器 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");

测试.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);
}
4

1 回答 1

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");
于 2013-05-30T06:31:00.023 回答