启动流程
LiteOS 和 ucos 第一种和第二种都可以使用,由用户选择,RT-Thread 和 FreeRTOS 则默认
- 创建各个任务,然后等待启动调度器
- 创建一个起始任务,任务都在这个起始任务内创建,然后删除起始任务,启动调度器
创建任务
BaseType_t xTaskCreate(
TaskFunction_t pvTaskCode,
const char * const pcName,
unsigned short usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * pvCreatedTask)
用法示例
//任务优先级
#define APPTask_TASK_PRIO 1
//任务堆栈大小 (单位为字,在32位处理器下,一个字等于4个字节)
#define AppTask_STK_SIZE 512
//任务句柄
TaskHandle_t AppTaskCreate_Handle;
//任务函数
void AppTaskCreate(void *pvParameters);
int main(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
/* 开发板硬件初始化 */
BSP_Init();
printf("这是一个[野火]-STM32全系列开发板-FreeRTOS任务管理实验!\n\n");
printf("按下KEY1挂起任务,按下KEY2恢复任务\n");
/* 创建AppTaskCreate任务 */
xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任务入口函数 */
(const char* )"AppTaskCreate",/* 任务名字 */
(uint16_t )AppTask_STK_SIZE, /* 任务栈大小 */
(void* )NULL,/* 任务入口函数参数 */
(UBaseType_t )APPTask_TASK_PRIO, /* 任务的优先级 */
(TaskHandle_t* )&AppTaskCreate_Handle);/* 任务控制块指针 */
/* 启动任务调度 */
if(pdPASS == xReturn)
vTaskStartScheduler(); /* 启动任务,开启调度 */
else
return -1;
while(1); /* 正常不会执行到这里 */
}
/***********************************************************************
* @ 函数名 : AppTaskCreate
* @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面
* @ 参数 : 无
* @ 返回值 : 无
**********************************************************************/
static void AppTaskCreate(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
taskENTER_CRITICAL(); //进入临界区
/* 创建LED_Task任务 */
xReturn = xTaskCreate((TaskFunction_t )LED_Task, /* 任务入口函数 */
(const char* )"LED_Task",/* 任务名字 */
(uint16_t )512, /* 任务栈大小 */
(void* )NULL, /* 任务入口函数参数 */
(UBaseType_t )2, /* 任务的优先级 */
(TaskHandle_t* )&LED_Task_Handle);/* 任务控制块指针 */
if(pdPASS == xReturn)
printf("创建LED_Task任务成功!\r\n");
/* 创建KEY_Task任务 */
xReturn = xTaskCreate((TaskFunction_t )KEY_Task, /* 任务入口函数 */
(const char* )"KEY_Task",/* 任务名字 */
(uint16_t )512, /* 任务栈大小 */
(void* )NULL,/* 任务入口函数参数 */
(UBaseType_t )3, /* 任务的优先级 */
(TaskHandle_t* )&KEY_Task_Handle);/* 任务控制块指针 */
if(pdPASS == xReturn)
printf("创建KEY_Task任务成功!\r\n");
vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务
taskEXIT_CRITICAL(); //退出临界区
}
任务状态
- 就绪(Ready):该任务在就绪列表中,就绪的任务已经具备执行的能力,只等待调度器进行调度,新创建的任务会初始化为就绪态。
- 运行(Running):该状态表明任务正在执行,此时它占用处理器,FreeRTOS 调度器选择运行的永远是处于最高优先级的就绪态任务,当任务被运行的一刻,它的任务状态就变成了运行态。
- 阻塞(Blocked):如果任务当前正在等待某个时序或外部中断,我们就说这个任务处于阻塞状态,该任务不在就绪列表中。包含任务被挂起、任务被延时、任务正在等待信号量、读写队列或者等待读写事件等。
- 挂起态(Suspended):处于挂起态的任务对调度器而言是不可见的,让一个任务进入挂起状态的唯一办法就是调用 vTaskSuspend()函数;而 把 一 个 挂 起 状态 的任 务 恢复的 唯 一 途 径 就 是 调 用 vTaskResume() 或 vTaskResumeFromISR()函数,我们可以这么理解挂起态与阻塞态的区别,当任务有较长的时间不允许运行的时候,我们可以挂起任务,这样子调度器就不会管这个任务的任何信息,直到我们调用恢复任务的 API 函数;而任务处于阻塞态的时候,系统还需要判断阻塞态的任务是否超时,是否可以解除阻塞。
任务延时
相对延时
void vTaskDelay( const TickType_t xTicksToDelay );
timeout:xTicksToDelay * tick
绝对延时(延时时间>>任务时间)
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime,const TickType_t xTimeIncrement );
pxPreviousWakeTime:当前时间
timeout:(*pxPreviousWakeTime + xTimeIncrement)
void vTaskA( void * pvParameters )
{
/* 用于保存上次时间。调用后系统自动更新 */
static portTickType PreviousWakeTime;
/* 设置延时时间,将时间转为节拍数 */
const portTickType TimeIncrement = pdMS_TO_TICKS(1000);
/* 获取当前系统时间 */
PreviousWakeTime = xTaskGetTickCount();
while (1)
{
/* 调用绝对延时函数, 任务时间间隔为 为 1000 个 个 tick */
vTaskDelayUntil( &PreviousWakeTime ,TimeIncrement );
// ...
// 这里为任务主体代码
// ...
}
启动流程
LiteOS 和 ucos 第一种和第二种都可以使用,由用户选择,RT-Thread 和 FreeRTOS 则默认
创建各个任务,然后等待启动调度器
创建一个起始任务,任务都在这个起始任务内创建,然后删除起始任务,启动调度器
创建任务
在这里插入图片描述
BaseType_t xTaskCreate(
TaskFunction_t pvTaskCode,
const char * const pcName,
unsigned short usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * pvCreatedTask)
用法示例
//任务优先级
#define APPTask_TASK_PRIO 1
//任务堆栈大小
#define AppTask_STK_SIZE 512
//任务句柄
TaskHandle_t AppTaskCreate_Handle;
//任务函数
void AppTaskCreate(void *pvParameters);
int main(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
/* 开发板硬件初始化 */
BSP_Init();
printf(“这是一个[野火]-STM32全系列开发板-FreeRTOS任务管理实验!\n\n”);
printf(“按下KEY1挂起任务,按下KEY2恢复任务\n”);
/* 创建AppTaskCreate任务 /
xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, / 任务入口函数 /
(const char )“AppTaskCreate”,/* 任务名字 /
(uint16_t )AppTask_STK_SIZE, / 任务栈大小 /
(void )NULL,/* 任务入口函数参数 /
(UBaseType_t )APPTask_TASK_PRIO, / 任务的优先级 /
(TaskHandle_t )&AppTaskCreate_Handle);/* 任务控制块指针 /
/ 启动任务调度 /
if(pdPASS == xReturn)
vTaskStartScheduler(); / 启动任务,开启调度 */
else
return -1;
while(1); /* 正常不会执行到这里 /
}
/**********************************************************************
- @ 函数名 : AppTaskCreate
- @ 功能说明: 为了方便管理,所有的任务创建函数都放在这个函数里面
- @ 参数 : 无
- @ 返回值 : 无
*********************************************************************/
static void AppTaskCreate(void)
{
BaseType_t xReturn = pdPASS;/ 定义一个创建信息返回值,默认为pdPASS */
taskENTER_CRITICAL(); //进入临界区
/* 创建LED_Task任务 /
xReturn = xTaskCreate((TaskFunction_t )LED_Task, / 任务入口函数 /
(const char )“LED_Task”,/* 任务名字 /
(uint16_t )512, / 任务栈大小 /
(void )NULL, /* 任务入口函数参数 /
(UBaseType_t )2, / 任务的优先级 /
(TaskHandle_t )&LED_Task_Handle);/* 任务控制块指针 /
if(pdPASS == xReturn)
printf(“创建LED_Task任务成功!\r\n”);
/ 创建KEY_Task任务 /
xReturn = xTaskCreate((TaskFunction_t )KEY_Task, / 任务入口函数 /
(const char )“KEY_Task”,/* 任务名字 /
(uint16_t )512, / 任务栈大小 /
(void )NULL,/* 任务入口函数参数 /
(UBaseType_t )3, / 任务的优先级 /
(TaskHandle_t )&KEY_Task_Handle);/* 任务控制块指针 */
if(pdPASS == xReturn)
printf(“创建KEY_Task任务成功!\r\n”);
vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreate任务
taskEXIT_CRITICAL(); //退出临界区
}
任务状态
在这里插入图片描述
就绪(Ready):该任务在就绪列表中,就绪的任务已经具备执行的能力,只等待调度器进行调度,新创建的任务会初始化为就绪态。
运行(Running):该状态表明任务正在执行,此时它占用处理器,FreeRTOS 调度器选择运行的永远是处于最高优先级的就绪态任务,当任务被运行的一刻,它的任务状态就变成了运行态。
阻塞(Blocked):如果任务当前正在等待某个时序或外部中断,我们就说这个任务处于阻塞状态,该任务不在就绪列表中。包含任务被挂起、任务被延时、任务正在等待信号量、读写队列或者等待读写事件等。
挂起态(Suspended):处于挂起态的任务对调度器而言是不可见的,让一个任务进入挂起状态的唯一办法就是调用 vTaskSuspend()函数;而 把 一 个 挂 起 状态 的任 务 恢复的 唯 一 途 径 就 是 调 用 vTaskResume() 或 vTaskResumeFromISR()函数,我们可以这么理解挂起态与阻塞态的区别,当任务有较长的时间不允许运行的时候,我们可以挂起任务,这样子调度器就不会管这个任务的任何信息,直到我们调用恢复任务的 API 函数;而任务处于阻塞态的时候,系统还需要判断阻塞态的任务是否超时,是否可以解除阻塞。
任务延时
相对延时
void vTaskDelay( const TickType_t xTicksToDelay );
timeout:xTicksToDelay * tick
绝对延时(延时时间>>任务时间)
void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime,const TickType_t xTimeIncrement );
pxPreviousWakeTime:当前时间
timeout:(*pxPreviousWakeTime + xTimeIncrement)
void vTaskA( void * pvParameters )
{
/* 用于保存上次时间。调用后系统自动更新 /
static portTickType PreviousWakeTime;
/ 设置延时时间,将时间转为节拍数 */
const portTickType TimeIncrement = pdMS_TO_TICKS(1000);
/* 获取当前系统时间 */
PreviousWakeTime = xTaskGetTickCount();
while (1)
{
/* 调用绝对延时函数, 任务时间间隔为 为 1000 个 个 tick */
vTaskDelayUntil( &PreviousWakeTime ,TimeIncrement );
// …
// 这里为任务主体代码
// …
}