FreeRTOS-01_创建动态任务
1、相关API函数
1.1、xTaskCreate()
任务创建函数
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
功能 :动态创建任务
返回值:BaseType_t 类型{
pdPASS:说明任务创建成功;
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY:说明任务创建失败;
}
参数 :
- pxTaskCode:任务函数
- pcName:任务名称
- usStackDepth:任务堆栈大小(单位为字,因为STM32是32位的,所以1字=4字节)
- pvParameters:任务函数参数(一般为空NULL)
- uxPriority:任务优先级(越大优先级越高)
- pxCreatedTask:任务控制句柄(相当于任务的身份证)
1.2、vTaskStartScheduler()
任务调度器
void vTaskStartScheduler( void )
功能:开启任务调度
无返回值无参
1.3、vTaskDelete()
任务删除函数
void vTaskDelete( TaskHandle_t xTaskToDelete )
功能:删除任务
无返回值
参数 :
- xTaskToDelete:任务控制句柄,如果句柄为空NULL则删除目前所在的任务本身(不过不会立刻删除,会等待当前任务执行完毕再删除当前任务)
1.4、vTaskDelay()
相对延时函数
void vTaskDelay( const TickType_t xTicksToDelay )
功能:任务延迟,其实就是将任务挂起,让出内核的使用权
无返回值
参数 :
- xTicksToDelay :要延迟的时间,单位ms
1.5、taskENTER_CRITICAL();
进入临界区
taskENTER_CRITICAL()
功能:关中断,进入临界区,防止临界段代码被其他任务打断(一般用于一开始创建运行任务时的创建任务函数,当运行任务全部创建完成后再重新退出临界区)
无返回值无参
1.6、taskEXIT_CRITICAL();
退出临界区
taskEXIT_CRITICAL()
功能:开中断,退出临界区
无返回值无参
2、操作流程
2.1、相应宏设置开启
configSUPPORT_DYNAMIC_ALLOCATION 1
功能:动态内存申请相关宏定义,要使用动态创建任务该宏需置一
2.2、创建宏定义参数变量
提前宏定义任务所需的参数
例如:
- START_TASK_PRIO 任务优先级
- START_TASK_STACK_SIZE 任务堆栈大小
- start_task_handler 任务句柄
- void start_task(void * pvParameters); 任务执行函数
/* START_TASK */
#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 128
TaskHandle_t start_task_handler;
void start_task(void * pvParameters);
/* TASK1 */
#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
void task1(void * pvParameters);
/* TASK2 */
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
void task2(void * pvParameters);
/* TASK3 */
#define TASK3_PRIO 4
#define TASK3_STACK_SIZE 128
TaskHandle_t task3_handler;
void task3(void * pvParameters);
2.3、创建开始任务并开启任务调度器
void freertos_demo(void)
{
BaseType_t xReturned = xTaskCreate((TaskFunction_t) start_task,
(char * ) "start_task",
(uint16_t ) START_TASK_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(TaskHandle_t *) &start_task_handler );
if(xReturned == pdPASS)
vTaskStartScheduler(); //开启任务调度器
else
printf("开始任务创建失败");
}
2.4、在开启任务中创建执行任务
void start_task(void * pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 防止创建任务过程被打断 */
xTaskCreate((TaskFunction_t) task1,
(char * ) "task1",
(uint16_t ) TASK1_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_PRIO,
(TaskHandle_t *) &task1_handler );
xTaskCreate((TaskFunction_t) task2,
(char * ) "task2",
(uint16_t ) TASK2_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK2_PRIO,
(TaskHandle_t *) &task2_handler );
xTaskCreate((TaskFunction_t) task3,
(char * ) "task3",
(uint16_t ) TASK3_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK3_PRIO,
(TaskHandle_t *) &task3_handler );
vTaskDelete(NULL); //删除自己
taskEXIT_CRITICAL(); /* 退出临界区 */
}
2.5、编写任务函数
void task1(void * pvParameters)
{
while(1)
{
;
}
}
void task2(void * pvParameters)
{
while(1)
{
;
}
}
void task3(void * pvParameters)
{
while(1)
{
;
}
}
3、点灯示例代码
/**************************************************************/
/* START_TASK */
#define START_TASK_PRIO 1
#define START_TASK_STACK_SIZE 128
TaskHandle_t start_task_handler;
void start_task(void * pvParameters);
/* TASK1 */
#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
void task1(void * pvParameters);
/* TASK2 */
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
void task2(void * pvParameters);
/* TASK3 */
#define TASK3_PRIO 4
#define TASK3_STACK_SIZE 128
TaskHandle_t task3_handler;
void task3(void * pvParameters);
/**************************************************************/
void freertos_demo(void)
{
BaseType_t xReturned = xTaskCreate((TaskFunction_t) start_task,
(char * ) "start_task",
(uint16_t ) START_TASK_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(TaskHandle_t *) &start_task_handler );
if(xReturned == pdPASS)
vTaskStartScheduler(); //开启任务调度器
else
printf("开始任务创建失败");
}
void start_task(void * pvParameters)
{
taskENTER_CRITICAL(); /* ½øÈëÁÙ½çÇø */
xTaskCreate((TaskFunction_t) task1,
(char * ) "task1",
(uint16_t ) TASK1_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_PRIO,
(TaskHandle_t *) &task1_handler );
xTaskCreate((TaskFunction_t) task2,
(char * ) "task2",
(uint16_t ) TASK2_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK2_PRIO,
(TaskHandle_t *) &task2_handler );
xTaskCreate((TaskFunction_t) task3,
(char * ) "task3",
(uint16_t ) TASK3_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK3_PRIO,
(TaskHandle_t *) &task3_handler );
vTaskDelete(NULL); //ɾ³ý×ÔÉí
taskEXIT_CRITICAL(); /* Í˳öÁÙ½çÇø */
}
/* 任务一:LED0每500ms翻转一次 */
void task1(void * pvParameters)
{
while(1)
{
printf("任务一运行中!!!\r\n");
GPIO_SetBits(GPIOB,GPIO_Pin_12);
vTaskDelay(500);
GPIO_ResetBits(GPIOB,GPIO_Pin_12);
vTaskDelay(500);
}
}
/* 任务一:LED1每500ms翻转一次 */
void task2(void * pvParameters)
{
while(1)
{
printf("任务二运行中!!!\r\n");
GPIO_SetBits(GPIOB,GPIO_Pin_13);
vTaskDelay(500);
GPIO_ResetBits(GPIOB,GPIO_Pin_13);
vTaskDelay(500);
}
}
/* 任务三:按下KEY0删除任务1 */
void task3(void * pvParameters)
{
printf("任务三运行中!!!\r\n");
while(1)
{
if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == SET){
vTaskDelay(10);
//while等待松手时加个延迟可以让任务三不会一直抢占线程
while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0) == SET)vTaskDelay(10);
if(task1_handler != NULL){
vTaskDelete(task1_handler);
printf("任务一删除成功!\r\n");
task1_handler = NULL;
}
}
vTaskDelay(10); //按键检测要加个延迟,因为任务三优先级最高,不然任务三会一直霸占线程
}
}
/**************************************************************/