📄 ucos51 移植心得.txt
字号:
INC R0
MOV DPH,@R0 ;全局变量OSTCBCur在IDATA中
INC R0
MOV DPL,@R0
;OSTCBCur->OSTCBStkPtr ===> DPTR 获得用户堆栈指针
INC DPTR ;指针占3字节。+0类型+1高8位数据+2低8位数据
MOVX A,@DPTR ;.OSTCBStkPtr是void指针
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV R1,A
MOV DPH,R0
MOV DPL,R1
;*UserStkPtr ===> R5 用户堆栈起始地址内容(即用户堆栈长度放在此处) 详见文档说明
指针用法详见C51.PDF第169页
MOVX A,@DPTR ;用户堆栈中是unsigned char类型数据
MOV R5,A ;R5=用户堆栈长度
;恢复现场堆栈内容
MOV R0,#OSStkStart
restore_stack:
INC DPTR
INC R0
MOVX A,@DPTR
MOV @R0,A
DJNZ R5,restore_stack
;恢复堆栈指针SP
MOV SP,R0
;OSRunning=TRUE
MOV R0,#LOW (OSRunning)
MOV @R0,#01
POPALL
SETB EA ;开中断
RETI
;-------------------------------------------------------------------------
RSEG ?PR?OSCtxSw?OS_CPU_A
OSCtxSw:
PUSHALL
OSIntCtxSw_in:
;获得堆栈长度和起址
MOV A,SP
CLR C
SUBB A,#OSStkStart
MOV R5,A ;获得堆栈长度
;OSTCBCur ===> DPTR 获得当前TCB指针,详见C51.PDF第178页
MOV R0,#LOW (OSTCBCur) ;获得OSTCBCur指针低地址,指针占3字节。+0类型+1高8位数据+2低8位数据
INC R0
MOV DPH,@R0 ;全局变量OSTCBCur在IDATA中
INC R0
MOV DPL,@R0
;OSTCBCur->OSTCBStkPtr ===> DPTR 获得用户堆栈指针
INC DPTR ;指针占3字节。+0类型+1高8位数据+2低8位数据
MOVX A,@DPTR ;.OSTCBStkPtr是void指针
MOV R0,A
INC DPTR
MOVX A,@DPTR
MOV R1,A
MOV DPH,R0
MOV DPL,R1
;保存堆栈长度
MOV A,R5
MOVX @DPTR,A
MOV R0,#OSStkStart ;获得堆栈起址
save_stack:
INC DPTR
INC R0
MOV A,@R0
MOVX @DPTR,A
DJNZ R5,save_stack
;调用用户程序
LCALL _?OSTaskSwHook
;OSTCBCur = OSTCBHighRdy
MOV R0,#OSTCBCur
MOV R1,#OSTCBHighRdy
MOV A,@R1
MOV @R0,A
INC R0
INC R1
MOV A,@R1
MOV @R0,A
INC R0
INC R1
MOV A,@R1
MOV @R0,A
;OSPrioCur = OSPrioHighRdy 使用这两个变量主要目的是为了使指针比较变为字节比较,以便节省时间。
MOV R0,#OSPrioCur
MOV R1,#OSPrioHighRdy
MOV A,@R1
MOV @R0,A
LJMP OSCtxSw_in
;-------------------------------------------------------------------------
RSEG ?PR?OSIntCtxSw?OS_CPU_A
OSIntCtxSw:
;调整SP指针去掉在调用OSIntExit(),OSIntCtxSw()过程中压入堆栈的多余内容
;SP=SP-4
MOV A,SP
CLR C
SUBB A,#4
MOV SP,A
LJMP OSIntCtxSw_in
;-------------------------------------------------------------------------
CSEG AT 000BH ;OSTickISR
LJMP OSTickISR ;使用定时器0
RSEG ?PR?OSTickISR?OS_CPU_A
OSTickISR:
USING 0
PUSHALL
CLR TR0
MOV TH0,#70H ;定义Tick=50次/秒(即0.02秒/次)
MOV TL0,#00H ;OS_CPU_C.C 和 OS_TICKS_PER_SEC
SETB TR0
LCALL _?OSIntEnter
LCALL _?OSTimeTick
LCALL _?OSIntExit
POPALL
RETI
;-------------------------------------------------------------------------
CSEG AT 0023H ;串口中断
LJMP SerialISR ;工作于系统态,无任务切换。
RSEG ?PR?_?serial?OS_CPU_A
SerialISR:
USING 0
PUSHALL
CLR EA
LCALL _?serial
SETB EA
POPALL
RETI
;-------------------------------------------------------------------------
END
;-------------------------------------------------------------------------
文件名 : OS_CPU_C.C
void *OSTaskStkInit (void (*task)(void *pd), void *ppdata, void *ptos,
INT16U opt) reentrant
{
OS_STK *stk;
ppdata = ppdata;
opt = opt; //opt没被用到,保留此语句防止告警产生
stk = (OS_STK *)ptos; //用户堆栈最低有效地址
*stk++ = 15; //用户堆栈长度
*stk++ = (INT16U)task & 0xFF; //任务地址低8位
*stk++ = (INT16U)task >> 8; //任务地址高8位
*stk++ = 0x00; //PSW
*stk++ = 0x0A; //ACC
*stk++ = 0x0B; //B
*stk++ = 0x00; //DPL
*stk++ = 0x00; //DPH
*stk++ = 0x00; //R0
*stk++ = 0x01; //R1
*stk++ = 0x02; //R2
*stk++ = 0x03; //R3
*stk++ = 0x04; //R4
*stk++ = 0x05; //R5
*stk++ = 0x06; //R6
*stk++ = 0x07; //R7
//不用保存SP,任务切换时根据用户堆栈长度计算得出。
return ((void *)ptos);
}
#if OS_CPU_HOOKS_EN
void OSTaskCreateHook (OS_TCB *ptcb) reentrant
{
ptcb = ptcb; /* Prevent compiler warning
*/
}
void OSTaskDelHook (OS_TCB *ptcb) reentrant
{
ptcb = ptcb; /* Prevent compiler warning
*/
}
void OSTimeTickHook (void) reentrant
{
}
#endif
//初始化定时器0
void InitTimer0(void) reentrant
{
TMOD=TMOD&0xF0;
TMOD=TMOD|0x01; //模式1(16位定时器),仅受TR0控制
TH0=0x70; //定义Tick=50次/秒(即0.02秒/次)
TL0=0x00; //OS_CPU_A.ASM 和 OS_TICKS_PER_SEC
ET0=1; //允许T0中断
TR0=1;
}
文件名 : YY.C
#include <includes.h>
#define MAX_STK_SIZE 64
void TaskStartyya(void *yydata) reentrant;
void TaskStartyyb(void *yydata) reentrant;
void TaskStartyyc(void *yydata) reentrant;
OS_STK
TaskStartStkyya[MAX_STK_SIZE+1];//注意:我在ASM文件中设置?STACK空间为40H即64,不要超出范围。
OS_STK TaskStartStkyyb[MAX_STK_SIZE+1];//用户栈多一个字节存长度
OS_STK TaskStartStkyyc[MAX_STK_SIZE+1];
void main(void)
{
OSInit();
InitTimer0();
InitSerial();
InitSerialBuffer();
OSTaskCreate(TaskStartyya, (void *)0, &TaskStartStkyya[0],2);
OSTaskCreate(TaskStartyyb, (void *)0, &TaskStartStkyyb[0],3);
OSTaskCreate(TaskStartyyc, (void *)0, &TaskStartStkyyc[0],4);
OSStart();
}
void TaskStartyya(void *yydata) reentrant
{
yydata=yydata;
clrscr();
PrintStr("\n\t\t*******************************\n");
PrintStr("\t\t* Hello! The world. *\n");
PrintStr("\t\t*******************************\n\n\n");
for(;;){
PrintStr("\tAAAAAA111111 is active.\n");
OSTimeDly(OS_TICKS_PER_SEC);
}
}
void TaskStartyyb(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\tBBBBBB333333 is active.\n");
OSTimeDly(3*OS_TICKS_PER_SEC);
}
}
void TaskStartyyc(void *yydata) reentrant
{
yydata=yydata;
for(;;){
PrintStr("\tCCCCCC666666 is active.\n");
OSTimeDly(6*OS_TICKS_PER_SEC);
}
}
打印本文 关闭窗口
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -