【FreeRTOS】任务的创建

启动流程

LiteOS 和 ucos 第一种和第二种都可以使用,由用户选择,RT-Thread 和 FreeRTOS 则默认

  1. 创建各个任务,然后等待启动调度器
  2. 创建一个起始任务,任务都在这个起始任务内创建,然后删除起始任务,启动调度器

创建任务

在这里插入图片描述

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 );

// …
// 这里为任务主体代码
// …

}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值