关于Small RTOS51的系统时间片分配程序

beibeishen 2009-04-25 09:26:14
由于Small RTOS51的系统时间片分配程序为OSTimeTick(),定时中断中调用OSTimeTick()这个函数控制时钟节拍 ,OSWait(K_TMO,5)这个
延时函数中,宏定义的临界区OS_ENTER_CRITICAL()关闭了中断,时钟节拍好像就无法运行了。while (OSWaitTick[OSTaskID] != 0) 一直运行退出不了。

可以给解释下吗?

uint8 OSWait(uint8 typ, uint8 ticks)

{
OSWaitTick[OSTaskID] = ticks; /* 设置超时时间 */
/* 可以优化寄存器的使用 */
switch(typ)
{
case K_SIG: /* 等待信号,即挂起自己 */
OSWaitTick[OSTaskID] = 0; /* 没有超时处理 */
OSClearSignal(OSTaskID); /* 任务进入等待状态 */
OSSched(); /* 运行下一个任务 */
return SIG_EVENT;
case K_TMO: /* 等待超时,即延时一段时间 */
OS_ENTER_CRITICAL();
while (OSWaitTick[OSTaskID] != 0) /* 判断超时时间是否到 */
{
OSClearSignal(OSTaskID); /* 任务进入等待状态 */
OSSched(); /* 运行下一个任务 */
}
OS_EXIT_CRITICAL();
return TMO_EVENT;
case (K_TMO | K_SIG): /* 等待信号(挂起自己)直到超时 */
/* 别的任务或中断可以恢复它 */
OS_ENTER_CRITICAL();
if (OSWaitTick[OSTaskID] == 0) /* 判断超时时间是否到 */
{
return TMO_EVENT;
}
OSClearSignal(OSTaskID); /* 任务进入等待状态 */
OS_EXIT_CRITICAL();
OSSched(); /* 运行下一个任务 */
if (OSWaitTick[OSTaskID] != 0)
{
OSWaitTick[OSTaskID] = 0;
return SIG_EVENT;
}
return TMO_EVENT;
default:
OSWaitTick[OSTaskID] = 0;
return NOT_OK;
}
}

不胜感激~~
...全文
252 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
风吟1987 2010-10-12
  • 打赏
  • 举报
回复
很久的帖子了,写给偶尔路过的兄弟:
这个问题的关键在:OSSched(); /* 运行下一个任务 */
这个函数的作用就是切换到下一个任务,调用了下面的函数:
#define OS_TASK_SW() OSCtxSw()
OSCtxSw()调用C_OSCtxSw()

C_OSCtxSw()调用 LoadCtx();
LoadCtx()中有以下语句
LoadCtx_2:
;判断是否需要开中断
INC Os_Enter_Sum
djnz Os_Enter_Sum,LoadCtx_3
SET_EA ;开中断
LoadCtx_3:
RET
到此中断才被打开

lengqing1309 2009-04-29
  • 打赏
  • 举报
回复
认真看了一下,的确没看出那个地方有允许总中断的。
个人认为应该是在任务切换汇编那部分里
如果可以,用keil单步仿真认真找找看。
另外里面有个允许中断嵌套要配置为1
lengqing1309 2009-04-27
  • 打赏
  • 举报
回复
搞定了没?
不知道你有没有修改过OS里面的函数?
如果没修改过,那么应该是OS任务配置出问题,或者时间基准中断未运行。
认真检查一下任务函数以及OS的配置。
我用了N久没出过问题啊。
beibeishen 2009-04-27
  • 打赏
  • 举报
回复
5楼
请问你使用OSWait(K_TMO,5)读它的代码可以读通吗?
OS_ENTER_CRITICAL(); 这句把总中断关闭了,清除当前任务之后调用别的任务,这时候你在定时中断中的时间服务程序是无法运行的

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

Os_Enter_Sum的值为0才开中断,
Os_Enter_Sum在 OSClearSignal(OSTaskID); OSSche(); 中都没变成0

请问是在哪里变为0的
morris88 2009-04-27
  • 打赏
  • 举报
回复
    POP    7 
POP 6
POP 5
POP 4
POP 3
POP 2
POP 1
POP 0
POP PSW
POP DPL
POP DPH
POP B
POP ACC


貌似切换时,重置了中断标志,使能了中断...
beibeishen 2009-04-26
  • 打赏
  • 举报
回复

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


/*********************************************************************************************************
** 函数名称: OSClearSignal
** 功能描述: 清除指定任务信号,既使指定任务休眠
** 输 入: TaskId : 任务ID
** 输 出: 无
** 全局变量: OSTaskRuning
** 调用模块: 无

void OSClearSignal(uint8 TaskId)
{
if (TaskId < OS_MAX_TASKS)
{
OS_ENTER_CRITICAL();
#if OS_MAX_TASKS < 9
OSTaskRuning &= ~OSMapTbl[TaskId];
#else
if (TaskId < 8)
{
((uint8 *)(&OSTaskRuning))[LOW_BYTE] &= ~OSMapTbl[TaskId];
}
else
{
((uint8 *)(&OSTaskRuning))[HIGH_BYTE] &= ~OSMapTbl[TaskId & 0x07];
}
#endif
OS_EXIT_CRITICAL();
}
}
************************************
** 函数名称: OSSched
** 功能描述: 非中断的任务切换函数
** 输 入: 无
** 输 出: 无
** 全局变量: OSIntNesting,OSNextTaskID
** 调用模块: OS_TASK_SW
**
------------------------------------------------------------------------------
********************************************************************************************************/
void OSSched(void)

{
uint8 temp;

OS_ENTER_CRITICAL();
#if EN_OS_INT_ENTER > 0
if (OSIntNesting == 0) /* 是否是中断中调用 */
{
#endif

#if OS_MAX_TASKS < 9
/* 查找处于就绪状态的任务中优先级最高的任务 */
temp = OSTaskRuning;
for (OSNextTaskID = 0; OSNextTaskID < OS_MAX_TASKS; OSNextTaskID++)
{
if ((temp & 0x01) != 0)
{
break;
}
temp = temp >> 1;
}
OS_TASK_SW(); /* 进行任务调度 */
#else
/* 查找处于就绪状态的任务中优先级最高的任务 */
temp = OSTaskRuning % 256;
for (OSNextTaskID = 0; OSNextTaskID < 8; OSNextTaskID++)
{
if ((temp & 0x01) != 0)
{
goto TaskSw;
}
temp = temp >> 1;
}

temp = OSTaskRuning / 256 ;
for (; OSNextTaskID < OS_MAX_TASKS; OSNextTaskID++)
{
if ((temp & 0x01) != 0)
{
break;
}
temp = temp >> 1;
}
TaskSw:
OS_TASK_SW(); /* 进行任务调度 */
#endif

#if EN_OS_INT_ENTER > 0
}
#endif
OS_EXIT_CRITICAL();
}
************************************
** 函数名称: OSTimeTick
** 功能描述: 系统时钟处理函数,处理各个任务的延时
** 输 入: 无
** 输 出: 无
** 全局变量: OSWaitTick
** 调用模块: OSIntSendSignal
**

void OSTimeTick(void)
{
uint8 i;

for (i = 0; i < OS_MAX_TASKS; i++)
{
if (OSWaitTick[i] != 0 )
{
OSWaitTick[i]--;
if (OSWaitTick[i] == 0)
{
OSIntSendSignal(i);
}
}
}
}
morris88 2009-04-26
  • 打赏
  • 举报
回复
关键就是 OS_TASK_SW 这个函数,贴出来瞧瞧...
beibeishen 2009-04-26
  • 打赏
  • 举报
回复
;/*********************************************************************************************************
;** 函数名称: OSCtxSw
;** 功能描述: 任务主动放弃CPU环境保存函数
;** 输 入: OSTaskID
;** 输 出 : 无
;** 全局变量: OSFastSwap
;** 调用模块: 无
;**
;** 作 者: 陈明计
;** 日 期: 2002年2月22日
;**-------------------------------------------------------------------------------------------------------
;** 修 改:
;** 日 期:
;**-------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
RSEG ?PR?OSCtxSw?OS_CPU_A
OSCtxSw:
USING 0
;设置标志:任务再次恢复运行时不必恢复所有寄存器
MOV DPTR,#OSMapTbl
MOV A,OSTaskID
#if OS_MAX_TASKS < 9
MOVC A,@A+DPTR
ORL A,OSFastSwap
MOV 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
;** 功能描述: 堆栈处理函数
;** 输 入: 无
;** 输 出 : 无
;** 全局变量: OSTaskID,OSTsakStackBotton,SP
;** 调用模块: LoadCtx
;**
;** 作 者: 陈明计
;** 日 期: 2002年2月22日
;**-------------------------------------------------------------------------------------------------------
;** 修 改: 陈明计
;** 日 期: 2002年12月2日
;**-------------------------------------------------------------------------------------------------------
;** 修 改:
;** 日 期:
;**-------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
RSEG ?PR?C_OSCtxSw?OS_CPU_C
C_OSCtxSw:
PUSH Os_Enter_Sum ;保存关中断计数器
mov r2,sp

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

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

INC R0
; temp = (unsigned char )OSTsakStackBotton[OSNextTaskID+1];
MOV A,#LOW (OSTsakStackBotton+01H)
ADD A,OSNextTaskID
MOV R1,A
MOV A,@R1
MOV R7,A
; cp2 = OSTsakStackBotton[OSTaskID+1];
MOV A,#LOW (OSTsakStackBotton+01H)
ADD A,OSTaskID
MOV R1,A
MOV A,@R1
MOV R1,A
; if( OSNextTaskID > OSTaskID)
MOV A,OSNextTaskID
SETB C
SUBB A,OSTaskID
JC ?C0001
; {
; while(cp2 != (unsigned char idata *)temp)
; {
; *cp1++ = *cp2++;
; }
MOV A,R7
CLR C
SUBB A,R1
MOV R6,A
?C0002:
MOV A,@R1
MOV @R0,A
INC R0
INC R1
DJNZ R6,?C0002
?C0003:
; temp = OSTsakStackBotton[OSTaskID+1] - (unsigned char idata *)SP-1;
MOV A,#LOW (OSTsakStackBotton+1)
ADD A,OSTaskID
MOV R1,A
MOV A,@R1
SETB C
;SUBB A,sp
SUBB A,r2
MOV R7,A
; SP = (unsigned char )cp1 - 1;
DEC R0;
MOV SP,R0
; for(i = OSTaskID+1;i < OSNextTaskID+1; i++)
; {
; OSTsakStackBotton[i] -= temp;
; }
MOV A,OSNextTaskID
CLR C
SUBB A,OSTaskID
MOV R6,A
JZ ?C0005

MOV A,#LOW (OSTsakStackBotton)
ADD A,OSTaskID
MOV R1,A
MOV A,R7
CPL A
INC A
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
;****************************************************************************************

;****************************************************************************************
;/*********************************************************************************************************
;** 函数名称: LoadCtx
;** 功能描述: 任务环境恢复函数
;** 输 入: OSTaskID,OSFastSwap
;** 输 出 : 无
;** 全局变量: 无
;** 调用模块: 无
;**
;** 作 者: 陈明计
;** 日 期: 2002年2月22日
;**-------------------------------------------------------------------------------------------------------
;** 修 改: 陈明计
;** 日 期: 2002年12月2日
;**-------------------------------------------------------------------------------------------------------
;** 修 改: 陈明计
;** 日 期: 2003年2月5日
;**-------------------------------------------------------------------------------------------------------
;** 修 改:
;** 日 期:
;**-------------------------------------------------------------------------------------------------------
;********************************************************************************************************/

RSEG ?PR?LoadCtx?OS_CPU_A
LoadCtx:
USING 0

POP Os_Enter_Sum ;恢复关中断计数器
;判断是否需要恢复所有寄存器
MOV A,OSTaskID
CJNE A,#OS_MAX_TASKS,LoadCtx_0
SJMP LoadCtx_2
LoadCtx_0:
MOV DPTR,#OSMapTbl
#if OS_MAX_TASKS < 9
MOVC A,@A+DPTR
ANL A,OSFastSwap
#else
MOV R6,OSFastSwap
CLR C
SUBB A,#8
JNC LoadCtx_1
MOV R6,OSFastSwap + 1
MOV A,OSTaskID
LoadCtx_1:
MOVC A,@A+DPTR
ANL A,R6
#endif
JNZ LoadCtx_2
;恢复寄存器
POP 7
POP 6
POP 5
POP 4
POP 3
POP 2
POP 1
POP 0
POP PSW
POP DPL
POP DPH
POP B
POP ACC
LoadCtx_2:
;判断是否需要开中断
INC Os_Enter_Sum
djnz Os_Enter_Sum,LoadCtx_3
SET_EA ;开中断
LoadCtx_3:
RET

;****************************************************************************************
lbing7 2009-04-25
  • 打赏
  • 举报
回复
LZ
给一下:

OS_ENTER_CRITICAL()
OSClearSignal(OSTaskID);
OSSched();

这三个的实现看看?

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧