【iCore4 雙核心板_uC/OS-II】例程七:互斥訊號量

XiaomaGee發表於2018-02-08

一、實驗說明:

  在介紹互斥訊號量前,我們先簡單地描述一下什麼是優先順序反轉。使用實時核心心,優先順序反轉問題是實時系統中出現得最多的問題。假設任務H優先順序高於任務M,任務M優先順序高於任務L。任務H和任務M處於掛起狀態,等待某一事件發生,任務L正在執行。此時,任務L要使用共享資源。使用共享資源之前,首先必須得到該資源的訊號量。任務L得到了該訊號量,並開始使用該共享資源。由於任務H的優先順序高,它等待的事件到來之後剝奪了任務L的CPU使用權,任務L被掛起,任務H開始執行。執行過程中任務H也要使用那個任務L正在使用著的資源,由於該資源的訊號量還被任務L佔用著,任務H只能進入掛起狀態,等待任務L釋放該訊號量。任務L得以繼續執行。由於任務M的優先順序高於任務L,當任務M等待的事件發生後,任務M剝奪了任務L的CPU使用權並開始執行。處理它該處理的事件,直到處理完之後將CPU控制權還給任務L。任務L接著執行,直到釋放那個共享資源的訊號量。直到此時,由於實時核心知道有個高優先順序的任務(任務H)在等待這個訊號量,核心做任務切換,使任務H得到該訊號量並接著執行。

  在這種情況下,任務H優先順序實際上降到了任務L的優先順序水平。因為任務H要等,一直等到任務L釋放佔有的那個共享資源。由於任務M剝奪了任務L的CPU使用權,使任務H的狀況更加惡化,任務M使任務H增加了額外的延遲時間。任務H和任務M的優先順序發生了反轉。

  任務優先順序反轉是不允許出現的,因為它可能會造成不可預期的嚴重後果,因此uC/OS-II提供了一種特殊的二值訊號量——互斥訊號量,它能夠順利地解決這種現象。

(1)任務H和任務M正在等待一個事件發生,處於掛起狀態,任務L正在執行。

(2)在某一時刻,任務L請求一個互斥訊號量以能夠訪問一個共享資源。

(3)任務L請求到共享資源的互斥訊號量,開始訪問該共享資源。

(4)任務H等待的事件發生,由於任務H的優先順序高於任務L的優先順序,核心掛起了任務L開始執行任務H。

(5)任務H開始執行。

(6)任務H也想訪問L現在正在訪問著的共享資源(它想從任務L得到互斥訊號量),為了儘快地讓任務H請求到互斥訊號量,並且在L訪問共享資源過程中不再被其他中等優先順序任務打斷,uC/OS-II將任務L的優先順序提升到任務H同等高度。

(7)任務L繼續訪問共享資源,然而它現在是以任務H的優先順序進行的,注意任務H還沒有執行,因為它正在等待任務L釋放互斥訊號量,換句話說,任務H在該互斥訊號量的等待列表中。

(8)任務L完成共享資源的使用,釋放掉互斥訊號量 。uC/OS-II發現任務L的優先順序被提高,因此將任務L的優先順序降低到原來的高度。然後,uC/OS-II將釋放的互斥訊號量分配給正在等待的任務H。

(9)任務H獲得互斥訊號量,開始訪問共享資源。

(10)任務H完成共享資源的使用,釋放掉互斥訊號量。

(11)沒有更高優先順序的任務執行,因此任務H繼續執行。

(12)任務H完成,開始等待一個事件。這時uC/OS-II恢復當任務H或者任務L正在執行時處於就緒態的任務M。

(13)任務M執行。

二、實驗截圖:

三、原始碼下載連結:

連結:https://pan.baidu.com/s/1qZavQpA 密碼:o8p5

四、核心程式碼

/*
 * Name                : main
 * Description         : ---
 * Author              : liu.
 *
 * History
 * --------------------
 * Rev                 : 0.00
 * Date                : 07/12/2017
 * 
 * create.
 * --------------------
 */
/*實驗現象:
  開啟串列埠工具putty.exe,終端顯示此時任務AppTask1_task,AppTask2_task和AppTask3_task
  的執行狀態,任務AppTask1_task請求到互斥訊號量紅色ARM.LED點亮,任務AppTask2_task運
  行過程中藍色ARM.LED閃爍。
  備註:當任務AppTask1_task請求互斥態進入就緒態時,之後本應該執行的任務AppTask2_task
  (藍色ARM.LED閃爍),由於任務AppTask3_task的優先順序被提高(高於任務AppTask2_task),
  所以任務AppTask2_task就進入了就緒態(藍色ARM.LED停止閃爍),等待任務AppTask3_task
  釋放出訊號量後繼續執行。
  */
int main(void)
{
    system_clock.initialize();                               //系統時鐘初始化
    led.initialize();                                        //LED初始化
    usart6.initialize(115200);                               //串列埠初始化
    key.initialize();

    OSInit(); 

    //UCOS初始化
    OSTaskCreate(start_task,                                 //建立開始任務
            (void*)0,                                   //任務引數
            (OS_STK*)&START_TASK_STK[START_STK_SIZE-1], //任務堆疊
            START_TASK_PRIO);                           //任務優先順序
    OSStart();                                               //開啟UCOS    
}
/*
 * Name                : start_task
 * Description         : ---
 * Author              : liu.
 *
 * History
 * --------------------
 * Rev                 : 0.00
 * Date                : 07/12/2017
 * 
 * create.
 * --------------------
 */
void start_task(void *pdata)
{
    INT8U      err;
    OS_CPU_SR cpu_sr;

    TaskMutex = OSMutexCreate(0, &err);//建立互斥訊號量    

    OSStatInit();//初始化統計任務

    OS_ENTER_CRITICAL();//關中斷

    OSTaskCreate(AppTask1_task,(void*)0,(OS_STK*)&AppTask1_TASK_STK[AppTask1_STK_SIZE-1],AppTask1_TASK_PRIO);//建立AppTask1任務
    OSTaskCreate(AppTask2_task,(void*)0,(OS_STK*)&AppTask2_TASK_STK[AppTask2_STK_SIZE-1],AppTask2_TASK_PRIO);//建立AppTask2任務
    OSTaskCreate(AppTask3_task,(void*)0,(OS_STK*)&AppTask3_TASK_STK[AppTask3_STK_SIZE-1],AppTask3_TASK_PRIO);//建立AppTask3任務
    OSTaskSuspend(OS_PRIO_SELF);//掛起start_task任務

    OS_EXIT_CRITICAL();//開中斷
}
/*
 * Name                : AppTask1_task
 * Description         : ---
 * Author              : liu.
 *
 * History
 * --------------------
 * Rev                 : 0.00
 * Date                : 07/12/2017
 * 
 * create.
 * --------------------
 */
void AppTask1_task(void *pdata)
{
    u8 err;

    while(1){
        usart6.printf("\x0c");                                           //清屏    
        usart6.printf("\033[1;32;40m");                                  //設定字型終端為綠色
        usart6.printf("\r\n The Task1 is running!\r");        
        OSTimeDlyHMSM(0,0,1,0);                                          //延時1s        
        usart6.printf("\r\n The Task1 is pending Mutex!\r");

        /*等待一個互斥訊號量*/
        OSMutexPend(TaskMutex, 0, &err);
        usart6.printf("\r\n The Task1 has got Mutex!\r");
        LED_RED_ON;
        /*釋放一個互斥訊號量*/
        OSMutexPost(TaskMutex);
        OSTimeDlyHMSM(0,0,1,0);                                           //延時1s        
        LED_RED_OFF;
    }
}
/*
 * Name                : AppTask2_task
 * Description         : ---
 * Author              : liu.
 *
 * History
 * --------------------
 * Rev                 : 0.00
 * Date                : 07/12/2017
 * 
 * create.
 * --------------------
 */
void AppTask2_task(void *pdata)
{
    while(1){    
        usart6.printf("\r\n The Task2 is running!\r");
        LED_BLUE_ON;
        OSTimeDlyHMSM(0,0,0,200);  //延時200ms
        LED_BLUE_OFF;
        OSTimeDlyHMSM(0,0,0,200);  //延時200ms
    }
}
/*
 * Name                : AppTask3_task
 * Description         : ---
 * Author              : liu.
 *
 * History
 * --------------------
 * Rev                 : 0.00
 * Date                : 07/12/2017
 * 
 * create.
 * --------------------
 */
void AppTask3_task(void *pdata)
{
    int i;
    u8 err;

    while(1){
        /*等待一個互斥訊號量*/
        OSMutexPend(TaskMutex, 0, &err);
        usart6.printf("\r\n The Task3 is running!\r");
        for(i = 0; i< 2000000; i ++){
            OS_Sched();
        }
        /*釋放一個互斥訊號量*/
        OSMutexPost(TaskMutex);
        OSTimeDlyHMSM(0,0,1,0);  //延時1s
    }
}

iCore4連結:

相關文章