搜索
bottom↓
回复: 5

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

[复制链接]

出0入0汤圆

发表于 2009-4-26 21:30:05 | 显示全部楼层 |阅读模式
由于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;
    }
}


#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);
            }
        }
    }
}



#define  OS_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[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
;** 输 出 : 无
;** 全局变量: 无
;** 调用模块: 无
;**

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

        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

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

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2009-4-27 20:43:19 | 显示全部楼层
1。51的东西怎么发到这里了?
2。已经要玩RTOS了,应该自己能沟调试了吧。

出0入0汤圆

发表于 2010-8-10 20:24:10 | 显示全部楼层
我想知道c_osctxsw这个函数是如何处理堆栈的

出0入0汤圆

发表于 2010-8-10 20:24:46 | 显示全部楼层
陈的代码注释实在太少

出0入0汤圆

发表于 2010-8-10 21:31:50 | 显示全部楼层
在函数OSCtxSw()中,切换到低优先级的已经就绪的任务上,
执行那个任务中的 OS_EXIT_CRITICAL();  关中断的次数减一。

出0入0汤圆

发表于 2012-7-6 10:47:18 | 显示全部楼层
你的系统时钟使用的那个定时器,用哪个,初始化就处理好那个,还有就是在os_cpu.h中,#define OS_TIME_ISR 要定义和你所选的定时器一样的中断号,比如说我选tmer2为系统的时钟节拍中断定时器,则我得定义   #define OS_TIME_ISR  5;
还有就是如果你用的是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
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-2 07:50

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表