好好学习,天天向上
分类:
2013-02-27 21:28:41
原文地址:关于周立功UCOS移植代码中任务切换的笔记 作者:cbqcgq
笔记一:
今天粗略的看了一下周立功关于uc/osII在lpc2104上的移植方面的说明,这之中印象最深的应该是irq中断和软中断方面的处理,由于arm芯片的特殊性(拥有7种处理器模式),即每种处理器模式都有自己的堆栈,这样在处理堆栈的时候就会相应的麻烦一些。
在响应异常时,该移植计划在初始代码里面比在没有操作系统的初始代码多了irq的处理,移植里面的irq处理多了由汇编语言编写的对任务环境的保存,没操作系统的中的任务环境的保存都是由在产生irq中断是用c语言声明的__irq关键字来完成了,移植中irq中断不能采用__irq关键字,因为c语言不能保证堆栈结构,而uc/osII必须要保证堆栈结构。除此之外,相对于没操作系统的初始代码,基本上是没有什么改变。
在uc/osII的任务切换中,采用了arm里面的软中断指令swi来执行,对于非中断性的任务切换(如挂起和等待信号量的时候)uc/osII是采用了宏os_task_sw()来执行的,然后联系到osctxsw()函数来完成任务切换,而遇到中断情况时在返回是需要任务切换是则采用了osintctxsw()来执行的,在周立功的移植当中,他把osctxsw()与osintctxsw()合二为一了,统一采用osintctxsw()来实现。之所以这样搞的原因是任务进行切换的时候,都必须进入软中断的状态,而对于软中断的异常响应代码已经将任务的环境变量进行了保存,从而也不需要像osctxsw()里面规定的那样对将环境变量进行保存。
这是我看今天看了移植说明后所理解的东西,当然还得细致的对代码进行分析,特别是osintctxsw()代码的分析,虽然移植的代码大体是遵从了uc/osII的编码规范,但对于arm的多种处理器模式移植代码有特别的改变,以实现cpu时间和ram的利用。
笔记二:
感觉osintctxsw()这个函数需要进行仔细的解读,好多其他函数都与他由关联,而在uc/osII中的原型是没有这样的情况的,我想出现这个现象的原因是由于arm芯片的特殊性(拥有7种处理器模式),这样在处理堆栈的时候就会相应的麻烦一些。
移植的osintctxsw()函数由两个部分,以标号osintctxsw_1作为分界点。
关于osintctxsw_1以下的程序,LPC2100_FAQ.pdf文档里面的第126问作了详细的解释,即实现的是任务的恢复运行。
而osintctxsw_1以上的程序段的功能如周立功的移植说明里面的解释:前面的关于中断与c语言的接口已经说明,寄存器应当保存到任务的堆栈中,但为了节省cpu时间和ram的空间,仅在必要的时候才将寄存器保存到任务的堆栈,OSTCBCur->OSTCBStkPtr=SP也是在必要的时候才执行,这一段代码就是来处理这两件事情的。(即将任务的环境变量由模式堆栈复制到当前任务的任务堆栈中,对照周立功书上374页与378页的两个堆栈图来理解这部分代码就很清晰明了了)。
理解了以上关于osintctxsw()两个部分代码的解释,也就不难理解为什么有些函数都来引用osintctxsw()了,就以__OSStartHighRdy中引用osintctxsw_1为例来说明,他在代码的末尾最后引用osintctxsw_1,就是要实现任务的恢复运行(从新任务堆栈中恢复所有寄存器,执行中断返回指令)。
最后对于osintctxsw()要注意的是,这个函数的移植并非是简单的ucos中的osintctxsw()原型的声明,因为在移植的代码中,要用到osintctxsw()必须得引用OS_TASK_SW()宏才可以,这样就引出了在ucos的c代码函数osintexit()时调用osintctxsw()函数该怎么办这个问题了。
周立功的移植是在includes.h中定义一个宏osintctxsw(),由于这个宏在c语言中使用,所以不会与汇编的函数osintctxsw冲突,宏定义如下所示:
#define osintctxsw()
{
OSEnterSum=0;
return;
}
而中断返回时要执行的任务切换这一行为实际上已经在irq异常响应代码中由它来完成了,也就是说移植完成后osintctxsw()起的作用已经不是ucos的作者想起的作用了。
现在感觉有点不明白的是OSEnterSum所起的作用,ucos原型中并不存在这一变量。
笔记三:
今天接着昨天的疑问看的,OSEnterSum所起的作用也搞清楚了,周立功的移植中对于开关中断,即OS_ENTER_CRITICAL()与OS_EXIT_CRITICAL()选用的方法是2(即OS_CRITICAL_METHOD=2),而在ucos的原型中关于OS_CRITICAL_METHOD=2的说明可以清楚的知道,它是想实现在先将关中断前将中断状态保存到内存中,然后关中断,尔后,恢复保存在堆栈中的关中断之前的中断状态,这样的说明清楚的说明了关中断是可以嵌套的,而参数OSEnterSum的出现正是为了实现关中断的嵌套而设计的。移植的关于OS_ENTER_CRITICAL()与OS_EXIT_CRITICAL()的说明周立功的书上说的很清楚了。而昨天看的定义的宏osintctxsw()之所以要用OSEnterSum是因为调用osintctxsw()的肯定是osintexit()函数,而调用osintexit()肯定是处于开中断状态的,则OSEnterSum肯定等于0。所以这个时候必须把OSEnterSum调整为0(看到这里我又产生了另外的一个问题,就是还有其他的地方引用OSEnterSum变量吗?不然,即使不将OSEnterSum也应该没什么关系)。
今天看到关于OSTaskInit()的移植有值得注意的地方,堆栈必须按设计好的进行初始化(周立功书上374页堆栈图)。还有任务的数据指针是由r0来传递的。
还有移植增加的特点的函数,感觉还是很好理解的。
至此,移植的理论部分基本上完成,接下来的应该是实践环节了,即进行操作系统在板上的调试。