lihmily 发表于 2009-4-26 21:30:05

请教马老师一个small rtos51的问题

由于Small RTOS51的系统时间片分配程序为OSTimeTick(),定时中断中调用OSTimeTick()这个函数控制时钟节拍 ,调用OSWait(K_TMO,5)这个延时函数,宏定义的临界区OS_ENTER_CRITICAL()关闭了中断,无法等到下个时钟节拍的到来。while (OSWaitTick != 0)一直运行退出不了。

可以给解释下吗?

uint8 OSWait(uint8 typ, uint8 ticks)

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


#defineOS_ENTER_CRITICAL()EA = 0,Os_Enter_Sum++            /* 禁止中断                                    */
#defineOS_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;
#else
      if (TaskId < 8)
      {
            ((uint8 *)(&OSTaskRuning)) &= ~OSMapTbl;
      }
      else
      {
            ((uint8 *)(&OSTaskRuning)) &= ~OSMapTbl;
      }
#endif
      OS_EXIT_CRITICAL();
    }
}
************************************
** 函数名称: OSSched
** 功能描述: 非中断的任务切换函数
** 输 入: 无
** 输 出: 无
** 全局变量: OSIntNesting,OSNextTaskID
** 调用模块: OS_TASK_SW
**
------------------------------------------------------------------------------
********************************************************************************************************/
voidOSSched(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
**

voidOSTimeTick(void)
{
    uint8 i;

    for (i = 0; i < OS_MAX_TASKS; i++)               
    {
      if (OSWaitTick != 0 )
      {
            OSWaitTick--;
            if (OSWaitTick == 0)
            {
                OSIntSendSignal(i);
            }
      }
    }
}



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


;/*********************************************************************************************************
;** 函数名称: OSCtxSw
;** 功能描述: 任务主动放弃CPU环境保存函数
;** 输 入: OSTaskID
;** 输 出 : 无
;** 全局变量: OSFastSwap
;** 调用模块: 无
;**

;********************************************************************************************************/
    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
;**
;**-------------------------------------------------------------------------------------------------------
;********************************************************************************************************/
        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;
    MOV   A,#LOW (OSTsakStackBotton+01H)
    ADD   A,OSNextTaskID
    MOV   R1,A
    MOV   A,@R1
    MOV   R7,A
;   cp2 = OSTsakStackBotton;
    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 - (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 - (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;
    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
;** 输 出 : 无
;** 全局变量: 无
;** 调用模块: 无
;**

;********************************************************************************************************/

        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

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

machao 发表于 2009-4-27 20:43:19

1。51的东西怎么发到这里了?
2。已经要玩RTOS了,应该自己能沟调试了吧。

779450343 发表于 2010-8-10 20:24:10

我想知道c_osctxsw这个函数是如何处理堆栈的

779450343 发表于 2010-8-10 20:24:46

陈的代码注释实在太少

fifthboy 发表于 2010-8-10 21:31:50

在函数OSCtxSw()中,切换到低优先级的已经就绪的任务上,
执行那个任务中的 OS_EXIT_CRITICAL();关中断的次数减一。

gagaguojia 发表于 2012-7-6 10:47:18

你的系统时钟使用的那个定时器,用哪个,初始化就处理好那个,还有就是在os_cpu.h中,#define OS_TIME_ISR 要定义和你所选的定时器一样的中断号,比如说我选tmer2为系统的时钟节拍中断定时器,则我得定义   #define OS_TIME_ISR5;
还有就是如果你用的是tmer2的话,TF2是要在中断中软件清除的,所以,
你要 使能---------》》》#define EN_USER_TICK_TIMER      1
并且在os_cfg.h中添加
#ifdef IN_OS_CPU_C
#if EN_USER_TICK_TIMER > 0
//extern void UserTickTimer(void);            /* 系统定时中断中调用的用户函数                              */
#define UserTickTimer() TF2=0;            /* 系统定时中断中调用的用户函数                              */
#endif
页: [1]
查看完整版本: 请教马老师一个small rtos51的问题