在上一节编写完成中断向量表后,这一节就开始配置具体的IRQ的中断服务函数
在嵌入式系统或微控制器的编程中,特别是在启动代码(如启动文件或复位中断服务例程)中,处理全局中断(也称为全局中断使能或中断屏蔽位)的方式对于系统的稳定性和可靠性至关重要
首先在复位中断函数中,关闭全局中断
Reset_Handler:
cpsid i /*关闭全局中断 */
MRC p15, 0, r0, c1, c0, 0
bic r0 , r0, #(0x1 << 12) /*关闭Icache*/
bic r0 , r0 ,#(0x1 << 11) /*关闭分支预测 */
bic r0 , r0 ,#(0x1 << 2) /*关闭Dcache */
bic r0 , r0 ,#( 1 << 1) /*关闭对齐 */
bic r0 , r0 ,#( 1 << 0) /*关闭MMU */
MCR p15, 0 , r0, c1, c0, 0
然后再在进入main函数之前,再次打开全局中断
/* 进入SVC模式 */
mrs r0, cpsr
bic r0, r0, #0x1f /* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 */
orr r0, r0, #0x13 /* r0或上0x13,表示使用SVC模式 */
msr cpsr, r0 /* 将r0 的数据写入到cpsr_c中 */
ldr sp,=0X80200000 /* 设置用户模式下的栈首地址为0X80200000,大小为2MB */
cpsie i
b main /* 跳转到main函数 */
首先,需要了解什么是全局中断,,全局中断是指通过控制一个特定的使能位(或者寄存器)来影响系统对所有中断请求的响应能力。当全局中断被关闭时,系系统将不会响应任何中断请求,即使这些请求被我们配置或者使能。然而如果全局中断被打开时,系统能够正常地响应和处理中断请求
复位中断是系统启动时首先执行的中断服务例程,用于进行系统的初始化。这个时候关闭全局中断,在复位中断服务函数执行期间,系统正在进行关键的初始化操作,如时钟配置、内存初始化等。如果此时允许中断,中断服务例程可能会与初始化代码产生冲突,导致初始化失败或系统状态不一致。
然后要在程序进入主函数之前重新打开,全局中断函数
在之后,出发的所有中断都是在IRQ的中断服务函数中执行,所以现在就要开始编写IRQ中断服务函数,
IRQ_Handler:
push, {lr} /*保存lr的地址 */
push, {r0-r3, r12}
首先lr指令(Link Register,叫做链接寄存器),push在英文当中也是推、压的意思,所以可以理解位将lr的值压入堆栈中。在我们ARM架构中,lr寄存器用于存储函数调用或中断发生前的返回地址。当从中断处理程序中返回时,这个地址会被用来继续执行被中断的代码。保存lr是为了在中断处理完成后,程序能够正确地返回到原来的执行点
然后下一条,这条指令将多个寄存器的值压入堆栈中,具体是r0到r3以及r12。这些寄存器在ARM架构中常用于存储函数的参数、返回值和局部变量。可能唯一需要注意的就是这里里面ARM寄存器应该是从r0-r15但是这里为什么只存入了r0-r3和r12,因为其余的寄存器都是它自动将其保存在了栈中,而没有保存的,我们在上面才将其用手动的方式保存
然后这里先读取CPSR的寄存器,然后同样将他的值存入到R0中,SPSR一个特殊的寄存器,用于在发生异常(如中断)时保存当前程序状态寄存器(CPSR, Current Program Status Register)的内容。CPSR 包含了当前处理器的状态信息,如条件码(如N、Z、C、V标志)、中断禁止位、模式控制位等。
因此,mrs r0, spsr 这条指令的目的是在发生异常处理之前(或之后,具体取决于上下文),将当前保存的处理器状态信息(即之前CPSR的内容)读取到 r0 寄存器中,以便后续可以对其进行检查或修改。
同样堆栈常用于通常用于保存临时数据、寄存器或者控制程序的执行流程,这里将之前通过MRS的指令从SPSR读取的值压入当前活动的堆栈中在ARM中通常与堆栈指针(SP, Stack Pointer)寄存器相关联。在执行 push {r0} 指令时,SP寄存器的值会自动减少(向下增长),以在堆栈上为新数据腾出空间,然后 r0 寄存器的值被写入到这个新分配的堆栈位置。
所以新增的两端代码则表示,将从SPSR寄存器中读取的处理器状态信息保存到 r0 寄存器中,然后将这个信息压入堆栈。用于保存异常发生前的处理器状态,以便在异常处理完成后能够恢复执行。
IRQ_Handler:
push {lr} /*保存lr的地址 */
push {r0-r3, r12}
mrs r0, spsr
push {r0}
接下来我们要读取下面的,CP15的CBAR寄存器,还是需要了解什么是CBAR,点击下面的蓝色链接跳转

CBAR寄存器(Coprocessor Barrier Address Register),它是协处理器(Coprocessor)的一个特殊寄存器,用于存储中断控制器(GIC,Generic Interrupt Controller)寄存器组的物理地址(或基地址)

GIC寄存器组偏移0x1000-0x10FFF是分发器,0x2000-0x3FFF对应GIC组中的CPU接口端,知道了这些那有什么作用呢,意味着我们就可以访问GIC控制器了
其实总结回来就是,CPU需要通过CBAR寄存器来获取GIC(或类似的中断控制器)的基地址。这个基地址是访问GIC寄存器组所有其他寄存器(如分发器、CPU接口端等)的起点,在进行中断处理时,CPU会首先从CBAR寄存器中读取GIC的基地址。
然后,CPU会根据这个基地址加上适当的偏移量来访问GIC寄存器组中的其他寄存器,目前大概流程
1. 就是当一个中断发生时,CPU会跳转到中断向量表,并执行相应的中断服务例程(ISR)
2. 在ISR中,CPU首先会从CBAR寄存器中读取GIC的基地址。
3. 接着,CPU会从GICC_IAR寄存器中读取中断ID,以确定是哪个中断源触发了中断。
4. 处理完中断后,CPU会将中断ID写入GICC_EOIR寄存器,以标记该中断已被处理

最低0.47元/天 解锁文章
2098

被折叠的 条评论
为什么被折叠?



