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

1、實驗說明:工具

  在介紹互斥信號量前,咱們先簡單地描述一下什麼是優先級反轉。使用實時內核心,優先級反轉問題是實時系統中出現得最多的問題。假設任務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的優先級發生了反轉。spa

  任務優先級反轉是不容許出現的,由於它可能會形成不可預期的嚴重後果,所以uC/OS-II提供了一種特殊的二值信號量——互斥信號量,它可以順利地解決這種現象。code

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

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

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

(4)任務H等待的事件發生,因爲任務H的優先級高於任務L的優先級,內核掛起了任務L開始執行任務H。ip

(5)任務H開始執行。資源

(6)任務H也想訪問L如今正在訪問着的共享資源(它想從任務L獲得互斥信號量),爲了儘快地讓任務H請求到互斥信號量,而且在L訪問共享資源過程當中再也不被其餘中等優先級任務打斷,uC/OS-II將任務L的優先級提高到任務H同等高度。get

(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執行。

2、實驗截圖:

3、源代碼下載連接:

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

4、核心代碼

/*
 * 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連接:

相關文章
相關標籤/搜索