例子:创建一个任务,并在任务里面翻转LED 灯
1. 函数原型
BaseType_t xTaskCreate(TaskFunction_t pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
“ lint !e971 Unqualified char types are allowed for strings and single characters only” 告诉编译器在编译的时候不要报警告,这里把char类型和字符串类型混用了,编译器你不要报警告
1.1 参数1: pxTaskCode,创建的任务函数名,类似中断服务服务函数入口,函数的入口地址
1.2 参数2:pcName,也是创建的任务函数名称,只不过这个是没有实际意义的,只是方便记住创建的函数叫什么名字,FreeRTOS不会调用这个东东的,名称可随意写,长度有限制, configMAX_TASK_NAME_LEN 定义了名称的长度,包括 \0 字符,超过会自动截断
FreeRTOSConfig.h
#define configMAX_TASK_NAME_LEN (16)
1.3 参数3:usStackDepth,栈大小,每创建一个任务,系统就会为该任务分配一块内存(堆栈),单位是字(word),而不是字节(Byte),在32位机中 (STM32xx), 1 word = 4Byte,分配的空间就是stackSize = usStackDepth * 4,默认最小栈大小 configMINIMAL_STACK_SIZE
FreeRTOSConfig.h
#define configMINIMAL_STACK_SIZE ((unsigned short)130)
具体大小需要自己调试
1.4 pvParameters,创建的任务的实参,创建任务的时候,给他传进来的参数,万能指针 void *
1.5 uxPriority,任务的优先级
FreeRTOSConfig.h
#define configMAX_PRIORITIES (32)
优先级必须比这个宏要小,数字越小,优先级越高
configMAX_PRIORITIES 宏大小可随意,但最好使用实际需要的最小数值以避免内存浪费
如果优先级设置的比configMAX_PRIORITIES 大,会将优先级自动设置为最大优先级configMAX_PRIORITIES
1.6 pxCreatedTask 创建的任务的句柄,跟第一个参数类似,操作这个句柄就相当于操作这个任务,可以通过句柄改变任务的优先级、删除任务等,如果不需要使用句柄,就设为NULL
1.7 返回值
1.7.1 pdPASS,创建任务成功
1.7.2 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY, 内存堆空间不够,创建任务失败,也有可能是堆内存碎片化导致创建失败
2. 创建任务
// create task2
void vTask2( void *pvParameters )
{
// each task must be a endless loop
for( ;; )
{
printf("task2 say: hello world");
}
}
// create task1
void vTask1( void *pvParameters )
{
// each task must be a endless loop, otherwise, the program will crash
for (;;)
{
printf("task1 say: hello world1");
}
}
int main( void )
{
// create task1
xTaskCreate(vTask1, // create task1
"Task 1", // task name
128, // stack size
NULL, // the task has no parameter
1, // task priority
NULL ); // task handle
// creat task2
xTaskCreate(vTask2, // create task2
"Task 2", // task name
128, // stack size
NULL,// the task has no parameter
2, // task priority, the task priority can not be same as other task priority
NULL );
// The system start to scheduler
vTaskStartScheduler();
// the program will not run here if there are no issues with the program, but if executed here, it is likely the memory heap space is insufficient resulting in idle
for (;;)
{
}
}
3. 两个任务按照时间片轮转方式运行,系统调度,轮流来,一人一口饭,你一口,我一口
3. 在任务里面创建任务,创建任务1,然后在任务1 里面创建任务2
// create task2
void vTask2( void *pvParameters )
{
// each task must be a endless loop
for( ;; )
{
printf("task2 say: hello world");
}
}
// create task1
void vTask1( void *pvParameters )
{
// creat task2
xTaskCreate(vTask2, // create task2
"Task 2", // task name
128, // stack size
NULL,// the task has no parameter
2, // task priority, the task priority can not be same as other task priority
NULL );
// each task must be a endless loop, otherwise, the program will crash
for (;;)
{
printf("task1 say: hello world1");
}
}
int main( void )
{
// create task1
xTaskCreate(vTask1, // create task1
"Task 1", // task name
128, // stack size
NULL, // the task has no parameter
1, // task priority
NULL ); // task handle
// The system start to scheduler
vTaskStartScheduler();
// the program will not run here if there are no issues with the program, but if executed here, it is likely the memory heap space is insufficient resulting in idle
for (;;)
{
}
}
4. 使用任务参数,创建任务的同时传递一个参数进任务里面 vTaskFunction
// create task2
void vTask2(void *pvParameters)
{
char *pcTaskName;
// (void *) forced conversion to string (char *)
pcTaskName = (char *)pvParameters;
// each task must be a endless loop
for( ;; )
{
printf("task2, %s", pcTaskName );
}
}
// create task1
void vTask1( void *pvParameters )
{
char *pcTaskName;
pcTaskName = (char *)pvParameters;
// each task must be a endless loop, otherwise, the program will crash
for (;;)
{
printf("task1, %s", pcTaskName );
}
}
int main( void )
{
// create task1
xTaskCreate(vTaskFunction, // create task1
"Task 1", // task name
128, // stack size
“hello world”, // pass parameters to task1
1, // task priority
NULL); // task handle
// creat task2
xTaskCreate(vTaskFunction, // create task2
"Task 2", // task name
128, // stack size
“hello world”, // pass parameters to task2
2, // task priority, the task priority can not be same as other task priority
NULL);
// The system start to scheduler
vTaskStartScheduler();
// the program will not run here if there are no issues with the program, but if executed here, it is likely the memory heap space is insufficient resulting in idle
for (;;)
{
}
}
与上面的第 2 步类似,只是在创建任务的同时传了一个字符串进任务里面了,然后在任务里面接收这个字符串,并打印出来
看起来写了一堆,很复杂,其实很简单,就一个函数调用,会使用就行了,调用函数的时候知道每个参数怎么填,怎么根据返回值判断创建结果就可以了
5. 在main 函数里面创建第一个任务
6. 在任务里面创建任务,理论上可以创建无数个,具体看系统,用的哪个操作系统,用的什么硬件平台,硬件资源够不够,内存够不够等等
7. 在任务的死循环里面执行任务操作,这个任务需要干些啥事都放在死循环里面写,死循环里面执行任务需要干的事,死循环前面基本都是一些初始化操作,STM32xx
8. 在死循环里面翻转LED灯,执行一遍该任务,LED1就会翻转一次,亮到灭到亮,反复亮灭