3753|8

75

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

关于Small RTOS51的系统时间片分配程序 [复制链接]

由于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;
    }
}

不胜感激~~

最新回复

认真看了一下,的确没看出那个地方有允许总中断的。 个人认为应该是在任务切换汇编那部分里 如果可以,用keil单步仿真认真找找看。 另外里面有个允许中断嵌套要配置为1  详情 回复 发表于 2009-4-29 11:01
点赞 关注

回复
举报

71

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
LZ
给一下:

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

这三个的实现看看?
 
 

回复

87

帖子

0

TA的资源

一粒金砂(初级)

板凳
 

#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 != 0 )
        {
            OSWaitTick--;
            if (OSWaitTick == 0)
            {
                OSIntSendSignal(i);
            }
        }
    }
}
 
 
 

回复

74

帖子

0

TA的资源

一粒金砂(初级)

4
 
关键就是 OS_TASK_SW 这个函数,贴出来瞧瞧...
 
 
 

回复

61

帖子

0

TA的资源

一粒金砂(初级)

5
 
;/*********************************************************************************************************
;** 函数名称: 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 -= 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 += 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

;****************************************************************************************
 
 
 

回复

67

帖子

0

TA的资源

一粒金砂(初级)

6
 
搞定了没?
不知道你有没有修改过OS里面的函数?
如果没修改过,那么应该是OS任务配置出问题,或者时间基准中断未运行。
认真检查一下任务函数以及OS的配置。
我用了N久没出过问题啊。
 
 
 

回复

70

帖子

0

TA的资源

一粒金砂(初级)

7
 
  1.     POP    7
  2.     POP    6
  3.     POP    5
  4.     POP    4
  5.     POP    3
  6.     POP    2
  7.     POP    1
  8.     POP    0
  9.     POP    PSW
  10.     POP    DPL
  11.     POP    DPH
  12.     POP    B
  13.     POP    ACC
复制代码


貌似切换时,重置了中断标志,使能了中断...
 
 
 

回复

78

帖子

0

TA的资源

一粒金砂(初级)

8
 
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的   
 
 
 

回复

71

帖子

0

TA的资源

一粒金砂(初级)

9
 
认真看了一下,的确没看出那个地方有允许总中断的。
个人认为应该是在任务切换汇编那部分里
如果可以,用keil单步仿真认真找找看。
另外里面有个允许中断嵌套要配置为1
 
 
 

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

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表