Zynq 7000 中断分析
GIC及中断机理
Crotex-A9常用汇编指令
类型 | 指令 | 描述 | 备注 |
---|
内部数据传输指令 | MOV R0 R1 | R1 2 R0 | #0xFF:立即数:MOV R0, #0xFF | 内部数据传输指令 | MRS R0,SR | SR 2 R0 | 读特殊寄存器: MRS R0, CRSR | 内部数据传输指令 | MSR SR R0 | RO 2 SR | 写特殊寄存器: MSR CRSR,R0 | 存储器访问指令 | LDR Rd,[Rn ,#offset] | 从存储器Rn+offset处读取数据写至Rd | 存储加载数据到寄存器中,数据为立即数时: LDR R0,=0xFFFF ,从0Xffff地址取数; LDR R1,[R0] | 存储器访问指令 | STR Rd,[Rn,#offset] | 将Rd中的数据写入到Rn+offset的位置中 | LDR R0,=0xFFFF R0保存地址; LDR R1,=0x1234 R1保存数据; STR R1,[R0] 将R1中的值写入R0中的地址 | 堆栈指令 | PUSH <reg list> | 将寄存器列表存入栈中 | 保护现场,即为将R0~R15寄存器值进行压栈; PUSH{R0~R3,R13} @将 R0~R3 和 R12 压栈 | 堆栈指令 | TMFD SP!, {reg list} | 将寄存器列表存入栈中 同Push | STMFD SP!,{R0~R3, R12} @R0~R3,R12 入栈 | 堆栈指令 | POP <reg list> | 从栈中恢复寄存器列表 | 恢复现场,即为弹栈,从栈中回复寄存器列表 POP{LR} 注意堆栈模型 | 堆栈指令 | LDMFD SP!,{reg lsit} | 从栈中恢复寄存器列表 | 同上 | 跳转指令 | B <label> | 跳转到lable | 如果跳转范围超过2KB可以制定B.W<lable> 指令以获取更大范围; B main 跳转至C函数main | 跳转指令 | BX <Rm> | 间接跳转 | 跳转到Rm存放的地址处,并切换指令集 | 跳转指令 | BL <label> | 跳转到lable并将返回地址保存在LR中 | 在跳转之前会在寄存器LR(R14)中保存PC寄存器值,意味着可以将PC值重新加载跳转至之前程序,中断的切换 | 跳转指令 | BLX <Rm> | 跳转到Rm指定的地址,并将返回地址保存至LR | 示例如下 |
push {r0, r1} @保存 r0,r1
cps #0x13 @进入 SVC 模式,允许其他中断再次进去
bl system_irqhandler @加载 C 语言中断处理函数到 r2 寄存器中
cps #0x12 @进入 IRQ 模式
pop {r0, r1}
str r0, [r1, #0X10] @中断执行完成,写 EOIR
Zynq中断控制
INT_MASK,INT_DIS,INT_EN为一组,表示对对应位是否使能。
INT_TYPE ,INT_POLARITY,INT_ANY为一组,表示触发的方式,是电平还是边缘以及是否双边缘。
INT_STAT 读之可以知道对应位是否发生了中断,对应位写1表示清除中断(实际应用中要以注意中断撤掉或者被屏蔽)
三级跳转,以IRQ中断为例
- 接收到中断信号,进入中断向量表,判断中断类型为IRQ, 执行
15-IRQHandler: 保存完现场后执行33- bl IRQInterrupt 跳转至IRQ中断处理函数
.globl _vector_table
.section .vectors
_vector_table:
B _boot
B Undefined
B SVCHandler
B PrefetchAbortHandler
B DataAbortHandler
NOP
B IRQHandler
B FIQHandler
IRQHandler:
stmdb sp!,{r0-r3,r12,lr}
#if FPU_HARD_FLOAT_ABI_ENABLED
vpush {d0-d7}
vpush {d16-d31}
vmrs r1, FPSCR
push {r1}
vmrs r1, FPEXC
push {r1}
#endif
#ifdef PROFILING
ldr r2, =prof_pc
subs r3, lr, #0
str r3, [r2]
#endif
bl IRQInterrupt
#if FPU_HARD_FLOAT_ABI_ENABLED
pop {r1}
vmsr FPEXC, r1
pop {r1}
vmsr FPSCR, r1
vpop {d16-d31}
vpop {d0-d7}
#endif
ldmia sp!,{r0-r3,r12,lr}
subs pc, lr, #4
- 进入IRQ中断处理函数,此函数不是自定义的中断处理函数,而是GIC(中断控制器)提前注册的响应中断类型的函数,作用在于判断哪个中断号发生了IRQ中断,用以找到相应的用户处理函数
- 跳转至用户处理函数执行之
void XScuGic_InterruptHandler(XScuGic *InstancePtr)
{
u32 InterruptID;
u32 IntIDFull;
XScuGic_VectorTableEntry *TablePtr;
IntIDFull = XScuGic_CPUReadReg(InstancePtr, XSCUGIC_INT_ACK_OFFSET);
InterruptID = IntIDFull & XSCUGIC_ACK_INTID_MASK;
if (XSCUGIC_MAX_NUM_INTR_INPUTS <= InterruptID) {
goto IntrExit;
}
TablePtr = &(InstancePtr->Config->HandlerTable[InterruptID]);
if (TablePtr != NULL) {
TablePtr->Handler(TablePtr->CallBackRef);
}
IntrExit:
XScuGic_CPUWriteReg(InstancePtr, XSCUGIC_EOI_OFFSET, IntIDFull);
}
GPIO
中断控制
单IP双通道
采用单个AXI GPIO IP核双通道, PL逻辑提供两路同步逻辑翻转输入
通道 | 结论 |
---|
双通道 | 双通道 IP仅产生一次中断,中断状态寄存器两通道状态位都置1,在中断处理中读取之来判断通道 |
单IP多位
通道 | 结论 |
---|
单通道 | 产生一次中断,中断状态寄存器置位响应通道,在中断处理中读取IO值判断 |
双IP中断源
采用两组AXI GPIO IP核, PL逻辑提供两路同步中断源
优先级 | 结论 | 延迟 | 描述 |
---|
GPIO1 > GPIO2 | ARM均可进行响应 | 时间不定(10us左右视具体情况而定) | ARM对同时来到的中断源均可响应但存在延迟,优先响应高优先级 | GPIO1 = GPIO2 | ARM均可进行响应 | 时间不定(10us左右视具体情况而定) | ARM对同时来到的中断源均可响应但存在延迟,存在固定顺序,影响因素未知 |
GPIO1 > GPIO2 | ARM均可进行响应 |时间不定(10us左右视具体情况而定)|ARM对同时来到的中断源均可响应但存在延迟,优先响应高优先级| |GPIO1 = GPIO2|ARM均可进行响应|时间不定(10us左右视具体情况而定)|ARM对同时来到的中断源均可响应但存在延迟,存在固定顺序,影响因素未知|
|