老古开发网首页
导航:老古开发网首页文章索引文章分类嵌入式系统→[uCOS-Ⅱ C51移植笔记]
| -文章搜索 - 最新文章 - |

uCOS-Ⅱ C51移植笔记

发布时间:2006年10月15日 点击次数:2846
来源:   作者:
 
(1)实时系统和前/后台系统;
前/后台系统:一个大循环,循环查询各种标志位。如果标志位置位,就执行相应的服务程序。标志位就是标志事件的发生,事件响应延时处于不可预测状态。最坏的情况是循环中所有其他的事件服务程序执行完,才响应当前事件。中断服务虽然能即时/优先响应,但是它们和主循环的通讯,也是通过置主循环中相应的标志位来完成的。
实时系统(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)uCOS C51移植的准备工作;
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个半星期。因为是工作需要,我才可以这样心安理得的在那里看呀看书^_^,辛苦呀。在这期间,为了自己的思想不受别人的影响,我坚决没有从网上下任何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:
     PUSH      ACC
     PUSH      B
     PUSH      DPH
     PUSH      DPL
     PUSH      PSW
     MOV      PSW,#00H
     PUSH      AR0
     PUSH      AR1
     PUSH      AR2
     PUSH      AR3
     PUSH      AR4
     PUSH      AR5
     PUSH      AR6
     PUSH      AR7
     
     用户代码
     
POP      AR7
     POP      AR6
     POP      AR5
     POP      AR4
     POP      AR3
     POP      AR2
     POP      AR1
     POP      AR0
     POP      PSW
     POP      DPL
     POP      DPH
     POP      B
     POP      ACC
     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、其他的移植;


欢迎进入老古论坛进行讨论
[嵌入式系统] 相关文章:
linux内核分析
简介:
启动   当PC启动时,Intel系列的CPU首先进入的是实模式,并开始执行位于地址0xFFFF0处 的代码,也就是ROM-BIOS起始位置的代码。BIOS先进行一系列的系统自检,然后初始化位 于地址0的中断向量表。最后BIOS将启动盘的第一个扇区装入到0x7C00,并开始执行此处 的代码。这就是对内核初始化过程的一个最简单的描述。   最初,linux核心的最开始部分是用8086汇编语言编写的。当开始运行时,核心将自 己装入到绝对地址0x90000,再将其后的2k字节装入到地址0x90200处,最后将核心的其余 部分装入到0x10000。   当系统装入时,会显示Loading...信息......

XSBase255 -linux 启动过程描述
一个linux设备驱动例程
嵌入式软件开发测试的秘诀
别踩static的地雷
让CVS来管理你的程序(1)——CVS概述
TI展出运行在同一数字信号处理器上的汇聚型平台
在51上用P1口模拟I2C
单片机看门狗
Microchip推出集成以太网外设的8位单片机
 
下一个:[单片机]为什么51系列单片机常用11.0592MHz的晶振设计
简介:
因为它能够准确地划分成时钟频率,与UART(通用异步接收器/发送器)量常见的波特率相关。特别是较高的波特率(19600,19200),不管多么古怪的值,这些晶振都是准确,常被使用的。 当定时器1被用作波特率发生器时,波特率工作于方式1和方式3是由定时器1的溢出率和SMOD的值(PCON.7------双倍速波特率)决定: 方式1、3波特率= (定时器1的溢出率) 特殊时,定时器被设在自动重袋模式(模式2,TMOD的高四位为0100B),其为: 方式1、 3波特率= 11.0592MHZ晶振的一些典型波特率如下: 波特率 S......
 

上一个:[单片机]什么是单片机,单片机有什么用

老古开发网版权所有 2006年9月 asp.Net V2.0 设计:老古
页面缓存:否 执行时间:63毫秒