SylixOS中的中断服务对象
系统中断向量表
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;#define LW_CFG_MAX_INTER_SRC 256 /* 系统使用中断向量表大小,中断源数量 < 9999 */
__KERNEL_EXT LW_CLASS_INTDESC _K_idescTable[LW_CFG_MAX_INTER_SRC];
/*********************************************************************************************************IRQ FLAG (设置为 QUEUE 模式向量后, 系统无法再返回非 QUEUE 模式向量)
*********************************************************************************************************/#define LW_IRQ_FLAG_QUEUE 0x0001 /* 单向量, 多服务 */
#define LW_IRQ_FLAG_PREEMPTIVE 0x0002 /* 是否允许抢占 (arch负责实现) */
#define LW_IRQ_FLAG_SAMPLE_RAND 0x0004 /* 是否可用作系统随机数种子 */
#define LW_IRQ_FLAG_GJB7714 0x0008 /* GBJ7714 无返回值服务 */
/*********************************************************************************************************中断向量表
*********************************************************************************************************/#define LW_IVEC_GET_IDESC(vector) \(&_K_idescTable[vector])#define LW_IVEC_GET_FLAG(vector) \(_K_idescTable[vector].IDESC_ulFlag)#define LW_IVEC_SET_FLAG(vector, flag) \(_K_idescTable[vector].IDESC_ulFlag = (flag))
每个系统中断向量包含三个成员,中断服务对象链表,中断向量选项和自旋锁。所有系统中断向量定义为一个数组,向量号就是索引号,通过向量号可直接获取系统中断向量。
中断服务对象
/*********************************************************************************************************中断向量表结构 (这里不保存中断向量优先级和 target cpu 使用时调用 bsp 服务获取)
*********************************************************************************************************/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;
中断服务对象处理
中断服务的连接和断开其实就是系统中断向量的服务链表添加或删除一个节点。
/*********************************************************************************************************
** 函数名称: API_InterVectorServiceCnt
** 功能描述: 获得指定中断向量服务函数个数
** 输 入 : ulVector 中断向量号
** piCnt 服务函数个数
** 输 出 : ERROR CODE
** 全局变量:
** 调用模块:API 函数
*********************************************************************************************************/
LW_API
ULONG API_InterVectorServiceCnt (ULONG ulVector, INT *piCnt)
{INTREG iregInterLevel;PLW_LIST_LINE plineTemp;PLW_CLASS_INTDESC pidesc;INT iCnt = 0;if (_Inter_Vector_Invalid(ulVector)) {_ErrorHandle(ERROR_KERNEL_VECTOR_NULL);return (ERROR_KERNEL_VECTOR_NULL);}if (!piCnt) {_ErrorHandle(EINVAL);return (EINVAL);}pidesc = LW_IVEC_GET_IDESC(ulVector);LW_SPIN_LOCK_QUICK(&pidesc->IDESC_slLock, &iregInterLevel); /* 关闭中断同时锁住 spinlock */for (plineTemp = pidesc->IDESC_plineAction;plineTemp != LW_NULL;plineTemp = _list_line_get_next(plineTemp)) {iCnt++;}LW_SPIN_UNLOCK_QUICK(&pidesc->IDESC_slLock, iregInterLevel); /* 打开中断, 同时打开 spinlock */*piCnt = iCnt;return (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: API_InterVectorConnectEx
** 功能描述: 设置系统指定向量中断服务
** 输 入 : ulVector 中断向量号
** pfuncIsr 服务函数
** pfuncClear 附加中断清除函数(可为 NULL)
** pvArg 服务函数参数
** pcName 中断服务名称
** 输 出 : ERROR CODE
** 全局变量:
** 调用模块: API 函数
*********************************************************************************************************/
LW_API
ULONG API_InterVectorConnectEx (ULONG ulVector,PINT_SVR_ROUTINE pfuncIsr,VOIDFUNCPTR pfuncClear,PVOID pvArg,CPCHAR pcName)
{INTREG iregInterLevel;BOOL bNeedFree;PLW_LIST_LINE plineTemp;PLW_CLASS_INTACT piactionOld;PLW_CLASS_INTACT piaction;PLW_CLASS_INTDESC pidesc;if (LW_CPU_GET_CUR_NESTING()) { /* 不能在中断中调用 */_DebugHandle(__ERRORMESSAGE_LEVEL, "called from ISR.\r\n");_ErrorHandle(ERROR_KERNEL_IN_ISR);return (ERROR_KERNEL_IN_ISR);}INTER_SHOWLOCK_CREATE();if (_Object_Name_Invalid(pcName)) { /* 检查名字有效性 */_DebugHandle(__ERRORMESSAGE_LEVEL, "name too long.\r\n");_ErrorHandle(ERROR_KERNEL_PNAME_TOO_LONG);return (ERROR_KERNEL_PNAME_TOO_LONG);}if (_Inter_Vector_Invalid(ulVector)) {_ErrorHandle(ERROR_KERNEL_VECTOR_NULL);return (ERROR_KERNEL_VECTOR_NULL);}if (pfuncIsr == LW_NULL) {_ErrorHandle(ERROR_KERNEL_VECTOR_NULL);return (ERROR_KERNEL_VECTOR_NULL);}piaction = (PLW_CLASS_INTACT)__KHEAP_ALLOC(sizeof(LW_CLASS_INTACT));if (piaction == LW_NULL) {_DebugHandle(__ERRORMESSAGE_LEVEL, "kernel low memory.\r\n");_ErrorHandle(ERROR_KERNEL_LOW_MEMORY);return (ERROR_KERNEL_LOW_MEMORY);}lib_bzero(piaction, sizeof(LW_CLASS_INTACT));piaction->IACT_pfuncIsr = pfuncIsr;piaction->IACT_pfuncClear = pfuncClear;piaction->IACT_pvArg = pvArg;if (pcName) {lib_strcpy(piaction->IACT_cInterName, pcName);} else {piaction->IACT_cInterName[0] = PX_EOS;}pidesc = LW_IVEC_GET_IDESC(ulVector);LW_SPIN_LOCK_QUICK(&pidesc->IDESC_slLock, &iregInterLevel); /* 关闭中断同时锁住 spinlock */if (LW_IVEC_GET_FLAG(ulVector) & LW_IRQ_FLAG_QUEUE) { /* 队列服务类型向量 */for (plineTemp = pidesc->IDESC_plineAction;plineTemp != LW_NULL;plineTemp = _list_line_get_next(plineTemp)) {piactionOld = _LIST_ENTRY(plineTemp, LW_CLASS_INTACT, IACT_plineManage);if ((piactionOld->IACT_pfuncIsr == pfuncIsr) &&(piactionOld->IACT_pvArg == pvArg)) { /* 中断处理函数是否被重复安装 */break;}}if (plineTemp) { /* 此中断被重复安装 */bNeedFree = LW_TRUE;} else {_List_Line_Add_Ahead(&piaction->IACT_plineManage,&pidesc->IDESC_plineAction);bNeedFree = LW_FALSE;}} else { /* 非队列服务式中断向量 */if (pidesc->IDESC_plineAction) {piactionOld = _LIST_ENTRY(pidesc->IDESC_plineAction, LW_CLASS_INTACT, IACT_plineManage);piactionOld->IACT_pfuncIsr = piaction->IACT_pfuncIsr;piactionOld->IACT_pfuncClear = piaction->IACT_pfuncClear;piactionOld->IACT_pvArg = piaction->IACT_pvArg;lib_strcpy(piactionOld->IACT_cInterName, piaction->IACT_cInterName);bNeedFree = LW_TRUE;} else {_List_Line_Add_Ahead(&piaction->IACT_plineManage,&pidesc->IDESC_plineAction);bNeedFree = LW_FALSE;}}LW_SPIN_UNLOCK_QUICK(&pidesc->IDESC_slLock, iregInterLevel); /* 打开中断, 同时打开 spinlock */if (bNeedFree) {__KHEAP_FREE(piaction);}_DebugFormat(__LOGMESSAGE_LEVEL, "IRQ %d : %s connect : %p\r\n",(INT)ulVector, (pcName ? pcName : ""), (PVOID)pfuncIsr);return (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: API_InterVectorDisconnectEx
** 功能描述: 解除系统指定向量中断服务
** 输 入 : ulVector 中断向量号
** pfuncIsr 服务函数
** pvArg 服务函数参数
** ulOption 删除选项
** 输 出 : ERROR CODE
** 全局变量:
** 调用模块: API 函数
*********************************************************************************************************/
LW_API
ULONG API_InterVectorDisconnectEx (ULONG ulVector,PINT_SVR_ROUTINE pfuncIsr,PVOID pvArg,ULONG ulOption)
{INTREG iregInterLevel;BOOL bNeedFree;PLW_LIST_LINE plineTemp;PLW_CLASS_INTACT piaction;PLW_CLASS_INTDESC pidesc;if (LW_CPU_GET_CUR_NESTING()) { /* 不能在中断中调用 */_DebugHandle(__ERRORMESSAGE_LEVEL, "called from ISR.\r\n");_ErrorHandle(ERROR_KERNEL_IN_ISR);return (ERROR_KERNEL_IN_ISR);}INTER_SHOWLOCK_CREATE();if (_Inter_Vector_Invalid(ulVector)) {_ErrorHandle(ERROR_KERNEL_VECTOR_NULL);return (ERROR_KERNEL_VECTOR_NULL);}if (!(ulOption & LW_IRQ_DISCONN_ALL) && (pfuncIsr == LW_NULL)) {_ErrorHandle(ERROR_KERNEL_VECTOR_NULL);return (ERROR_KERNEL_VECTOR_NULL);}__disconn:bNeedFree = LW_FALSE;INTER_SHOWLOCK_LOCK();pidesc = LW_IVEC_GET_IDESC(ulVector);LW_SPIN_LOCK_QUICK(&pidesc->IDESC_slLock, &iregInterLevel); /* 关闭中断同时锁住 spinlock */for (plineTemp = pidesc->IDESC_plineAction;plineTemp != LW_NULL;plineTemp = _list_line_get_next(plineTemp)) {piaction = _LIST_ENTRY(plineTemp, LW_CLASS_INTACT, IACT_plineManage);if (ulOption & LW_IRQ_DISCONN_ALL) { /* 删除所有 */bNeedFree = LW_TRUE;} else if (ulOption & LW_IRQ_DISCONN_IGNORE_ARG) {if (piaction->IACT_pfuncIsr == pfuncIsr) { /* 删除匹配的函数 */bNeedFree = LW_TRUE;}} else {if ((piaction->IACT_pfuncIsr == pfuncIsr) &&(piaction->IACT_pvArg == pvArg)) { /* 删除匹配的函数与参数 */bNeedFree = LW_TRUE;}}if (bNeedFree) {_List_Line_Del(&piaction->IACT_plineManage,&pidesc->IDESC_plineAction);break;}}LW_SPIN_UNLOCK_QUICK(&pidesc->IDESC_slLock, iregInterLevel); /* 打开中断, 同时打开 spinlock */INTER_SHOWLOCK_UNLOCK();if (bNeedFree) {__KHEAP_FREE(piaction);if (ulOption & (LW_IRQ_DISCONN_ALL | LW_IRQ_DISCONN_IGNORE_ARG)) {goto __disconn;}}return (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: API_InterEnter
** 功能描述: 内核中断入口函数 (在关中断的情况下被调用)
** 输 入 :
** 输 出 : 中断层数
** 全局变量:
** 调用模块: API 函数
*********************************************************************************************************/
LW_API
ULONG API_InterEnter (ARCH_REG_T reg0,ARCH_REG_T reg1,ARCH_REG_T reg2,ARCH_REG_T reg3)
{PLW_CLASS_CPU pcpu;pcpu = LW_CPU_GET_CUR();pcpu->CPU_ulInterNesting++;#if !defined(__SYLIXOS_ARM_ARCH_M__) || (LW_CFG_CORTEX_M_SVC_SWITCH > 0)archIntCtxSaveReg(pcpu, reg0, reg1, reg2, reg3);
#endifreturn (pcpu->CPU_ulInterNesting);
}
/*********************************************************************************************************
** 函数名称: API_InterExit
** 功能描述: 内核中断出口函数 (在关中断的情况下被调用)
** 输 入 : NONE
** 输 出 : NONE
** 全局变量:
** 调用模块: API 函数
*********************************************************************************************************/
LW_API
VOID API_InterExit (VOID)
{PLW_CLASS_CPU pcpu;pcpu = LW_CPU_GET_CUR();#if LW_CFG_INTER_INFO > 0if (pcpu->CPU_ulInterNestingMax < pcpu->CPU_ulInterNesting) {pcpu->CPU_ulInterNestingMax = pcpu->CPU_ulInterNesting;}
#endif /* LW_CFG_INTER_INFO > 0 */if (pcpu->CPU_ulInterNesting) { /* 系统中断嵌套层数-- */pcpu->CPU_ulInterNesting--;}if (pcpu->CPU_ulInterNesting) { /* 查看系统是否在中断嵌套中 */return; /* LW_CFG_INTER_DSP > 0 */}__KERNEL_SCHED_INT(pcpu); /* 中断中的调度 */archIntCtxLoad(pcpu); /* 中断返回 (当前任务 CTX 加载)*/
}
中断服务统一调佣接口,已简化源码。
/*********************************************************************************************************
** 函数名称: API_InterVectorIsr
** 功能描述: 向量中断总服务
** 输 入 : ulVector 中断向量号 (arch 层函数需要保证此参数正确)
** 输 出 : 中断返回值
** 全局变量:
** 调用模块:
** 注 意 : 这里并不处理中断嵌套, 他需要 arch 层移植函数支持.
*********************************************************************************************************/
LW_API
irqreturn_t API_InterVectorIsr (ULONG ulVector)
{PLW_CLASS_CPU pcpu;PLW_LIST_LINE plineTemp;PLW_CLASS_INTDESC pidesc;PLW_CLASS_INTACT piaction;irqreturn_t irqret = LW_IRQ_NONE;pcpu = LW_CPU_GET_CUR(); /* 中断处理程序中, 不会改变 CPU*/pidesc = LW_IVEC_GET_IDESC(ulVector); /* LW_CFG_SMP_EN > 0 */for (plineTemp = pidesc->IDESC_plineAction;plineTemp != LW_NULL;plineTemp = _list_line_get_next(plineTemp)) {piaction = (PLW_CLASS_INTACT)plineTemp;irqret = piaction->IACT_pfuncIsr(piaction->IACT_pvArg, ulVector); if (irqret != 0) { piaction->IACT_iIntCnt[LW_CPU_GET_ID(pcpu)]++; if (piaction->IACT_pfuncClear) { piaction->IACT_pfuncClear(piaction->IACT_pvArg, ulVector); } if (irqret != LW_IRQ_HANDLED_CONT) { break; } } }return (irqret);
}
SylixOS中的中断服务对象相关推荐
- SylixOS中的中断接口基础实现
SylixOS中断实现相对简单,主要借助arch接口,bsp接口,cpu对象,调度接口等实现.还通过数组和链表管理中断对象. 基于arch接口实现类 全局中断开关接口的简单封装. #define KN ...
- SylixOS中select原理及使用分析
2019独角兽企业重金招聘Python工程师标准>>> 1. select接口简介 1.1 select接口使用用例 select是操作系统多路I/O复用技术实现的方式之一. 多路I ...
- SylixOS中的CPU集合及其操作
SylixOS中的CPU集合及其操作 SylixOS支持SMP多核模式,在表示CPU集合时(如中断和线程绑定)通过一个位图来表示,操作和SylixOS位图接口类似,但并需要快速查找最低位,所以并不使用 ...
- SylixOS中APIC HPET定时器字符驱动实现
1.简介 1.1 APIC介绍 "APIC"是Advanced Programmable Interrupt Controller的缩写,即高级可编程中断控制器.引入APIC机制是 ...
- SylixOS中的几个常用虚拟设备文件
空闲设备 /dev/null 空闲设备,是一个特殊的设备文件,通常称它为"黑洞",它等价于一个只写文件,所有写入它的内容将会永远丢失,但成功返回写入的字节数.SylixOS 中,此 ...
- 嵌入式中的中断服务程序
嵌入式中的中断服务程序 中断是嵌入式系统中重要的组成部分,但是在标准 C 中不包含中断.许多编译开发商在标准 C 上增加了对中断的支持,提供新的关键字用于标示中断服务程序(ISR),类似于__inte ...
- Keyboard驱动中button中断的处理机制
Keyboard驱动中button中断的处理机制 ********************************LoongEmbedded************************ 作者:Lo ...
- uboot中的中断macro宏
目录 uboot中的中断macro宏 引入 内存分配 流程概览 普通中断 保存现场 中断函数打印具体寄存器 恢复现场 软中断 空间获取 保存现场 附录速记 疑惑待解 uboot中的中断macro宏 引 ...
- Microsoft Windows CE .NET 中的中断体系结构
概述 通过 Microsoft Windows CE .NET,Microsoft 已经升级了 Windows CE 的中断体系结构.该操作系统 (OS) 所具有的处理共享中断的能力极大地扩展了 Wi ...
最新文章
- Eclipse 快捷键(转载)
- Spring Boot 2.0(三):Spring Boot 开源软件都有哪些?
- socket , 套接口还是套接字,傻傻分不清楚
- 【Linux网络编程】TCP网络编程中connect listen和accept三者之间的关系
- 【Linux系统编程】特殊进程之孤儿进程
- 华东云友会主播栏目01期 阿里云X海底捞,千人千锅就是如此任性!
- springmvc web.xml和application.xml配置详情(附:完整版pom.xml)
- Android 自定义View关于measure流程的基本思路整理
- @RunWith报错/SpringJUnit4ClassRunner报错或无法使用
- TAS5754应用笔记
- 计算机处理器i3 i5,realme Book笔记本高清渲染图曝光 配置上搭载11代酷睿i3/i5处理器...
- python有道字典翻译_使用Python从有道词典网页获取单词翻译
- vector subscript out of range
- odroid-xu4(ubuntu mate 16.04)源码编译opencv 3.2
- 如何对互联网上产生的舆情传播动态进行分析的方法
- 【论文阅读】【HLLDA】 A Hierarchical Model of Web Summaries
- NoSQL之Redis配置与数据库常用命令
- Linux下lsof命令详解
- ubuntu下80端口无权限问题
- OIM同步OID(OID-Connector 9.0.4.12)
热门文章
- 下班后10条最佳放松方法
- 项目无法启动,Disconnected from the target VM
- 【个人博客】Hexo个人博客搭建与配置详细教程 + Fluid主题 + Gitee发布
- [PyG] 1.如何使用GCN完成一个最基本的训练过程(含GCN实现)
- SAP SD发货流程中托盘的管理
- gii无法访问 yii2_yii2 学习历程——gii配置外部用户访问权限问题
- 利用二进制位求平均值
- [免费专栏] 车联网基础理论之车联网安全车端知识科普
- 从哈密尔顿路径谈NP问题
- ideal拉代码和提交代码