【嵌入式Linux】i.MX6ULL 复位中断服务函数的编写


本文章结合了正点原子的 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

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 Cache
    bic r0, r0, #(1<<1)         @ 关闭对齐控制
    bic r0, r0, #(1<<0)         @ 关闭MMU
    MCR 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          @ 加载中断向量表的基地址到寄存器r0
    dsb                         @ Data Synchronization Barrier 数据同步屏障
    isb                         @ Instruction Synchronization Barrier 指令同步屏障
    MCR p15, 0, r0, c12, c0, 0  @ 设置VBAR寄存器为0x87800000
    dsb                         @ 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之前后使用dsbisb确保任何之前的操作完成并且之后的指令加载更新后的信息,这是确保系统稳定性和一致性的关键步骤。
  • 这样做可以确保系统在处理中断时的响应更加迅速和可靠。

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指向的内存地址,并自增r0
    cmp 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 Cache
    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 Cache
    bic r0, r0, #(1<<1)         @ 关闭对齐控制
    bic r0, r0, #(1<<0)         @ 关闭MMU
    MCR p15, 0, r0, c1, c0, 0   @ Move to Coprocessor from Register

    @ 2.设置中断向量偏移
    @ 方式:修改VBAR寄存器
    @ (Vector Base Address Register,可以通过 CP15 协处理器访问)
    ldr r0, =0x87800000
    dsb
    isb
    MCR p15, 0, r0, c12, c0, 0  @ 设置VBAR寄存器为0x87800000
    dsb
    isb

    @ 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指向的内存地址,并自增r0
    cmp 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函数的入口
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

__Witheart__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值