函数流程
int main(void) { /* 第一步:开发板硬件初始化 */ BSP_Init(); /* 第二步:创建APP应用任务,所有的应用任务都可以放在这个函数里面 */ AppTaskCreate(); /* 第三步:启动FreeRTOS,开始多任务调度,启动成功则不返回 */ vTaskStartScheduler(); while (1) { } }
创建APP应用任务,
static void AppTaskCreate(void) { xTaskCreate(vTaskLed1, /* 任务函数名 */ "Task Led1", /* 任务名,字符串形式,方便调试 */ 512, /* 栈大小,单位为字,即4个字节 */ NULL, /* 任务形参 */ 0, /* 优先级,数值越大,优先级越高 */ &xHandleTaskLED1); /* 任务句柄 */ xTaskCreate(vTaskBeep,"Task Beep",512,NULL,2,&xHandleTaskBeep); }
pvTaskCode 任务只是永不退出的 C 函数,实现通常是一个死循环。参数pvTaskCode 只是一个指向任务的实现函数的指针(效果上仅仅是函数名)。
pcName 具有描述性的任务名。这个参数不会被 FreeRTOS 使用。其只是单纯地用于辅助调试。识别一个具有可读性的名字总是比通过句柄来识别容易得多。
应用程序可以通过定义常量 config_MAX_TASK_NAME_LEN 来定义任务名的最大长度——包括’\0’结束符。如果传入的字符串长度超过了这个最大值,字符串将会自动被截断。
usStackDepth 当任务创建时,内核会分为每个任务分配属于任务自己的唯一状态。
usStackDepth 值用于告诉内核为它分配多大的栈空间。这个值指定的是栈空间可以保存多少个字(word),
而不是多少个字节(byte)。比如说,如果是 32 位宽的栈空间,传入的 usStackDepth值为 100,
则将会分配 400 字节的栈空间(100 * 4bytes)。栈深度乘以栈宽度的结果千万不能超过一个 size_t 类型变量所能表达的最大值。
应用程序通过定义常量 configMINIMAL_STACK_SIZE 来决定空闲任务任用的栈空间大小。
在 FreeRTOS 为微控制器架构提供的Demo 应用程序中,赋予此常量的值是对所有任务的最小建议值。
如果你的任务会使用大量栈空间,那么你应当赋予一个更大的值。
没有任何简单的方法可以决定一个任务到底需要多大的栈空间。
计算出来虽然是可能的,但大多数用户会先简单地赋予一个自认为合理的值,
然后利用 FreeRTOS 提供的特性来确证分配的空间既不欠缺也不浪费。
pvParameters 任务函数接受一个指向 void 的指针(void*)。pvParameters 的值即是传递到任务中的值。
uxPriority 指定任务执行的优先级。优先级的取值范围可以从最低优先级 0 到最高优先级(configMAX_PRIORITIES – 1)。
configMAX_PRIORITIES 是一个由用户定义的常量。优先级号并没有上限(除了受限于采用的数据类型和系统的有效内存空间),
但最好使用实际需要的最小数值以避免内存浪费。如果 uxPriority 的值超过了(configMAX_PRIORITIES – 1),
将会导致实际赋给任务的优先级被自动封顶到最大合法值。
void vTaskLed1(void *pvParameters) { /* 任务都是一个无限,不能返回 */ while(1) { LED1_ON; /* 阻塞延时,单位ms */ vTaskDelay( 500 ); LED1_OFF; vTaskDelay( 500 ); } } void vTaskBeep(void *pvParameters) { /* 任务都是一个无限,不能返回 */ while(1) { BEEP_ON; /* 阻塞延时,单位ms */ vTaskDelay( 500 ); BEEP_OFF; vTaskDelay( 500 ); }
调度器保证总是在所有可运行的任务中选择具有最高优先级的任务,并使其进入运行态。
如果被选中的优先级上具有不止一个任务,调度器会让这些任务轮流执行。这种行为方式在本例中可以明显看出来。
两个测试任务被创建在同一个优先级上,并且一直是可运行的。所以每个任务都执行一个”时间片”,
任务在时间片起始时刻进入运行态,在时间片结束时刻又退出运行态。
图 中 t1 与 t2 之间的时段就等于一个时间片。
来源:https://www.cnblogs.com/Liu-Jing/p/7067395.html