单片机
返回首页

Linux-3.0.8中基于S5PV210的IRQ模块代码追踪和分析

2025-01-24 来源:cnblogs

init/main.c:


1 asmlinkage void start_kernel(void)

2 {

3     ......

4     early_irq_init();

5     init_IRQ();

6     ......

7 }


early_irq_init()函数有两种实现,一种是基于radix tree,一种是定义静态数组,如果要使用radix tree实现的,那么需要打开SPARSE_IRQ配置选项,由于我对数据结构不了解,所以分析以下静态数组实现方式版本的。


/kernel/irq/irqdesc.c


 1 struct irq_desc irq_desc[NR_IRQS] __cacheline_aligned_in_smp = {

 2     [0 ... NR_IRQS-1] = {

 3         .handle_irq    = handle_bad_irq,

 4         .depth        = 1,

 5         .lock        = __RAW_SPIN_LOCK_UNLOCKED(irq_desc->lock),

 6     }

 7 };

 8 

 9 int __init early_irq_init(void)

10 {

11     int count, i, node = first_online_node;

12     struct irq_desc *desc;

13 

14     init_irq_default_affinity();

15 

16     printk(KERN_INFO 'NR_IRQS:%dn', NR_IRQS);

17 

18     desc = irq_desc;

19     count = ARRAY_SIZE(irq_desc);

20 

21     for (i = 0; i < count; i++) {

22         desc[i].kstat_irqs = alloc_percpu(unsigned int);

23         alloc_masks(&desc[i], GFP_KERNEL, node);

24         raw_spin_lock_init(&desc[i].lock);

25         lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);

26         desc_set_defaults(i, &desc[i], node);

27     }

28     return arch_early_irq_init();

29 }


  第一次见到这种初始化数组全部成员为同样内容的方式,可以学习积累下。


  NR_IRQS在arch/arm/mach-s5pv210/include/mach/irqs.h下定义:


1 #define NR_IRQS            (IRQ_EINT(31) + S5P_GPIOINT_COUNT + 1)

  上面函数的核心就是调用desc_set_defaults()来初始化上述中断描述符数组,kernel/irq/irqdesc.c:


 1 static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)

 2 {

 3     int cpu;

 4 

 5     desc->irq_data.irq = irq;

 6     desc->irq_data.chip = &no_irq_chip;

 7     desc->irq_data.chip_data = NULL;

 8     desc->irq_data.handler_data = NULL;

 9     desc->irq_data.msi_desc = NULL;

10     irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS);

11     irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED);

12     desc->handle_irq = handle_bad_irq;

13     desc->depth = 1;

14     desc->irq_count = 0;

15     desc->irqs_unhandled = 0;

16     desc->name = NULL;

17     for_each_possible_cpu(cpu)

18         *per_cpu_ptr(desc->kstat_irqs, cpu) = 0;

19     desc_smp_init(desc, node);

20 }


  最后返回时调用的arch_early_irq_init()函数并没有做事情。


  接着看init_IRQ():


1 void __init init_IRQ(void)

2 {

3     machine_desc->init_irq();

4 }

  machine_desc是全局变量,定义在板文件中,由于我们使用的是s5pv210,且demo板号选的是smdkv210,所以这个全局变量就在arch/arm/mach-s5pv210/mach-s5pv210.c中:


1 MACHINE_START(SMDKV210, 'SMDKV210')

2     /* Maintainer: Kukjin Kim */

3     .boot_params    = S5P_PA_SDRAM + 0x100,

4     .init_irq    = s5pv210_init_irq,

5     .map_io        = smdkv210_map_io,

6     .init_machine    = smdkv210_machine_init,

7     .timer        = &s5p_timer,

8 MACHINE_END


arch/arm/mach-s5pv210/mach-s5pv210.c中还有如下函数定义:


 1 void __init s5pv210_init_irq(void)

 2 {

 3     u32 vic[4];    /* S5PV210 supports 4 VIC */

 4 

 5     /* All the VICs are fully populated. */

 6     vic[0] = ~0;

 7     vic[1] = ~0;

 8     vic[2] = ~0;

 9     vic[3] = ~0;

10 

11     s5p_init_irq(vic, ARRAY_SIZE(vic));

12 }


arch/arm/plat-s5p/irq.c


 1 void __init s5p_init_irq(u32 *vic, u32 num_vic)

 2 {

 3 #ifdef CONFIG_ARM_VIC

 4     int irq;

 5 

 6     /* initialize the VICs */

 7     for (irq = 0; irq < num_vic; irq++)

 8         vic_init(VA_VIC(irq), VIC_BASE(irq), vic[irq], 0);

 9 #endif

10 

11     s3c_init_vic_timer_irq(5, IRQ_TIMER0);

12 

13     s3c_init_uart_irqs(uart_irqs, ARRAY_SIZE(uart_irqs));

14 }


  上面涉及到的函数都是去操作VIC相关的寄存器,这部分操作还不是很清楚,先不往下继续追踪了。


进入单片机查看更多内容>>
相关视频
  • 【TI MSPM0 应用实战】智能小车+工业角度编码器+血氧仪+烟雾探测器!硬核参考设计详解!

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

  • 直播回放: Microchip Timberwolf™ 音频处理器在线研讨会

  • 基于灵动MM32W0系列MCU的指夹血氧仪控制及OTA升级应用方案分享

精选电路图
  • 1瓦线性调频增强器

  • 1瓦四级调频发射机

  • 500W MOS场效应管电源逆变器,12V转110V/220V

  • 红外开关

  • LM317过压保护

  • 0-30V/20A 大功率稳压电源(采用LM338)

    相关电子头条文章