我们从2011年坚守至今,只想做存粹的技术论坛。  由于网站在外面,点击附件后要很长世间才弹出下载,请耐心等待,勿重复点击不要用Edge和IE浏览器下载,否则提示不安全下载不了

 找回密码
 立即注册
搜索
查看: 685|回复: 0

μC/OS-II在C8051F上的移植 - 软件编程/OS - 电子工程师俱乐部

[复制链接]

该用户从未签到

1万

主题

1292

回帖

2万

积分

管理员

积分
29577

社区居民最爱沙发原创达人社区明星终身成就奖优秀斑竹奖宣传大使奖特殊贡献奖

QQ
发表于 2013-3-30 00:25:22 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区

您需要 登录 才可以下载或查看,没有账号?立即注册

×
在嵌入式应用中,使用RTOS的最主要原因是提高系统的可靠性,其次是提高开发效率、缩短开发周期。μC/OS-II 是一个基于优先级的抢占式实时内核,支持56 个用户任务,90%的代码使用标准的ANSI C语言书写,程序可读性强,移植性好,代码可固化,可裁剪,非常灵活。C8051F是美国Cygnal公司生产的与51系列兼容的微控制器,流水线指令结构70%的指令的执行时间为1个或2个系统时钟周期。当时钟频率为25MHz时,速度可达25MIPS,是一款不错的片上系统。

<strong>1开发工具和运行环境</strong>

实现μC/OS-II的移植,要求所用的C编译器支持混合编程。KEIL C51可为众多的8051派生器件编程。我们选用的是KEIL7.02集成开发环境,仿真板基于C8051F015芯片。

<strong>2移植中所需修改的文件</strong>

和CPU相关的文件主要有三个,分别是汇编文件OS_CPU_A.ASM、C语言文件 OS_CPU_C.C和头文件OS_CPU.H。

2.1OS_CPU.H文件

OS_CPU.H文件中定义了数据类型及与硬件相关的基本信息。其中改动部分如下:
typedef unsigned char OS_STK; /* 堆栈的宽度为8位 */
OS_CPU_EXT INT8U IE_SHADOW;
#define OS_ENTER_CRITICAL() IE_SHADOW = IE; IE &= 0x7F /* 关中断 */
#define OS_EXIT_CRITICAL() IE = IE_SHADOW /* 恢复中断 */
#define OS_STK_GROWTH 0
#define OS_TASK_SW() OSCtxSw()

在C8051F中,堆栈都是按字节操作的,故数据类型OS_STK声明为8位。方向从低地址向高地址方向递增,所以OS_STK_GROWTH设置为 0。μC/OS-II在进入系统临界代码区之前要关中断,等到退出临界区后再打开,以保护核心数据不被多任务环境下的其它任务或中断破坏。开、关中断可通过设置SFR中的中断屏蔽位实现。在关中断时,先将IE的内容保存在全局变量IE_ SHADOW中,然后关中断;退出临界区时,还原IE_SHADOW的值。OS_TASK_SW()用来实现任务切换。就绪任务的堆栈初始化应该模拟一次中断发生后的样子,堆栈中应该按入栈次序设置好各个寄存器。OS_TASK_SW()函数模拟一次中断过程,在中断返回的时候进行任务切换。由于 C8051F015没有软中断,故直接定义宏OS_TASK_SW()为函数OSCtxSw()。

2.2OS_CPU_A.ASM文件

编译器将每个文件作为一个模块,编译模块以主名命名,称为编译模块名,用NAME 来声明。因此,应在文件头部声明NAME OS_CPU_A。

函数有程序部分和局部变量部分,它们分别放在独立的段中。在大模式下,段名声明的固定格式为 ?PR?函数名?模块名 SEGMENT CODE。因此需要将OSStartHighRdy()、OSCtxSw()、OSIntCtxSw()和OSTickISR()用上面的格式一一声明。如?PR?OSStartHighRdy?OS_CPU_A SEGMENT CODE,本模块实现的函数需要用PUBLIC声明,如PUBLIC OSStartHighRdy等。

C51将所有定义说明的数据标识符转换为大写字符,对函数则根据有无寄存器参数传送和函数是否可重入进行换名,如:void OSIntEnter(void) reentrant函数的名字OSIntEnter换成_?OSIntEnter。这些规则可从编译后的LST文件中看出。程序中声明引用的五个全局变量为OSTCBCur、OSTCBHighRdy、OSRunning、OSPrioCur、OSPrioHighRdy,声明格式是EXTRN IDATA (OSTCBCur)等。调用四个外部子程序OSTaskSwHook()、OSIntEnter()、OSIntExit()、 OSTimeTick(),固定格式为:EXTRN CODE (_?OSTaskSwHook)等。

由于C8051F的堆栈指针只有8位,只能指向内部数据区的256个字节,因此,当前运行的任务的堆栈在IDATA区,堆栈大小为40H(64字节),堆栈起点由KEIL决定。通过标号可以获得KEIL分配的SP起点,代码如下:
?STACK SEGMENT IDATA
RSEG ?STACK
OSStack:
DS 40H
OSStkStart IDATA OSStack-1

为简化子程序特定义压栈出栈宏。压栈的次序为PSW、ACC、B、DPL、DPH、R0~R7,出栈的次序与入栈相反。
PUSHALL MACRO
  IRP REG, <SW,ACC, B, DPL, DPH, 0, 1, 2, 3, 4, 5, 6, 7>
  PUSH REG
  ENDM
POPALL MACRO
  IRP REG, <7, 6, 5, 4, 3, 2, 1, 0, DPH, DPL, B, ACC, PSW>
  POP REG
  ENDM

具体函数的修改部分见本刊网络补充版(http://www.dpj.com.cn)。

2.3OS_CPU_C.C文件

移植μC/OS-II 需要在OS_CPU_C.C中定义六个函数,而实际上需要定义的只有OSTaskStkInit()一个函数。该函数用来初始化任务的堆栈。初始状态的堆栈只须初始化?C_XBP (仿真堆栈指针)、任务地址及堆栈的长度。由于只有INC DPTR指令,故返回栈的最低地址,且最低地址处存放栈的长度,方便用汇编语言实现任务的切换。堆的大小可根据任务的实际情况自行确定,由参数 ppdata所指的值确定。

void *OSTaskStkInit (void (*task)(void *pd), void *ppdata,
  void *ptos, INT16U opt) reentrant
{
  OS_STK *stk;
  INT8U HeapSize;
  HeapSize=*(INT8U *)ppdata;
  opt = opt;
  stk = (OS_STK *)ptos+HeapSize+2;
  *stk++ = 15;
  *stk++ = (INT16U)task & 0xFF;
  *stk++ = (INT16U)task >> 8;
  stk = (OS_STK *)ptos+HeapSize+2;
  *--stk = (INT16U) (ptos+HeapSize-1) >> 8;
  *--stk = (INT16U) (ptos+HeapSize-1) & 0xFF;
  return ((void *)stk);
}

<strong>3可重入函数</strong>

因为51系列堆栈空间的限制, KEIL编译器没有像大系统那样使用调用堆栈。一般C语言调用过程中,会把过程的参数和使用的局部变量入栈。为了提高效率,编译器没有提供这种堆栈,而是提供一种压缩栈,每个过程被给定一个空间用于存放局部变量。过程中的每个变量都放在这个空间的固定位置,当递归调用这个过程时,会导致变量被覆盖。编译器允许将函数定义成可重入函数,由reentrant关键字指定,可重入函数可被单独保存。因为这些堆栈是模拟的,可重入函数一般都比较大,运行起来也比较慢。模拟栈不允许传递bit类型的变量,也不能定义局部位标量。移植中最好是将可能被多个任务使用的函数定义成可重入函数。

<strong>参考文献</strong>

1Labrosse Jean J. μC/OS-II源码公开的实时嵌入式操作系统. 邵贝贝译. 北京:中国电力出版社, 2001
2www.ucos-ii.com;www.xhl.com.cn;www.laogu.com

作 者:华中科技大学 江平新 容太平
来 源:单片机与嵌入式系统应用 2003(9)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

公告:服务器刚移机,
大家请不要下载东西。
会下载失败


Copyright ©2011-2024 NTpcb.com All Right Reserved.  Powered by Discuz! (NTpcb)

本站信息均由会员发表,不代表NTpcb立场,如侵犯了您的权利请发帖投诉

( 闽ICP备2024076463号-1 ) 论坛技术支持QQ群171867948 ,论坛问题,充值问题请联系QQ1308068381

平平安安
TOP
快速回复 返回顶部 返回列表