了解FreeRTOS
任务相关API
FreeRTOS任务创建API
FreeRTOS 中,任务的创建有两种方法,一种是使用动态创建,一种是使用静态创建。动态创建时,任务控制块和栈的内存是创建任务时动态分配的,任务删除时,内存可以释放。静态创建时,任务控制块和栈的内存需要事先定义好,是静态的内存 ,任务删除时 ,内存不能释放 。
动态创建API:xTaskCreate()
BaseType_t  xTaskCreate(
TaskFunction_t	pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t  uxPriority,
TaskHandle t* const  pxCreatedTask 
)
 返回值:
返回值:
 pdPASS:任务创建成功
 errCIOULD_NOT_ALLOCATE_REQUIRED_MEMORY:任务创建失败,因为内存不足
静态创建API:xTaskCreateStatic()
TaskHandle  xTaskCreateStatic(
TaskFunction_t	pxTaskCode,
const char * const pcName,
const uint16_t usStackDepth,
void * const pvParameters,
UBaseType_t  uxPriority,
StaticType_t *const puStackBuffer,
StaticTask_t *const pxTaskBuffer)
 返回值:
返回值:
 NULL:任务创建失败
 其他:任务创建成功,返回任务句柄
删除任务API
vTaskDelete():删除一个任务。
vTaskDelete(TaskHandle_t xTaskToDelete)
参数:
 xTaskToDelete:要删除的任务的句柄
任务挂起和恢复API
任务挂起:vTaskToSuspend
此函数用于将某个任务设置为挂起态, 进入挂起态的任务永远都不会进入运行态。退出挂
 起态的唯一方法就是调用任务恢复函数 vTaskResume()或 xTaskResumeFromISR()。
void vTaskToSuspend(TaskHandle_t xTaskSuspend)
参数:
 
任务恢复
vTaskResume():恢复一个任务的运行。
将一个任务从挂起态恢复到就绪态, 只有通过函数 vTaskSuspend()设置为挂起态的任务才可以使用 vTaskRexume()恢复!
void vTaskResume(TaskHandleToResume)
xTaskResumeFromISR():中断服务函数中恢复一个任务的运行
此函数是 vTaskResume()的中断版本,用于在中断服务函数中恢复一个任务后
BaseType_t xTaskResumeFromISR(Task_Handle_t xTaskToResume)
参数:
 xTaskToResume:要恢复的任务句柄
任务创建参考代码
对开始任务进入临界态再创建任务存在疑问
#include "sys.h"   
#include "usart.h" 
#include "gpio.h"                
#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"//LCD刷屏时使用的颜色//任务优先级
#define START_TASK_PRIO		4
//任务堆栈大小	
#define START_STK_SIZE 		128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);//任务优先级
#define LED0_TASK_PRIO		0
//任务堆栈大小	
#define LED0_STK_SIZE 		20
//任务句柄
TaskHandle_t LED0Task_Handler;
//任务函数
void led0_task(void *pvParameters);//任务优先级
#define LED1_TASK_PRIO	  0
//任务堆栈大小	
#define LED1_STK_SIZE 		20
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 delay_init();	    				//延时函数初始化	  My_USART_Init();				//初始化串口MX_GPIO_Init();		  		//初始化GPIO//创建开始任务xTaskCreate((TaskFunction_t )start_task,            //任务函数(const char*    )"start_task",          //任务名称(uint16_t       )START_STK_SIZE,        //任务堆栈大小(void*          )NULL,                  //传递给任务函数的参数(UBaseType_t    )START_TASK_PRIO,       //任务优先级(TaskHandle_t*  )&StartTask_Handler);   //任务句柄              vTaskStartScheduler();          //开启任务调度
}//开始任务任务函数
void start_task(void *pvParameters)
{taskENTER_CRITICAL();           //进入临界区//创建LED0任务xTaskCreate((TaskFunction_t )led0_task,     	(const char*    )"led0_task",   	(uint16_t       )LED0_STK_SIZE, (void*          )NULL,				(UBaseType_t    )LED0_TASK_PRIO,	(TaskHandle_t*  )&LED0Task_Handler);   //创建LED1任务xTaskCreate((TaskFunction_t )led1_task,     (const char*    )"led1_task",   (uint16_t       )LED1_STK_SIZE, (void*          )NULL,(UBaseType_t    )LED1_TASK_PRIO,(TaskHandle_t*  )&LED1Task_Handler); vTaskDelete(StartTask_Handler); //删除开始任务taskEXIT_CRITICAL();            //退出临界区
}//LED0任务函数 
void led0_task(void *pvParameters)
{while(1){LED0 = !LED0;vTaskDelay(500);}
}   
/* jwiw */
//LED1任务函数
void led1_task(void *pvParameters)
{uint16_t flag=0;while(1){if(flag==0){flag=1;vTaskDelay(200);}else flag=0;GPIO_ResetBits(GPIOE,GPIO_Pin_5);vTaskDelay(200);GPIO_SetBits(GPIOE,GPIO_Pin_5);vTaskDelay(800);}
}队列相关API
了解队列
队列是为了任务与任务、任务与中断之间的通信而准备的,可以在任务与任务、任务与中断之间传递消息,队列中可以存储有限的、大小固定的数据项目。任务与任务、任务与中断之间要交流的数据保存在队列中,叫做队列项目。队列所能保存的最大数据项目数量叫做队列的长度,创建队列的时候会指定数据项目的大小和队列的长度。 由于队列用来传递消息的,所以也称为消息队列。 FreeRTOS 中的信号量的也是依据队列实现的! 所以有必要深入的了解FreeRTOS 的队列。
特点:先进先出,固定大小/长度
读取队列的两种方式
如果读取时队列 Q 是空
不阻塞:阻塞时间决定的,这个阻塞时间单位是时钟节拍数。 阻塞时间为 0 的话就是不阻塞,没有数据的话就马上返回任务继续执行接下来的代码。
阻塞:如果阻塞时间为 0~ portMAX_DELAY, 当任务没有从队列中获取到消息的话就进入阻塞态,阻塞时间指定了任务进入阻塞态的时间,当阻塞时间到了以后还没有接收到数据的话就退出阻塞态,返回任务接着运行下面的代码,如果在阻塞时间内接收到了数据就立即返回,执行任务中下面的代码