首页 > 系统相关 >13. linux 中断式驱动编程

13. linux 中断式驱动编程

时间:2023-06-05 18:03:34浏览次数:48  
标签:13 mem 编程 dev intr TIMER lp linux example

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);
}

标签:13,mem,编程,dev,intr,TIMER,lp,linux,example
From: https://blog.51cto.com/u_4018548/6418216

相关文章

  • 使用 TypeScript 探索面向对象编程
    在软件开发领域,面向对象编程(OOP)已成为创建复杂且可扩展应用程序的基本范例。支持OOP概念的最流行的编程语言之一是TypeScript。TypeScript是JavaScript的超集,它增加了静态类型和其他功能以增强代码的可维护性和可读性。在这篇博客中,我们将探讨TypeScript中面向对象编程......
  • Linux命令速查手册
    man-获得帮助manls#许多Linux自带命令可以通过man查看使用帮助ls--help#有些程序可以通过-h,--help查看使用帮助ls-显示目录内容ls#显示目录内容ls-l#以列表显示形式显示目录内容,通常在~/.bashrc文件......
  • 实验6 turtle绘图与python库应用编程体验
    任务1fromturtleimport*defmove(x,y):penup()goto(x,y)pendown()defdraw(n,size=100):foriinrange(n):fd(size)left(360/n)defmain():pensize(2)pencolor('red')move(-200,0)draw(3)mov......
  • linux 上使用的命令
    常用的命令mkdir文件夹名(创建文件夹)touch文件名 (创建文件)mv 文件要目标地址 (移动文件)解压命令:tar-zxvf/bbs.tar.zip-C/zzz/bbs将文件解压到指定文件夹下tar-xvffilename.tartar-zxvffilename.tar.gztar-zxvffilename.tgz......
  • Linux软连接和硬链接
    1.Linux链接概念Linux链接分两种,一种被称为硬链接(HardLink),另一种被称为符号链接(SymbolicLink)。默认情况下,ln命令产生硬链接。【硬连接】硬连接指通过索引节点来进行连接。在Linux的文件系统中,保存在磁盘分区中的文件不管是什么类型都给它分配一个编号,称为索引节点号(InodeIndex)......
  • CS13 BOM展开报错 Error 'MM 104' (Material has no base unit of measure)物料无
    目的介绍如何解决SAP报错信息MM104在使用事务码CS13进行BOM展开时.现象错误信息'Materialhasnobaseunitofmeasure'(错误消息号:MM104)在使用CS13订单展开时会报以下错误、可以的原因如下某个BOM组件有特殊采购类型(specialprocurementtype)70'Reservationfro......
  • 1315. 祖父节点值为偶数的节点和
    1315.祖父节点值为偶数的节点和题目算法设计:深度优先搜索 题目传送门:https://leetcode.cn/problems/sum-of-nodes-with-even-valued-grandparent/ 算法设计:深度优先搜索遍历二叉树,记录祖父节点,祖父节点是偶数,累加当前节点。或者,对于节点值为偶数的节点,累加它的孙子节点的值即......
  • 实验5 文件应用编程
    实验任务6:实验源码:withopen('data6.csv','r',encoding='gbk')asf:data=f.readlines()data1=[str(eval(data[i]))foriinrange(1,len(data))]data2=[str(int(eval(data[i])+0.5))foriinrange(1,len(data))]info=[[data1[i],dat......
  • Linux基础24 定时任务, 发邮件, date命令
    date命令[root@localhost~]#date2023年06月01日星期四00:57:36CST[root@localhost~]#date+%F2023-06-01[root@localhost~]#date+%F-%T2023-06-01-01:17:37[root@localhost~]#date+%Y2023[root@localhost~]#date+%m06[root@localhost~]#date+%d......
  • Windows和Linux的环境变量
    环境变量概述环境变量(EnvironmentVariables)一般是指在操作系统中用来指定操作系统运行环境的一些参数,如:临时文件夹位置和系统文件夹位置等。环境变量是在操作系统中一个具有特定名字的对象,它包含了一个或者多个应用程序所将使用到的信息。例如Windows和DOS操作系统中的pat......