μ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所打断,发生优先级反转。

注意:若将app.c中的任务中的信号量全部修改为互斥信号量-Mutex,并将其优先级提升自最高优先级,则Task2在延时过程中不会被Task1所打断,不会发生优先级反转。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值