SylixOS中断系统分析
中断向量表
在SylixOS中,系统默认存在一张大小为256(可以手动配置)的中断向量表,用于管理SylixOS中的每一个中断向量。该向量表存在于k_globalvar.h文件中,其定义格式如程序清单1-1所示。
程序清单1-1 系统中断向量表定义
/********************************************************************************************************* 系统中断向量表 *********************************************************************************************************/ __KERNEL_EXT LW_CLASS_INTDESC _K_idescTable[LW_CFG_MAX_INTER_SRC]; __KERNEL_EXT LW_SPINLOCK_DEFINE (_K_slVectorTable);
_K_idescTable是大小为256的数组,数组元素为256个中断向量,_K_slVectorTable是一个自旋锁,用于对中断向量表的互斥访问。
_K_idescTable的类型为LW_CLASS_INTDESC,该类型是SylixOS的中断向量表结构,定义如程序清单1-2所示。
程序清单1-2 中断向量表结构定义
typedef struct { LW_LIST_LINE_HEADER IDESC_plineAction; /* 判断中断服务函数列表 */ ULONG IDESC_ulFlag; /* 中断向量选项 */ LW_SPINLOCK_DEFINE (IDESC_slLock); /* 自旋锁 */ } LW_CLASS_INTDESC; typedef LW_CLASS_INTDESC *PLW_CLASS_INTDESC;
LW_CLASS_INTDESC类型的原型分析如下:
- IDESC_plineAction是用于管理中断服务函数的链表,通常情况下,一个中断号对应一个中断服务函数,那么该链表内只有一个成员;但有些特殊情况,一个中断号可以对应多个中断服务函数,则该链表有多个成员。
- IDESC_ulFlag 中断向量选项。
- IDESC_slLock 中断向量自旋锁
中断向量的选项如表1-1所示。
表1-1 中断向量类型
宏名 |
含义 |
LW_IRQ_FLAG_QUEUE |
支持单向量,多服务 |
LW_IRQ_FLAG_PREEMPTIVE |
允许中断抢占 |
LW_IRQ_FLAG_SAMPLE_RAND |
可用作系统随机数种子 |
LW_IRQ_FLAG_GJB7714 |
支持GJB7714国军标体系 |
1.2中断描述符
在SylixOS中,每一个中断服务函数对应一个中断描述符结构,并将该中断描述符结构加入到中断向量表对应的表项中,如果一个中断向量对应多个中断服务函数,则这些中断服务函数对应的中断描述符就组成了一个链表,并由中断向量表对应的表项来进行管理。中断描述符结构如程序清单1-3所示。
程序清单1-3 中断描述符结构体定义
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; /* 中断描述符 */ typedef LW_CLASS_INTACT *PLW_CLASS_INTACT;
中断描述符类型的原型分析:
- IACT_plineManage 管理链表,用于将中断描述符加入到中断向量表表项
- IACT_iIntCnt 中断计数器,每一次中断该数值加1
- IACT_pfuncIsr 中断服务函数
- IACT_pfuncClear 中断清理函数
- IACT_pvArg 中断服务函数参数
- IACT_cInterName 中断服务函数名字
1.3SylixOS中断服务函数流程
1.3.1总中断服务函数
以ARM体系为例,当ARM内核检测到中断时,会自动将PC指向中断异常入口处去执行中断异常函数,SylixoS的中断异常函数定义为archIntEntry,它是由汇编语言编写,可以用ctrl+h来全局查找该函数进行详细分析。这就是SylixOS的总中断服务函数,也就是说,无论是哪一个中断向量产生中断,都会先进入archIntEntry函数。实际上,在执行工程师自己定义的中断服务函数之前,需要进行一些准备工作,比如上下文的保存,中断嵌套的判断等;执行完工程师自己定义的中断服务函数后,还需要进行上下文的恢复等操作;这些都是由archIntEntry函数来完成,archIntEntry函数就相当于一层外壳,它对底层工程师隐藏了整个中断响应复杂的细节。
那么,archIntEntry函数,来查找中断服务函数。是如何找到工程师自己定义的中断服务函数呢?通过分析archIntEntry函数的源代码可知, archIntEntry函数通过调用bspIntHandle函数,bspIntHandle函数调用archIntHandle函数,来查找中断服务函数。
1.3.2查找中断服务函数
archIntHandle函数定义如程序清单1-4所示。
程序清单1-4 archIntHandle函数定义
LW_WEAK VOID archIntHandle (ULONG ulVector, BOOL bPreemptive)
archIntHandle函数原型分析:
- 参数ulVector是中断向量号
- 参数bPreemptive表示是否允许中断抢占,这里只是根据是否允许抢占来判断是否打开中断,中断嵌套上下文的保存是在archIntEntry函数中处理的。
archIntHandle函数的大体流程如图1-1所示。
图1-1 中断服务函数流程
1.3.3中断服务函数返回值
archIntHandle函数在遍历中断服务函数链表时,会根据中断服务函数的返回值判断是否需要结束遍历,它的返回值有三种选项,如表1-2所示。
表1-2 中断服务函数返回值选项
宏名 |
含义 |
LW_IRQ_NONE |
不是本中断服务函数产生的中断,继续遍历 |
LW_IRQ_HANDLED |
是本中断服务函数产生的中断,结束遍历 |
LW_IRQ_HANDLED_DISV |
中断处理结束,并屏蔽本次中断 |
可参考SylixOS GIT上的文档《TN0032_SylixOS共用中断号机制》,来对中断服务函数返回值做更详细的了解。
2.SylixOS中断的连接与释放
在SylixOS中,中断的连接与释放的函数分别是API_InterVectorConnect函数和API_InetrVectorDisable函数,下面介绍SylixOS中断的连接和释放过程。
2.1SylixOS中断连接函数简介
API_InterVectorConnect函数定义如程序清单2-1所示。
程序清单2-1 中断连接函数
LW_API ULONG API_InterVectorConnect(ULONG ulVector, PINT_SVR_ROUTINE pfuncIsr, PVOID pvArg, CPCHAR pcName); /* 设置指定向量的服务程序 */
函数API_InterVectorConnect原型分析:
- 函数返回为连接成功或失败
- 参数ulVector是中断向量号
- 参数pfuncIsr是中断服务函数
- 参数pvArg是中断服务函数参数
- 参数pcName是中断服务名称
API_InterVectorConnect函数的功能是将中断向量号与中断服务函数进行连接。
API_InterVectorConnect函数的大体流程如图2-所示。
图2- 1 中断服务连接函数流程
SylixOS中断释放函数简介
API_InterVectorDisable函数的定义如程序清单2-2所示。
程序清单2-2 中断释放函数
LW_API ULONG API_InterVectorDisconnect(ULONG ulVector, PINT_SVR_ROUTINE pfuncIsr, PVOID pvArg); /* 删除指定向量的服务程序 */
API_InterVectorDisable函数原型分析:
- 函数返回值是释放成功或失败
- 参数ulVector是中断向量号
- 参数pfuncIsr是中断服务函数
- 参数pvArg是中断服务函数的参数
API_InterVectorDisable函数仅仅只是释放与参数pfuncIsr和参数pvArg相对应的中断服务函数,当一个向量对应多个函数时,它并不会释放该向量的所有中断服务函数。
如果要想一次性释放所有中断服务函数,SylixOS提供了另外的接口,API_InterVectorDisconnectEx函数,它的定义如程序清单2-3所示。
程序清单2-3 中断释放扩展函数
LW_API ULONG API_InterVectorDisconnectEx(ULONG ulVector, PINT_SVR_ROUTINE pfuncIsr, PVOID pvArg, ULONG ulOption); /* 删除指定向量的服务程序 */
API_InterVectorDisconnectEx函数原型分析:
- 该函数的前三个参数与API_InterVectorDisable函数参数相同,实际上API_InterVectorDisable就是调用了该函数。
- 参数ulOption是删除选项
删除选项的选项如表2- 1所示。
表2- 1 中断释放函数的删除选项
宏名 |
含义 |
LW_IRQ_DISCONN_DEFAULT |
解除匹配函数和函数参数的中断服务连接 |
LW_IRQ_DISCONN_ALL |
解除所有中断服务连接 |
LW_IRQ_DISCONN_IGNORE_ARG |
解除匹配函数的中断服务连接(忽略函数参数) |
API_InterVectorDisconnectEx函数的大体流程如图2-2所示。
图2-2 中断释放函数流程