zoukankan      html  css  js  c++  java
  • Linux Zynq GPIO中断

    注册中断:对每个pin进行循环遍历for (pin_num = 0; pin_num < min_t(int, ZYNQ_GPIO_NR_GPIOS,  (int)chip->ngpio); pin_num++)

    gpio_irq = irq_find_mapping(irq_domain, pin_num); 将GPIO号映射为Linux系统中断号。

    在Linux中断系统中,一个irq_domain表示一个中断控制器,其内中断由0开始编号(尚存在疑问

    unsigned int irq_find_mapping(struct irq_domain *domain, irq_hw_number_t hwirq)

    将一个中断控制器上的某个硬件中断映射为某个Linux系统中断。

    /**
     * struct irq_domain - Hardware interrupt number translation object
     * @link: Element in global irq_domain list.
     * @name: Name of interrupt domain
     * @ops: pointer to irq_domain methods
     * @host_data: private data pointer for use by owner.  Not touched by irq_domain
     *             core code.
     *
     * Optional elements
     * @of_node: Pointer to device tree nodes associated with the irq_domain. Used
     *           when decoding device tree interrupt specifiers.
     * @gc: Pointer to a list of generic chips. There is a helper function for
     *      setting up one or more generic chips for interrupt controllers
     *      drivers using the generic chip library which uses this pointer.
     *
     * Revmap data, used internally by irq_domain
     * @revmap_direct_max_irq: The largest hwirq that can be set for controllers that
     *                         support direct mapping
     * @revmap_size: Size of the linear map table @linear_revmap[]
     * @revmap_tree: Radix map tree for hwirqs that don't fit in the linear map
     * @linear_revmap: Linear table of hwirq->virq reverse mappings
     */
    struct irq_domain {
    	struct list_head link;
    	const char *name;
    	const struct irq_domain_ops *ops;
    	void *host_data;
    
    	/* Optional data */
    	struct device_node *of_node;
    	struct irq_domain_chip_generic *gc;
    
    	/* reverse map data. The linear map gets appended to the irq_domain */
    	irq_hw_number_t hwirq_max;
    	unsigned int revmap_direct_max_irq;
    	unsigned int revmap_size;
    	struct radix_tree_root revmap_tree;
    	unsigned int linear_revmap[];
    };


    revmap_direct_max_irq: 小于该值的中断,Linux中断号和硬件中断号相同,直接返回。

    revmap_size: 线性反向映射(似乎要求域内IRQ从零开始,有点矛盾),小于该值的hwirq直接利用linear_revmap做查找。

    否则用radix tree来查找映射。

    irq_set_chip_and_handler(gpio_irq, &zynq_gpio_irqchip, handle_simple_irq);

    调用irq_get_desc_lock(irq, &flags, 0);,获取irq对应的irq_desc。并设定irq_desc的chip:desc->irq_data.chip = chip;

    调用irq_reserve_irq(irq);,将allocated_irqs中断位图中相应的中断标识为已占用。

    调用__irq_set_handler,将irq_desc中的handle_irq设定:desc->handle_irq = handle;

    irq_set_chip_data(gpio_irq, (void *)gpio);

    这个比较简单,将要用私有的变量关联到irq,desc->irq_data.chip_data = data;

    set_irq_flags(gpio_irq, IRQF_VALID);


    总体调用:
    irq_set_handler_data(irq_num, (void *)gpio);

    这里的irq_num是通过irq_num = platform_get_irq(pdev, 0);获取的系统配置文件里面的irq配置。这个函数也简单,实质为:desc->irq_data.handler_data = data;

    irq_set_chained_handler(irq_num, zynq_gpio_irqhandler);

    这个函数实质为:desc->handle_irq = handle;


    最终调用关系为:调用zynq_gpio_irqhandler,然后在该函数中通过调用generic_handle_irq来调用最终的handle_simple_irq。

  • 相关阅读:
    ACM-ICPC SouthWestern Europe Regional Contest 2017题解
    Ubuntu系统Anaconda下载安装与切换源教程
    HZNUOJ开发者学习计划
    Codeforces Round #473 (Div. 2)
    正方教务系统自动评教代码
    QQ空间自动点赞
    妈妈我要当全栈工程师
    基于Koa开发学生导师管理系统
    SSH框架实现登陆界面
    谈ACM生涯总结的经验
  • 原文地址:https://www.cnblogs.com/dabbler/p/5173263.html
Copyright © 2011-2022 走看看