新闻中心

EEPW首页>嵌入式系统>设计应用> uCOS-Ⅱ C51移植笔记

uCOS-Ⅱ C51移植笔记

作者: 时间:2016-11-23 来源:网络 收藏
(1)实时系统和前/后台系统;

前/后台系统:一个大循环,循环查询各种标志位。如果标志位置位,就执行相应的服务程序。标志位就是标志事件的发生,事件响应延时处于不可预测状态。最坏的情况是循环中所有其他的事件服务程序执行完,才响应当前事件。中断服务虽然能即时/优先响应,但是它们和主循环的通讯,也是通过置主循环中相应的标志位来完成的。

本文引用地址://m.amcfsurvey.com/article/201611/320408.htm

实时系统(uCOS):整个程序分成一个个看起来好象是并行的任务,每个任务都在等待事件的发生。除了最低优先级任务(在uCOS中是IDLE任务)是死循环以外,其他的任务都不能死循环,只能在驱动事件驱动下工作。任何驱动事件的产生,都使优先级最高的就绪任务运行。任务和任务/任务和中断的通讯,是通过相应事件驱动来完成的。

驱动事件:

不论是什么系统,CPU不可能一直在工作。CPU的工作是在各种驱动事件的驱动下工作的。CPU在完成一次驱动事件事件服务程序以后,进入IDLE模式等待新的驱动事件的发生。包括实时系统和前/后台系统都是在驱动事件的驱动下运行的。

按照uCOS中的观点,驱动事件分为三类:

1、事件 (Event)。包括信号量(Semaphores)、事件标志组(Flag)、邮箱(Message Box)、邮箱队列(Message Queue)。

2、时间(Time Tick)。包括时间延时和事件超时。

3、中断(Interrupt)。可以发出各种event。

由于第1种事件,通常都是在第2、3种状态下发出的,所以其实事件的驱动只有两种:时间(定时)和中断(各种异步中断)。

时间实际上也是中断的一种,可以说程序的驱动事件只有一种,就是:中断。

前/后台系统中还有一种驱动事件的产生,在主循环中不断的查询。有别与一般的定时查询,这种查询是为了将事件的响应时间降到最低,也可以将其归纳于定时(时间)事件。

(2)uCOSC51移植的准备工作;

2004年8月份,我在书城买了一本《uCOS-Ⅱ第2版》,准备学习RTOS。因为以前没有玩过RTOS,在工作之余断断续续的看了3、4章。一直到12月初的时候,公司要重新设计一个项目,恰好要把uCOS移植到c51上。我的RTOS学习才正式开始。

因为对OS向往以久,我并不想在网上Down一个现成的移植OS程序,做一个OS的应用者。揭开OS的神秘面纱,了解OS的内部运行机制,这才是我想要做的。本文的主要目的是讨论uCOS的移植,希望对即将进行uCOS c51移植的兄弟有些帮助。对于OS的内部运行机制,由于东西比较多,在这里不想太展开。如果以后有时间,也想写一篇文章来讨论讨论。

最开始,我的计划就是看书,看《uCOS-Ⅱ 第2版》。看完这本几百页的大本本,花了我2个半星期。因为是工作需要,我才可以这样心安理得的在那里看呀看书^_^,辛苦呀L。在这期间,为了自己的思想不受别人的影响,我坚决没有从网上下任何uCOS的资料,我手头的资料就是uCOS-Ⅱ的书和附带光盘,这些就是最权威的资料了。在看书的时候,我都坚持做笔记,把每天的重点,明白的东西和心中的疑问都随时记录下来。对付这种大本本,前后的知识又相互关联,光靠我们的大脑是搞不定啊。

弄懂了uCOS的内核,下一本书应该是《单片机高级语言C51Windows环境编程与应用》。对于Keil C我还是很熟的,还是花了2、3天来复习。这里的重点是C51对汇编的转换结构,例于数据/系统堆栈的使用,C&Asm混合编程。我想对于任何CPU的uCOS移植,C语言的实现机制,你都是要了解的。这里也是要花大把时间的。

《uCOS-Ⅱ 第2版》和《单片机高级语言C51Windows环境编程与应用》这两本书网上都可以下电子档的,我这里也有(大家需要可以来信索取)。

uCOS和C51的书都看完了。我就下载了一堆uCOS的C51移植资料。其中的源程序有很多个版本的,不过详细的移植文档只有一个版本:巨龙一位大虾的“uCOS C51移植心得”,相信很多人都看过。这些资料的作者都是我移植过程中的老师,有了这些资料,我才能把心中的朦胧想法变成源程序。但是我也发现这些资料中大多都有一些错误和遗漏,当然这是难免的。这也正是驱使我写这篇文章的原因,希望在前辈的基础上有所进步。欢迎大家来批评!

真正的源代码移植,我花了大概一个星期时间。

(3)uCOS C51的移植概况;

1、工具:

uCOS 2.52版;

Keil C V6.23a。

2、uCOS V2.52的文件结构与移植所需要的修改:

A、与处理器无关的文件:

OS_CORE.C

OS_FLAG.C

OS_MBOX.C

OS_MEM.C

OS_MUTEX.C

OS_Q.C

OS_SEM.C

OS_TASK.C

OS_TIME.C

uCOS_II.C

uCOS_II.H

这些文件在c51的移植过程中,只需要给函数加上重入属性即可。

B、与应用相关的文件:

INCLUDES.H: 包含C51的标准库头文件;对”pdata”等c51关键字的重定义

OS_CFG.H: “OS_TICKS_PER_SEC”、“ OS_FLAGS”注意可能需要修改。

C、与处理器相关的文件:

OS_CPU.H: 数据类型、关中断方法、任务堆栈方向、任务切换的宏定义都需要修改。

OS_CPU_A.ASM: OSTickISR()、OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()这几个函数的编写,是整个移植的关键。

OS_CPU_C.C:OSTaskStkInit()函数的编写。

(4)uCOS C51具体的移植过程;

1、C51的堆栈结构;

这是整个移植过程中的重中之重,所以特别详细介绍。

A、系统堆栈;

c51中,系统堆栈的栈底地址是“?STACK”,栈顶指针就是“SP”拉,栈的生长方向是向上的,栈空间分配在51的内部RAM(idata)中。“?STACK”分配在所有内部RAM数据段的最后面,所以系统堆栈的范围是从?STACK到内部RAM的最高位(0x80或者0xFF)。

B、数据堆栈;

c51中,由于我们使用OS,采用的LARGE编译模式,所以数据堆栈的指针是“?C_XBP”,栈的生长方向是向下的,栈空间分配在51的外部RAM(xdata)中。

C、C51中断中堆栈的保护;

研究中断中堆栈的保护的意义在于,因为uCOS中的任务切换,本身就是模拟一次中断的发生:保护Task1的CPU寄存器,SP切换到Task2的堆栈,弹出Task2的CPU寄存器。用C51写中断函数的时候,编译器会自动保护CPU的寄存器,所以中断返回时任务调度OSIntCtxSw(),就不用重新保护寄存器。

C51中断中调用函数可以分为四种情况(中断函数本身不设为reentrant):

一、没有函数调用;

二、调用非reentrant函数,函数中没有嵌套调用其他函数;

三、调用非reentrant函数,函数中嵌套调用其他函数;

四、调用reentrant函数。

t0_isr:

PUSHACC

PUSHB

PUSHDPH

PUSHDPL

PUSHPSW

MOVPSW,#00H

PUSHAR0

PUSHAR1

PUSHAR2

PUSHAR3

PUSHAR4

PUSHAR5

PUSHAR6

PUSHAR7

用户代码

POPAR7

POPAR6

POPAR5

POPAR4

POPAR3

POPAR2

POPAR1

POPAR0

POPPSW

POPDPL

POPDPH

POPB

POPACC

RETI

因为uCOS中所有的函数都必须是重入函数,因此我们只需要研究第四种情况下的堆栈保护,对于其他情况有兴趣可以在c51中看看。(注意:可能因为c51编译器的版本不同,上述压栈的顺序可能不同。)

2、uCOS C51任务切换时的堆栈操作;

每个任务都有一个独立的数据堆栈,系统堆栈是公用空间。

保护Task1的CPU寄存器:首先将CPU寄存器按上例压进Task1系统堆栈,再将整个Task1系统堆栈压进Task1数据堆栈;

SP切换:?C_XBP = Task2 的数据堆栈栈顶地址。

弹出Task2的CPU寄存器:从Task2的数据堆栈重新恢复整个系统堆栈,然后再从Task2系统堆栈中恢复CPU寄存器值。

实现的方法有很多种,只要遵循uCOS任务切换的原理就可以了。

3、INCLUDES.H的移植;

4、OS_CPU.H的移植;

5、OS_CPU_A.ASM的移植;

6、OS_CPU_C.C的移植;

7、其他的移植;



关键词:uCOS-ⅡC51移植笔

评论


相关推荐

技术专区

关闭