close

FreeRTOSlogo-lg-1260x471.jpeg

FreeRTOS移植完成後,就要來進行程式撰寫與測試,FreeRTOS的程式碼可分成任務、通訊和硬體界面這三個區塊,

1. 任務(task)在FreeRTOS中的基本單位,每個task是由C函數所組成,首先建立C語言的函數,再使用xTaskCreate()這個API來建立一個task,task通常會在一個無限迴圈中進行,FreeRTOS不允許task自行結束

2. 通訊在task間的溝通是透過把資料傳送到queue和讀取queue中資料實現

3. 硬體界面在好幾千行的FreeRTOS程式碼中,將FreeRTOS核心代碼與硬體做了結合,可使FreeRTOS在不同硬體平台上運行

以簡單的程式來講解FreeRTOS任務(task)要怎麼使用,第一支API是建立任務xTaskCreate,函數說明如下,

BaseType_t xTaskCreate(
                    TaskFunction_t pvTaskCode,
                    const char * const pcName,
                    configSTACK_DEPTH_TYPE usStackDepth,
                    void *pvParameters,
                    UBaseType_t uxPriority,
                    TaskHandle_t *pvCreatedTask
                   );

# TaskFunction_t pvTaskCode: 將建立好的C語言函數設置在此任務中,此C語言函數不得有回傳(return)的方法

# const char * const pcName: 任務的名字,在FreeRTOS不會用到它,這只是用於debug用途,名字長度限制為configMAX_TASK_NAME_LEN,為16個字元

# configSTACK_DEPTH_TYPE usStackDepth: 指定此任務stack的數量,例如stack寬度為16 bits,usStackDepth可設為100或200,將被分配用於stack儲存

# void *pvParameters: 要傳給task的參數陣列,也就是我們在C函數宣告的參數

# UBaseType_t uxPriority: 任務運行優先權設定

# TaskHandle_t *pvCreatedTask: 這個task的reference,用於動態調整這個task的priority,或是刪掉這個task

# BaseType_t: 會回傳此任務是否創建成功,創建成功會回pdPASS代碼,否則會回projdefs.h中定義一個錯誤代碼

了解xTaskCreate後就以實際範例來做說明,此範例需要建立配置GPIO與UART這兩個功能才能運行,將建立配置好的GPIO與UART放在STM32F407_Configuration資料夾裡,如下所示,

2.JPG

本人會在增加task_programs.ctask_programs.h這兩支程式來撰寫FreeRTOS任務程式,存放在User資料夾內,如下所示,

3.JPG

task_programs.c程式如下所示,

#include "task_programs.h"

/* 任務控制代碼 */
TaskHandle_t vTaskOne,vTaskTwo;

/*
程式名稱:創建任務
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/8
程式修改日期:N/A
程式說明:

*/
void AppTaskCreate(void){
    /* 創建任務LED1 */
    if(xTaskCreate(vTaskLED1, "vTask LED1", 512, "LED1 RUN\r\n", 2, &vTaskOne)==pdPASS){
        UART2_Send((uint8_t*)"LED1 PASS\r\n", 11);
    }else{
        UART2_Send((uint8_t*)"LED1 ERROR\r\n", 12);
    }
        
    /* 創建任務LED2 */
    if(xTaskCreate(vTaskLED2, "vTask LED2", 512, "LED2 RUN\r\n", 1, &vTaskTwo)==pdPASS){
        UART2_Send((uint8_t*)"LED2 PASS\r\n", 11);
    }else{
        UART2_Send((uint8_t*)"LED2 ERROR\r\n", 12);
    }
}    

/*
程式名稱:任務LED1
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/8
程式修改日期:N/A
程式說明:

*/
void vTaskLED1(void *pvParameters){
    portTickType xLastWakeTime = xTaskGetTickCount();
    
    for(;;){
        if(GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_10)==1){
            GPIO_SetBits(GPIOF, GPIO_Pin_9);
        }else{
            GPIO_ResetBits(GPIOF, GPIO_Pin_9);
        }
        /* 顯示此任務訊息 */
        UART2_Send(pvParameters, strlen(pvParameters));
        vTaskDelayUntil( &xLastWakeTime, (500/portTICK_RATE_MS));
    }
}

/*
程式名稱:任務LED2
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/8
程式修改日期:N/A
程式說明:

*/
void vTaskLED2(void *pvParameters){
    portTickType xLastWakeTime = xTaskGetTickCount();
    
    for(;;){
        if(GPIO_ReadOutputDataBit(GPIOF, GPIO_Pin_10)==0){
            GPIO_SetBits(GPIOF, GPIO_Pin_10);
        }else{
            GPIO_ResetBits(GPIOF, GPIO_Pin_10);
        }        
        /* 顯示此任務訊息 */
        UART2_Send(pvParameters, strlen(pvParameters));
        vTaskDelayUntil( &xLastWakeTime, (500/portTICK_RATE_MS));
    }
}

4.JPG

5.JPG

6.JPG

task_programs.h程式如下所示,

#ifndef __TASK_PROGRAMS_H
#define __TASK_PROGRAMS_H

#include "main.h"

/* 創建任務 */
void AppTaskCreate(void);
/* 任務LED1 */
void vTaskLED1(void *pvParameters);
/* 任務LED2 */
void vTaskLED2(void *pvParameters);

#endif 

7.JPG

其他程式部分bsp.c如下所示,

#include "bsp.h"

/*
程式名稱:開發板全域變數初始化
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/6
程式修改日期:N/A
程式說明:

*/
void BSP_VariableInit(void){
    uint16_t i=0;
    
    for(i=0; i<255; i++){
        UART2_Ptr->rxData[i] = 0;
    }
    UART2_Ptr->rxCount = 0;
    UART2_Ptr->rxFlag = 0;
}

/*
程式名稱:開發板整體系統初始化
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/6
程式修改日期:N/A
程式說明:

*/
void BSP_Init(void){
    /* 設置系統中斷優先級分組4 */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
    /* GPIO配置初始化 */
    GPIO_CONFIGInit();
    /* UART2配置初始化 */
    UART2_ConfigInit(115200);
    /* 創建任務 */
    AppTaskCreate();
    /* 任務排程開始 */
    vTaskStartScheduler();        
}

8.JPG

10.JPG

main.c程式如下所示,

#include "main.h"

/*
程式名稱:主程式
程式版本:V1.0
程式撰寫者:Michael Jheng(鄭智遠)
程式撰寫日期:2018/1/6
程式修改日期:N/A
程式說明:

*/
int main(void){

    /* 開發板全域變數初始化 */
    BSP_VariableInit();
    /* 開發板整體系統初始化 */
    BSP_Init();    
    
  /* Infinite loop */
  for(;;){
        
  }
}

11.JPG

把程式編譯完成後,無錯誤就點擊上方LOAD圖示把程式燒入至MCU,

12.JPG

執行結果如下,LED1 PASS與LED2 PASS就代表任務創建成功,由於LED1任務權限比LED2任務大,所以LED1 RUN訊息會先出現,再來出現LED2 RUN,

1.JPG

LED呈現結果如下,紅色與綠色LED交互閃爍,

S__48021506.jpg

S__48021507.jpg

arrow
arrow
    創作者介紹
    創作者 鄭智遠 的頭像
    鄭智遠

    Michael_Jheng的部落格

    鄭智遠 發表在 痞客邦 留言(6) 人氣()