利用中断或异常实现协程多任务的切换
1赞
利用中断或异常实现协程多任务的切换
-- 微控制器中基于协程的实时协作多任务方法 (5)
在以往用汇编编程时,我有时借用中断实现协程多任务的切换,即借用中断完成协程的YIELD。这种方法也可用于C与汇编混合编程实现无标号切换。
前面说到,用CALL指令可以取得后一指令的地址而无须使用标号。除此之外,另一个不用标号而可以取得后一指令的地址就是中断;对ARM而言,就是异常(Exceptions)。
例如,在8051的具体应用中,我们往往不会用完所有的中断,我们可以借用空置的中断来取得后一指令的地址。
设某中断INTn被借用,我们可以用
SETB INTn_flag ;中断标志往往可以用软件来置位
来取代前面的
CALL yield ;
而用前面yield的汇编指令作为INTn的中断响应。一进入中断,“后一指令的地址”就已经在堆栈中。
具体变化多而灵活,无法在此一一罗列汇编代码。熟悉汇编的工程师自然可以自行写出混合编程的代码了。
利用中断实现协程多任务切换,带来一个好处。就是,我们可以在一定程度上掌握协程多任务切换的优先权。甚至可以选择最高优先权,在与抢占式方法联合使用时,协程切换时的优先权可以高于任一抢占式的优先权。
对应于ARM Cortex-M,自然是“异常”了。ARM Cortex-M的系统服务调用指令SVC(软中断指令)很适合作此运用。
在这之前,我必须先说一下Cortex-M的YIELD指令。
在ARM Cortex-M的具体产品问世后,我觉得,在产品设计中MCU的选择从8051升级到Cortex-M的时机到了。因此,一些以前在8051或其他MCU中使用的成功方法,也该转移到Cortex-M。
其中,我考虑上述通过中断切换协程多任务的方法,该如何移植到Cortex-M。首先,吸引我的是YIELD指令。数据手册中对它的描述是:
YIELD indicates to the hardware that the current thread is performing a task, for example a spinlock, that can be swapped out. Hardware can use this hint to suspend and resume threads in a multithreading system.
YIELD 可告知硬件有线程正在执行任务,例如可换出的自旋锁。 硬件可使用此提示在多线程系统中暂挂并恢复执行线程。
但是找不到YIELD是如何执行的。直到在姚文祥(Joseph Yiu)的《Cortex_M3权威指南》看到YIELD是一条未支持的hint指令。
为了搞清原委,2011年1月在圣塔克拉拉会展中心的RTECC(Real-Time & Embedded Computing Conference)展会上,我问ARM展台的产品经理Robert Boys先生:为什么Cortex-M3不支持YIELD指令。他说:没有这回事(it is not true)。
回家后,我找到了姚文祥的原文,当晚给Bob Boys发了一份邮件,并告知,我想借用YIELD实现实时多任务的切换,而不借助于RTOS。
Robert Boys把邮件转给了ARM权威姚文祥,姚先生第二天给我回了邮件,说明YIELD指令是为具有“硬件多线程处理能力”的处理器而预设的。目前还没有这样的处理器,所以等效于NOP。有兴趣的话,可看一下附件:姚文祥(Joseph Yiu)关于YIELD指令的邮件.pdf 。
这等于透露了一个消息,预计会出现具有“硬件多线程处理能力”的处理器,而无需软件介入了。
Joseph 还说到,可用Cortex-M的SVC来实现这种切换。这与我前面的想法一致,所以我回应说:我知道怎么办了。
用Cortex-M的SVC实现协程多任务的切换。
实际上,看了我前面所介绍的混合编程实现协程多任务的切换方法;以及知道进入SVC异常服务程序,可从栈中保存的PC取得“后一指令的地址”这一招;掌握汇编的人,都该“知道怎么办了”。 使用SVC,可能要多花费几条指令。
SVC #immd指令后面的立即数,可分别指示way_out、yield函数等等;以及传递ret_code等等。不过,SVC往往还承担其他功能调用,如何协调,只能各显神通。大家可自由发挥,海阔天空,无法一一穷尽。再写,就显得多余和啰嗦了。
顺便说说,某些培训教材,说的是针对Cortex-M0,关于SVC调用,抄的是《Cortex_M3权威指南》中Cortex-M3关于SVC调用的指令例子。其中,好多条M3的指令在Cortex-M0中是行不通的,千万要注意。最好是去看看Joseph Yiu的《The Definitive Guide to the ARM Cortex-M0》。
只可惜,已经告别产品设计了,不能亲手将这种用于ARM Cortex-M的实施方法,用在一个具体的应用产品中去。
===
fy_zhu
2013-02-26 SV_CA