API関数
タスクの作成xTaskCreate()
関数プロトタイプ(tasks.c内):
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
パラメータ:
-
pxTaskCode:自分で作成したタスク関数の関数名
-
pcName:タスクの名前、自由に開始、文字列タイプ
-
usStackDepth:タスクスタックのサイズ(実際にはアプリケーションのサイズの4倍)。小さすぎるタスクは実行できない可能性があります。
-
pvParameters:タスク関数のパラメーター。パラメーターをNULLに渡す必要はありません。
-
uxPriority:タスクの優先度、0〜(configMAX_PRIORITIES-1)
- pxCreatedTask:タスクハンドル。実際には、タスクのポインターとタスクスタックです。
戻り値:
-
pdPASS:値は1です。タスクは正常に作成され、準備完了リストに追加されます。
- エラーコード:負の数、タスク作成の認識
ここでの戻り値はBaseType_tで、これは実際にはlong型です。その定義はportmacro.hファイルで確認できます。
typedef long BaseType_t;
さらに、タスクハンドルのタイプはTaskHandle_tであり、実際にはvoid *です。その定義はtask.hファイルで確認できます。
typedef void * TaskHandle_t;
注:xTaskCreate()は、タスクを動的に作成する方法です。システムは、heap_4.cの構成を通じて、タスクに関連するメモリを自動的に割り当てます。タスクを作成する静的な方法であるxTaskCreateStatic()もありますが、ここでは紹介しません。
タスク削除vTaskDelete()
関数プロトタイプ(tasks.c内):
void vTaskDelete( TaskHandle_t xTaskToDelete )
パラメータ:
- xTaskToDelete:削除するタスクのタスクハンドル
注:xTaskCreate()によって動的に作成されたタスクがvTaskDelete()を使用して削除された後、タスクの作成時に適用されたスタックとメモリは、システムのアイドルタスクで解放されます。
タスクのスケジューリングvTaskStartScheduler()
関数プロトタイプ(tasks.c内):
void vTaskStartScheduler( void )
パラメータは不要で、FreeRTOSはオンにされた後にタスクのスケジューリングを開始します。
プログラミング
メイン機能
main関数は今でも私たちがよく知っているmain関数ですが、FreeRTOSのmain関数は、それ自体で無限ループに設計する必要はありません。システムを実行し続けるには、タスクを作成してタスクのスケジューリングを開始するだけです。
タスクの作成は、通常、最初に開始タスクを作成し、次にタスクを開始してから、他のサブタスクの作成を担当します。
int main(void)
{
//设置系统中断优先级分组4(FreeRTOS中的默认方式!)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
//初始化LED端口
LED_Init();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
//开启任务调度
vTaskStartScheduler();
}
タスク開始機能タスク開始機能の機能は、
他のサブタスクを作成することであり、作成後にそれ自体を削除します。
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建TASK1任务
xTaskCreate((TaskFunction_t )task1_task,
(const char* )"task1_task",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_TASK_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
//创建TASK2任务
xTaskCreate((TaskFunction_t )task2_task,
(const char* )"task2_task",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_TASK_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
2つのタスク機能
各タスク関数は無限ループです。タスク切り替えのために、vTaskDelay()遅延関数をループに追加する必要があることに注意してください。
//task1任务函数
void task1_task(void *pvParameters)
{
while(1)
{
LEDa_Toggle;
vTaskDelay(500); //延时500ms
}
}
//task2任务函数
void task2_task(void *pvParameters)
{
while(1)
{
LEDb_ON;
vTaskDelay(200); //延时200ms
LEDb_OFF;
vTaskDelay(800); //延时800ms
}
}
main.cすべてのプログラム
#include "stm32f4xx.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
//任务参数--------------------------
//优先级 堆栈大小 任务句柄 任务函数
#define START_TASK_PRIO 1
#define START_STK_SIZE 128
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);
#define TASK1_TASK_PRIO 2
#define TASK1_STK_SIZE 128
TaskHandle_t Task1Task_Handler;
void task1_task(void *pvParameters);
#define TASK2_TASK_PRIO 3
#define TASK2_STK_SIZE 128
TaskHandle_t Task2Task_Handler;
void task2_task(void *pvParameters);
int main(void)
{
//设置系统中断优先级分组4(FreeRTOS中的默认方式!)
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
//初始化LED端口
LED_Init();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
//开启任务调度
vTaskStartScheduler();
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建TASK1任务
xTaskCreate((TaskFunction_t )task1_task,
(const char* )"task1_task",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_TASK_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
//创建TASK2任务
xTaskCreate((TaskFunction_t )task2_task,
(const char* )"task2_task",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_TASK_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//task1任务函数
void task1_task(void *pvParameters)
{
while(1)
{
LEDa_Toggle;
vTaskDelay(500); //延时500ms
}
}
//task2任务函数
void task2_task(void *pvParameters)
{
while(1)
{
LEDb_ON;
vTaskDelay(200); //延时200ms
LEDb_OFF;
vTaskDelay(800); //延时800ms
}
}
運転結果
実行効果は、ボード上の2つのLEDが、それぞれのタスク機能で設定されたオンオフ時間に従って点滅し続けることです。
このシステムを使用する理由は、2つのタスクが同時に実行されているように見せるためです。ベアメタルシステムの場合、同じ機能を実現できますが、想像してみてください(これら2つのLEDタスクの点滅法則は比較的単純)、2つのタスクを組み合わせる必要があります。2つのタスクが絡み合ってライトオフ時間を管理する場合、さらに2つの複雑なタスクの場合、ベアメタルシステムではそれを達成できない可能性があります。