打印

uC/OS-II任务调度的疑惑,就绪态如何进入运行态?

[复制链接]
3299|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
北京户口|  楼主 | 2010-4-25 21:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
感觉很不明白:
就绪态进入运行态只能通过三个系统调用,即OSStart(),OSIntExit(), OS_TASK_SW()。
但是,比如当前运行的是空闲任务OS_TaskIdle(),而空闲任务当中不包含它们当中的任何一个系统调用;我还看了OSTimeTick()中的代码也不包含它们中的任何一个。
那么,其它高优先级的任务就绪了,怎么能从就绪态进入到运行态呢?

相关帖子

沙发
北京户口|  楼主 | 2010-4-25 21:44 | 只看该作者
再补充一下:(下面是源码)

两个任务都延时之后将执行空闲任务。延时到任务将变为就绪态,我的疑惑是就绪的任务是怎么调度进入执行态的,没有看到相关的调度代码。

盼高手给予解答,谢谢!



#include "config.h"
//#include "stdlib.h"

#define   LED1 (1 << 18)            // P1.18控制LED1

#define Task0StkLengh 64    // 定义用户任务0的堆栈长度
#define TaskLED1StkSize 128    // 定义任务TaskLED1的堆栈长度

OS_STK Task0Stk [Task0StkLengh];  // 定义用户任务0的堆栈
OS_STK TaskLED1Stk [TaskLED1StkSize]; // 定义任务TaskLED1的堆栈

void  Task0(void *pdata);    // Task0 任务0
void  TaskLED1(void *data);    // 任务TaskLED1

/*
*********************************************************************************************************
** 函数名称 :main()
** 函数功能 :c语言的主函数,由它启动多任务环境
*********************************************************************************************************
*/
int main (void)
{
OSInit ();                          
OSTaskCreate (Task0,(void *)0, &Task0Stk[Task0StkLengh - 1], 2);  
OSStart ();
return 0;               
}

/*
********************************************************************************************************
**          Task0 任务0
**        完成目标板初始化和创建TaskLED1任务
********************************************************************************************************
*/

void Task0 (void *pdata)
{
pdata = pdata;
TargetInit ();
OSTaskCreate (TaskLED1,(void *)0, &TaskLED1Stk[TaskLED1StkSize - 1], 3);  

while (1)
{
  OSTimeDly(10);
}
}

/*
********************************************************************************************************
**          TaskLED1
**             LED1任务
********************************************************************************************************
*/
void  TaskLED1(void *pdata)
{
    pdata = pdata;                             // 避免编译警告

PINSEL2 = PINSEL2 & (~0x08);        // P1[25:16]选择GPIO
   
    IO1DIR |= LED1;                        // 设置LED1控制口输出
    IO1SET  = LED1;
   
    for (;;)
    {
        IO1CLR = LED1;
        OSTimeDly(OS_TICKS_PER_SEC / 4);
        IO1SET = LED1;
        OSTimeDly(OS_TICKS_PER_SEC / 2);
    }
}

使用特权

评论回复
板凳
米其林r| | 2010-4-25 21:45 | 只看该作者
你提到的具体实例是这样调用的,

用OSTimeDly()函数挂起的任务在每次时钟节拍的时候都会被查询一次,

当挂起的时间到了之后,就会取消等待进入就绪状态,同时引发一次任务调度(即从就绪任务中找到最高优先级任务并执行)





OSStart(),OSIntExit(), OS_TASK_SW()是显式的任务调度(其中OSIntExit()出现在中断),其实ucos系统中在时钟节拍中断,在请求事件操作等都会引发任务调度。

使用特权

评论回复
地板
S3C2440| | 2010-4-25 21:46 | 只看该作者
周立功的实验光盘中的例子:

        void TargetInit(void)
{
    OS_ENTER_CRITICAL();
    srand((uint32) TargetInit);
    VICInit();
    Timer0Init();
    OS_EXIT_CRITICAL();
}



        void VICInit(void)
{
    extern void IRQ_Handler(void);
    extern void Timer0_Handler(void);

    VICIntEnClr = 0xffffffff;
    VICDefVectAddr = (uint32)IRQ_Handler;

    VICVectAddr0 = (uint32)Timer0_Handler;
    VICVectCntl0 = (0x20 | 0x04);
    VICIntEnable = 1 << 4;
}



        void Timer0_Exception(void)
{
    T0IR = 0x01;
    VICVectAddr = 0;            // 通知中断控制器中断结束
    OSTimeTick();
}



void  OSTimeTick (void)
{
#if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr;
#endif   
    OS_TCB    *ptcb;


    OSTimeTickHook();                                      /* Call user definable hook                 */
#if OS_TIME_GET_SET_EN > 0   
    OS_ENTER_CRITICAL();                                   /* Update the 32-bit tick counter           */
    OSTime++;
    OS_EXIT_CRITICAL();
#endif   
    ptcb = OSTCBList;                                      /* Point at first TCB in TCB list           */
    while (ptcb->OSTCBPrio != OS_IDLE_PRIO) {              /* Go through all TCBs in TCB list          */
        OS_ENTER_CRITICAL();
        if (ptcb->OSTCBDly != 0) {                         /* Delayed or waiting for event with TO     */
            if (--ptcb->OSTCBDly == 0) {                   /* Decrement nbr of ticks to end of delay   */
                if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == 0x00) {   /* Is task suspended?             */
                    OSRdyGrp               |= ptcb->OSTCBBitY; /* No,  Make task Rdy to Run (timed out)*/
                    OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
                } else {                                       /* Yes, Leave 1 tick to prevent ...     */
                    ptcb->OSTCBDly = 1;                        /* ... loosing the task when the ...    */
                }                                              /* ... suspension is removed.           */
            }
        }
        ptcb = ptcb->OSTCBNext;                                /* Point at next TCB in TCB list        */
        OS_EXIT_CRITICAL();
    }
}





我的想法是,两个任务都被延时后,执行空闲任务,延时到了以后,变为就绪态,应该由时间中断函数执行调度,可是在OSTimeTick()函数中,只是将就绪表置1,并没有OSIntExit()函数来执行任务切换。我想知道的是任务切换在这样一个程序里究竟是怎么样实现的,由什么代码来实现的?谢谢啦

使用特权

评论回复
5
思行合一| | 2010-4-25 21:46 | 只看该作者
虽然没有使用OSInitExit(),但是他用代码实现了函数的功能,可以参考一下OSInitExit()这个函数的源码。

使用特权

评论回复
6
北京户口|  楼主 | 2010-4-25 21:47 | 只看该作者
我的问题已解决。

关键是宏  handle

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

107

主题

521

帖子

1

粉丝