認識FreeRTOS多任務同步和通信機制


FreeRTOS多任務同步和通信機制的掌握

本周課堂任務為:

  • 在github上,Fork例程項目(https://github.com/cbhust/

  • STM32F429_Discovery_FreeRTOS_9.git) 到自己的個人賬號。

  • clone項目到本地電腦的Ubuntu虛擬機中(虛擬機環境在第一次作業中已搭建)。

  • 按照/Projects/Demo1/README.md中的提示編譯Demo1例程並通過Qemu運行例程。

  • 在Demo1的框架基礎上完成自己的本次編程作業(具體要求見第3點)。

  • 代碼完成后提交到自己的github賬號上,確保助教可以正常的clone並編譯運行。

  • 在作業博客上給出代碼的github鏈接、代碼說明以及運行結果展示。

clone項目並初運行

參考第一次作業的內容,按照指示,fork老師的代碼后,在終端輸入:
git clone https://github.com/czphappy/STM32F429_Discovery_FreeRTOS_9.git
獲得相應編程環境。如圖

根據老師的提示,按照README.md中的流程,安裝QEMU(如圖)

接着是為qemu加入環境變量,在終端輸入: (這一步每次重啟終端都需要重新輸入,謝謝老師的提醒,少走許多彎路)

#cd ~/work
#tar xvf gnuarmeclipse-qemu-debian64-2.8.0-201612271623-dev.tgz
#chmod -R -w ./qemu
#export PATH=~/work/qemu/2.8.0-201612271623-dev/bin/:$PATH
#qemu-system-gnuarmeclipse --version

結果如圖,配置成功。

接着按照指示,在Demo1下make之后,在終端輸入:
#./qemu.sh
運行結果如下,驗證完畢,環境已經建好。:

GDB調試

繼續依照指示,在終端輸入:
#./qemu_gdb.sh
開啟UI后,新開一個終端,輸入:

#arm-none-eabi-gdb  
(gdb)target remote localhost:1234 
(gdb)continue

得到如下結果(驗證完畢)

新建通信任務

這個問題我想主要難點在於Monitor_Task的書寫,由於三個任務同步進行,Monitor_Task如果設置不恰當很有可能錯誤判斷,因為最常見的結果是Sender_Task已經把數據傳出,只是 Receiver_Task還沒有接收,但我發現sender每次傳輸的值和其傳輸的次數是相同的(或者具體說是除10000的余數),所以我就設置兩個全局變量,一個用於存儲Receiver_Task最新接收的值,另外一個用於存儲傳輸次數,通過比較兩者是否相等,就可以直接進行判斷。

以下是具體實現流程,在老師給的main.c的框架下,我設置的全局變量

void Hardware_Init(void);
void Monitor_Task( void *pvParameters );
void Sender_Task( void *pvParameters );
void Receiver_Task( void *pvParameters );
void Red_LED_On(void);
void Red_LED_Off(void);
void Green_LED_On(void);
void Green_LED_Off(void);
extern unsigned long ReceiverFlag =0;
extern unsigned long nflag=0;

ReceiverFlag用於存儲Receiver_Task最新接收的值,nflag存儲傳輸次數,以下是我新建的三個任務:

      
       xTaskCreate(                                                                                  
	   Sender_Task,                 /* Function pointer */
		  ( signed portCHAR * )"Sender_Task", /* Task name - for debugging only*/
		  configMINIMAL_STACK_SIZE,         /* Stack depth in words */
		  (void*) NULL,                     /* Pointer to tasks arguments ````(parameter) */
		  tskIDLE_PRIORITY + 2UL,           /* Task priority*/
		  NULL                              /* Task handle */
       );

      xTaskCreate(
		  Receiver_Task,                 /* Function pointer */
		  ( signed portCHAR * )"Receiver_Task",  /* Task name - for debugging only*/
		  configMINIMAL_STACK_SIZE,         /* Stack depth in words */
		  (void*) NULL,                     /* Pointer to tasks arguments (parameter) */
		  tskIDLE_PRIORITY + 4UL,           /* Task priority*/
		  NULL                              /* Task handle */
       );
       xTaskCreate(
		  Monitor_Task,                 /* Function pointer */
		   ( signed portCHAR * )"Monitor_Task", /* Task name - for debugging only*/
		  configMINIMAL_STACK_SIZE,         /* Stack depth in words */
		  (void*) NULL,                     /* Pointer to tasks arguments (parameter) */
		  tskIDLE_PRIORITY + 3UL,           /* Task priority*/
		  NULL                              /* Task handle */
       );

其中優先級取為Sender_Task<Receiver_Task<Monitor_Task(其實后兩者可以一樣) ,結果是一致的。

void Sender_Task(void *pvParameters)
     {    
       unsigned long  SendNum = 1;     
       unsigned long SenderSum =0;    
       for( ;; )  
      {  
        vTaskDelay(2);  
        /* 向隊列中填充內容 */  
        xQueueSend( MsgQueue, ( void* )&SendNum, 0 );  
        SenderSum=SendNum+SenderSum;
        SendNum=(SendNum+1)%10000;
      }  
      }

sender_Task的任務比較簡單,只需要有個累加值以及一個基數即刻,優先級較低。

void Receiver_Task(void *pvParameters)
{
    unsigned long ReceiverSum = 0;
    unsigned long ReceiverNum =1;
    for( ;; )
    {  
        
        vTaskDelay(1000);
        /* 從隊列中獲取內容 */  
        for( ;xQueueReceive( MsgQueue,&ReceiverNum, 0 ) == pdPASS;)  
        {  
            ReceiverSum = ReceiverNum+ReceiverSum; 
            nflag++;
            ReceiverFlag=ReceiverNum;
        }  
    }  
}

Receiver_Task的任務相對復雜,除了兩個累加值之外,還需要設置兩個全局變量,取出值和累加值

void Monitor_Task(void *pvParameters)
{  
    for( ;; )  
    {  
        vTaskDelay(10000);
        if( ReceiverFlag == (nflag % 10000))  
        {  
             Green_LED_On();
             vTaskDelay(1000);
             Green_LED_Off();
        }  
        else 
        {
            Red_LED_On();
            vTaskDelay(1000);
            Red_LED_Off();
        }
    }  
}

正如前面所說,Monitor_Task就是簡單判斷兩個全局變量是否相等,正確則綠燈亮,錯誤則紅燈亮。

結果是綠燈持續閃爍,說明傳輸沒有問題。
完成后將我的代碼push到遠程倉庫。
以下是我的github鏈接
https://github.com/czphappy/STM32F429_Discovery_FreeRTOS_9


此次實驗,我的進度把握不是很好,師兄也是一在把時間延后,從一開始什么都不知道,到現在的任務完成,期間遇到各種問題,多謝師兄和同學們也耐心講解,讓我完成這個作業,對於GitHub和FreeRTOS也有了一定的認識。謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM