中断管理基础学习笔记 - 4.注册中断

本文详细解读了ARM平台Linux内核中中断管理的request_threaded_irq接口,包括中断标志位(IRQF_*、IRQS_*、IRQD_*)的作用,以及如何注册中断、线程化处理和中断状态管理。着重介绍了共享中断和非共享中断的处理策略。

1. 前言

本专题我们开始学习进程管理部分。本文主要参考了《奔跑吧, Linux内核》、ULA、ULK的相关内容。
本节记录ARM架构下中断是如何管理的,Linux内核中的中断管理机制是如何设计与实现的,以及常用的下半部机制,如软中断、tasklet、workqueue等。本文及后续中断相关笔记均以qemu 5.0.0内嵌平台为例,中断控制器采用GIC-400控制器,支持GIC version2技术规范。本文主要以GIC为例记录注册中断的过程。

kernel版本:5.10
平台:arm64

注:
为方便阅读,正文标题采用分级结构标识,每一级用一个"-“表示,如:两级为”|- -", 三级为”|- - -“

2. 注册中断接口

接口说明

  • request_irq

/**
 * request_irq - Add a handler for an interrupt line
 * @irq:        The interrupt line to allocate
 * @handler:    Function to be called when the IRQ occurs.
 *              Primary handler for threaded interrupts
 *              If NULL, the default primary handler is installed
 * @flags:      Handling flags
 * @name:       Name of the device generating this interrupt
 * @dev:        A cookie passed to the handler function
 *
 * This call allocates an interrupt and establishes a handler; see
 * the documentation for request_threaded_irq() for details.
 */
static inline int __must_check
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
            const char *name, void *dev)
{
   
   
		return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}

中断注册旧有接口,实际是对request_threaded_irq接口的封装,其中线程处理函数为NULL

  • request_threaded_irq
/**
 *      request_threaded_irq - allocate an interrupt line
 *      @irq: Interrupt line to allocate
 *      @handler: Function to be called when the IRQ occurs.
 *                Primary handler for threaded interrupts
 *                If NULL and thread_fn != NULL the default
 *                primary handler is installed
 *      @thread_fn: Function called from the irq handler thread
 *                  If NULL, no irq thread is created
 *      @irqflags: Interrupt type flags
 *      @devname: An ascii name for the claiming device
 *      @dev_id: A cookie passed back to the handler function
 *
 *      This call allocates interrupt resources and enables the
 *      interrupt line and IRQ handling. From the point this
 *      call is made your handler function may be invoked. Since
 *      your handler function must clear any interrupt the board
 *      raises, you must take care both to initialise your hardware
 *      and to set up the interrupt handler in the right order.
 *
 *      If you want to set up a threaded irq handler for your device
 *      then you need to supply @handler and @thread_fn. @handler is
 *      still called in hard interrupt context and has to check
 *      whether the interrupt originates from the device. If yes it
 *      needs to disable the interrupt on the device and return
 *      IRQ_WAKE_THREAD which will wake up the handler thread and run
 *      @thread_fn. This split handler design is necessary to support
 *      shared interrupts.
 *
 *      Dev_id must be globally unique. Normally the address of the
 *      device data structure is used as the cookie. Since the handler
 *      receives this value it makes sense to use it.
 *
 *      If your interrupt is shared you must pass a non NULL dev_id
 *      as this is required when freeing the interrupt.
 *
 *      Flags:
 *
 *      IRQF_SHARED             Interrupt is shared
 *      IRQF_TRIGGER_*          Specify active edge(s) or level
 *
 */
int request_threaded_irq(unsigned int irq, irq_handler_t handler,
                         irq_handler_t thread_fn, unsigned long irqflags,
                         const char *devname, void *dev_id)

在Linux2.6.30引入,是线程化的中断注册函数。由于可以把中断处理中的一些繁重任务作为内核线程执行,可以大大减少由于中断导致实时进程的延迟。

参数 说明
irq IRQ软中断号
handler primary handler,中断发生时优先执行primary handler,如果primary handler为NULL且 thread_fn不为空,那么系统执行默认的primary handler:irq_default_primary_handler()
thread_fn 中断线程化的处理程序,如果不为空会创建一个内核线程。handler和thread_fn不能同时为空
irqflags 中断标志位
devname 该中断名称
dev id 传递给中断处理程序的参数

IRQF_*中断标志位

<include/linux/interrupt.h>
/*
 * These flags used only by the kernel as part of the
 * irq handling routines.
 *
 * IRQF_SHARED - allow sharing the irq among several devices
 * IRQF_PROBE_SHARED - set by callers when they expect sharing mismatches to occur
 * IRQF_TIMER - Flag to mark this interrupt as timer interrupt
 * IRQF_PERCPU - Interrupt is per cpu
 * IRQF_NOBALANCING - Flag to exclude this interrupt from irq balancing
 * IRQF_IRQPOLL - Interrupt is used for polling (only the interrupt that is
 *                registered first in a shared interrupt is considered for
 *                performance reasons)
 * IRQF_ONESHOT - Interrupt is not reenabled after the hardirq handler finished.
 *                Used by threaded interrupts which need to keep the
 *                irq line disabled until the threaded handler has been run.
 * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend.  Does not guarantee
 *                   that this interrupt will wake the system from a suspended
 *                   state.  See Documentation/power/suspend-and-interrupts.rst
 * IRQF_FORCE_RESUME - Force enable it on resume even if IRQF_NO_SUSPEND is set
 * IRQF_NO_THREAD - Interrupt cannot be threaded
 * IRQF_EARLY_RESUME - Resume IRQ early during syscore instead of at device
 *                resume time.
 * IRQF_COND_SUSPEND - If the IRQ is shared with a NO_SUSPEND user, execute this
 *                interrupt handler after suspending interrupts. For system
 *                wakeup devices users need to implement wakeup detection in
 *                their interrupt handlers.
 */
 /*多个设备共享一个中断号,需要硬件支持以区分哪个设备发生的中断*/
#define IRQF_SHARED             0x00000080
#define IRQF_PROBE_SHARED       0x00000100
#define __IRQF_TIMER            0x00000200
/*属于特定某个cpu的中断*/
#define IRQF_PERCPU             0x00000400
/*禁止多CPU的中断均衡*/
#define IRQF_NOBALANCING        0x00000800
/*中断被用作轮询*/
#define IRQF_IRQPOLL            0x00001000
/*
 *表示一次性触发的中断,不能嵌套。
 *(1)在硬件中断处理完成之后才能打开中断;
 *(2)在中断线程化中保持中断关闭状态,直到该中断源上所有的thread_fn完成之后才能打开中断:
 *(3)如果request threaded irq()时primary handler为NULL且中断控制器不支持硬件ONESHOT功能,那应该显示地设置该标志位?
 */
#define IRQF_ONESHOT            0x00002000
/*系统睡眠过程中不要关闭该中断*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值