diff --git a/IMX6ULL/doc_pic/08_Interrupt/11_异常向量表的安装与调用.md b/IMX6ULL/doc_pic/08_Interrupt/11_异常向量表的安装与调用.md new file mode 100644 index 0000000..8c9bfe6 --- /dev/null +++ b/IMX6ULL/doc_pic/08_Interrupt/11_异常向量表的安装与调用.md @@ -0,0 +1,107 @@ +## 异常向量表的安装与调用 + +### 1. 回顾中断的发生、处理过程 + +* 中断发生的硬件过程 + +![image-20210626114958795](pic/08_Interrupt/060_interrupt_flow.png) + + + +* 中断处理的软件处理流程 + * CPU执行完当前指令,检查到发生了中断,跳到向量表 + * 保存现场、执行GIC提供的处理函数、恢复现场 + + + +### 2. 异常向量表的安装 + +#### 2.1 复制向量表 + +* 汇编代码 + +```c +// arch\arm\kernel\head.S +1. bl __lookup_processor_type + ...... +2. bl __create_page_tables +3. ldr r13, =__mmap_switched +4. b __enable_mmu + b __turn_mmu_on + mov r3, r13 + ret r3 +5. __mmap_switched: // arch\arm\kernel\head-common.S +6. b start_kernel +``` + + + +* 复制向量表 + +```c +start_kernel // init\main.c + setup_arch(&command_line); // arch\arm\kernel\setup.c + paging_init(mdesc); // arch\arm\mm\mmu.c + devicemaps_init(mdesc); // arch\arm\mm\mmu.c + vectors = early_alloc(PAGE_SIZE * 2); // 1.分配新向量表 + early_trap_init(vectors); // 2.从代码把向量表复制到新向量表 + + // 3. 映射新向量表到虚拟地址0xffff0000 + /* + * Create a mapping for the machine vectors at the high-vectors + * location (0xffff0000). If we aren't using high-vectors, also + * create a mapping at the low-vectors virtual address. + */ + map.pfn = __phys_to_pfn(virt_to_phys(vectors)); + map.virtual = 0xffff0000; + map.length = PAGE_SIZE; + #ifdef CONFIG_KUSER_HELPERS + map.type = MT_HIGH_VECTORS; + #else + map.type = MT_LOW_VECTORS; + #endif + create_mapping(&map); +``` + +![image-20210626120817244](pic/08_Interrupt/061_copy_vectors.png) + +#### 2.2 向量表在哪 + +上面代码中可以看到代码中向量表位于`__vectors_start`,它在`arch/arm/kernel/vmlinux.lds`中定义: + +```shell + __vectors_start = .; + .vectors 0xffff0000 : AT(__vectors_start) { + *(.vectors) + } + . = __vectors_start + SIZEOF(.vectors); + __vectors_end = .; + __stubs_start = .; + .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) { + *(.stubs) + } +``` + +在代码里搜`.vectors`,可以找到向量表: + +![image-20210626124004537](pic/08_Interrupt/062_vectors_in_source.png) + +### 3. 中断向量 + +发生中断时,CPU跳到向量表去执行`b vector_irq`。 + +vector_irq函数使用宏来定义: + +![image-20210626125245059](pic/08_Interrupt/063_vector_irq.png) + + + +### 4. 处理流程 + +![image-20210626130003359](pic/08_Interrupt/064_handle_irq.png) + + + +### 5. 处理函数 + +![image-20210626130412855](pic/08_Interrupt/065_irq_handler.png) \ No newline at end of file diff --git a/IMX6ULL/doc_pic/08_Interrupt/12_GIC驱动程序分析.md b/IMX6ULL/doc_pic/08_Interrupt/12_GIC驱动程序分析.md new file mode 100644 index 0000000..90e42d4 --- /dev/null +++ b/IMX6ULL/doc_pic/08_Interrupt/12_GIC驱动程序分析.md @@ -0,0 +1,81 @@ +## GIC驱动程序分析 + +参考资料: + +* [linux kernel的中断子系统之(七):GIC代码分析](http://www.wowotech.net/irq_subsystem/gic_driver.html) + +### 1. 回顾 + + + +### 2. 函数调用过程 + +```c +start_kernel (init\main.c) + init_IRQ (arch\arm\kernel\irq.c) + irqchip_init (drivers\irqchip\irqchip.c) + of_irq_init (drivers\of\irq.c) + desc->irq_init_cb = match->data; + + ret = desc->irq_init_cb(desc->dev, + desc->interrupt_parent); + +``` + +#### 2.1 platform_driver支持多个device + +按照设备树的套路:驱动程序注册platform_driver,它的of_match_table里有多个of_device_id,表示能支持多个设备。 + +有多种版本的GIC,在内核为每一类GIC定义一个结构体of_device_id,并放在一个段里: + +```c +// drivers\irqchip\irq-gic.c +IRQCHIP_DECLARE(gic_400, "arm,gic-400", gic_of_init); +IRQCHIP_DECLARE(arm11mp_gic, "arm,arm11mp-gic", gic_of_init); +IRQCHIP_DECLARE(arm1176jzf_dc_gic, "arm,arm1176jzf-devchip-gic", gic_of_init); +IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init); +IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init); +IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init); +IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init); +IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init); +IRQCHIP_DECLARE(pl390, "arm,pl390", gic_of_init); +``` + +把宏`IRQCHIP_DECLARE`展开: + +```c +// include\linux\irqchip.h +#define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn) + +#define OF_DECLARE_2(table, name, compat, fn) \ + _OF_DECLARE(table, name, compat, fn, of_init_fn_2) + +#define _OF_DECLARE(table, name, compat, fn, fn_type) \ + static const struct of_device_id __of_table_##name \ + __used __section(__##table##_of_table) \ + = { .compatible = compat, \ + .data = (fn == (fn_type)NULL) ? fn : fn } +``` + +展开示例: + +```c +IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init); +展开后得到: +static const struct of_device_id __of_table_cortex_a7_gic \ + __used __section(__irqchip_of_table) \ + = { .compatible = "arm,cortex-a7-gic", \ + .data = gic_of_init } +``` + + + +#### 2.2 没有定义platform_driver但是套路一样 + +`drivers\irqchip\irqchip.c`中并没有定义一个platform_driver,但是套路是一样的。 + +![image-20210626083319383](pic/08_Interrupt/058_irqchip_init.png) + +调用过程: + +![image-20210626084850583](pic/08_Interrupt/059_gic_init.png) \ No newline at end of file diff --git a/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/058_irqchip_init.png b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/058_irqchip_init.png new file mode 100644 index 0000000..a863541 Binary files /dev/null and b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/058_irqchip_init.png differ diff --git a/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/059_gic_init.png b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/059_gic_init.png new file mode 100644 index 0000000..14f7a23 Binary files /dev/null and b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/059_gic_init.png differ diff --git a/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/060_interrupt_flow.png b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/060_interrupt_flow.png new file mode 100644 index 0000000..1b0cf11 Binary files /dev/null and b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/060_interrupt_flow.png differ diff --git a/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/061_copy_vectors.png b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/061_copy_vectors.png new file mode 100644 index 0000000..05a4042 Binary files /dev/null and b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/061_copy_vectors.png differ diff --git a/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/062_vectors_in_source.png b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/062_vectors_in_source.png new file mode 100644 index 0000000..114cb5f Binary files /dev/null and b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/062_vectors_in_source.png differ diff --git a/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/063_vector_irq.png b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/063_vector_irq.png new file mode 100644 index 0000000..bb3c451 Binary files /dev/null and b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/063_vector_irq.png differ diff --git a/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/064_handle_irq.png b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/064_handle_irq.png new file mode 100644 index 0000000..3bdc87a Binary files /dev/null and b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/064_handle_irq.png differ diff --git a/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/065_irq_handler.png b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/065_irq_handler.png new file mode 100644 index 0000000..e836ce3 Binary files /dev/null and b/IMX6ULL/doc_pic/08_Interrupt/pic/08_Interrupt/065_irq_handler.png differ diff --git a/README.md b/README.md index d87b6f6..9b48d8f 100644 --- a/README.md +++ b/README.md @@ -272,7 +272,11 @@ git clone https://e.coding.net/weidongshan/linux/doc_and_source_for_drivers.git 09_中断的硬件框架 10_GIC介绍与编程 ``` +* 2021.06.26 发布"Interrupt子系统" + ```shell + 11_异常向量表的安装与调用 + ``` diff --git a/STM32MP157/doc_pic/08_Interrupt/11_异常向量表的安装与调用.md b/STM32MP157/doc_pic/08_Interrupt/11_异常向量表的安装与调用.md new file mode 100644 index 0000000..8c9bfe6 --- /dev/null +++ b/STM32MP157/doc_pic/08_Interrupt/11_异常向量表的安装与调用.md @@ -0,0 +1,107 @@ +## 异常向量表的安装与调用 + +### 1. 回顾中断的发生、处理过程 + +* 中断发生的硬件过程 + +![image-20210626114958795](pic/08_Interrupt/060_interrupt_flow.png) + + + +* 中断处理的软件处理流程 + * CPU执行完当前指令,检查到发生了中断,跳到向量表 + * 保存现场、执行GIC提供的处理函数、恢复现场 + + + +### 2. 异常向量表的安装 + +#### 2.1 复制向量表 + +* 汇编代码 + +```c +// arch\arm\kernel\head.S +1. bl __lookup_processor_type + ...... +2. bl __create_page_tables +3. ldr r13, =__mmap_switched +4. b __enable_mmu + b __turn_mmu_on + mov r3, r13 + ret r3 +5. __mmap_switched: // arch\arm\kernel\head-common.S +6. b start_kernel +``` + + + +* 复制向量表 + +```c +start_kernel // init\main.c + setup_arch(&command_line); // arch\arm\kernel\setup.c + paging_init(mdesc); // arch\arm\mm\mmu.c + devicemaps_init(mdesc); // arch\arm\mm\mmu.c + vectors = early_alloc(PAGE_SIZE * 2); // 1.分配新向量表 + early_trap_init(vectors); // 2.从代码把向量表复制到新向量表 + + // 3. 映射新向量表到虚拟地址0xffff0000 + /* + * Create a mapping for the machine vectors at the high-vectors + * location (0xffff0000). If we aren't using high-vectors, also + * create a mapping at the low-vectors virtual address. + */ + map.pfn = __phys_to_pfn(virt_to_phys(vectors)); + map.virtual = 0xffff0000; + map.length = PAGE_SIZE; + #ifdef CONFIG_KUSER_HELPERS + map.type = MT_HIGH_VECTORS; + #else + map.type = MT_LOW_VECTORS; + #endif + create_mapping(&map); +``` + +![image-20210626120817244](pic/08_Interrupt/061_copy_vectors.png) + +#### 2.2 向量表在哪 + +上面代码中可以看到代码中向量表位于`__vectors_start`,它在`arch/arm/kernel/vmlinux.lds`中定义: + +```shell + __vectors_start = .; + .vectors 0xffff0000 : AT(__vectors_start) { + *(.vectors) + } + . = __vectors_start + SIZEOF(.vectors); + __vectors_end = .; + __stubs_start = .; + .stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) { + *(.stubs) + } +``` + +在代码里搜`.vectors`,可以找到向量表: + +![image-20210626124004537](pic/08_Interrupt/062_vectors_in_source.png) + +### 3. 中断向量 + +发生中断时,CPU跳到向量表去执行`b vector_irq`。 + +vector_irq函数使用宏来定义: + +![image-20210626125245059](pic/08_Interrupt/063_vector_irq.png) + + + +### 4. 处理流程 + +![image-20210626130003359](pic/08_Interrupt/064_handle_irq.png) + + + +### 5. 处理函数 + +![image-20210626130412855](pic/08_Interrupt/065_irq_handler.png) \ No newline at end of file diff --git a/STM32MP157/doc_pic/08_Interrupt/12_GIC驱动程序分析.md b/STM32MP157/doc_pic/08_Interrupt/12_GIC驱动程序分析.md new file mode 100644 index 0000000..90e42d4 --- /dev/null +++ b/STM32MP157/doc_pic/08_Interrupt/12_GIC驱动程序分析.md @@ -0,0 +1,81 @@ +## GIC驱动程序分析 + +参考资料: + +* [linux kernel的中断子系统之(七):GIC代码分析](http://www.wowotech.net/irq_subsystem/gic_driver.html) + +### 1. 回顾 + + + +### 2. 函数调用过程 + +```c +start_kernel (init\main.c) + init_IRQ (arch\arm\kernel\irq.c) + irqchip_init (drivers\irqchip\irqchip.c) + of_irq_init (drivers\of\irq.c) + desc->irq_init_cb = match->data; + + ret = desc->irq_init_cb(desc->dev, + desc->interrupt_parent); + +``` + +#### 2.1 platform_driver支持多个device + +按照设备树的套路:驱动程序注册platform_driver,它的of_match_table里有多个of_device_id,表示能支持多个设备。 + +有多种版本的GIC,在内核为每一类GIC定义一个结构体of_device_id,并放在一个段里: + +```c +// drivers\irqchip\irq-gic.c +IRQCHIP_DECLARE(gic_400, "arm,gic-400", gic_of_init); +IRQCHIP_DECLARE(arm11mp_gic, "arm,arm11mp-gic", gic_of_init); +IRQCHIP_DECLARE(arm1176jzf_dc_gic, "arm,arm1176jzf-devchip-gic", gic_of_init); +IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init); +IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init); +IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init); +IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init); +IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init); +IRQCHIP_DECLARE(pl390, "arm,pl390", gic_of_init); +``` + +把宏`IRQCHIP_DECLARE`展开: + +```c +// include\linux\irqchip.h +#define IRQCHIP_DECLARE(name, compat, fn) OF_DECLARE_2(irqchip, name, compat, fn) + +#define OF_DECLARE_2(table, name, compat, fn) \ + _OF_DECLARE(table, name, compat, fn, of_init_fn_2) + +#define _OF_DECLARE(table, name, compat, fn, fn_type) \ + static const struct of_device_id __of_table_##name \ + __used __section(__##table##_of_table) \ + = { .compatible = compat, \ + .data = (fn == (fn_type)NULL) ? fn : fn } +``` + +展开示例: + +```c +IRQCHIP_DECLARE(cortex_a7_gic, "arm,cortex-a7-gic", gic_of_init); +展开后得到: +static const struct of_device_id __of_table_cortex_a7_gic \ + __used __section(__irqchip_of_table) \ + = { .compatible = "arm,cortex-a7-gic", \ + .data = gic_of_init } +``` + + + +#### 2.2 没有定义platform_driver但是套路一样 + +`drivers\irqchip\irqchip.c`中并没有定义一个platform_driver,但是套路是一样的。 + +![image-20210626083319383](pic/08_Interrupt/058_irqchip_init.png) + +调用过程: + +![image-20210626084850583](pic/08_Interrupt/059_gic_init.png) \ No newline at end of file diff --git a/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/058_irqchip_init.png b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/058_irqchip_init.png new file mode 100644 index 0000000..a863541 Binary files /dev/null and b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/058_irqchip_init.png differ diff --git a/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/059_gic_init.png b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/059_gic_init.png new file mode 100644 index 0000000..14f7a23 Binary files /dev/null and b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/059_gic_init.png differ diff --git a/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/060_interrupt_flow.png b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/060_interrupt_flow.png new file mode 100644 index 0000000..1b0cf11 Binary files /dev/null and b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/060_interrupt_flow.png differ diff --git a/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/061_copy_vectors.png b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/061_copy_vectors.png new file mode 100644 index 0000000..05a4042 Binary files /dev/null and b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/061_copy_vectors.png differ diff --git a/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/062_vectors_in_source.png b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/062_vectors_in_source.png new file mode 100644 index 0000000..114cb5f Binary files /dev/null and b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/062_vectors_in_source.png differ diff --git a/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/063_vector_irq.png b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/063_vector_irq.png new file mode 100644 index 0000000..bb3c451 Binary files /dev/null and b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/063_vector_irq.png differ diff --git a/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/064_handle_irq.png b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/064_handle_irq.png new file mode 100644 index 0000000..3bdc87a Binary files /dev/null and b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/064_handle_irq.png differ diff --git a/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/065_irq_handler.png b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/065_irq_handler.png new file mode 100644 index 0000000..e836ce3 Binary files /dev/null and b/STM32MP157/doc_pic/08_Interrupt/pic/08_Interrupt/065_irq_handler.png differ