Small RTOS OSSched 函数解析

Small RTOS OSSched 函数解析

变量解析:

OSTaskRuning
初始值:对应的比特位为0 ,表示该任务 休眠,
对应的比特位为1 ,表示该任务 准备执行
uint8 OSTaskRuning = 0xff;

OSTaskID
初始值为0 当前运行的任务的序号
uint8 data OSTaskID = 0;

OSMapTbl[ ]
一些常数: bit0 bit1 bit2 bit3 bit4 bit5 bit6 bit7
uint8 const OSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00};

OSIntNesting
uint8 OSIntNesting;

OSNextTaskID 等待运行的下一个 要切换的任务的ID
uint8 data OSNextTaskID = 0;

OSWaitTick[ ]
uint8 OSWaitTick[OS_MAX_TASKS];

OS_TASK_SW()
#define OS_TASK_SW() OSCtxSw() /* 任务切换函数 */

Os_Enter_Sum
uint8 data Os_Enter_Sum = 0;

OSFastSwap
uint8 data OSFastSwap = 0xff; /* 任务是否可以快速切换 */

#if EN_OS_INT_ENTER >0 
#define  OS_INT_ENTER() OSIntNesting++,EA=1
#endif

#define  OS_ENTER_CRITICAL()  EA = 0,Os_Enter_Sum++             /* 禁止中断                                     */
#define  OS_EXIT_CRITICAL()   if (--Os_Enter_Sum==0) EA = 1     /* 允许中断                                     */

/* 查找处于就绪状态的任务中优先级最高的任务 */

然后进入切换:
#define OS_TASK_SW() OSCtxSw() /* 任务切换函数 */

OSCtxSw()

LJMP C_OSCtxSw

C:0138H PUBLIC _OSWait

OSCtxSw

RSEG ?PR?OSCtxSw?OS_CPU_A
OSCtxSw:
USING 0
;设置标志:任务再次恢复运行时不必恢复所有寄存器
MOV DPTR,#OSMapTbl
MOV A,OSTaskID
#if OS_MAX_TASKS < 9
MOVC A,@A+DPTR // A = OSMapTbl[OSTaskID]
ORL A,OSFastSwap // A = A|0xFF
MOV OSFastSwap,A // OSFastSwap = A
#else
CLR C
SUBB A,#8
JC OSCtxSw_1
MOVC A,@A+DPTR
ORL A,OSFastSwap
MOV OSFastSwap,A
LJMP C_OSCtxSw
OSCtxSw_1:
MOV A,OSTaskID
MOVC A,@A+DPTR
ORL A,OSFastSwap+1
MOV OSFastSwap+1,A
#endif
LJMP C_OSCtxSw

C_OSCtxSw

RSEG  ?PR?C_OSCtxSw?OS_CPU_C

C_OSCtxSw:
PUSH Os_Enter_Sum ;保存关中断计数器 ;首先SP =SP+1 ,然后 赋值到 SP地址
mov r2,sp ; SP寄存器的内容是一个数字,该数字表示一个地址

; cp1 = (unsigned char idata *)SP +1;
MOV R0,SP

IF EN_SP2 <> 0
mov sp,#(Sp2-1) ;堆栈指向临时空间,允许“软非屏蔽中断”
ENDIF

INC     R0    ;  数字加1

; temp = (unsigned char )OSTsakStackBotton[OSNextTaskID+1];
MOV A,#LOW (OSTsakStackBotton+01H) ; OSTsakStackBotton = 0x10 ,A=0x11
ADD A,OSNextTaskID ; A = OSTsakStackBotton+01H + OSNextTaskID
MOV R1,A ; R1 = OSTsakStackBotton+01H + OSNextTaskID
MOV A,@R1 ;A = OSTsakStackBotton+01H + OSNextTaskID 这个地址存放的值
MOV R7,A ; R7 = OSTsakStackBotton+01H + OSNextTaskID 这个地址存放的值
; cp2 = OSTsakStackBotton[OSTaskID+1];
MOV A,#LOW (OSTsakStackBotton+01H); OSTsakStackBotton = 0x10 ,A=0x11
ADD A,OSTaskID ; A = OSTsakStackBotton+01H + OSTaskID
MOV R1,A ; R1 = OSTsakStackBotton+01H + OSTaskID
MOV A,@R1 ; A = OSTsakStackBotton+01H + OSTaskID 这个地址存放的值
MOV R1,A ;R1 = OSTsakStackBotton+01H + OSTaskID 这个地址存放的值
; if( OSNextTaskID > OSTaskID)
MOV A,OSNextTaskID ; A = OSNextTaskID
SETB C ; 进位位设置为1
SUBB A,OSTaskID ; A = OSNextTaskID- OSTaskID - Cy
JC ?C0001 ; 如果进位位 = 1 就跳转
; {
; while(cp2 != (unsigned char idata *)temp)
; {
; *cp1++ = *cp2++;
; }
MOV A,R7 ;A = R7 = OSTsakStackBotton+01H + OSNextTaskID 这个地址存放的值
CLR C ; 清进位位
SUBB A,R1 ; A = A -R1 -Cy; A= OSTsakStackBotton+01H + OSNextTaskID 这个地址存放的值
减去
OSTsakStackBotton+01H + OSTaskID 这个地址存放的值
MOV R6,A ; R6 = 上面的差值
?C0002:
MOV A,@R1 ;A7 = OSTsakStackBotton+01H + OSTaskID 这个地址存放的值 对应的地址的值
MOV @R0,A ;R0存放的数字对应的地址 赋值为 A7,也就是 SP 指向的 Stack存入 A7那个值
INC R0 ;R0 = R0 +1
INC R1 ;R1 = R1 +1
DJNZ R6,?C0002 ; SP赋值 多次
?C0003:
; temp = OSTsakStackBotton[OSTaskID+1] - (unsigned char idata *)SP-1;
MOV A,#LOW (OSTsakStackBotton+1) ;A = OSTsakStackBotton+01H
ADD A,OSTaskID ; A = OSTsakStackBotton + 01H + OSTaskID
MOV R1,A ; R1 = OSTsakStackBotton + 01H + OSTaskID
MOV A,@R1 ;A = OSTsakStackBotton + 01H + OSTaskID地址存放的值
SETB C ;进位位设置为1
;SUBB A,sp
SUBB A,r2 ; A =( OSTsakStackBotton + 01H + OSTaskID地址存放的值) - r2 - Cy
MOV R7,A ; R7 = ( OSTsakStackBotton + 01H + OSTaskID地址存放的值) - r2 - Cy
; SP = (unsigned char )cp1 - 1;
DEC R0;
MOV SP,R0 // 设置SP堆栈指针的地址
; for(i = OSTaskID+1;i < OSNextTaskID+1; i++)
; {
; OSTsakStackBotton[i] -= temp;
; }
MOV A,OSNextTaskID ; A = OSNextTaskID
CLR C
SUBB A,OSTaskID ; A = OSNextTaskID - OSTaskID
MOV R6,A ; R6 = OSNextTaskID - OSTaskID
JZ ?C0005 ; 累加器为0 则跳转

MOV     A,#LOW (OSTsakStackBotton)
ADD     A,OSTaskID
MOV     R1,A     ; R1 = OSTaskID + OSTsakStackBotton
MOV     A,R7     ;A = 
CPL     A            ; 进位位取反
INC     A              ;加1
MOV     R7,A     ;

?C0004:
INC R1
MOV A,R7
ADD A,@R1
MOV @R1,A
DJNZ R6,?C0004
?C0005:
; OSTaskID = OSNextTaskID;
MOV OSTaskID,OSNextTaskID
; LoadCtx();
LJMP LoadCtx
; }
?C0001:
;
; if( OSNextTaskID != OSTaskID)
MOV A,OSNextTaskID
XRL A,OSTaskID
JZ ?C000r
; {
; cp2–;
; cp1–;
; while(cp2 != (unsigned char idata *)temp)
; {
; *cp2-- = *cp1–;
; }
;MOV A,R7
;CLR C
;SUBB A,R1
;MOV R6,A
mov a,r0
clr c
subb a,r7
mov r6,a
?C0008:
DEC R0
DEC R1
MOV A,@R0
MOV @R1,A
DJNZ R6,?C0008
?C0009:
; temp = OSTsakStackBotton[OSTaskID+1] - (unsigned char idata *)SP-1;
MOV A,#LOW (OSTsakStackBotton+01H)
ADD A,OSTaskID
MOV R1,A
MOV A,@R1
SETB C
;SUBB A,SP
SUBB A,r2
MOV R7,A
; SP = (unsigned char )OSTsakStackBotton[OSNextTaskID+1];
MOV A,#LOW (OSTsakStackBotton+01H)
ADD A,OSNextTaskID
MOV R1,A
MOV A,@R1
MOV SP,A
; for(i = OSNextTaskID+1;i < OSTaskID+1; i++)
; {
; OSTsakStackBotton[i] += temp;
; }

MOV     A,OSTaskID
CLR     C
SUBB    A,OSNextTaskID
JZ      ?C0011

MOV     R6,A
MOV     A,#LOW (OSTsakStackBotton)
ADD     A,OSNextTaskID
MOV     R1,A    

?C0010:
INC R1
MOV A,R7
ADD A,@R1
MOV @R1,A
DJNZ R6,?C0010

?C0011:
; OSTaskID = OSNextTaskID;
MOV OSTaskID,OSNextTaskID
; SP–;
DEC SP
; }
?C0007:
; LoadCtx();
LJMP LoadCtx
?C000r:
IF EN_SP2 <> 0
mov SP,r2
ENDIF
LJMP LoadCtx

Small RTOS(51) 1.20.3v 说明文件 编写动机: 就像在嵌入系统中使用C语言替代汇编一样,在嵌入系统中使用RTOS是大势所趋。原因主要是现在在大多数情况下编程效率比执行效率重要(单片机便宜嘛)。但纵观51的RTOS,keil c51 所带的RTX Full 太大(6k多),且需要外部ram,又无源代码,很多时候不实用。RTX Tiny虽然小(900多字节),但是任务没有优先级和中断管理,也无源代码,也不太实用。而ucosII虽有源代码,但是它太大,又需要外部ram,所有函数又必须是重入函数,用在51这类小片内RAM的单片机上有点勉强。于是,我借鉴ucosII和RTX Tiny编写了Small RTOS 51,虽然它为51系列编写,但是它还是比较容易移植到其它CPU上。 与作者联系方法: 可以给chenmingji@tom.com(原chenmingji@163.net)写信,或是在www.zlgmcu.com.cn上的论坛ARM与ucosII区提问(目前本人是版主)或是在www.c51bbs.com的论坛上提问(不推荐。c51bbs和21ic网名均为cmj)。 版本号定义方式: a.bc.d a:主版本号,一般重大改变时改变它。 bc:次便本号,一般功能增加时改变它。 d:同一版本的修订序号。 版本升级: 1.20.3版 2004年6月8日 修正Os_q.c的一个BUG,造成FIFO发送数据时,在队列中有大量数据且队列较大时,可能会出错。 1.20.2版 2004年2月4日 修正for Keil c51的Os_cpu_c.c的StkDelB函数的BUG,它会影响任务删除的正确执行。 1.20.1版 2004年2月4日 修改OSWait(K_SIG | K_TMO, x) 只能通过信号唤醒的bug。 1.20.0版 2003年8月3日 支持任务动态建立与删除。函数功能向一般的RTOS靠拢。支持C51的重入函数(用关键字reentrant定义的函数)。支持动态内存分配(使用动态内存分配的任务必须使用重入栈)。 1.12.1版 2003年2月5日 修正OS_MAX_TASKS为8、16时的bug。同时修正一些小bug。 1.12.0版 2003年1月24日 OS_MAX_TASKS就是用户任务数量。同时修正一些小bug。 1.11.0版 2002年12月2日 各个任务具有自己的关中断计数器,不在互相影响(这意味着如果一个任务在任务放弃CPU前关了中断,当它再次进入运行态时中断还是关的)。优先级最低的任务作为系统保留任务不再需要用户编写,同时节约一些内存。增加一些注释。更正在Keil C51下Memory Model为非Small 模式的Bug。 1.10.5版 2002年10月26日 更正许多小Bug。 1.10.4版 2002年10月6日 合并Os_cpu_a.asm和OS_CPU_A_task16.ASM。统一了一下代码风格 1.10.3版 2002年9月16日 修改了Os_cpu_a.asm和OS_CPU_A_task16.ASM的LoadCtx代码使之执行更快,代码更小 1.10.2版 2002年9月9日 更正OSWait()的Bug,在极端情况下,这个Bug可能造成可能锁死任务。 修改OSQIntPost()的Keil C51特殊代码,它会造成阅读障碍。 1.10.1版 2002年9月4日 更正OSTimeTick的Bug,它在keil c51中不会有问题,但移植的其它系统可能出错。 1.10版 2002年9月1日 增加Small RTOS 对消息队列(简化的)和信号量的支持;改变了开关中断的方式;增加可移植的变量定义;修正一些Bug。 1.00版 2002年6月20日 使用户可以进行更多的配置,可以禁止中断管理,51系列支持软的非屏蔽中断,并调整目录结构等. 0.60版 2002年5月10日 修改OS_CORE.c使之在keil c51可以重入。不再需要禁止覆盖分析。 0.52版
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值