2.stm32freeRTOS---创建一个任务


前言

上一次是初步接触实时系统,这次开始认真学习


一、创建一个任务需要注意哪些?

1、任务创建函数xTaskCreate

 BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, //任务名
                            const char * const pcName,  //任务标签
                            const configSTACK_DEPTH_TYPE usStackDepth,//栈大小
                            void * const pvParameters,//传入参数
                            UBaseType_t uxPriority,//任务优先级
                            TaskHandle_t * const pxCreatedTask )//任务句柄

这里说一下 任务标签 ,它可以和任务名重名,也可以不重名。
任务优先级值越小,优先级越低。
任务句柄,就是在代码前面需要定义一个
TaskHandle_t Task1_Handler = NULL;

所以传任务句柄参数时可以传NULL。

2、代码分析

#include "sys.h"
#include "usart.h"
#include "led.h"

#include "FreeRTOS.h"
#include "task.h"

//任务句柄
TaskHandle_t	Task1_Handler = NULL;
TaskHandle_t	Task2_Handler = NULL;

void *Task1_func  (void *param)
{
    while(1)
        {
        printf("AS");
    }
}

void *Task2_func  (void *param)
{
    while(1)
        {
        printf("BJ");
    }
}
int main(void)
{
	delay_init();									//延时函数初始化	  
	uart_init(115200);								//初始化串口
	LED_Init(); 
										//初始化LED
	xTaskCreate((TaskFunction_t)Task1_func, "Task1", 52, NULL, 1, &Task1_Handler);
    xTaskCreate((TaskFunction_t)Task2_func, "Task2", 52, NULL, 1, NULL);

	vTaskStartScheduler();//开始任务调度
}


这里我一下创建2个任务,如果只是一个任务的创建,
只需要对上面代码删除一些东西就好。
我需要说一下实验现象:
ASASASASASASBJBJBJBJBJBJ......

所以任务1和任务2就是交替实行的,就类似于时分复用。
这次是串口打印,如果是用其他实验现象,比如是led的
闪烁,那么我们看见的就是两个任务在同时运行。




在这里插入图片描述

二、动态/静态分配

每一个任务都有一个TCB(任务控制块)的结构体TCB_t。
任务控制块里面就有malloc去申请堆空间。

1· 动态分配

xTaskCreate((TaskFunction_t)Task1_func, “Task1”, 52, NULL, 1, &Task1_Handler);

xTaskCreate函数就是动态分配TCB,动态分配栈。
上面代码就是动态分配。

2· 静态分配:

静态分配就是自己分配TCB,自己分配栈。

 TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
                                    const char * const pcName,
                        /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                                    const uint32_t ulStackDepth,
                                    void * const pvParameters,
                                    UBaseType_t uxPriority,
                                    StackType_t * const puxStackBuffer, //传入栈
                                    StaticTask_t * const pxTaskBuffer )//TCB结构体
                                 

使用静态配需要打开一些配置:
在这里插入图片描述

在这里插入图片描述
configSUPPORT_STATIC_ALLOCATION 需要置为1.

在开任务调度的函数里面,如果configSUPPORT_STATIC_ALLOCATION 置为1了需要开一个空闲函数,所以需要提供一个vApplicationGetIdleTaskMemory函数
在这里插入图片描述

代码:

#include "sys.h"
#include "usart.h"
#include "led.h"


#include "FreeRTOS.h"
#include "task.h"






//任务句柄
TaskHandle_t	Task1_Handler = NULL;
TaskHandle_t	Task2_Handler = NULL;
//--------------------------------------
StackType_t    task3stackbuff[100];
StaticTask_t *  task3TCB;
//--------------------------------------
StackType_t    idelstackbuff[100];
StaticTask_t *  idelTCB;
/*---------------任务函数-----------------------------------*/
void *Task1_func  (void *param)
{
    while(1)
        {
        printf("AS");
    }

}
void *Task2_func  (void *param)
{
    while(1)
        {
        printf("BJ");
    }
}
void *Task3_func  (void *param)
{
    while(1)
        {
        printf("NK");
    }

}
/*---------------任务函数-----------------------------------*/
/*---------------创建一个空闲函数函数-----------------------------------*/
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
                                    StackType_t ** ppxIdleTaskStackBuffer,
                                    uint32_t * pulIdleTaskStackSize )
{
    * ppxIdleTaskTCBBuffer = idelTCB;
    * ppxIdleTaskStackBuffer = idelstackbuff;
    * pulIdleTaskStackSize = 100;
}
/*---------------创建一个空闲函数函数-----------------------------------*/


int main(void)
{
	//delay_init();									//延时函数初始化	  
	uart_init(115200);								//初始化串口
	LED_Init(); 									//初始化LED



	xTaskCreate((TaskFunction_t)Task1_func, "Task1", 52, NULL, 1, &Task1_Handler);
    xTaskCreate((TaskFunction_t)Task2_func, "Task2", 52, NULL, 1, &Task2_Handler);
    xTaskCreateStatic(Task3_func,"task3",52,NULL,1,task3stackbuff,task3TCB);

    vTaskStartScheduler();//开始任务调度

}

注意:一定要configSUPPORT_STATIC_ALLOCATION 置为1.
再说一下关于优先级问题:freeRTOS中的优先级值越大,则程序越先执行。
多个任务的优先级一致,则多个任务时分复用执行(依次轮流循环执行)。
若多个任务的优先级不一致,则优先级高的先执行并且在该任务没有主动
放弃CPU的控制的情况下会一直执行,其他低优先级的任务根本没有把那发执行。


三、删除任务

在这里插入图片描述

vTaskDelete 函数传参是任务句柄,如果需要删除某个任务,就把该任务的任务句柄传进去。
在这里插入图片描述

【xTaskCreateStatic 静态分配的任务的返回值是该任务的任务句柄,所以需要定义一个变量来存储这个返回值,再把这个返回值传给vTaskDelete 】

四、一个函数创建两个任务

#include "sys.h"
#include "usart.h"
#include "led.h"


#include "FreeRTOS.h"
#include "task.h"


//任务句柄
TaskHandle_t	Task1_Handler = NULL;
TaskHandle_t	Task2_Handler = NULL;

StackType_t    task3stackbuff[100];
StaticTask_t *  task3TCB;

/*--------------------------------------------------*/
void *Task1_func  (void *param)
{
    while(1)
        {
        printf("AS");
    }

}

void *Task2_func  (void *param)
{
    while(1)
        {
        printf("BJ");
    }

}

void *Task3_func  (void *param)
{
    while(1)
        {
        printf("NK");
    }

}

/*--------------------------------------------------*/

/*---------通用函数-----------------------------------------*/
void taskGenericFunction(void *param)
{
    int val = (int ) param;
        while(1)
            {
            printf("%d",val);
        }
}
/*---------通用函数-----------------------------------------*/

int main(void)
{
	//delay_init();									//延时函数初始化	  
	uart_init(115200);								//初始化串口
	LED_Init(); 									//初始化LED
	
	xTaskCreate((TaskFunction_t)Task1_func, "Task1", 52, NULL, 1, &Task1_Handler);
    xTaskCreate((TaskFunction_t)Task2_func, "Task2", 52, NULL, 1, NULL);

    /*---------多个任务调用一个通用函数-----------------------------------------*/
    xTaskCreate((TaskFunction_t)taskGenericFunction, "Task3", 52, NULL, 1, NULL);
    xTaskCreate((TaskFunction_t)taskGenericFunction, "Task4", 52, NULL, 1, NULL);
    /*---------多个任务调用一个通用函数-----------------------------------------*/
    vTaskStartScheduler();//开始任务调度

}

原因:每一个任务都有自己独立的栈。

总结

1·归根结底,实时操作系统和裸机程序的不同就是 时分复用 和 挨个函数执行。
2·创建一个任务的那些参数就是给这个任务营造一种“生存条件”,比如它的栈大小,它的任务控制块TCB等。
3·任务优先级一致与不一致的情况。优先级一致,则时分复用;不一致则高优先级先执行,若高优先级不放弃cpu的控制权,则低优先级没有办法执行。
4·多个任务可以调用一个功能函数时,是因为任务都有独立的栈,这个功能函数只是一个函数而已。【xTaskCreate 只有调用这样的函数才可以给任务分配栈空间】

问题:
1、任务句柄的作用是什么?可以赋值为NULL?
任务句柄 就是指向 任务控制块的指针。

2、为什么要加一个任务调度函数?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值