您好、欢迎来到现金彩票网!
当前位置:老k棋牌 > 栈内容 >

uCOS-II在51单片机上的移植2

发布时间:2019-06-10 18:09 来源:未知 编辑:admin

  任务函数中带有形参和局部变量时若使用reentrant关键字会引起重入,从C51.PDF 129-131页的内容知:为了函数重入,形参和局部变量必须保存在堆栈里,由于51硬件堆栈太小,KEIL将根据内存模式在相应内存空间仿真堆栈(生长方向由上向下,与硬件栈相反)。对于大模式编译,函数返回地址保存在硬件堆栈里,形参和局部变量放在仿真堆栈中,栈指针为?C_XBP,XBPSTACK=1时,起始值在stap.a51中初始化为FFFFH+1。仿真堆栈效率低下,KEIL建议尽量不用,但为了重入操作必须使用。KEIL可以混合使用3种仿真堆栈(大、中、小模式),为了提高效率,针对51推荐统一使用大模式编译。

  为了支持重入,重新设计了堆栈结构(如下图)。增加了保存仿真堆栈指针?C_XBP和堆栈内容的数据结构。相应改变的文件有:OS_CPU_A.ASM、OS_CPU_C.C、OS_CPU.H、YY.C。由图可知,用户栈中保存的仿真栈与硬件栈相向生长,中间为空闲间隔,显然uCOSII的堆栈检测函数失效。硬件栈的保存恢复详见上节,仿线移植中的一样,OS只提供堆栈空间和只操作堆栈指针,不进行内存拷贝,效率相对很高。

  建议使用统一的固定大小的堆栈空间,尽管uCOSII原作者把不同任务使用不同空间看成是优点,但为了在51上有效实现任务重入,针对51笔者还是坚持不使用这个优点。

  用户堆栈空间的大小是可以精确计算出来的。用户堆栈空间=硬件堆栈空间+仿真堆栈空间。硬件栈占用内部RAM,内部RAM执行效率高,如果堆栈空间过大,会影响KEIL编译的程序性能。如果堆栈空间小,在中断嵌套和程序调用时会造成系统崩溃。综合考虑,我把硬件堆栈空间大小定成了64字节,用户根据实际情况可以自行设定。仿真堆栈大小取决于形参和局部变量的类型及数量,可以精确算出。因为所有用户栈使用相同空间大小,所以取占用空间最大的任务函数的空间大小为仿真堆栈空间大小。这样用户堆栈空间大小就唯一确定了。我将用户堆栈空间大小用宏定义在OS_CFG.H文件中,宏名为MaxStkSize。

  51的SP只有8位,无法在64K空间中自由移动,只好采用拷贝全部硬件堆栈内容的笨办法。51 本来就弱,这么一来缺点更明显了。其实,引入OS必然要付出代价,一般OS要占用CPU10%-20%的负荷能力,请权衡利弊决定。切换频率决定了CPU的耗费,频率越高耗费越大,大到一定程度就该换更强的CPU了。我选了50Hz的切换频率,不高也不低,用户可以根据需要自行定夺。在耗费无法避免的情况下,我采取了几个措施来提高效率:1。ret和reti混用减少代码;2。IE、SP不入出栈,通过另外方式解决;3。用IDATA关键字声明在汇编中用到的全局变量,变DPTR操作为Ri操作;4。设计堆栈结构,简化算法;5。让串口输入输出工作在系统态,不占用任务TCB和优先级,增加弹性缓冲区,减少等待。

  zyware网友2002/11/22来信询问uCOS51在单片机上的硬件仿线核,以及一些构件,keilc上仿真通过,用wave接硬件仿真程序乱飞,wave仿真以前的程序没有问题,不知是何缘故”。

  由于我的OS程序已经在KEIL软件仿真和硬件上实际测试过,所以不可能是程序错。可能的原因只能是硬件仿真软件设置问题。本人用的是Medwin软件,在Insight上调试,使用uCOS51编译测试程序一样跑飞。即使添加修改后的startup.a51(详见《在51单片机上固化uCOS51的说明》)也不正常。我发现Medwin似乎没有编译startup.a51,因为它把该文件加在了other Files目录下而不是source Files目录,于是我猜测只有放在source Files目录下的文件才被编译。由观察知,以.c和.asm做后缀的文件均被放在此目录下且被编译。于是我立即将startup.a51改成startup.asm并加入项目编译,结果测试正常。不必担心startup改名造成冲突,KEIL在链接目标文件时会自动处理重名段,本目录的文件优先级高(我是这么理解的,具体原理不清楚,这只是根据实践得到的结论,希望了解此处理过程的朋友能告之,不胜感激。)。

  近来,收到多位网友来信询问uCOS51在51单片机上的固化问题,归纳其焦点就是:为什么OS在KeilC51上模拟可以正常运行,但把它烧录在CPU上却不能工作?理论上,程序在软件仿真通过测试后,将其烧录在硬件上,硬件调试应该一次成功。许多网友也有这个经验,可为什么在调试uCOS51时失效了呢?难道操作系统调试很特殊吗?

  其实问题出在重入函数的引入。原来KEILC51软件仿真在不修改startup.a51文件的情况下,缺剩使用64K外部RAM,它把0000H-FFFFH全部仿真为可读写的RAM,而用户的硬件系统可能没有用到那么大的RAM空间,比如只用了8K/16K/32K等,或者用户把一些地址空间映射给了别的设备,比如8019AS等。在没有调用OSTaskCreate前,定义为reentrant的函数将用FFE0H做仿真堆栈栈顶指针,而此处在用户的系统里不是RAM,造成程序跑飞。比如在我的用户板上,将FE00H-FFFFH空间的一部分分配给8019AS使用,如果把demo程序编译后直接烧到51上,将不能运行。解决办法是根据系统RAM配置,修改startup.a51文件,并将其加入项目编译,如下所示:

  按此修改后,在有32K外部RAM的系统上可以正常运行。用户可根据自己XRAM的实际配置情况修改startup.a51相关参数,并将其添加到项目里编译。不必理会KEIL/C51/LIB目录下的同名文件,此处的startup.a51优先级高,KEIL将按此处该文件的配置编译项目。

  这也解释了有些网友问到的,“为什么加入reentrant关键字,在软件仿真时正确,烧在芯片上就死机,去掉reentrant后两者都正常”的问题。由于大多数人很少使用重入函数,往往不了解这个细节,特此提请大家注意。

  以上是我这次移植uCOS51的一些心得,写出来只是让准备在51上运行操作系统的同行们少走弯路并增强使用信心。我强烈推荐大家在自己的51系统中使用uCOS这个简单实用的自己的操作系统。它的大小应该不是问题,性能上的提高却是显著的。但愿此文能对朋友们有所帮助,错误在所难免,希望读者指正。

http://theenigmaco.com/zhannarong/65.html
锟斤拷锟斤拷锟斤拷QQ微锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷微锟斤拷
关于我们|联系我们|版权声明|网站地图|
Copyright © 2002-2019 现金彩票 版权所有