实验描述:
注意:占有资源的低优先级不能主动放弃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所打断,不会发生优先级反转。