1.应用场景
在一些情况下,对于一些紧急的中断任务,系统需要为其提供稳定可靠的中断响应时间,但一般的中断服务函数,它的响应时间可能会受到其他中断向量的影响,延迟响应。在SylixOS中有两种解方案。
1.提高该中断向量优先级,打开中断嵌套来确保紧急中断的响应时间。
2.对于多核处理器,可以采用中断绑核的形式,即将紧急中断绑定到某一核上,该核只处理紧急任务。
下面通过测试正常情况下、中断嵌套情况下、中断绑核情况下的中断响应时间,来对比采用上述两种方式的优点。
2.中断响应时间测试方案
使用示波器自带的1KHZ输出方波作为CPU的中断源,下降沿中断,在中断服务里改变CPU引脚输出电平并捕获。中断响应时间为1KHZ方波由从高电平上升到0.7*VCC开始到CPU输出低电平的时间差。具体测试方案见PPT支持SMP的大型实时操作系统(IDE目录下的ppt目录里)。硬件连接图如图2- 1所示。
图2- 1 中断响应时间测试硬件连接
测试以zynq7000开发板为例,zynq7000处理器为双核处理器,中断控制器为GIC pl350,它支持中断嵌套和中断绑核。测试程序如程序清单2- 1所示。
程序清单2- 1 中断响应时间测试代码
/********************************************************************************************************* * 函数名称: __doIsr ** 功能描述: 中断服务函数 ** 输 入 : VOID ** 输 出 : ** 全局变量: ** 调用模块: *********************************************************************************************************/ static irqreturn_t __doIsr (PVOID pvArg, ULONG iVector) { API_GpioClearIrq(GPIO_NUM); /* 清中断 */ writel(readl(0xE000A204) | (1 << 0), 0xE000A204); /* 11号脚,设置为出输出 */ writel(readl(0xE000A208) | (1 << 0), 0xE000A208); /* 11号脚,设置为出输出使能 */ writel(readl(0xE000A200) | (1 << 0), 0xE000A000); /* 11号脚,设置为低电平 */ bspDelayUs(1); /* 延迟1us */ writel(readl(0xE000A200) | (0 << 0), 0xE000A000); /* 11号脚,设置为高电平 */ return LW_IRQ_HANDLED; } /********************************************************************************************************* ** 函数名称: module_init ** 功能描述: 模块加载函数 ** 输 入 : VOID ** 输 出 : 0 表示成功,非0表示失败 ** 全局变量: ** 调用模块: *********************************************************************************************************/ int module_init (void) { system("shfile /etc/thread_affinity.sh"); LW_CLASS_CPUSET cpuset; LW_CPU_ZERO(&cpuset); LW_CPU_SET(1, &cpuset); API_GpioRequestOne(GPIO_NUM, LW_GPIOF_IN, "intIn"); /* 下降沿触发中断 */ LW_IRQ = API_GpioSetupIrq(GPIO_NUM, LW_FALSE, 0); API_InterVectorConnect(LW_IRQ, /* 安装操作系统中断向量表 */ (PINT_SVR_ROUTINE)__doIsr, (PVOID)LW_NULL, "isr"); API_InterSetTarget(LW_IRQ, sizeof(LW_CLASS_CPUSET), &cpuset); /* 设置中断目标CPU1 */ API_InterVectorEnable(LW_IRQ); /* 中断使能 */ return 0; }
在不开中断嵌套和中断不绑核的情况下,用上述方案进行测试。在不加负载的情况下,其中断响应时间如图3- 1所示。3.正常情况下中断响应时间测试
图3- 1 无负载下中断响应时间测试
由图3- 1可以看出其中断响应时间大概为3.5us,并且实际测试时波动较大,中断响应时间不稳定。在加负载的情况下(内存拷贝负载和CPU负载),其中断响应时间测试结果如下图3- 2所示。
图3- 2 加负载下中断响应时间测试
由图3- 2可以看出,加负载后,内存拷贝等任务可能会产生中断,从而影响测试中断向量的中断响应时间,测试中断向量的中断响应时间已经达到7us,并且实际响应时间很不稳定,有时可能出现十几微妙的情况。对于紧急任务,这种不稳定情况是不允许出现的。
4.中断嵌套下中断响应时间测试
在SylixOS下,可以采用中断嵌套的方式加快高优先级中断向量的响应时间,将测试中断向量的优先级设置为最高,并且打开中断嵌套,测试中断响应时间,图4- 1可以看出各个中断向量分布在不同的CPU核上。
图4- 1
如图4- 2所示,测试中断向量的中断响应时间为3.5us,并且实际响应时没有太大波动(响应时间稳定在3.5us)。
图4- 2 中断嵌套下无压力中断响应时间测试
如图4- 3所示是在加负载(CPU负载和内存拷贝负载)的情况下,测试中断向量的响应时间为5us左右,并且实际响应没有太大波动(响应时间稳定在5us)。
图4- 3 中断嵌套下加负载中断响应时间测试
由测试结果可以看出,中断嵌套可以提高中断的响应时间。
在单核处理器下,只能通过中断嵌套来保证紧急中断的响应时间,但多级中断嵌套存在中断栈溢出的风险,用户在使用时需要注意这一点。
大部分中断控制器为了防止中断栈溢出,一般会限制中断嵌套的层数,例如AIC支持最多8级中断嵌套,GIC支持最多7级中断嵌套。
SylixOS中用户可以手动配置中断栈的大小,通过memory_cfg.h 下的LW_CFG_INT_STK_SIZE选项进行中断栈大小的设置,SylixOS默认中断栈大小为4K,用户可以根据自身情况进行配置,配置选项程序如程序清单4- 1所示。
程序清单4- 1 中断栈大小配置
/********************************************************************************************************* * 基本二进制大小单位定义 *********************************************************************************************************/ #ifndef LW_CFG_KB_SIZE #define LW_CFG_KB_SIZE (1024) #define LW_CFG_MB_SIZE (1024 * LW_CFG_KB_SIZE) #define LW_CFG_GB_SIZE (1024 * LW_CFG_MB_SIZE) #endif /********************************************************************************************************* * KERNEL THREAD & INTERUPT STACK * (不包括网络与其他扩展子系统相关线程) *********************************************************************************************************/ #define LW_CFG_INT_STK_SIZE (4 * LW_CFG_KB_SIZE)/* 系统中断堆栈大小 (字节) */ ... …
5.中断绑核下中断响应时间测试
开中断嵌套存在一定风险,在多核处理器下,中断控制器一般都支持中断绑核。可以采用中断绑核的方式提高紧急中断向量的响应时间,中断绑核程序如程序清单5- 1所示。
程序清单5- 1 中断绑核设置
LW_CLASS_CPUSET cpuset; LW_CPU_ZERO(&cpuset); LW_CPU_SET(1, &cpuset); API_GpioRequestOne(GPIO_NUM, LW_GPIOF_IN, "intIn"); /* 下降沿触发中断 */ LW_IRQ = API_GpioSetupIrq(GPIO_NUM, LW_FALSE, 0); API_InterVectorConnect(LW_IRQ, /* 安装操作系统中断向量表 */ (PINT_SVR_ROUTINE)__doIsr, (PVOID)LW_NULL, "isr"); API_InterSetTarget(LW_IRQ, sizeof(LW_CLASS_CPUSET), &cpuset); /* 设置中断目标CPU1 */ API_InterVectorEnable(LW_IRQ); /* 中断使能 */
程序运行后,如图5- 2所示可以看出,测试中断向量绑定到CPU 1,其他中断向量绑定到了CPU 0。
图5- 2 中断绑核
在不加负载的情况下,中断响应时间测试结果如图5- 3所示,可以看出中断响应时间在3us左右,并且实际测试时响应时间没有太大波动。
图5- 3 绑核无负载中断响应时间测试结果
在加负载(CPU负载和内存拷贝负载)的情况下,响应测试结果如图5- 4所示,响应时间为4us,并且实际测试时响应时间没有太大波动,负载对紧急任务的中断响应时间影响很小。
图5- 4 绑核有负载中断响应时间测试结果
根据上述测试结果可以看出,中断绑核也可以保证中断响应时间的稳定可靠