一、静态方式创建任务和删除任务
1>测试环境
系统:WIN7
MDK:keil v5.26
开发板:GD32F303C-EVAL
固件库:V1.0.2
FreeRTOS版本:V10.4.0
2>需要满足条件
条件一:需要在FreeRTOS.h或FreeRTOSConfig.h中定义
#define configSUPPORT_STATIC_ALLOCATION 1
条件二:加载头文件时,加载FreeRTOS.h必须在task.h之前,如下:
#include "FreeRTOS.h"
#include "task.h"
否则会出现如下错误
.\FreeRTOS\Source\include\task.h(32): error: #35: #error directive: “include FreeRTOS.h must appear in source files before include task.h”
3>代码如下:
#include "gd32f30x.h"
#include "led.h"
#include "systick.h"
#include <stdio.h>
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#define START_TASK_STACK_SIZE 200
StaticTask_t StartTaskBuffer;
StackType_t StartTaskStack[ START_TASK_STACK_SIZE ];
#define LED1_TASK_STACK_SIZE 200
StaticTask_t Led1TaskBuffer;
StackType_t Led1TaskStack[ LED1_TASK_STACK_SIZE ];
#define LED2_TASK_STACK_SIZE 200
StaticTask_t Led2TaskBuffer;
StackType_t Led2TaskStack[ LED2_TASK_STACK_SIZE ];
//空闲任务任务堆栈
static StackType_t IdleTaskStack[configMINIMAL_STACK_SIZE];
//空闲任务控制块
static StaticTask_t IdleTaskTCB;
/*********************************************************************************
//定时器服务任务堆栈
static StackType_t TimerTaskStack[configTIMER_TASK_STACK_DEPTH];
//定时器服务任务控制块
static StaticTask_t TimerTaskTCB;
获取空闲任务地任务堆栈和任务控制块内存,因为本例程使用的
静态内存,因此空闲任务的任务堆栈和任务控制块的内存就应该
有用户来提供,FreeRTOS提供了接口函数vApplicationGetIdleTaskMemory()
实现此函数即可。
ppxIdleTaskTCBBuffer:任务控制块内存
ppxIdleTaskStackBuffer:任务堆栈内存
pulIdleTaskStackSize:任务堆栈大小
*********************************************************************************/
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer=&IdleTaskTCB;
*ppxIdleTaskStackBuffer=IdleTaskStack;
*pulIdleTaskStackSize=configMINIMAL_STACK_SIZE;
}
/*********************************************************************************
获取定时器服务任务的任务堆栈和任务控制块内存
ppxTimerTaskTCBBuffer:任务控制块内存
ppxTimerTaskStackBuffer:任务堆栈内存
pulTimerTaskStackSize:任务堆栈大小
如果开启了软件定时器有关的配置选项,则在静态创建任务时,下面的函数也需要用户自己创建
比如如果在FreeRTOS.h中开启
#define configUSE_TIMERS 1 //为1时启用软件定时器
#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1) //软件定时器优先级
#define configTIMER_QUEUE_LENGTH 5 //软件定时器队列长度
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2) //软件定时器任务堆栈大小
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize)
{
*ppxTimerTaskTCBBuffer=&TimerTaskTCB;
*ppxTimerTaskStackBuffer=TimerTaskStack;
*pulTimerTaskStackSize=configTIMER_TASK_STACK_DEPTH;
}
*********************************************************************************/
#define START_TASK_PRIO ( tskIDLE_PRIORITY + 1 )
#define LED1_TASK_PRIO ( tskIDLE_PRIORITY + 2 )
#define LED2_TASK_PRIO ( tskIDLE_PRIORITY + 3 )
void START_task(void * pvParameters);
void LED1_task(void * pvParameters);
void LED2_task(void * pvParameters);
/*创建START_task任务的句柄,用于删除等操作。*/
TaskHandle_t xHandle = NULL;
int main(void)
{
/* configure 4 bits pre-emption priority ,这样设置避免了MCU的抢占优先级,更简单*/
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
GW_LedInit(LED1);
GW_LedInit(LED2);
GW_ComInit(GW_COM3);
xHandle = xTaskCreateStatic(
(TaskFunction_t ) START_task,
(const char* ) "start_task", /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
(uint32_t ) START_TASK_STACK_SIZE,
(void* ) 1,
(UBaseType_t ) START_TASK_PRIO,
(StackType_t* ) StartTaskStack,
(StaticTask_t* ) &StartTaskBuffer
);
/* start scheduler */
vTaskStartScheduler();
while(1){
}
}
/*开始任务:创建两个任务后删除自身*/
void START_task(void * pvParameters)
{
static uint8_t ucParameterToPass=5;
taskENTER_CRITICAL(); //进入临界区
xTaskCreateStatic(
(TaskFunction_t ) LED1_task,
(const char* ) "LED1_task", /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
(uint32_t ) LED1_TASK_STACK_SIZE,
(void* ) &ucParameterToPass,
(UBaseType_t ) LED2_TASK_PRIO,
(StackType_t* ) Led1TaskStack,
(StaticTask_t* ) &Led1TaskBuffer
);
xTaskCreateStatic(
(TaskFunction_t ) LED2_task,
(const char* ) "LED2_task", /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
(uint32_t ) LED2_TASK_STACK_SIZE,
(void* ) NULL,
(UBaseType_t ) LED1_TASK_PRIO,
(StackType_t* ) Led2TaskStack,
(StaticTask_t* ) &Led2TaskBuffer
);
configASSERT( xHandle );
if( xHandle != NULL )
{
// vTaskDelete( xHandle );
// vTaskDelete( NULL ); //在自身任务中删除任务本身,可以使用NULL代替xHandle
vTaskSuspend( xHandle );//任务挂起
printf("Delete START_task!\r\n");
}
taskEXIT_CRITICAL(); //退出临界区
}
/*任务1:LED1每隔300ms翻转一次,并打印接收的参数的值*/
void LED1_task(void * pvParameters)
{
uint8_t *tmp=NULL;
tmp = (uint8_t *)pvParameters;
for( ;; ){
/* toggle LED2 each 500ms */
printf("LED1_task,value:%d\r\n",*tmp);
GW_LedToggle(LED1);
vTaskDelay(300);
}
}
/*任务2: LED2每隔500ms翻转一次*/
void LED2_task(void * pvParameters)
{
for( ;; ){
/* toggle LED2 each 500ms */
printf("LED2_task\r\n");
GW_LedToggle(LED2);
vTaskDelay(500);
}
}
二、测试结果
工程下载链接:GD32F303_FreeRTOS静态创建任务