历史上的今天
返回首页

历史上的今天

今天是:2025年02月03日(星期一)

2021年02月03日 | 提高uCOS-II在ARM上的执行效率

2021-02-03 来源:eefocus

uCOS-II是一个公开源码的抢占式、多任务的实时操作系统,因其具有开源性、实时性强、代码紧凑、稳定可靠等特点在各种系统中得到了广泛应用.uCOS-II在ARM 处理器上的移植也已经实现.ARM处理器加uCOS-II操作系统的嵌入式系统常用于工业实时控制,对执行效率特别是实时性要求较高.提高uCOS-II执行效率的关键是减少任务切换时间,任务切换时主要的操作是任务栈的出栈和入栈操作.由于ARM处理器在不同的处理器运行模式具有不同的堆栈,合理利用该特性并结合处理器运行模式切换特点能够减少任务栈操作次数,减少任务切换时间.本文主要提出了两类提高uCOS-II在ARM 上执行效率的方法:

① 减少任务栈操作次数.

② ARM处理器上的uCOS-II的可重入中断的实现.


1 uCOS-II在ARM 上的任务切换

uCOS-II中进行任务切换的函数是OSStartHighRdy()、OSCtxSw()、OSIntCtxSw().其中OSStartHighRdy()是在操作系统第一次启动的时候调用的,OSCtxSw()是用户主动调用进行任务切换,这两个函数和中断无关,所以和ARM 的处理器模式无关,在ARM上的实现方法和一般处理器类似.


OSIntCtxSw()用于在中断中进行任务切换.嵌入式实时系统响应外部事件主要通过外部中断,在中断中将高优先级的任务设置为就绪状态,然后在中断退出时自动切换到高优先级的任务.为了实现该功能,uCOS-II要求用户在中断中:

① 若需运行高优先级任务,设置该高优先级任务的就绪标志位.

② 在中断函数末尾调用OSIntExit()函数,OSIntExit()函数检查是否有高优先级任务就绪,有则调用OSIntCtxSw(),并切换到该高优先级任务.


进行任务切换时需将当前任务的状态变量压入堆栈(也就是当前任务栈),然后将堆栈指针指向高优先级任务的任务栈,并弹出该高优先级任务堆栈中的状态变量.由于OSIntCtxSw()在中断中调用,而进入中断函数后一般已经保存状态变量到堆栈,于是OSIntCtxSw()不需要进行上述压栈操作.但是由于ARM体系结构决定了中断和非中断中使用不同的运行模式和堆栈,使得该问题变得复杂.例如,假设在非中断中使用SVC模式(管理模式)和SVC堆栈;中断中使用IRQ模式(外部中断模式)和IRQ堆栈;任务切换时需要保存的状态变量为PC,R12-R0,RL,CPSR,SPSR,且它们任务栈中的排列顺序如图1所示.设中断函数为OSInt1(),则通常在ARM上实现OSInt1()和OSIntCtxSw()可用表1、表2的伪代码表述:

图1 任务栈结构图


表1 OSInt1中断服务程序的伪代码

OSInt1

{

将LR_irq-4、R12至R0的内容依次入栈;

/*LR-4是中断服务程序的返回地址即PC*//*A处*/

清除中断标志位; /*B处*/

调用OSIntEnter;

中断事件处理,例如使得高优先级任务就绪;

调用OSIntExit;

将堆栈的内容依次弹出到R0至R12、PC寄存器中,同时从SPSR_irq恢复状态寄存器;

}

表2 OSIntCtxSw程序的伪代码

OSIntCtxSw

{

调整堆栈指针SP到表1中”A处”; /*C处*/

保存SPSR_irq(中断返回状态寄存器),从堆栈中弹出R0-R12,LR_irq,并保存LR_irq(中断返回地址);/*D处*/

强制切换到SVC模式;

将LR_irq,LR_SVC,R12-R0,CPSR_irq,SPSR_irq依次压入堆栈; /*E处*/

调用_OSCtxSw;/*_OSCtxSw是OSCtxSW 函数去除入栈操作的部分*/

}

从表1、表2可见在ARM 处理器上OSIntCtxSw()不仅没有节省压栈操作,而且还多了一步出栈操作.这是由于中断函数OSInt1()压入的状态变量不在任务栈(即SVC堆栈)中而是在IRQ堆栈中,所以OSIntCtxSw()必须重新从IRQ堆栈中弹出状态变量,并将其压入SVC堆栈.该额外的出栈入栈操作增加了任务切换时间.这也是现有的uCOS-II在ARM 上实现的方式.


2 减少任务栈操作次数的改进

为了防止OSIntCtxSw()中进行额外的出栈入栈操作,本文提出了两种改进方案:

2.1 中断中使用SVC堆栈

假如在中断中直接使用SVC堆栈,那么进入中断函数后的压栈操作将状态变量直接压入了任务栈,这样就不需要在OSIntCtxSw()中进行额外的出栈和入栈操作.实现方法是,在进入中断函数的第一时刻,将SVC堆栈寄存器SP_svc的内容拷贝到IRQ堆栈寄存器SP_irq中.此后虽然中断中仍然使用SP_irq寄存器,然而实际指向任务栈.本文实现该方案的伪代码如表3、表4所示:

表3 改进1的OSInt1中断服务程序的伪代码

OSInt1

{

切换到SVC模式;

将 SP_SVC保存到临时变量save_sp_svc中;

切换回IRQ模式;

将save_sp_svc的内容加载到SP_irq中;

跳转到_OSInt1;/*这里的_OSInt1和表1的OSInt1完全一样*/

}

表4 改进1的OSIntCtxSw程序的伪代码

OSIntCtxSw

{

调整堆栈指针SP_irq;

保存SPSR_irq(中断返回状态寄存器)到R0,保存SP_irq到R2;

强制切换到SVC模式;

复制R2(=SP_irq)到 SP_SVC;将LR_svc,R0(=SPSR_irq),R0(=CPSR),依次压入堆栈;

调用_OSCtxSw;

}

本文实际汇编程序实现表1、2的代码共需45次出栈入栈操作,而实现表3、4的代码减少到17次出栈入栈操作.


2.2 中断中使用SVC模式

§2.1的改进需要首先切换到SVC模式,然后切换回IRQ模式(如表3所示),最后在OSIntCtxSw()中又要切换到svc模式(如表4所示),假如在IRQ中直接使用SVC模式,即可以同样使用SVC堆栈达到§2.1改进的效果,同时减少了在SVC和IRQ之间来回切换的麻烦.本文实现在中断中使用SVC模式的伪代码如表5、6所示:

表5 改进2的OSInt1中断服务程序的伪代码

OSInt1

{

保存lr-4到临时变量INT_RET_ADDR;

将SPSR_irq(返回后的CPSR内容)保存到INT_RET_CPSR;

强制切换到SVC模式;

将INT_RET_ADDR,R12-0,LR_SVC,INT_RET_CPSR依次入栈;

清除中断标志位; /*F处*/

调用OSIntEnter;

中断事件处理,例如使得高优先级任务就绪;

调用OSIntExit;

从堆栈中弹出INT_RET_CPSR,写入CPSR;

表6 改进2的OSIntCtxSw程序的伪代码

OSIntCtxSw

{

调整堆栈指针SP;

将SPSP_SVC压入堆栈;

调用_OSCtxSw;

}

实际代码中该方案的出栈入栈次数也是17次.但该方法要求在IRQ模式切换到SVC模式之前保存IRQ模式下的一些变量(如SPSR_irq、LR_irq)这增加额外的一些操作.§2.3的实验表明该改进的效率没有§2.1的改进高效,但是该改进为§3的可重入中断做好了准备.


2.3 任务切换时间的比较

为验证改进方法对减少任务切换时间的效果,本文设计如下实验:

让uCOS-II的一个任务Task1等待(用OSSemPend函数实现)信号量mysem,此时Task1挂起.当键盘按下时进入OSInt1中断函数,在该中断中发送(使用OSSemPost函数)mysem信号量,使得Task1进入就绪状态.当OSInt1退出时切换到Task1任务.对于三种实现方法:通常的任务切换方法、中断中使用SVC堆栈的任务切换方法和中断中使用SVC模式的任务切换方法,分别测试键盘按下到切换到Task1的时间差.为此在OSInt1()中断函数开始处获取定时器初始值t1,在进入Task1以后读取定时器当前值t2,则t=|t1-t2|就是想要的时间差.

对三种实现方法分别进行43次实验,测得的t如图2所示.实验时,定时器以PCLK/2(PCI K设置为50700000)的速率减法计数.

图2 三种方法的任务切换时间比较

从图2可知,两种改进的方法比通常方法需要更少的任务切换时间;§2.2的方法比§2.1的方法需要更多的任务切换时间与原先的分析符合.

从改善的性能上,这里可以从计数值的相对值来看,§2.1的方法比通常方法约改善了61/1403=4.3% ,但是必须考虑到时间t包含了中断产生到切换到Task1的整个代码的执行时间,其中包含了OSSemPost()、OSIntExit()等较复杂函数,所以可以说该改进是有效的.


3 可重入中断对任务切换时间的影响

3.1 uCOS-II对可重入中断的支持

uCOS-II本身支持可重入中断,它在OSIntExit中使用IntNesting变量表示了中断嵌套的层数,uCOS-II只在退出最后一层嵌套时才进行任务的切换,这可以通过检查IntNesting变量来获知.

中断的嵌套增加了任务切换的实时性,以例子说明如下:假设有两个任务:taskTimer和taskKey,taskTimer由定时器触发;taskKey由外部中断源(例如按键)触发,taskKey的优先级比taskTimer高.如图3所示,当外部中断发生时,若处理器正好处于定时中断中.中断可重入时,系统马上进入外部中断服务程序让Task_Key就绪,并在退出最后一层中断(定时中断)时,切换到Task_Key;中断不可重入时,需要首先切换到低优先级任务TaskTimer,然后再次进入中断,然后才切换到高优先级任务Task_Key.

由此可见中断可重入时,在有多个优先级的任务共存的情况下,高优先级任务的实时响应时间更短了.

图3 中断可以重入和不可重入时任务切换的差别


3.2 ARM处理器对可重入中断的支持

在默认情况下ARM处理器不支持可重入中断.当ARM进入IRQ中断以后自动关闭IRQ使能标志,禁止IRQ中断的嵌套.为了支持IRQ的可重入,需要:

(1)在重新使能IRQ中断之前保存必要的寄存器.

(2)在重新使能IRQ之前使用SVC模式,并在中断退出以前一直保持SVC模式.


3.3 在Arm上实现uCOS-II可重入中断

§2.2的方法实际已具备可重入中断的要求,只要在表5的“F处”之后重新使能IRQ中断标志位即可.在重新使能IRQ中断之前需要注意的是首先需要清除中断源的中断位,防止重新使能IRQ中断标志位后同一中断源重复中断.


4 结论

本文提出了两点提高uCOS-II在ARM 上执行效率的方法:减少任务栈操作次数和实现可重入中断.在中断中直接使用SVC堆栈和在中断中直接使用SVC模式的改进减少了额外的出栈入栈操作,减少了任务切换时间,实验结果证实该改进的有效性.可重入中断在ARM处理器的uCOS-II上的实现,使得高优先级任务的实时响应时间更短了.两点提高效率的方法不仅有助于提高ARM 上uCOS-II的执行效率.同时也对在ARM上实现高实时的嵌入式操作系统有借鉴意义.


推荐阅读

史海拾趣

Heidenhain Corp公司的发展小趣事

随着智能制造的兴起,海德汉公司积极转型为智能制造解决方案提供商。该公司与多家电子企业合作,共同探索智能制造的新模式和新路径。通过集成海德汉的数控系统、自动化设备和智能管理软件,这些企业成功构建了高效、灵活、智能的生产体系。海德汉的智能制造解决方案不仅提高了生产效率和产品质量,还降低了生产成本和能耗,为电子行业的可持续发展做出了积极贡献。

FOSLINK公司的发展小趣事

面对全球气候变化的严峻挑战,FOSLINK公司积极响应国家关于绿色发展的号召,将绿色转型作为企业发展的重要方向。公司致力于研发和生产低能耗、环保型的电子产品,并不断优化生产工艺流程,减少资源消耗和环境污染。同时,FOSLINK还积极推广绿色供应链管理,与供应商和客户共同构建绿色、低碳的产业链生态。这一系列的绿色转型举措,不仅彰显了FOSLINK的社会责任感,也为其赢得了更多消费者的青睐和支持。

长江微电(cjiang)公司的发展小趣事

长江微电(CJIANG)自创立以来,始终专注于电感产品的材料研发、技术研发、生产工艺和生产设备的研发和改进。面对国外品牌在电感技术领域的领先地位,长江微电并未退缩,而是选择迎难而上。通过多年的努力,其技术团队基于对磁性材料的深入研究和对生产工艺的不断改进,成功突破了VISHAY等国外品牌的技术壁垒,拥有了全系列的一体成型电感产品。这一突破不仅彰显了长江微电的技术实力,也为公司的发展奠定了坚实基础。

昆泰(CHRONTEL)公司的发展小趣事

多年来,昆泰始终秉持着创新的理念,不断推动其在CRO领域的技术突破和业务创新。通过与全球各地的药企、科研机构合作,昆泰在药物研发、临床试验等领域取得了多项重要成果。展望未来,昆泰将继续坚持创新驱动的发展战略,为全球医药行业的发展做出更大的贡献。

All Sensors公司的发展小趣事

在过去的30年里,All Sensors一直致力于为OEM客户设计定制各种经典的传感器。这些传感器不仅具有高精度、高可靠性和高灵敏度,还广泛应用于航天航空、医疗设备、环保仪器等多个领域。凭借卓越的产品性能,All Sensors的部分经典产品甚至被业界某大公司收购并发扬光大,进一步扩大了其在电子行业的影响力。

Fischer Connectors公司的发展小趣事

随着电子行业的快速发展和市场竞争的加剧,All Sensors面临着越来越多的挑战。然而,公司始终保持着敏锐的市场洞察力和创新精神。通过与客户紧密合作,仔细聆听客户需求,All Sensors不断开发出适应市场变化的新产品和技术。同时,公司还注重提升产品质量和服务水平,赢得了客户的广泛认可和信赖。

这些故事只是All Sensors在电子行业发展历程中的一部分缩影。作为一家全球领先的传感器技术领军企业,All Sensors将继续秉承创新精神,不断推动电子行业的发展和进步。

问答坊 | AI 解惑

VHDL设计中电路简化问题的探讨

摘 要:从描述方法、设计规则、逻辑函数分析了VHDL设计中容易引起电路复杂化的原因,并提出了相应的解决方法。    关键词:VHDL 电路简化 近年来,随着集成电路技术的发展,用传统的方法进行芯片或系统设计已不能满足要求,迫切需要提高 ...…

查看全部问答>

给大学生就业支招3--部分面试试题

看了我们历年来的部分招聘试题,大家一定会觉得太容易了,但大多数学生还是做不出来,包括研究生在内,比例达到98%以上,所以我不得不投入到创新教育实践活动之中去。我们每次出题之前都要翻看各种版本的教材与实验指导书,如果只有一本书上有类似 ...…

查看全部问答>

各种开关电源电路图

各种开关电源电路图…

查看全部问答>

2010 TI 模拟产品应用及技术研讨会

2010 TI 模拟产品应用及技术研讨会 6/01 Hefei 合肥 6/03 Shenyang 沈阳 6/22 Suzhou  苏州 全球半导体领导厂商 - 德州仪器(Texas Instruments, TI),多年来致力于高效能模拟技术的研发与推广,为了协助中国开发更多高效能模拟技术 ...…

查看全部问答>

超级终端串口

我的计算机没有串口,请问可以把开发版与pc用usb相连接,达到超级终端的效果吗?我买的jtag也不要配套,一个是2.0一个是2.54.没有超级终端就进不了uboot,也就没法下载程序,着急啊。…

查看全部问答>

关于DS18B20的程序问题,急请各位帮帮忙!

谢谢大家,我是做毕业设计,板子焊接好了,程序在1820资料中找了一下,拼在一起,但是。。。不知道哪里出了问题,显示一直是00.0 DQ接的是P3.3,显示部分是3位一体的LED,P0做段选,P2.0P2.1P2.2做位选。我的想法是按照程序说的是读出的温度是存在3 ...…

查看全部问答>

显示JPEG图象失真?

  在WinCE平台上用IIMAGE 绘制 数码相机拍出来的JPEG图象时会失真,有什么好的解决办法吗?…

查看全部问答>

电源完整性和信号完整性方面的测试

来自:电子工程师技术交流(12425841)大家分享分享经验啊!…

查看全部问答>

【讨论】(十分古怪的)关于msp430 IAR编译器对堆栈的分配的疑问

我发现 在一个子函数中使用到 unsigned char DotBuf[32];这个时候,堆栈的使用量猛增! 而且在一个函数中多次调用fun1();堆栈的使用量是累加在一起的,为什么这么古怪,每次退出 fun1();程序不会释放 这个函数中的局部变量的嘛???? void fun1() { ...…

查看全部问答>

为什么TIM_ARRPreloadConfig在我的程序中没有作用 他到底有什么作用?

我用TIM2定时一秒,可是 不管我将TIM_ARRPreloadConfig设置为DISABLE 还是ENABLE,结果都不变。我都不明白TIM_ARRPreloadConfig有什么作用了;  另外,TIM_TimeBaseStructure.TIM_Prescaler=0还是9我都试过,定时还是一秒;不知道为什 ...…

查看全部问答>