• 13. linux 中断式驱动编程


    引用网址:https://www.cnblogs.com/standardzero/p/12551162.html

    1. 根据硬件工程生成设备数文件 dts

    / {
        amba_pl: amba_pl {
            #address-cells = <1>;
            #size-cells = <1>;
            compatible = "simple-bus";
            ranges ;
            axi_timer_0: timer@42800000 {
                clock-frequency = <100000000>;
                clock-names = "ref_clk";
                clocks = <&clkc 0>;
                compatible = "ricky,xps-timer-1.00.a";
                interrupt-parent = <&intc>;
                interrupts = <0 29 4>;
                reg = <0x42800000 0x10000>;
                xlnx,count-width = <0x20>;
                xlnx,gen0-assert = <0x1>;
                xlnx,gen1-assert = <0x1>;
                xlnx,one-timer-only = <0x0>;
                xlnx,trig0-assert = <0x1>;
                xlnx,trig1-assert = <0x1>;
            };
        };
    };
    
    

    2. 驱动程序

    *  intr_example.c - The simplest kernel module.
     */
    #include <linux/kernel.h>
    #include <linux/init.h>
    #include <linux/module.h>
    #include <linux/slab.h>
    #include <linux/io.h>
    #include <linux/interrupt.h>
    
    
    #include <linux/of_address.h>
    #include <linux/of_device.h>
    #include <linux/of_platform.h>
    
    
    /* Standard module information, edit as appropriate */
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR
        ("Xilinx Inc.");
    MODULE_DESCRIPTION
        ("intr_example - loadable module template generated by petalinux-create -t modules");
    
    
    #define DRIVER_NAME "intr_example"
    
    
    #define XIL_AXI_TIMER_BASEADDR 0x42800000
    #define XIL_AXI_TIMER_HIGHADDR 0x4280FFFF
    
    
    #define XIL_AXI_TIMER_TCSR_OFFSET        0x0
    #define XIL_AXI_TIMER_TLR_OFFSET        0x4
    #define XIL_AXI_TIMER_TCR_OFFSET        0x8
    #define XIL_AXI_TIMER_CSR_INT_OCCURED_MASK    0x00000100
    
    
    #define XIL_AXI_TIMER_CSR_CASC_MASK        0x00000800
    #define XIL_AXI_TIMER_CSR_ENABLE_ALL_MASK    0x00000400
    #define XIL_AXI_TIMER_CSR_ENABLE_PWM_MASK    0x00000200
    #define XIL_AXI_TIMER_CSR_INT_OCCURED_MASK    0x00000100
    #define XIL_AXI_TIMER_CSR_ENABLE_TMR_MASK    0x00000080
    #define XIL_AXI_TIMER_CSR_ENABLE_INT_MASK    0x00000040
    #define XIL_AXI_TIMER_CSR_LOAD_MASK        0x00000020
    #define XIL_AXI_TIMER_CSR_AUTO_RELOAD_MASK    0x00000010
    #define XIL_AXI_TIMER_CSR_EXT_CAPTURE_MASK    0x00000008
    #define XIL_AXI_TIMER_CSR_EXT_GENERATE_MASK    0x00000004
    #define XIL_AXI_TIMER_CSR_DOWN_COUNT_MASK    0x00000002
    #define XIL_AXI_TIMER_CSR_CAPTURE_MODE_MASK    0x00000001
    
    
    #define TIMER_CNT    0xF8000000
    
    
    /* Simple example of how to receive command line parameters to your module.
       Delete if you don't need them */
    unsigned myint = 0xdeadbeef;
    char *mystr = "default";
    
    
    module_param(myint, int, S_IRUGO);
    module_param(mystr, charp, S_IRUGO);
    
    
    struct intr_example_local {
        int irq;
        unsigned long mem_start;
        unsigned long mem_end;
        void __iomem *base_addr;
    };
    
    
    static int int_cnt;
    
    
    static irqreturn_t intr_example_irq(int irq, struct intr_example_local *lp)
    {
        unsigned int data;
    
    
    
    
        /* 
        * Clear Interrupt
        */
        data = ioread32(lp->base_addr + XIL_AXI_TIMER_TCSR_OFFSET);
        iowrite32(data | XIL_AXI_TIMER_CSR_INT_OCCURED_MASK,
        lp->base_addr + XIL_AXI_TIMER_TCSR_OFFSET);
    
    
    
    
        return IRQ_HANDLED;
    }
    
    
    static int intr_example_probe(struct platform_device *pdev)
    {
        struct resource *r_irq; /* Interrupt resources */
        struct resource *r_mem; /* IO mem resources */
        struct device *dev = &pdev->dev;
        struct intr_example_local *lp = NULL;
    
        unsigned int data = 0;
        int rc = 0;
    
        dev_info(dev, "Device Tree Probing\n");
    
    
        /* Get iospace for the device */
        r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!r_mem) {
            dev_err(dev, "invalid address\n");
            return -ENODEV;
        }
    
        lp = (struct intr_example_local *) kmalloc(sizeof(struct intr_example_local), GFP_KERNEL);
        if (!lp) {
            dev_err(dev, "Cound not allocate intr_example device\n");
            return -ENOMEM;
        }
    
        dev_set_drvdata(dev, lp);
    
        lp->mem_start = r_mem->start;
        lp->mem_end = r_mem->end;
    
    
        if (!request_mem_region(lp->mem_start,
                    lp->mem_end - lp->mem_start + 1,
                    DRIVER_NAME)) {
            dev_err(dev, "Couldn't lock memory region at %p\n",
                (void *)lp->mem_start);
            rc = -EBUSY;
            goto error1;
        }
    
    
        lp->base_addr = ioremap_nocache(lp->mem_start, lp->mem_end - lp->mem_start + 1);
        if (!lp->base_addr) {
            dev_err(dev, "intr_example: Could not allocate iomem\n");
            rc = -EIO;
            goto error2;
        }
    
    
        /* Get IRQ for the device */
        r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!r_irq) {
            dev_info(dev, "no IRQ found\n");
            dev_info(dev, "intr_example at 0x%08x mapped to 0x%08x\n",
                (unsigned int __force)lp->mem_start,
                (unsigned int __force)lp->base_addr);
            return 0;
        }
        lp->irq = r_irq->start;
    
    
        rc = request_irq(lp->irq, &intr_example_irq, 0, DRIVER_NAME, lp);
        if (rc) {
            dev_err(dev, "testmodule: Could not allocate interrupt %d.\n",
                lp->irq);
            goto error3;
        }
    
    
        dev_info(dev,"intr_example at 0x%08x mapped to 0x%08x, irq=%d\n",
            (unsigned int __force)lp->mem_start,
            (unsigned int __force)lp->base_addr,
            lp->irq);
    
    
    
    
        return 0;
    error3:
        free_irq(lp->irq, lp);
    error2:
        release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
    error1:
        kfree(lp);
        dev_set_drvdata(dev, NULL);
        return rc;
    }
    
    
    static int intr_example_remove(struct platform_device *pdev)
    {
        struct device *dev = &pdev->dev;
        struct intr_example_local *lp = dev_get_drvdata(dev);
        free_irq(lp->irq, lp);
        release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1);
        kfree(lp);
        dev_set_drvdata(dev, NULL);
        return 0;
    }
    
    
    #ifdef CONFIG_OF
    static struct of_device_id intr_example_of_match[] = {
        { .compatible = "ricky,xps-timer-1.00.a", },
        { /* end of list */ },
    };
    MODULE_DEVICE_TABLE(of, intr_example_of_match);
    #else
    # define intr_example_of_match
    #endif
    
    
    
    
    static struct platform_driver intr_example_driver = {
        .driver = {
            .name = DRIVER_NAME,
            .owner = THIS_MODULE,
            .of_match_table    = intr_example_of_match,
        },
        .probe        = intr_example_probe,
        .remove        = intr_example_remove,
    };
    
    
    static int __init intr_example_init(void)
    {
        printk("<1>Hello module world.\n");
        printk("<1>Module parameters were (0x%08x) and \"%s\"\n", myint,
               mystr);
    
    
        return platform_driver_register(&intr_example_driver);
    }
    
    
    
    
    static void __exit intr_example_exit(void)
    {
        platform_driver_unregister(&intr_example_driver);
        printk(KERN_ALERT "Goodbye module world.\n");
    }
    
    
    module_init(intr_example_init);
    module_exit(intr_example_exit);
    
     
  • 相关阅读:
    window对象open方法详解
    jse中将数据反转
    jqery实现10X10的表格,双击消失
    Filter实现登录功能限制
    jQuery全选功能
    Fliter设置字符编码,解决中文问题
    innerHTML、innerText和outerHTML、outerText的区别
    Delphi ActiveX Form的使用实例
    Mina 客户端,服务器简单Demo
    Mina 资料
  • 原文地址:https://www.cnblogs.com/bruce1992/p/16564306.html
Copyright © 2020-2023  润新知