文章目录
- 1. 复位中断服务函数
- 0.1 禁止IRQ中断
- 0.1.1 方式
- 0.1.2 代码
- 0.1.3 缩写说明
- 0.1.4 PSTATE寄存器简介
- 0.1.5 禁止IRQ中断的目的
- 1.1 关闭I/D Cache, MMU
- 1.1.1 方式
- 1.1.2 代码
- 1.1.3 缩写说明
- 1.1.4 关闭I/D Cache, MMU的目的
- 2.2 设置中断向量偏移
- 2.2.1 方式
- 2.2.2 代码
- 2.2.3 缩写说明
- 2.2.4 设置中断向量偏移的目的
- 3.1 清除bss段
- 3.1.1 方式
- 3.1.2 代码
- 3.1.3 缩写说明
- 3.1.4 bss段简介
- 3.1.5 清除bss段的目的
- 4.1 设置处理器进入IRQ模式
- 4.1.1 方式
- 4.1.2 代码
- 4.1.3 缩写说明
- 4.1.4 CPSR寄存器简介
- 4.1.5 设置处理器进入IRQ模式的目的
- 5.1 设置处理器进入SYS模式
- 6.1 设置处理器进入SVC模式
- 7.1 使能IRQ中断
- 7.1.1 方式
- 7.1.2 代码
- 7.1.3 缩写说明
- 7.1.4 PSTATE寄存器简介
- 7.1.5 使能IRQ中断的目的
- 8.1 跳转到main函数的入口
- 8.1.1 代码
- 8.1.2 缩写说明
- 8.1.3 主函数跳转的目的
- 9.1 完整代码
本文章结合了正点原子的 i.mx6u嵌入式Linux开发指南和笔者的理解。
1. 复位中断服务函数
0.1 禁止IRQ中断
0.1.1 方式
- 方式:修改PSTATE处理器状态寄存器
- PSTATE 是一个特殊的寄存器,它包含了处理器当前的运行状态信息。
0.1.2 代码
cpsid i @ 禁止IRQ中断
0.1.3 缩写说明
- PSTATE: Processor State 寄存器,包含处理器当前的运行状态信息。
- cpsid: Change Processor State Disable 中断禁用状态修改指令
i
: 代表禁用IRQ中断
0.1.4 PSTATE寄存器简介
- A (Application) 位:控制应用程序模式下的中断是否允许。
- I (IRQ) 位:控制 IRQ 中断是否允许。
- F (FIQ) 位:控制 FIQ 中断是否允许。
- M (Mode) 位:控制处理器当前运行的模式。
0.1.5 禁止IRQ中断的目的
- 在进行关键的系统配置或者在特定的操作期间,禁用IRQ中断可以防止中断处理程序干扰或者修改正在执行的敏感操作。
- 确保在执行某些关键代码段时系统的稳定性和可预测性,例如系统初始化、关键数据结构的更新等。
- 通过禁用中断,可以简化程序的设计和调试,因为它减少了并发执行和竞态条件的复杂性。
1.1 关闭I/D Cache, MMU
1.1.1 方式
- 方式:修改SCTLR寄存器(System Control Register,可以通过 CP15 协处理器访问)
- SCTLR寄存器:
@ bit0:MMU
@ bit1:对齐控制
@ bit2:D Cache
@ bit11:分支预测控制
@ bit12:I Cache
- SCTLR寄存器:
1.1.2 代码
MRC p15, 0, r0, c1, c0, 0 @ Move to Register from Coprocessor(这个形式操作的是SCTLR寄存器)bic r0, r0, #(1<<12) @ 关闭I Cache(bic:Bit Clear)bic r0, r0, #(1<<11) @ 关闭分支预测bic r0, r0, #(1<<2) @ 关闭D Cachebic r0, r0, #(1<<1) @ 关闭对齐控制bic r0, r0, #(1<<0) @ 关闭MMUMCR p15, 0, r0, c1, c0, 0 @ Move to Coprocessor from Register
1.1.3 缩写说明
- SCTLR: System Control Register 系统控制寄存器,可以通过 CP15 协处理器访问
- MRC: Move to general-purpose register from System register 从系统寄存器读到通用目的寄存器中
- MCR: Move to System register from general-purpose register or execute a System instruction 从通用寄存器移到系统寄存器或执行系统指令
- bic: Bit Clear 清除特定比特位
- MMU: Memory Management Unit 的缩写,中文意思是内存管理单元
- I/D Cache: Instruction Cache and Data Cache 它们是处理器中用来加速指令和数据访问的内存
- CP15: coprocessor15 用于控制和配置ARM处理器系统,包括架构和功能识别
1.1.4 关闭I/D Cache, MMU的目的
- 编写 i.MX6ULL 的复位中断服务函数时,要先关闭 I/D Cache 和 MMU,是为了确保系统在启动时处于一个干净的状态。
- 因为在复位之后,系统处于一个未知的状态,缓存和 MMU 可能保存着之前运行程序的残留数据,这会导致系统运行不稳定。
- 关闭 I/D Cache 和 MMU 可以清除这些残留数据,确保系统从一个干净的状态开始运行。
- 此外,关闭 I/D Cache 和 MMU 可以避免在启动过程中出现一些潜在的问题,例如缓存一致性问题。
2.2 设置中断向量偏移
2.2.1 方式
- 方式:修改VBAR寄存器(Vector Base Address Register,可以通过 CP15 协处理器访问)
2.2.2 代码
ldr r0, =0x87800000 @ 加载中断向量表的基地址到寄存器r0dsb @ Data Synchronization Barrier 数据同步屏障isb @ Instruction Synchronization Barrier 指令同步屏障MCR p15, 0, r0, c12, c0, 0 @ 设置VBAR寄存器为0x87800000dsb @ Data Synchronization Barrier 数据同步屏障isb @ Instruction Synchronization Barrier 指令同步屏障
2.2.3 缩写说明
- VBAR: Vector Base Address Register 矢量基地址寄存器,用于设置中断向量表的基地址
- MCR: Move to System register from general-purpose register or execute a System instruction 从通用寄存器移到系统寄存器或执行系统指令
- ldr: Load Register 加载寄存器
- dsb: Data Synchronization Barrier 数据同步屏障,保证之前的存储操作完成后才执行后续的操作
- isb: Instruction Synchronization Barrier 指令同步屏障,保证之前的指令执行完成后才开始执行后续的指令
- CP15: coprocessor15 用于控制和配置ARM处理器系统,包括架构和功能识别
2.2.4 设置中断向量偏移的目的
- 在处理器启动或系统重配置过程中,需要设置中断向量表的基地址,以便处理器在接收到中断时能够正确跳转到适当的处理代码。
- 使用VBAR寄存器来设置中断向量表的基地址,可以灵活地根据系统的需要调整中断处理程序的位置。
- 在设置VBAR之前后使用
dsb
和isb
确保任何之前的操作完成并且之后的指令加载更新后的信息,这是确保系统稳定性和一致性的关键步骤。 - 这样做可以确保系统在处理中断时的响应更加迅速和可靠。
3.1 清除bss段
3.1.1 方式
- 方式:使用循环逐个清除
3.1.2 代码
ldr r0, _bss_start @ 将_bss_start地址加载到r0寄存器ldr r1, _bss_end @ 将_bss_end地址加载到r1寄存器mov r2, #0 @ 将0存储到r2寄存器
bss_loop:stmia r0!, {r2} @ 存储r2寄存器的值到r0指向的内存地址,并自增r0cmp r0, r1 @ 比较r0和r1的值ble bss_loop @ 如果r0小于等于r1,则跳转到bss_loop标签继续循环
3.1.3 缩写说明
- ldr: Load Register,从内存加载数据到寄存器。
- mov: Move,将立即数或寄存器值移动到另一个寄存器。
- stmia: Store Multiple Increment After,存储多个寄存器的内容到内存,并在存储后地址自增。
- cmp: Compare,比较两个寄存器的值。
- ble: Branch if Less than or Equal,如果第一个操作数小于或等于第二个操作数,则跳转到指定标签。
3.1.4 bss段简介
- bss段(Block Started by Symbol)是程序编译后生成的一个内存区域,用于存放程序中未初始化的全局变量和静态变量。
- 在程序启动时,bss段需要被清零,以确保所有未初始化的变量从一个固定的基线开始,避免出现随机数据导致程序行为不可预测。
3.1.5 清除bss段的目的
- 程序执行前清零bss段是为了初始化所有未初始化的全局变量和静态变量,确保它们从0开始。
- 这一步是重要的初始化过程,帮助防止程序在运行时遇到不确定的状态,增强程序的稳定性和可靠性。
- 通过逐个内存地址清零,保证了bss段内的每个变量都被正确初始化。
4.1 设置处理器进入IRQ模式
4.1.1 方式
- 修改cpsr寄存器(Current Program Status Register,当前程序状态寄存器)
4.1.2 代码
mrs r0, cpsr @ 读取CPSR寄存器的值到r0寄存器bic r0, r0, #0x1f @ 通过位清除操作,清除r0寄存器的低5位orr r0, r0, #0x12 @ 将r0寄存器的值设置为IRQ模式msr cpsr, r0 @ 将r0寄存器的值写回CPSR寄存器ldr sp, =0x80600000 @ 设置IRQ下的sp栈指针
4.1.3 缩写说明
- mrs: Move from Special register,从特殊寄存器(如CPSR)移动数据到通用寄存器。
- bic: Bit Clear,对寄存器值进行位清除操作。
- orr: Logical inclusive OR,对寄存器值进行逻辑包含或操作。
- msr: Move to Special register,将数据从通用寄存器移动到特殊寄存器(如CPSR)。
- ldr: Load Register,从内存加载数据到寄存器。
4.1.4 CPSR寄存器简介
- CPSR(Current Program Status Register)包含了处理器状态和控制信息,例如:
- APSR(Application Program Status Register):应用程序状态寄存器,包含条件标志等。
- 指令集状态
- IT块状态
- 字节序
- 当前处理器模式。
4.1.5 设置处理器进入IRQ模式的目的
- 在IRQ(中断请求)模式下,处理器能响应外部或硬件触发的中断。
- 通过设置特定模式的栈指针,可以确保中断处理过程中的数据独立于其他模式,提高中断处理的效率和安全。
- 清除CPSR的低5位并设置为IRQ模式,是为了确保处理器切换到正确的操作模式来处理即将到来的中断。这种模式切换是必要的,以便在处理外部中断时保持系统的稳定和响应。
5.1 设置处理器进入SYS模式
与4的代码基本相同
6.1 设置处理器进入SVC模式
与4的代码基本相同
7.1 使能IRQ中断
7.1.1 方式
- 修改PSTATE处理器状态寄存器
7.1.2 代码
cpsie i @ 使能IRQ中断
7.1.3 缩写说明
- cpsie: Change Processor State Enable - 用于使能处理器状态寄存器中的某些位。
- i: 表示具体操作的是I(IRQ)位。
7.1.4 PSTATE寄存器简介
- PSTATE(Processor State Register)是一个特殊寄存器,包含了处理器当前的运行状态信息:
- A (Application) 位:控制应用程序模式下的中断是否允许。
- I (IRQ) 位:控制 IRQ 中断是否允许。
- F (FIQ) 位:控制 FIQ 中断是否允许。
- M (Mode) 位:控制处理器当前运行的模式。
7.1.5 使能IRQ中断的目的
- 通过使能IRQ中断,处理器可以响应外部或硬件触发的中断请求。
- 这是一种重要的系统功能,允许操作系统或应用程序有效地处理异步事件,如硬件设备的信号。
- 保持系统的响应性和功能性,确保在关键时刻可以处理外部事件。
8.1 跳转到main函数的入口
8.1.1 代码
b main @ 跳转到main函数的入口
8.1.2 缩写说明
- b: Branch - 跳转指令,用于无条件跳转到指定的标签或地址。
8.1.3 主函数跳转的目的
- main函数通常是程序的入口点,在完成了初步的系统设置和环境准备后,跳转到main函数开始执行程序的主体部分。
- 这标志着从低级的启动代码(如引导或初始化代码)到高级应用逻辑的过渡,允许程序开始执行其核心功能。
9.1 完整代码
@ 复位中断服务函数
Reset_Handler:@ 0.禁止IRQ中断@ 方式:修改PSTATE处理器状态寄存器@ Change PE State (CPS) 用于修改处理器状态寄存器 (PSTATE) 中的某些位@ PSTATE 是一个特殊的寄存器,它包含了处理器当前的运行状态信息,包括:@ A (Application) 位: 控制应用程序模式下的中断是否允许。@ I (IRQ) 位: 控制 IRQ 中断是否允许。@ F (FIQ) 位: 控制 FIQ 中断是否允许。@ M (Mode) 位: 控制处理器当前运行的模式。cpsid i@ 1.关闭I/D Cache, MMU@ 方式:修改SCTLR寄存器@ (System Control Register,可以通过 CP15 协处理器访问)@ SCTLR寄存器:@ bit0:MMU @ bit1:对齐控制 @ bit2:D Cache @ bit11:分支预测控制 @ bit12:I CacheMRC p15, 0, r0, c1, c0, 0 @ Move to Register from Coprocessor(这个形式操作的是SCTLR寄存器)bic r0, r0, #(1<<12) @ 关闭I Cache(bic:Bit Clear)bic r0, r0, #(1<<11) @ 关闭分支预测bic r0, r0, #(1<<2) @ 关闭D Cachebic r0, r0, #(1<<1) @ 关闭对齐控制bic r0, r0, #(1<<0) @ 关闭MMUMCR p15, 0, r0, c1, c0, 0 @ Move to Coprocessor from Register@ 2.设置中断向量偏移@ 方式:修改VBAR寄存器@ (Vector Base Address Register,可以通过 CP15 协处理器访问)ldr r0, =0x87800000dsbisbMCR p15, 0, r0, c12, c0, 0 @ 设置VBAR寄存器为0x87800000dsbisb@ 3.清除bss段@ 方式:使用循环逐个清除ldr r0, _bss_start @ 将_bss_start地址加载到r0寄存器ldr r1, _bss_end @ 将_bss_end地址加载到r1寄存器mov r2, #0 @ 将0存储到r2寄存器
bss_loop:stmia r0!, {r2} @ 存储r2寄存器的值到r0指向的内存地址,并自增r0cmp r0, r1 @ 比较r0和r1的值ble bss_loop @ 如果r0小于等于r1,则跳转到bss_loop标签(继续循环)@ 4.设置处理器进入IRQ模式@ 方式:修改cpsr寄存器@ (Current Program Status Register,当前程序状态寄存器)@ 它包含了处理器状态和控制信息,例如 APSR、指令集状态、IT 块状态、字节序和当前处理器模式。 mrs r0, cpsr @ 读取CPSR寄存器的值到r0寄存器bic r0, r0, #0x1f @ 通过位清除操作,清除r0寄存器的低5位orr r0, r0, #0x12 @ 使用IRQ模式msr cpsr, r0 @ 将r0寄存器的值写回CPSR寄存器ldr sp, =0x80600000 @ 设置IRQ下的sp指针@ 5.设置处理器进入SYS模式@ 方式:修改cpsr寄存器@ (Current Program Status Register,当前程序状态寄存器)@ 它包含了处理器状态和控制信息,例如 APSR、指令集状态、IT 块状态、字节序和当前处理器模式。 mrs r0, cpsr @ 读取CPSR寄存器的值到r0寄存器bic r0, r0, #0x1f @ 通过位清除操作,清除r0寄存器的低5位orr r0, r0, #0x1f @ 使用SYS模式msr cpsr, r0 @ 将r0寄存器的值写回CPSR寄存器ldr sp, =0x80400000 @ 设置SYS下的sp指针@ 6.设置处理器进入SVC模式@ 方式:修改cpsr寄存器@ (Current Program Status Register,当前程序状态寄存器)@ 它包含了处理器状态和控制信息,例如 APSR、指令集状态、IT 块状态、字节序和当前处理器模式。 mrs r0, cpsr @ 读取CPSR寄存器的值到r0寄存器bic r0, r0, #0x1f @ 通过位清除操作,清除r0寄存器的低5位orr r0, r0, #0x13 @ 使用SVC模式msr cpsr, r0 @ 将r0寄存器的值写回CPSR寄存器ldr sp, =0x80200000 @ 设置SVC下的sp指针@ 7.使能IRQ中断@ 方式:修改PSTATE处理器状态寄存器@ Change PE State (CPS) 用于修改处理器状态寄存器 (PSTATE) 中的某些位@ PSTATE 是一个特殊的寄存器,它包含了处理器当前的运行状态信息,包括:@ A (Application) 位: 控制应用程序模式下的中断是否允许。@ I (IRQ) 位: 控制 IRQ 中断是否允许。@ F (FIQ) 位: 控制 FIQ 中断是否允许。@ M (Mode) 位: 控制处理器当前运行的模式。cpsie i@ 8.跳转到main函数的入口b main @ 跳转到main函数的入口