一、中断相关结构体
1.irq_desc中断描述符
struct irq_desc {
#ifdef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
struct irq_data irq_data;
#else
union {
struct irq_data irq_data; //中断数据
struct {
unsigned int irq; //中断号
unsigned int node; //节点号
struct irq_chip *chip; //irq_chip
void *handler_data;
void *chip_data;
struct msi_desc *msi_desc;
#ifdef CONFIG_SMP
cpumask_var_t affinity;
#endif
};
};
#endif
struct timer_rand_state *timer_rand_state;
unsigned int *kstat_irqs;
irq_flow_handler_t handle_irq; //中断处理句柄
struct irqaction *action; /* 中断动作列表 */
unsigned int status; /* 中断状态 */
unsigned int depth; /* nested irq disables */
unsigned int wake_depth; /* nested wake enables */
unsigned int irq_count; /* For detecting broken IRQs */
unsigned long last_unhandled; /* Aging timer for unhandled count */
unsigned int irqs_unhandled;
raw_spinlock_t lock;
#ifdef CONFIG_SMP
const struct cpumask *affinity_hint;
#ifdef CONFIG_GENERIC_PENDING_IRQ
cpumask_var_t pending_mask;
#endif
#endif
atomic_t threads_active;
wait_queue_head_t wait_for_threads;
#ifdef CONFIG_PROC_FS
struct proc_dir_entry *dir; //proc接口目录
#endif
const char *name; //名字
} ____cacheline_internodealigned_in_smp;
2.irq_chip 芯片相关的处理函数集合
struct irq_chip { //芯片相关的处理函数集合
const char *name; //"proc/interrupts/name"
#ifndef CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED
unsigned int (*startup)(unsigned int irq);
void (*shutdown)(unsigned int irq);
void (*enable)(unsigned int irq);
void (*disable)(unsigned int irq);
void (*ack)(unsigned int irq);
void (*mask)(unsigned int irq);
void (*mask_ack)(unsigned int irq);
void (*unmask)(unsigned int irq);
void (*eoi)(unsigned int irq);
void (*end)(unsigned int irq);
int (*set_affinity)(unsigned int irq,const struct cpumask *dest);
int (*retrigger)(unsigned int irq);
int (*set_type)(unsigned int irq, unsigned int flow_type);
int (*set_wake)(unsigned int irq, unsigned int on);
void (*bus_lock)(unsigned int irq);
void (*bus_sync_unlock)(unsigned int irq);
#endif
unsigned int (*irq_startup)(struct irq_data *data); //中断开始
void (*irq_shutdown)(struct irq_data *data); //中断关闭
void (*irq_enable)(struct irq_data *data); //中断使能
void (*irq_disable)(struct irq_data *data); //中断禁用
void (*irq_ack)(struct irq_data *data);
void (*irq_mask)(struct irq_data *data);
void (*irq_mask_ack)(struct irq_data *data);
void (*irq_unmask)(struct irq_data *data);
void (*irq_eoi)(struct irq_data *data);
int (*irq_set_affinity)(struct irq_data *data, const struct cpumask *dest, bool force);
int (*irq_retrigger)(struct irq_data *data);
int (*irq_set_type)(struct irq_data *data, unsigned int flow_type);
int (*irq_set_wake)(struct irq_data *data, unsigned int on);
void (*irq_bus_lock)(struct irq_data *data);
void (*irq_bus_sync_unlock)(struct irq_data *data);
#ifdef CONFIG_IRQ_RELEASE_METHOD
void (*release)(unsigned int irq, void *dev_id);
#endif
};
3.irqaction中断行动结构体
struct irqaction {
irq_handler_t handler; //中断处理函数
unsigned long flags; //中断标志
const char *name; //中断名
void *dev_id; //设备id号,共享中断用
struct irqaction *next; //共享中断类型指向下一个irqaction
int irq; //中断号
struct proc_dir_entry *dir; //proc接口目录
irq_handler_t thread_fn; //中断处理函数(线程)
struct task_struct *thread; //线程任务
unsigned long thread_flags; //线程标志
};
在整个中断系统中将勾勒出以下的关系框图
二、中断初始化工作
从start_kernel看起,大致按以下的分支顺序初始化
start_kernel
setup_arch //设置全局init_arch_irq函数
early_trap_init //搬移向量表
early_irq_init(); //初始化全局irq_desc数组
init_IRQ(); //调用init_arch_irq函数
[ //板级中断初始化常用到的API
set_irq_chip
set_irq_handler
set_irq_chained_handler
set_irq_flags
set_irq_type
set_irq_chip_data
set_irq_data
]
1.在setup_arch中主要是设置全局init_arch_irq函数
void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
struct machine_desc *mdesc;
char *from = default_command_line;
init_tags.mem.start = PHYS_OFFSET;
unwind_init();
setup_processor();
mdesc = setup_machine(machine_arch_type);
machine_name = mdesc->name;
if (mdesc->soft_reboot)
reboot_setup("s");
if (__atags_pointer)
tags = phys_to_virt(__atags_pointer);
else if (mdesc->boot_params) {
#ifdef CONFIG_MMU
if (mdesc->boot_params < PHYS_OFFSET ||mdesc->boot_params >= PHYS_OFFSET + SZ_1M) {
printk(KERN_WARNING"Default boot params at physical 0x%08lx out of reach\n",mdesc->boot_params);
}
else
#endif
{
tags = phys_to_virt(mdesc->boot_params);
}
}
#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
if (tags->hdr.tag != ATAG_CORE)
convert_to_tag_list(tags);
#endif
if (tags->hdr.tag != ATAG_CORE)
tags = (struct tag *)&init_tags;
if (mdesc->fixup)
mdesc->fixup(mdesc, tags, &from, &meminfo);
if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
squash_mem_tags(tags);
save_atags(tags);
parse_tags(tags);
}
init_mm.start_code = (unsigned long) _text;
init_mm.end_code = (unsigned long) _etext;
init_mm.end_data = (unsigned long) _edata;
init_mm.brk = (unsigned long) _end;
strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
*cmdline_p = cmd_line;
parse_early_param();
arm_memblock_init(&meminfo, mdesc);
paging_init(mdesc);
request_standard_resources(&meminfo, mdesc);
#ifdef CONFIG_SMP
if (is_smp())
smp_init_cpus();
#endif
reserve_crashkernel();
cpu_init();
tcm_init();
arch_nr_irqs = mdesc->nr_irqs;
init_arch_irq = mdesc->init_irq; //设置全局init_arch_irq函数
//void (*init_arch_irq)(void) __initdata = NULL;
system_timer = mdesc->timer;
init_machine = mdesc->init_machine;
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
conswitchp = &dummy_con;
#endif
#endif
early_trap_init();//调用early_trap_init函数
}
1.1.early_trap_init主要挪移了中断向量表到特定位置
void __init early_trap_init(void)
{
unsigned long vectors = CONFIG_VECTORS_BASE; //0xffff0000
extern char __stubs_start[], __stubs_end[];
extern char __vectors_start[], __vectors_end[];
extern char __kuser_helper_start[], __kuser_helper_end[];
int kuser_sz = __kuser_helper_end - __kuser_helper_start;
memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); //移动中断向量表
memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); //移动__stubs_start段
memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz);
kuser_get_tls_init(vectors);
memcpy((void *)