uCOS51移植心得[社区]
发布时间:2008/5/27 0:00:00 访问次数:377
前一段时间,我参与了一个snmp网管板的项目,我负责硬件设计和单板软件开发。该板的硬件由mcs51+rtl8019as组成,有64k flash 和64k sram。软件部分有操作系统和tcpip协议栈。硬件比较简单,用了一个月就搞定了,协议栈我参考了老古开发板的部分程序又上网找了snmp源代码也很快完成了,但是测试时发现当使用较低时钟频率的cpu时(为了降低成本),由于asn.1编解码部分过于庞大,而我的程序又是一个大循环,agent的响应速度受到严重影响,用户界面也反应迟钝。更坏的消息是公司为了适应市场需求,还要在上面跑ppp和http。那样的话,我就得用40mhz的at89c51rd2或者人为的把程序断成几部分然后用状态机的方法在运行时再把它们连接起来。不过,我不想增加成本,也不想把程序搞乱,迫不得已,只好使用操作系统。
说实在的,一开始我也不是很有把握,一来我不清楚51的flash是否装得下这么多代码,二来我只做过os应用开发,对于它的移植想都不敢想。不过,我在bbs上搜索了一阵儿后还是有了一些头绪。我找到了几个os的源代码(我喜欢用现成的),按照代码大小、实时性、使用人数、众人口碑等标准,最后选定了ucos2。我感觉它的实时性有保障,延时可预测,代码据说可小到2k,网上讨论这个话题的人也比较多,而且它的网站上有针对keil c51的移植实例。
经过一番查找,我得到了5个版本。其中3个是用keil编译的。本来我想直接把os代码嵌到应用程序中,但后来发现没有一个可以直接使用。有的无法用keil直接编译,有的需要修改dll在软件仿真下使用。而我需要的是能在串口输入输出,不需要修改任何无关软件,能在软件仿真和硬件上运行的实时多任务操作系统。没有办法,我只好硬着头皮去改编。
我分析了自己的劣势:1。keil刚开始使用,不太熟悉;2。混合编程以前从没有作过;3。时间紧迫,要在1个月内搞定。而我的优势就是有5个移植实例可供参考,可以上网查资料。一开始,我用“堆栈”、“混合编程”、“汇编”、“ucos”等关键字在c51bbs和老古论坛上检索相关信息并逐条阅读,读过之后,头脑中的思路逐渐清晰了。我了解到在keil的hlp目录下有a51.pdf和c51.pdf非常全面的介绍了汇编和c51,是keil的权威用户手册;sp初始化、内存清0等操作在startup.a51文件中实现,用户可以改写它;keil的变量,子程序等的分配信息可以在.m51文件里查到;keil自己的论坛里有很多疑难问题的解答……通过阅读并经过思考,解决了堆栈起点、堆栈空间大小的设定等关键问题。论坛里的问题有些是我没有想到的,这使我发现了自己的疏漏。
在网上获得大量信息后,我开始阅读《ucosii》中文版,一共读了3遍。第一遍是浏览,了解到ucosii包括任务调度、时间管理、内存管理、资源管理(信号量、邮箱、消息队列)四大部分,没有文件系统、网络接口、输入输出界面。它的移植只与4个文件相关:汇编文件(os_cpu_a.asm)、处理器相关c文件(os_cpu.h、os_cpu_c.c)和配置文件(os_cfg.h)。有64个优先级,系统占用8个,用户可创建56个任务,不支持时间片轮转。第二遍主要是把整个工作过程在头脑里过了一下,不懂地方有针对性的查书,重点是思考工作原理和流程。我发现其实它的思路挺简单的。就是 “近似地每时每刻总是让优先级最高的任务处于运行状态” 。为了保证这一点,它在调用系统api函数、中断结束、定时中断结束时总是执行调度算法。原作者通过事先计算好数据,简化了运算量,通过精心设计就绪表结构,使得延时可预知。任务的切换是通过模拟一次中断实现的。第三遍重点看了移植部分的内容。对照实例,研究了代码的具体实现方法。
前期准备用了20几天,真正编写代码只用了1.5天,调试用了2天。具体过程如下:
(1)拷贝书后附赠光盘sourcecode目录下的内容到c:\yy下,删除不必要的文件和ex1l.c,只剩下p187(《ucosii》)上列出的文件。
(2)改写最简单的os_cpu.h
数据类型的设定见c51.pdf第176页。注意boolean要定义成unsigned char 类型,因为bit类型为c51特有,不能用在结构体里。
ea=0关中断;ea=1开中断。这样定义即减少了程序行数,又避免了退出临界区后关中断造成的死机。
mcu-51堆栈从下往上增长(1=向下,0=向上),os_stk_growth定义为0
#define os_task_sw() osctxsw() 因为mcu-51没有软中断指令,所以用程序调用代替。两者的堆栈格式相同,reti指令复位中断系统,ret则没有。实践表明,对于mcu-51,用子程序调用入栈,用中断返回指令reti出栈是没有问题的,反之中断入栈ret出栈则不行。总之,对于入栈,子程序调用与中断调用效果是一样的,可以混用。在没有中断发生的情况下复位中断系统也不会影响系统正常运行。详见《uc/os-ii》第八章193页第12行
(3)改写os_cpu_c.c
我设计的堆栈结构如下图所示:
*****************************************************************
前一段时间,我参与了一个snmp网管板的项目,我负责硬件设计和单板软件开发。该板的硬件由mcs51+rtl8019as组成,有64k flash 和64k sram。软件部分有操作系统和tcpip协议栈。硬件比较简单,用了一个月就搞定了,协议栈我参考了老古开发板的部分程序又上网找了snmp源代码也很快完成了,但是测试时发现当使用较低时钟频率的cpu时(为了降低成本),由于asn.1编解码部分过于庞大,而我的程序又是一个大循环,agent的响应速度受到严重影响,用户界面也反应迟钝。更坏的消息是公司为了适应市场需求,还要在上面跑ppp和http。那样的话,我就得用40mhz的at89c51rd2或者人为的把程序断成几部分然后用状态机的方法在运行时再把它们连接起来。不过,我不想增加成本,也不想把程序搞乱,迫不得已,只好使用操作系统。
说实在的,一开始我也不是很有把握,一来我不清楚51的flash是否装得下这么多代码,二来我只做过os应用开发,对于它的移植想都不敢想。不过,我在bbs上搜索了一阵儿后还是有了一些头绪。我找到了几个os的源代码(我喜欢用现成的),按照代码大小、实时性、使用人数、众人口碑等标准,最后选定了ucos2。我感觉它的实时性有保障,延时可预测,代码据说可小到2k,网上讨论这个话题的人也比较多,而且它的网站上有针对keil c51的移植实例。
经过一番查找,我得到了5个版本。其中3个是用keil编译的。本来我想直接把os代码嵌到应用程序中,但后来发现没有一个可以直接使用。有的无法用keil直接编译,有的需要修改dll在软件仿真下使用。而我需要的是能在串口输入输出,不需要修改任何无关软件,能在软件仿真和硬件上运行的实时多任务操作系统。没有办法,我只好硬着头皮去改编。
我分析了自己的劣势:1。keil刚开始使用,不太熟悉;2。混合编程以前从没有作过;3。时间紧迫,要在1个月内搞定。而我的优势就是有5个移植实例可供参考,可以上网查资料。一开始,我用“堆栈”、“混合编程”、“汇编”、“ucos”等关键字在c51bbs和老古论坛上检索相关信息并逐条阅读,读过之后,头脑中的思路逐渐清晰了。我了解到在keil的hlp目录下有a51.pdf和c51.pdf非常全面的介绍了汇编和c51,是keil的权威用户手册;sp初始化、内存清0等操作在startup.a51文件中实现,用户可以改写它;keil的变量,子程序等的分配信息可以在.m51文件里查到;keil自己的论坛里有很多疑难问题的解答……通过阅读并经过思考,解决了堆栈起点、堆栈空间大小的设定等关键问题。论坛里的问题有些是我没有想到的,这使我发现了自己的疏漏。
在网上获得大量信息后,我开始阅读《ucosii》中文版,一共读了3遍。第一遍是浏览,了解到ucosii包括任务调度、时间管理、内存管理、资源管理(信号量、邮箱、消息队列)四大部分,没有文件系统、网络接口、输入输出界面。它的移植只与4个文件相关:汇编文件(os_cpu_a.asm)、处理器相关c文件(os_cpu.h、os_cpu_c.c)和配置文件(os_cfg.h)。有64个优先级,系统占用8个,用户可创建56个任务,不支持时间片轮转。第二遍主要是把整个工作过程在头脑里过了一下,不懂地方有针对性的查书,重点是思考工作原理和流程。我发现其实它的思路挺简单的。就是 “近似地每时每刻总是让优先级最高的任务处于运行状态” 。为了保证这一点,它在调用系统api函数、中断结束、定时中断结束时总是执行调度算法。原作者通过事先计算好数据,简化了运算量,通过精心设计就绪表结构,使得延时可预知。任务的切换是通过模拟一次中断实现的。第三遍重点看了移植部分的内容。对照实例,研究了代码的具体实现方法。
前期准备用了20几天,真正编写代码只用了1.5天,调试用了2天。具体过程如下:
(1)拷贝书后附赠光盘sourcecode目录下的内容到c:\yy下,删除不必要的文件和ex1l.c,只剩下p187(《ucosii》)上列出的文件。
(2)改写最简单的os_cpu.h
数据类型的设定见c51.pdf第176页。注意boolean要定义成unsigned char 类型,因为bit类型为c51特有,不能用在结构体里。
ea=0关中断;ea=1开中断。这样定义即减少了程序行数,又避免了退出临界区后关中断造成的死机。
mcu-51堆栈从下往上增长(1=向下,0=向上),os_stk_growth定义为0
#define os_task_sw() osctxsw() 因为mcu-51没有软中断指令,所以用程序调用代替。两者的堆栈格式相同,reti指令复位中断系统,ret则没有。实践表明,对于mcu-51,用子程序调用入栈,用中断返回指令reti出栈是没有问题的,反之中断入栈ret出栈则不行。总之,对于入栈,子程序调用与中断调用效果是一样的,可以混用。在没有中断发生的情况下复位中断系统也不会影响系统正常运行。详见《uc/os-ii》第八章193页第12行
(3)改写os_cpu_c.c
我设计的堆栈结构如下图所示:
*****************************************************************
上一篇:QNX环境下多线程编程