portBASE_TYPE xTaskCreate( pdTASK_CODE pvTaskCode,
//pvTaskCode只一个指向任务的实现函数的指针(效果上仅仅是函数名)。
const char * const pcName,
//pcName 具有描述性的任务名,只在调试时使用(可以用 config_MAX_TASK_NAME_LEN定义最大长度,超过会被截断)
unsigned portSHORT usStackDepth,
//分配多少字的空间,一个字等于4个字节
void *pvParameters,
//接受传入void的参数,可以是字符串
unsigned portBASE_TYPE uxPriority,
//设置优先级,一般取符合需求的最小值
xTaskHandle *pxCreatedTask );
//用于传出任务的句柄,也是任务控制块,在API调用删除修改该函数时使用,不用可以设为NULL
返回值可以是
a.pdTRUE 表明任务创建成功
b.errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY 由于内存堆空间不足,分配不出,所以无法创建
portBASE_TYPE xTaskCreateStatic( pdTASK_CODE pvTaskCode,
//pvTaskCode只一个指向任务的实现函数的指针(效果上仅仅是函数名)。
const signed portCHAR * const pcName,
//pcName 具有描述性的任务名,只在调试时使用(可以用config_MAX_TASK_NAME_LEN定义最大长度,超过会被截断)
unsigned portSHORT usStackDepth,
//需要多少字的空间,一个字等于4个字节
void *pvParameters,
//接受传入void的参数,可以是字符串
unsigned portBASE_TYPE uxPriority,
//设置优先级,一般取符合需求的最小值
StackType_t* const puxStackBuffer,
//任务堆栈,一般为数组,用户自己给堆栈分配大小
StaticTask_t* const pxTaskBuffer)
//任务控制块指针,又用户分配
返回值可以是
a.其他值 表明任务创建成功
b.NULL 内存不足,分配不出,任务失败
void vTaskDelete(xTaskHandle pxTaskToDelete);
参数:目标任务的句柄
a.任务可以通过传入NULL删除自己
b.通过空闲任务将分配给已删除任务的内存释放掉
c.静态任务的删除,需要用户在任务被删除前提前释放之前申请的内存
d.使用删除任务函数需将洪INCLUDE_vTaskDelete配置为1
typedef struct tskTaskConlBlock
{
volatile StackType_t *pxTopOfStack; //任务栈顶,必须为TCB的第一个成员
Listltem_t xStateListltem; //任务状态列表项
Listltem_t xRvevtListltem; //任务事件列表项
UBaseType_t uxPriority; //任务优先级,数值越大,优先级越高
StackType_t *pxStack; //任务栈起始地址
portCHAR pcTaskName[configMAX_TASK_NAME_LEN];//任务名字
}tskTCB
a.高优先级抢占低优先级,实现资源利用
b.通过阻塞高优先级,运行较低优先级,实现资源利用
c.然后解除阻塞,又运行高优先级(优先级数值越低,优先级越低)
d.优先级任务是个容器,把要运行的任务放进去,优先级任务会置1,表示里面有任务,在就绪列表中就能被选中,变成运行态
一个用rtos点亮LED的程序
#include "./SYSTEM/sys/sys.h"
#include "./SYSTEM/usart/usart.h"
#include "./SYSTEM/delay/delay.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
#include "./BSP/SRAM/sram.h"
#include "./MALLOC/malloc.h"
#include "freertos_demo.h"
int main(void)
{
HAL_Init(); /* 初始化HAL库 */
sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */
delay_init(168); /* 延时初始化 */
usart_init(115200); /* 串口初始化为115200 */
led_init(); /* 初始化LED */
lcd_init(); /* 初始化LCD */
key_init(); /* 初始化按键 */
sram_init(); /* SRAM初始化 */
my_mem_init(SRAMIN); /* 初始化内部SRAM内存池 */
my_mem_init(SRAMEX); /* 初始化外部SRAM内存池 */
my_mem_init(SRAMCCM); /* 初始化内部CCM内存池 */
freertos_demo(); //freertos函数
}
静态任务的创建和释放
需要把FreeRTOSConfig.h中的configSUPPORT_STATIC_ALLOCATION(第39行)置1
#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
/* START_TASK 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务 分配数组空间 任务控制块
*/
#define START_TASK_PRIO 1 //优先级大小
#define START_TASK_STACK_SIZE 128 //堆栈大小
TaskHandle_t start_task_handler; //任务句柄
StackType_t start_task_stack[START_TASK_STACK_SIZE]; //创建数组,分配空间
StaticTask_t start_task_tcb; //任务控制块
void start_task(void * pvParameters); //创建任务
/* TASK1 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务 分配数组空间 任务控制块
*/
#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
StackType_t task1_stack[TASK1_STACK_SIZE];
StaticTask_t task1_tcb;
void task1(void* pv);
/* TASK2 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务 分配数组空间 任务控制块
*/
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
StackType_t task2_stack[TASK2_STACK_SIZE];
StaticTask_t task2_tcb;
void task2(void* pv);
/* TASK3 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务 分配数组空间 任务控制块
*/
#define TASK3_PRIO 4
#define TASK3_STACK_SIZE 128
TaskHandle_t task3_handler;
StackType_t task3_stack[TASK3_STACK_SIZE];
StaticTask_t task3_tcb;
void task3(void* pv);
//空闲任务配置
//任务控制块 分配堆栈 堆栈大小
StaticTask_t idle_task_tcb;
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE];
//软件定时器任务配置
//任务控制块 分配堆栈 堆栈大小
StaticTask_t timer_task_tcb;
StackType_t timer_task_stack[configTIMER_TASK_STACK_DEPTH];
//空闲任务内存分配
void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
uint32_t * pulIdleTaskStackSize )
{
* ppxIdleTaskTCBBuffer = &idle_task_tcb; //任务控制块
* ppxIdleTaskStackBuffer = idle_task_stack; //创建数组,分配堆栈空间
* pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; //堆栈大小
}
//软件定时器内存分配
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
StackType_t ** ppxTimerTaskStackBuffer,
uint32_t * pulTimerTaskStackSize )
{
* ppxTimerTaskTCBBuffer = &timer_task_tcb;
* ppxTimerTaskStackBuffer = timer_task_stack;
* pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
void freertos_demo(void)
{
start_task_handler = xTaskCreateStatic( (TaskFunction_t ) start_task, //指向函数的指针
(char * ) "start_task", //任务名
( uint32_t ) START_TASK_STACK_SIZE, //任务需要的空间大小
(void * ) NULL, //函数带入的参数,这里没有
(UBaseType_t ) START_TASK_PRIO, //优先级
(StackType_t * ) start_task_stack, //静态需要的,人为分配内存空间数组
(StaticTask_t * ) &start_task_tcb); //任务控制块
vTaskStartScheduler(); //任务调度器,开启后系统才会自动协调任务
}
void start_task(void* pvPara)
{
taskENTER_CRITICAL(); //进入临界区,临界区作用保护程序段不被打断
task1_handler = xTaskCreateStatic( (TaskFunction_t ) task1, //指向任务的指针
(char * ) "task1", //任务名
( uint32_t ) TASK1_STACK_SIZE, //任务需要的空间大小
(void * ) NULL, //函数带入的参数,这里没有
(UBaseType_t ) TASK1_PRIO, //优先级
(StackType_t * ) task1_stack, //静态需要的,人为分配内存空间数组
(StaticTask_t * ) &task1_tcb); //任务控制块
task2_handler = xTaskCreateStatic( (TaskFunction_t ) task2,
(char * ) "task2",
( uint32_t ) TASK1_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK2_PRIO,
(StackType_t * ) task2_stack,
(StaticTask_t * ) &task2_tcb);
task3_handler = xTaskCreateStatic( (TaskFunction_t ) task3,
(char * ) "task3",
( uint32_t ) TASK3_STACK_SIZE,
(void * ) NULL,
(UBaseType_t ) TASK3_PRIO,
(StackType_t * ) task3_stack,
(StaticTask_t * ) &task3_tcb);
/*创建任务也可以写成
task3_handler = xTaskCreateStatic(task3,"task3",TASK3_STACK_SIZE,NULL,TASK3_PRIO,task3_stack,&task3_tcb)
这里为了方便定义参数,所以保留了也做了强转
*/
vTaskDelete(start_task_handler); //删除任务,虽然是静态任务,但因为申请的内存是静态数组,所以不用自己释放,系统会自动释放
taskEXIT_CRITICAL(); //退出临界区
}
//任务一 实现LED0每500ms翻转一次
void task1(void* pv)
{
while(1)
{
printf("task1正在运行\r\n");
LED0_TOGGLE(); //反转API
vTaskDelay(500); //阻塞500毫秒
}
}
//任务二 实现LED1每500ms翻转一次
void task2(void* pv)
{
while(1)
{
printf("task2正在运行\r\n");
LED1_TOGGLE();
vTaskDelay(500);
}
}
//任务三 判断按键KEY0,按下KEY0删除task1
void task3(void* pv)
{
uint8_t key = 0;
while(1)
{
printf("task3正在运行\r\n");
key = key_scan(0); //定义按键为按键0
if(key == KEY0_PRES) //按键0按下
{
printf("删除task1任务\r\n");
vTaskDelete(task1_handler);
}
vTaskDelay(10); //阻塞10毫秒
}
}
动态任务的创建与释放:
需要把FreeRTOSConfig.h中的configSUPPORT_DYNAMIC_ALLOCATION(第40行)置1
#include "freertos_demo.h"
#include "./SYSTEM/usart/usart.h"
#include "./BSP/LED/led.h"
#include "./BSP/LCD/lcd.h"
#include "./BSP/KEY/key.h"
/*FreeRTOS*********************************************************************************************/
#include "FreeRTOS.h"
#include "task.h"
/* START_TASK 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define START_TASK_PRIO 1 //优先级
#define START_TASK_STACK_SIZE 128 //堆栈大小
TaskHandle_t start_task_handler; //任务句柄
void start_task(void * pvParameters); //创建任务
/* TASK1 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK1_PRIO 2
#define TASK1_STACK_SIZE 128
TaskHandle_t task1_handler;
void task1(void* pv);
/* TASK2 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK2_PRIO 3
#define TASK2_STACK_SIZE 128
TaskHandle_t task2_handler;
void task2(void* pv);
/* TASK3 任务 配置
* 包括: 任务句柄 任务优先级 堆栈大小 创建任务
*/
#define TASK3_PRIO 4
#define TASK3_STACK_SIZE 128
TaskHandle_t task3_handler;
void task3(void* pv);
/******************************************************************************************************/
/**
* @brief FreeRTOS例程入口函数
* @param 无
* @retval 无
*/
void freertos_demo(void)
{
xTaskCreate((TaskFunction_t ) start_task, //任务名
(char* ) "start_task", //别名
(unsigned portSHORT) START_TASK_STACK_SIZE, //需要的内存大小
(void * ) NULL, //函数带入的参数,这里不需要
(portBASE_TYPE ) START_TASK_PRIO, //优先级
(TaskHandle_t* ) &start_task_handler ); //任务控制块
vTaskStartScheduler(); //任务调度器,开启后系统才会自动协调任务
}
void start_task(void* pvPara)
{
taskENTER_CRITICAL(); //进入临界区
xTaskCreate((TaskFunction_t ) task1,
(char* ) "task1",
(unsigned portSHORT) TASK1_STACK_SIZE,
(void * ) NULL,
(portBASE_TYPE ) TASK1_PRIO,
(TaskHandle_t* ) &task1_handler );
xTaskCreate((TaskFunction_t ) task2,
(char* ) "task2",
(unsigned portSHORT) TASK2_STACK_SIZE,
(void * ) NULL,
(portBASE_TYPE ) TASK2_PRIO,
(TaskHandle_t* ) &task2_handler );
xTaskCreate((TaskFunction_t ) task3,
(char* ) "task3",
(unsigned portSHORT) TASK3_STACK_SIZE,
(void * ) NULL,
(portBASE_TYPE ) TASK3_PRIO,
(TaskHandle_t* ) &task3_handler );
vTaskDelete(NULL); //删除任务自身
taskEXIT_CRITICAL(); //退出临界区
}
//任务一 实现LED0每500ms翻转一次
void task1(void* pv)
{
while(1)
{
printf("task1正在运行\r\n");
LED0_TOGGLE(); //反转api
vTaskDelay(500);
}
}
//任务二 实现LED1每500ms翻转一次
void task2(void* pv)
{
while(1)
{
printf("task2正在运行\r\n");
LED1_TOGGLE();
vTaskDelay(500);
}
}
//任务三 判断按键KEY0,按下KEY0删除task1
void task3(void* pv)
{
uint8_t key = 0;
while(1)
{
printf("task3正在运行\r\n");
key = key_scan(0);
if(key == KEY0_PRES)
{
printf("删除task1任务\r\n");
vTaskDelete(task1_handler);
}
vTaskDelay(10);
}
}