μC/OS-II实验:实验二 优先级反转及解决方法

实验描述:
注意:占有资源的低优先级不能主动放弃CPU,不然优先级肯定反转。实验手册的实验是错的。

涉及的μC/OS-II系统函数:
。。。

实验代码:
 app.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/* 任务 TA0 的优先级最高,它需要使用信号量 mutex */
void Task0( void* pdata)
{
    INT8U err;
    INT8U id;
    id = *( int *)pdata;
     while( 1)
    {
        printf( "Task_%d waitting for an EVENT\r\n",id); 
        OSTimeDly( 1000);                           /* Delay 1000 clock tick        */ 
        printf( "Task_%d's EVENT CAME!\r\n",id); 
        printf( "Task_%d trying to GET MUTEX\r\n",id); 
        OSMutexPend(pmutex, 0,&err);                            /* Acquire mutex */ 
         switch(err) 
        { 
             case OS_NO_ERR: 
                printf( "Task_%d GOT mutex.\r\n",id); 
                 break
             default
                printf( "Task_%d CANNOT get mutex, has been SUSPENDED.\r\n",id); 
          } 
          OSTimeDly( 1000);                             /* Delay 1000 clock tick        */ 
          printf( "Task_%d RELEASE mutex\r\n",id); 
          OSMutexPost(pmutex);                           /* Release mutex          */ 
    }
}
/* 任务 TA1 具有中等优先级,它不使用信号量 */
void Task1( void* pdata)
{
    INT8U   id; 
    id=*( int *)pdata;
     while( 1)
    {
        printf( "Task_%d waitting for an EVENT\r\n",id); 
        OSTimeDly( 500);                         /* Delay 500 clock tick        */ 
        printf( "Task_%d's EVENT CAME!\r\n",id); 
        OSTimeDly( 500); 
    }
}

/* 任务 TA2 的优先级最低,和高优先级任务 TA0 共用信号量 mutex */
void Task2( void* pdata)
{
    INT8U   err; 
    INT8U   id;  
    INT32U i;
    id=*( int *)pdata; 
    
     while( 1)
    {
        printf( "Task_%d trying to GET MUTEX\r\n",id); 
        OSMutexPend(pmutex, 0,&err);                        /*  Acquire mutex */ 
         switch(err) 
        { 
             case OS_NO_ERR: 
                printf( "Task_%d GOT mutex.\r\n",id); 
                 /* 此时Task2占有资源和CPU,但是会被Task1抢占,发生优先级反转 */
                 for(i= 0;i< 40000000;i++);
                 break
             default : 
                printf( "Task_%d CANNOT get mutex,  has been SUSPENDED.\r\n",id); 
                 /* 此时Task2占有资源和CPU,但是会被Task1抢占,发生优先级反转 */
                 for(i= 0;i< 40000000;i++);
                 break
        } 
        printf( "Task_%d RELEASE mutex\r\n",id); 
        OSMutexPost(pmutex);                        /* Releasemutex          */ 
    }
}

 app.h
1
2
3
4
5
GLOBAL OS_EVENT* psem;
GLOBAL OS_EVENT* pmutex;

#define N_TASKS      3
GLOBAL  INT8U TaskData[N_TASKS];

 app_cfg.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#define TASK0_STK_SIZE       64
#define TASK1_STK_SIZE       64
#define TASK2_STK_SIZE       64

#define TASK0_TASK_PRIO      4
#define TASK1_TASK_PRIO      5
#define TASK2_TASK_PRIO      6

#ifdef GLOBAL_STASK_DEFINE
#define GLOBAL 
#else
#define GLOBAL  extern
#endif

GLOBAL OS_STK   TASK_TASK0_STK[TASK0_STK_SIZE];
GLOBAL OS_STK   TASK_TASK1_STK[TASK1_STK_SIZE];
GLOBAL OS_STK   TASK_TASK2_STK[TASK2_STK_SIZE];

void Task0( void* pdata);
void Task1( void* pdata);
void Task2( void* pdata);

 main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//启动任务
static  void TaskStart( void* pdata)
{
    INT8U err;
    INT8U   i;  
      for (i =  0; i <N_TASKS; i++)     // Create N_TASKS identical tasks 
     { 
        TaskData[i] = i; 
     } 
    pdata = pdata; 
     //APP Initialization
     //系统时钟必须在OSStart()之后调用
    Systick_Configuration();
    
#if(OS_TASK_STAT_EN >  0)
    OSStatInit();
#endif
#if OS_SEM_EN >  0 && OS_MAX_EVENTS >  0
    psem = OSSemCreate((INT16U) 1);
#endif
#if OS_MUTEX_EN > 0 && OS_MAX_EVENTS >  0
    pmutex = OSMutexCreate( 1,&err);
#endif

     /* 实验二  优先级反转 */
    OSTaskCreate(Task0,( void*)&TaskData[ 0],(OS_STK*)&TASK_TASK0_STK[TASK0_STK_SIZE- 1],TASK0_TASK_PRIO);
    OSTaskCreate(Task1,( void*)&TaskData[ 1],(OS_STK*)&TASK_TASK1_STK[TASK1_STK_SIZE- 1],TASK1_TASK_PRIO);
    OSTaskCreate(Task2,( void*)&TaskData[ 2],(OS_STK*)&TASK_TASK2_STK[TASK2_STK_SIZE- 1],TASK2_TASK_PRIO);
    
     //创建其他任务之后删除自己
    OSTaskDel(OS_PRIO_SELF);
}


若要switch分支发挥作用,则需修改os_sem.c中的OSSemPend函数:
不然,switch分支不起作用,其中的default分支表示的是 在获得信号量的道路上有没有被打断过
PS:为了方便观察,os_sem.c的文件未作修改。


实验结果:
此时使用 二值信号量-Binary Semaphore,则再Task2的延时过程中,不断被Task1所打断,发生优先级反转。
μC/OS-II实验:实验二 优先级反转及解决方法_第1张图片
注意:若将app.c中的任务中的信号量全部修改为 互斥信号量-Mutex,并将其优先级提升自最高优先级,则Task2在延时过程中不会被Task1所打断,不会发生优先级反转。

你可能感兴趣的:(ucos-II,优先级反转及解决方法)