POP ACC
MOV REG, A
ENDM
POP PSW
POP DPL
POP DPH
POP B
POP ACC
ENDM
Chapter 5 [pwl999] 2005-1-24 19:34:13
LoadXBP MACRO
MOV DPH, ?C_XBP
MOV DPL, ?C_XBP+1
ENDM
SaveXBP MACRO
USH IE
;CLR EA
MOV ?C_XBP, DPH
MOV ?C_XBP+1,DPL
OP IE
ENDM
LoadReg MACRO REG
MOVX A, @DPTR
MOV REG, A
ENDM
SaveReg MACRO REG
MOV A, REG
MOVX @DPTR, A
ENDM
Chapter 6 [pwl999] 2005-1-24 19:34:59
作者: linuxarm 时间: 2006-6-30 12:57
;******************************************************************
; VARIABLE DEFINE
;******************************************************************
RSEG ?STACK
DS 1 ;
RSEG DT?OS_CPU_A
OSTickRate:
DS 1
OSTickCtr:
DS 1
;******************************************************************
; void _?OSStartHighRdy(void);
;******************************************************************
RSEG ?PR?_?OSStartHighRdy?OS_CPU_A
_?OSStartHighRdy:
LCALL _?OSTaskSwHook
; OSRunning = TRUE;
MOV DPL, #LOW(OSRunning)
MOV DPH, #HIGH(OSRunning)
SaveReg #01
LJMP ?C_XBP_Load
Chapter 7 [pwl999] 2005-1-24 19:36:32
;******************************************************************
; void OSCtxSw(void);
;******************************************************************
RSEG ?PR?_?OSCtxSw?OS_CPU_A
_?OSCtxSw:
PUSHALL
SP_Offset:
LoadXBP
MOV A, SP
CLR C
SUBB A, #?STACK-1
MOV R5, A
INC A
CLR C
XCH A, DPL
SUBB A, DPL
JNC SP_Save
DEC DPH
SP_Save:
MOV DPL, A
SaveXBP
Chapter 8 [pwl999] 2005-1-24 19:37:17
SaveREG R5
MOV R0, #?STACK-1
Stack_Save_Loop:
INC DPTR
INC R0
SaveREG @R0
DJNZ R5, Stack_Save_Loop
OPALL
; OSTCBCur->OSTCBStkPtr = ?C_XBP;
MOV DPL, #LOW(OSTCBCur)
MOV DPH, #HIGH(OSTCBCur)
INC DPTR
LoadReg R0
INC DPTR
LoadReg DPL
MOV DPH, R0
INC DPTR
SaveReg ?C_XBP
INC DPTR
SaveReg ?C_XBP+1
Chapter 9 [pwl999] 2005-1-24 19:39:21
; OSTCBCur = OSTCBHighRdy;
MOV DPL, #LOW(OSTCBHighRdy)
MOV DPH, #HIGH(OSTCBHighRdy)
LoadReg R0
INC DPTR
LoadReg R1
INC DPTR
LoadReg R2
MOV DPL, #LOW(OSTCBCur)
MOV DPH, #HIGH(OSTCBCur)
SaveReg R0
INC DPTR
SaveReg R1
INC DPTR
SaveReg R2
; OSPrioCur = OSPrioHighRdy;
MOV DPL, #LOW(OSPrioHighRdy)
MOV DPH, #HIGH(OSPrioHighRdy)
LoadReg R0
MOV DPL, #LOW(OSPrioCur)
MOV DPH, #HIGH(OSPrioCur)
SaveReg R0
作者: linuxarm 时间: 2006-6-30 12:58 标题: C51编程:2005版uCOSⅡ C51移植心得
Chapter 1 [pwl999] 2005-1-24 11:43:25
uCOS-Ⅱ C51移植笔记
深圳中慧电子公司 CyberTeam 彭伟林 完整源代码欢迎来信索取。Email:marine_love@163.com
(1)实时系统和前/后台系统;
前/后台系统:一个大循环,循环查询各种标志位。如果标志位置位,就执行相应的服务程
序。标志位就是标志事件的发生,事件响应延时处于不可预测状态。最坏的情况是循环中所
有其他的事件服务程序执行完,才响应当前事件。中断服务虽然能即时/优先响应,但是它
们和主循环的通讯,也是通过置主循环中相应的标志位来完成的。
实时系统(uCOS):整个程序分成一个个看起来好象是并行的任务,每个任务都在等待事件
的发生。因为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个
半星期。因为是工作需要,我才可以这样心安理得的在那里看呀看书^_^,辛苦呀9。在这期
间,为了自己的思想不受别人的影响,我坚决没有从网上下任何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()函数的编写。
[此贴子已经被linuxarm于2006-6-30 12:58:50编辑过]
作者: linuxarm 时间: 2006-6-30 12:59
Chapter 10 [pwl999] 2005-1-24 19:39:54
?C_XBP_Load:
; ?C_XBP = OSTCBCur->OSTCBStkPtr;
MOV DPL, #LOW(OSTCBCur)
MOV DPH, #HIGH(OSTCBCur)
INC DPTR
LoadReg R0
INC DPTR
LoadReg DPL
MOV DPH, R0
INC DPTR
LoadReg ?C_XBP
INC DPTR
LoadReg ?C_XBP+1
SP_Load:
LoadXBP
LoadREG R5
MOV R0, #?STACK-1
Stack_Load_Loop:
INC DPTR
INC R0
LoadREG @R0
DJNZ R5, Stack_Load_Loop
MOV SP, R0
INC DPTR
SaveXBP
; OSTCBCur->OSTCBStkPtr = ?C_XBP;
POPALL
RET
Chapter 11 [pwl999] 2005-1-24 19:40:30
;******************************************************************
; void OSIntCtxSw(void);
;******************************************************************
RSEG ?PR?_?OSIntCtxSw?OS_CPU_A
_?OSIntCtxSw:
DEC SP
DEC SP
DEC SP
DEC SP
LJMP SP_Offset
;******************************************************************
; void OSTickISR(void);
;******************************************************************
CSEG AT 000BH
LJMP _?OSTickISR
RSEG ?PR?_?OSTickISR?OS_CPU_A
_?OSTickISR:
LCALL ResetHwIntr
PUSHALL
;DEC OSTickCtr
;MOV A, OSTickCtr
;JNZ OSTick_End
;MOV OSTickCtr, OSTickRate
LCALL _?OSIntEnter
LCALL _?OSTimeTick
LCALL _?OSIntExit
OSTick_End:
POPALL
RET
ResetHwIntr:
RETI
END
Chapter 12 [pwl999] 2005-1-24 19:41:15
6、OS_CPU_C.C的移植;
重点:
1.OSTaskStkInit函数的pdata参数在堆栈中怎么存放。
源代码:
OS_STK *OSTaskStkInit (void (*task)(void *pd) KCREENTRANT, void *pdata, OS_STK
*ptos, INT16U opt) KCREENTRANT
{
INT8U * stk;
opt = opt; /* 'opt' is not used, prevent
warning */
stk = (INT8U *) ptos; /* Load stack
pointer */
/*
stk -= sizeof(void *);
*(void**)stk = pdata;
*/
/*
*--stk = 0x01;
*--stk = ((INT16U)pdata >> 8);
*--stk = ((INT16U)pdata & 0xFF);
*/
*--stk = ((INT32U)pdata & 0xFF0000) >> 8;
*--stk = ((INT32U)pdata & 0x00FF00) >> 4;
*--stk = (INT32U)pdata & 0xFF;
*--stk = 7;
*--stk = 6;
*--stk = 5;
*--stk = 4;
/*
*--stk = 3;
*--stk = 2;
*--stk = 1;
*/
/*
stk -= sizeof(void *);
*(void**)stk = pdata;
*/
*--stk = 0x01;
*--stk = ((INT16U)pdata >> 8);
*--stk = ((INT16U)pdata & 0xFF);
*--stk = 0;
*--stk = PSW;
*--stk = 'L';
*--stk = 'H';
*--stk = 'B';
*--stk = 'A';
*--stk = ((INT16U)task >> 8);
*--stk = ((INT16U)task & 0x00FF);
*--stk = 15;
return ((void *)stk);
}
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) |
Powered by Discuz! 7.0.0 |