1)如何声明任务函数原型:
void ATaskFunction( void *pvParamaters);
- 返回值必须为无效的,且带有一个空隙指针参数;
- 任务可以理解为在自己权限范围内的小程序,是一个死循环,不会退出;
- 没有返回值,决不能出现回报;
2)一个任务函数是什么样的(任务描述)?
//@func : 如何实现一个任务;
void ATaskFunction(void *pvParamaters)
{
int iVariableExample = 0;
// 任务可以像普通函数一样定义变量,用这个任务创建的每个任务都有一个属于自己的iVariableExample变量。
static int iVariableExample1 = 0;
// 如果变量用静态变量修饰,则用这个任务创建的每个任务共享iVariableExample1变量。
for(;;)
{
//任务函数的实现
}
// 任务通常是一个死循环;
vTaskDelete(NULL);
// 假如任务的具体实现会跳出上面的死循环,则此任务需在跳出循环后删除,传入NULL表示删除的是当前任务;
}
3)微控制器只有一个内核(芯),那么不同的任务是如何调度执行的?
给定一个时间,内核只能运行一个任务,这就意味着任务可以简单的分为两个状态:运行状态和非运行状态。
- 任务的切入和切出由调度器来执行;
- 任务切出时,保存任务的相关状态,当任务再次切入时,读取任务状态并继续执行;
4)如何创建一个任务?
任务函数原型:
//@func :创建任务的函数声明
portBASE_TYPE xTaskCreate (
pdTASK_CODE pvTaskCode,
// 指向此任务的实现函数的指针;
const signed portCHAR *const pcName,
// 具有描述性的任务名。此参数不会被FreeRTOS使用。通常是容易识别的名字,用于辅助调试;
unsigned portSHORT usStackDepth,
/* 1) 当任务创建时,内核会为每个任务分配属于其自己的唯一状态;
2) usStackDepth 值指的是告诉内核分配多大的栈空间;
3)栈空间指的是可以保存的word数,而不是字节数。比如值为100,则空间大小为100word*4=400byte;
4) 请根据任务大小合理的分配栈空间;
*/
void *pvPatamaters,
// 函数指针,指向void的指针(void *)
unsigned portBASE_TYPE uxpriority,
// 指定任务的优先级;数目从0到configMAX_PRIORITIES(用户自定义)-1;
xTaskHandle *pxCreateTask
// 用于传出任务的句柄。这个句柄将在API调用时对创建出来的任务进行引用,比如删除任务或者变更优先级;如不用句柄,则设置为NULL;
);
1.返回值:
1)pdTURE表明任务创建成功;
2)errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY表明内存堆栈空间不足;
5)如何通过两个任务调度,说明FreeRTOS的运行原理?
#include <stdio.h>
//@ 任务1 和 任务2描述
void vTask1(void *pvPatamaters)
{
const char *pcTaskName = "Task 1 is running!\r\n";
volatile unsigned long u1;
for(;;)
{
vPrintString(pcTaskName);
for(u1=0;u1<1000,u1++)
{
}
}
}
void vTask2(void *pvPatamaters)
{
const char *pcTaskName = "Task 2 is running!\r\n";
volatile unsigned long u1;
for(;;)
{
vPrintString(pcTaskName);
for(u1=0;u1<1000,u1++)
{
}
}
}
int main(void)
{
// 创建一个任务,注意应用中应当检测xTaskCreate()的返回值以确保任务创建成功;
xTaskCreate(
vTask1, // 指向任务函数的指针;
"Task 1" // 任务的文本名字,便于调试;
1000, // 栈深度:1000*4byte;
1, // 任务优先级;
NULL // 不用任务句柄;
);
xTaskCreate(
vTask2, // 指向任务函数的指针;
"Task 2" // 任务的文本名字,便于调试;
1000, // 栈深度:1000*4byte;
1, // 任务优先级;
NULL // 不用任务句柄;
vTaskStartScheduler(); // 启用调度器,任务开始执行;
}
6)如何理解任务的优先级:
- 任意数量的任务可以共享同一优先级,来保证最大设计弹性;
- 优先级号越低,优先级越低,优先级号为0表示最低优先级;
- 调度器总是在所有可运行的任务中选择最高优先级的任务,并使其进入运行状态。如果最高优先级数不止一个任务,则这些任务轮流执行;(*如果最高优先级轮流执行时,如果想运行低优先级任务,则在高优先级任务中,设置任务睡眠vTaskDelay(n)即会执行低优先级任务);