一.任务栈与优先级定义
优先级数值越大,优先级越高。栈设为128是比较大,可以使用函uxTaskGetStackHighWaterMark ( TaskHandle_t xTask );检测任务栈剩余的大小。但是在不确定栈大小的情况下可以将栈设置的偏大以避免任务无法创建。
#define START_TASK_STACK_SIZE 128 //栈大小
#define START_TASK_PRIO 1 //优先级
TaskHandle_t start_task_handler; //句柄
void start_task( void * pvParameters );//任务函数
#define TASK1_STACK_SIZE 128
#define TASK1_PRIO 2
TaskHandle_t task1_handler;
void task1( void * pvParameters );
#define TASK2_STACK_SIZE 128
#define TASK2_PRIO 3
TaskHandle_t task2_handler;
void task2( void * pvParameters );
#define TASK3_STACK_SIZE 128
#define TASK3_PRIO 4
TaskHandle_t task3_handler;
void task3( void * pvParameters );
二.任务创建
freertos_demo创建start_task任务,创建后启动任务调度器。taskENTER_CRITICAL();是进入临界区,进入后可以避免进入中断。导致task1或者task2虽然优先级低但是会先执行。先执行原因是start_task任务创建后启动了任务调度器导致task1创建后进入运行态,在其阻塞后才继续执行start_task创建task2。接着重复出现此现象。通过串口通信可以看到被打断的过程。
以下摘自官网:
BaseType_t xTaskCreate( TaskFunction_t pvTaskCode, const char * const pcName, const configSTACK_DEPTH_TYPE uxStackDepth, void *pvParameters, UBaseType_t uxPriority, TaskHandle_t *pxCreatedTask );、
创建一个新任务并将其添加到准备运行的任务列表中。 configSUPPORT_DYNAMIC_ALLOCATION 必须在 FreeRTOSConfig.h 中被设置为 1(config.h中默认为1),或保留未定义状态(此时,它默认为 1) ,才能使用此 RTOS API 函数。
每个任务都需要 RAM 来保存任务状态,并由任务用作其 堆栈。 如果使用 xTaskCreate()
创建任务,则所需的 RAM 将自动 从 FreeRTOS 堆中分配。 如果创建任务 使用了 xTaskCreateStatic(),则 RAM 由应用程序编写者提供,因此可以在编译时进行静态分配。
pvTaskCode 指向任务入口函数的指针。
任务通常 以 无限循环的形式实现;实现任务的函数决不能试图返回 或退出。 但是,任务可以 自我删除。
pcName 任务的描述性名称。主要是为了方便 调试,但也可用于 获取任务句柄。
任务名称的最大长度由 FreeRTOSConfig.h 中的 configMAX_TASK_NAME_LEN
定义。
uxStackDepth 要分配用于 任务堆栈的 堆栈。例如,如果堆栈的宽度为 16 位,uxStackDepth 为 100,则将分配 200 字节用作该任务的堆栈。 再举一例,如果堆栈的宽度为 32 位,uxStackDepth 为 400,则将分配 1600 字节用作该任务的堆栈。
堆栈深度与堆栈宽度的乘积不得超过 size_t
类型变量所能包含的最大值。
pvParameters 作为参数传递给创建的任务的一个值。
如果 pvParameters
设置为变量的地址, 则在执行创建的任务时该变量必须仍然存在——因此 传递堆栈变量的地址是无效的。
uxPriority 创建任务执行的优先级 。
包含 MPU 支持的系统可在特权(系统)模式下选择性地创建任务, 方法是在 uxPriority
中设置 portPRIVILEGE_BIT
位。 例如,要创建一个优先级为 2 的特权任务,可将 uxPriority
设置为 ( 2 | portPRIVILEGE_BIT
)。
断言优先级低于 configMAX_priority
。 如果未定义 configASSERT
,则优先级会被静默限制为 ( configMAX_priority
- 1)。
pxCreatedTask 用于将句柄传递至由 xTaskCreate()
函数创建的任务 。 pxCreatedTask
是可选的,可设置为 NULL。
返回:
如果任务创建成功,则返回 pdPASS
。 否则 返回 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY
。
void freertos_demo(void)
{
xTaskCreate( (TaskFunction_t ) start_task,
(char * ) "start_task",
(configSTACK_DEPTH_TYPE) START_TASK_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) START_TASK_PRIO,
(TaskHandle_t * ) &start_task_handler );
vTaskStartScheduler();//开启任务调度器
}
void start_task( void * pvParameters )
{
taskENTER_CRITICAL();/*进入临界区*/
xTaskCreate( (TaskFunction_t ) task1,
(char * ) "task1",
(configSTACK_DEPTH_TYPE) TASK1_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK1_PRIO,
(TaskHandle_t * ) &task1_handler );
xTaskCreate( (TaskFunction_t ) task2,
(char * ) "task2",
(configSTACK_DEPTH_TYPE) TASK2_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK2_PRIO,
(TaskHandle_t * ) &task2_handler );
xTaskCreate( (TaskFunction_t ) task3,
(char * ) "task3",
(configSTACK_DEPTH_TYPE) TASK3_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK3_PRIO,
(TaskHandle_t * ) &task3_handler );
vTaskDelete(NULL);
taskEXIT_CRITICAL(); /*退出临界区*/
}
void task1( void * pvParameters )
{
while(1)
{
printf("task1正在运行\r\n");
LED0_TOGGLE();
vTaskDelay(500);
}
}
void task2( void * pvParameters )
{
while(1)
{
printf("task2正在运行\r\n");
LED1_TOGGLE();
vTaskDelay(500);
}
}
void task3( void * pvParameters )
{
uint8_t key = 0;
while(1)
{
printf("task3正在运行\r\n");
key = key_scan(0);
if(key == KEY0_PRES)
{
if(task1_handler != NULL)//执行一次,避免重复释放内存。
{
printf("删除task1\r\n");
vTaskDelete(task1_handler);
task1_handler = NULL;
}
}
vTaskDelay(10);
}
}