ATMEL精妙的IRQ中断处理过程
A: 从栈地址开始,栈顶为AT91SAM7S64的16K片内RAM尽头0x00204000
IRQ_STACK_SIZE =
3*8*4
FIQ_STACK_SIZE = 0x004
ABT_STACK_SIZE = 0x004
UND_STACK_SIZE =
0x004
SVC_STACK_SIZE = 0x800
SYS_STACK_SIZE =
0x400
irq栈为什么用3*8*4=96B呢?因为irq最多8级嵌套,ARM字长4B,而3,是由于每次进栈均破坏了3个寄存器r0、spsr、lr,所以需要压栈保存的也就是3。计算十分精准,没有一个字浪费,这是AT第一牛X的地方。
当irq发生时,下列操作处理器自动完成:
1。r14(irq)=返回地址
2。spsr(irq)=cpsr(中断发生前的模式)
3。改cpsr,成模式为irq,禁止irq中断。
4。设pc,跳转到0x00000018去
下面看中断0x00000018指向的irq_handle代码:
;因为要继续调用函数,lr会被冲掉,所以压irq栈
sub
lr,lr,#4
stmfd sp!,{lr}
;将r0和spsr压irq栈,因为下面用到r0,spsr
mrs
r14,spsr
stmfd
sp!,{r0,r14}
;写IVR,支持保护模式,普通模式无效
;释放NIRQ,清除保护模式下中断源
ldr
r14,=AT91C_BASE_AIC
ldr r0,[r14,#AIC_IVR]
str r14,[r14,
#AIC_IVR]
;允许中断嵌套,由irq模式切换入svc模式
msr cpsr_c,
#ARM_MODE_SVC
;保存scratch和被使用到的寄存器、lr入svc堆栈
stmfd sp!, {r1-r3, r12,
r14}
;跳转到AIC_IVR指向的中断服务程序地址
mov r14,pc
bx
r0
;恢复scratch、被用到的寄存器、lr
ldmia sp!,{r1-r3, r12,
r14}
;禁止irq中断嵌套,由svc切换到irq模式。
msr cpsr_c,#I_BIT |
ARM_MODE_IRQ
;写AIC_EOICR
ldr r14,=AT91C_BASE_AIC
str r14,[r14,
#AIC_EOICR]
;恢复spsr、r0
ldmia sp!,{r0, r14}
msr spsr_cxsf,
r14
;中断返回
ldmia sp!,
{pc}^
以上就是全部,让我惊叹的是如上做法支持了中断嵌套,想了想,自己以前搞的东西还真是全部回避回去了,也就是说,以前各个中断并没有优先级区分,进了中断就关门i->I。中断服务程序执行完了再打开,优点是简单明了,缺点是中断服务程序必须迅速处理完.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本