-
说明
本文章分析了ARM架构下SylixOS内核中断流程,共包含三部分:
分析SylixOS运用数组和双向链表实现中断服务函数的注册
阐述ARM硬件中断机制
分析SylixOS中断处理流程
-
SylixOS中断注册
SylixOS中断注册是通过数组和双向链表实现的。
系统中断向量结构索引数组
_K_idescTable [256]是SylixOS内核中的系统中断向量结构索引数组,用于索引注册的中断服务函数,其类型如清单 21所示
清单 21
typedef struct { LW_LIST_LINE_HEADER IDESC_plineAction; /* 判断中断服务函数列表 */ ULONG IDESC_ulFlag; /* 中断向量选项 */ LW_SPINLOCK_DEFINE (IDESC_slLock); /* 自旋锁 */ } LW_CLASS_INTDESC
第一个成员是双向链表的头指针,用于指向将来注册的中断向量结构链表。中断向量结构链表
每进行一次中断注册,内核创建一个中断向量结构。如果有多个中断源共享一个中断号,内核将这些中断源的各个中断向量结构链接成双向链表。中断向量结构类型如清单 22所示:
清单 22
typedef struct { LW_LIST_LINE IACT_plineManage; /* 管理链表 */ INT64 IACT_iIntCnt[LW_CFG_MAX_PROCESSORS]; /* 中断计数器 */ PINT_SVR_ROUTINE IACT_pfuncIsr; /* 中断服务函数 */ VOIDFUNCPTR IACT_pfuncClear; /* 中断清理函数 */ PVOID IACT_pvArg; /* 中断服务函数参数 */ CHAR IACT_cInterName[LW_CFG_OBJECT_NAME_SIZE]; } LW_CLASS_INTACT
当进行一次中断注册,内核依次完成如下事务:
构建一个中断向量结构
在此中断向量结构中记录中断服务函数地址和中断服务函数名等信息
将此中断向量结构插入到此中断号的中断向量结构链表
以中断向量号为下标索引_K_idescTable数组,将其中的头指针指向上一步构建的双向链表
如图 21所示,中断注册实质是构建中断向量结构双向链表。
图 21中断注册
-
ARM硬件中断机制
当中断发生后,ARM内核自动完成如下事务:
保存执行状态:保存CPSR到中断模式的SPSR中
模式切换:处理器进入中断模式,并关闭中断,防止中断嵌套
保存返回地址:保存PC-4到中断模式的LR中
跳入中断向量表:强制设置PC为中断向量地址,跳转到中断处理程序中
保存执行状态
当前程序的执行状态是保存在CPSR中的,中断发生时,要保存当前CPSR中的执行状态到中断模式的SPSR中,将来中断返回时,恢复到CPSR,恢复执行状态。
模式切换
硬件自动将中断异常码写入CPSR中的模式位,CPU进入中断模式。同时硬件自动切换处理器到ARM状态下执行指令,并且CPU通过设置CPSR相应位来关闭中断。
保存返回地址
当前程序被中断打断,切换到中断处理程序里,中断处理完后,返回当前被打断模式继续执行,因此必须要保存当前指令的下一条指令的地址到中断模式下的LR中。由于ARM异常模式不同以及ARM内核采用流水线技术,中断处理程序需要重新计算正确的返回地址。
跳入中断向量表
该操作是CPU硬件自动完成的,当异常发生时,CPU强制将PC的值改为一个固定内存地址,并跳到此地址处执行。
- SylixOS中断处理流程
中断处理程序
SylixOS中断处理程序完成如下事务:
修正返回地址,LR=LR-4
保存现场寄存器
中断处理阶段1
恢复现场寄存器
返回现场,PC=LR,回到返回地址处继续执行
中断处理阶段1
中断处理阶段1完成了3件事务:
获得中断源的中断向量号
中断处理阶段2
中断结束处理
获得中断向量号一般都是通过读取中断控制器的某个寄存器来获得;中断处理结束后需要通知中断控制器中断处理已经完成,一般都是向某个寄存器写入任意值即可。
中断处理阶段2
此阶段是真正的进行中断处理,完成以下事务:
以中断向量号作为索引,通过_K_idescTable数组找到此中断向量号的中断结构链表
依次遍历之前注册的中断服务函数,并根据返回值判断是否已经执行了相应中断源的中断服务函数。如果已经执行则退出遍历,否则继续遍历直到找到相应的服务函数或者找不到退出。
- 总结
通过中断注册构建中断向量结构链表
中断发生时通过中断向量号索引_K_idescTable数组找到此中断向量号的中断结构链表,然后遍历之前注册在其中的中断服务函数,直到找到相应的服务函数或者找不到退出。