以太网LED图文显示系统的设计 第5页

以太网LED图文显示系统的设计 第5页
同时预留挂接拼C/OS一11系统服务的函数的接口。
(3)05_STK‘GROWTH
环C/OS一n使用结构常量05_ST--KGROWTH中指定堆栈的生长方式,虽然ARM处理
器核对于两种方式均支持,但ADS的C语言编译器仅支持一种方式,即从上往下增长,
并且必须是满递减堆栈,所以必须置05_ST--KGROwm为1。
2.3.5编写05_CPU_C.C文件
编写05_CP让C.C文件所做的工作主要有以下几个方面:
(1)编写任务堆栈初始化函数OSTaksskt瓦0t,在编写此函数之前,必须先确定任务
的堆栈结构。任务的堆栈结构与CPU的体系结构、编译器有着密切的关系。本文移植的
堆栈是满递减堆栈,寄存器的顺序是首先是PC寄存器然后是LR、R12、Rll直到RO,然
后是CPSR,最后是全局变量中断计数器OEsntersmu。OEsniersmu用来保存关中断的次
数,这样关中断和开中断就可以嵌套了。在调用05一XI--TCFJTICALO时,它的值减少,
并且仅在值为O时开中断。每个任务都有独立的OsEntersmu,在任务切换时保存和恢复
各自的OsEntersmu。
(2)软件中断异常Swi服务程序C语言部分,这部分程序有两个入口参数:功能号
sW--I-Num和指向堆栈中保存寄存器的位置Rges,程序中使用了一个swithc语句把各个功
能分开。软中断的o、1号功能在05_CPU匕八.5中实现。
(3)开中断和关中断宏的编写。拜C/OS一n使用宏05--ENTE--RCFJTICALO和
OSesEXI几c班TICALO分别来关中断和开中断。关中断和开中断是为了保护临界段代
码。这些代码和处理器相关,是需要移植的代码。在ARM处理器核中关中断和开中断是
通过改变程序状态寄存器CPSR中的相应控制位实现的。具体修改寄存器的代码是由汇
编语言编写的。OSeeENTE凡CFJTICALO的汇编代码和程序文件05_cP--UA.s中x002号
软中断调用相似,05多XI--TCRITIcALO则和x003号软中断调用相似。
俨)编写启动高优先级函数0SStartHigRhdy()。环C/OS一n的启动多任务环境的函数叫
做OSSt叭O,用户在调用OSSt献O之前,必须己经建立了一个或多个任务。oSStarto最
终调用函数OSStartHighRdy()运行多任务启动前优先级最高的任务。而函数
OSSt叭Hi沙卫dyo则是通过调用软中断的1号功能来实现的。
2.3.6编写05_CPU一S
05一PU多.5的移植需要编写4个汇编语言函数:OSSt叭HigRhdy()、ose饮Sw()、
OShiiCtXtSwO、0STikclSR()。本文中只给出这几个函数代码实现的算法。
(1)OSStartHigRhdy()
基于以太网的LED图文显示系统的设计
OsstartHigRhdyo使就绪态任务中优先级最高的任务开始运行,函数的伪代码如下
所列。
voidOSSt压rtHigRhdy(void)
{
调用用户定义的OSTaskSWHook();(l)
OSRunnin犷TL)RE;(2)
得到将要恢复运行任务的堆栈指针;(3)
StaekPoi掀半OSTCBHighRd梦>OSTCBStkPtr;
从新任务堆栈中恢复处理器的所有寄存器;(4)
执行中断返回指令;(5)
}
①OsstartHi沙RIdyO必须调用OsTaskswHook()函数;但OSStartHlghRdyO函数只是
做了任务切换工作的一半—只是完成了高优先级任务寄存器的恢复,而没有保存当前任务的寄存器。oSTaskswHokoO函数必须检查OSR卫几亩ng标志位,以确定
osTasksWHookO函数是被osstartHigRhdy()调用的(OSRunni铭是FALSE),还是在Ei常
的任务切换之中(osRunnnig是TUR卫)被调用的。
②OSStartHigRhdy()调用完oSTaskswHook()后,将OSR月nning标志设为TURE,这
时更高优先级任务的寄存器还没有被恢复。
③osstHartigRhdy()要得到更高优先级任务的堆栈指针。osst斌HihgRdv()假设
osTCBHi砂Rtdy指向最高优先级的任务控制块。需要恢复的任务堆栈指针总是存储在任
务控制块的偏移地址为O的位置。
④拜C/os一n中,处于就绪状态任务的堆栈结构看起来就像刚发生过中断一样,所有
的寄存器都保存在堆栈中。要想运行最高优先级的任务,需将所有处理器寄存器按顺序
从任务堆栈中恢复出来,并执行中断返回指令。osstartHigRhdyO函数中最后一个步骤
即时执行中断返回指令,使得CPU从堆栈中恢复程序指针以及CPU的状态寄存器,该操
作使得CPU开始恢复执行最高优先级任务的第一条指令。
(2)OSC饮Sw()
任务级的切换是通过执行软中断指令,或者依据处理器的不同,执行TRAP指令来
实现的。中断服务子程序、陷阱或异常处理的向量地址必须指向OSCtxswO。如果当前
任务调用系统提供的功能函数,并使得更高优先级任务进入就绪态,产C/OS一11就会借助
中断服务子程序、陷阱或异常处理的向量地址找到OSC饮SwO。函数的伪代码如下所列。
voidOSCXtSw(void)
{
大连理工大学硕士学位论文
保存处理器寄存器;()l
在当前任务的任务控制块中保存当前任务的堆栈指针;(2)
OSTCBCur一>OSTCBStkPtr=Stac冲ointer;
OSTaskswHook():(3)
OSTCBC=urOSTCBHig叹dy;(4)
OSPrioC=urOSPrioHighRdy;(5)
得到将要重新开始运行的任务的堆栈指针;(6)
Stac冲oinie二OSTCB凡沙卫d-y>OSTCBStkPrt;
从新任务的任务堆栈中恢复处理器所有寄存器的值;(7)
执行中断返回指令;(8)
}
①OSC饮Swo按照同OsTasknlitO函数一样的顺序将处理器的寄存器保存到堆栈中。
②当将要被挂起的任务的所有CPu寄存器都已经入栈后,osC饮SwO将堆栈指针保
存在当前任务的任务控制块中。
③当用户的移植需要扩展任务切换函数的功能时,OSC饮swo调用函数
OSTaskswHookO。
④OSC饮SwO将指向当前任务的指针指向要恢复运行的任务。
⑤OSCxtswo将新任务的优先级复制给当前任务的优先级。
⑥从新任务的任务控制块中得到新任务的堆栈指针。
⑦OSCxtsw()’恢复将运行任务的CPu寄存器。
⑧因为高优先级任务的程序计数器仍然在堆栈中,此时一个中断返回指令使得所
有的寄存器都从堆栈中弹出到对应的CPU寄存器中,从而使用户任务恢复运行。
(3)05瓦tCXtSw()
05加tExitO通过调用05玩itC饮Sw(),在IsR中执行任务切换功能。因为Osnlite饮Sw()
是在SIR中被调用的,所以假定所有的处理器寄存器都被正确地保存到了被中断任务的
堆栈中去了。OSnItiC饮SwO函数中的绝大部分代码同OSCxtswo函数一样。区别在于,
因为SIR己经保存了CPu的寄存器,而不需要再在05顶Etxi()t中保存寄存器。
(4)OSTiekISR()
拜C/OS一n要求用户提供一个周期性的时钟源,来实现时间的延迟和超时功能。时钟
节拍应该每秒发生10一100次。可以使用硬件定时器,也可以从交流电中获得50/6HOz的
时钟频率。时钟节拍中断服务子程序的伪代码如下所列。
OSTiekISR(void)
基于以太网的ELD图文显示系统的设计
{
保存处理器寄存器;
调用05玩tEnterO或者直接给OSnINtesting加1;
i(fOShiNtesting==l)
OSTCBC-ur>OSTCBStkPtr二Stac沙ointer;
给产生中断的设备清中断;
重新允许中断(可选);
OSTmieTick();
OShItExitO;
恢复处理器寄存器;
执行中断返回指令;
}
①此时中断已经禁止,可以直接给OShlNtesting(中断嵌套次数寄存器)加1,而不用
担心数据被其他中断服务破坏。如果中断嵌套层数远没有达到255,就可以不调用
OsnItEnte()r函数。
②时钟节拍中断服务子程序检查05玩Ntestnig的数值。如果05玩创estnig等于1,则
需要在当前任务的任务控制块中保存堆栈指针。
③这里取决于中断源,有些中断设备需要在中断响应时清中断。
④此处可以开中断,用来响应更高优先级的中断。也可以不允许中断嵌套。
⑤OTsciklsRO必须调用OsTimeTikcO来维持拼CO/S一n内部的定时。定时器允许任务
被挂起一定的时间,或者允许PEND类型调用的超时功能。
⑥因为执行了这个中断服务子程序,在此必须调用0snItExi()t。0SnItEx(ti)决定是
否因为这个中断服务子程序的执行,使得更高优先级的任务就绪。如果更高级别的任务
就绪,osnltExiot就不会返回到被中断的任务,而是切换到更高优先级的任务。

上一页  [1] [2] [3] [4] [5] [6] [7] [8] [9] [10]  ... 下一页  >> 

Copyright © 2007-2012 www.chuibin.com 六维论文网 版权所有