第一章创建任务
1.硬件初始化
我们在写代码之前都会对硬件进行初始化,将所需的硬件初始化函数放置在BSP_Init()函数当中,便于之后所添加的各类硬件函数初始化,方便我们的管理。这里先放着一个LED_GPIO的初始化函数,便于接下来观察实验现象,串口初始化函数用来发送给电脑串口助手发送实验信息。
/***********************************************************************
* @ 函数名: BSP_Init
* @ 功能说明:板级外设初始化,所有板子上的初始化均可放在这个函数里面
* @ 参数:
* @ 返回值:无
*********************************************************************/
static void BSP_Init(void)
{
/*
/*
* STM32中断优先级分组为4,即4bit都用来表示抢占优先级,范围为:0~15
* 优先级分组只需要分组一次即可,以后如果有其他的任务需要用到中断,
* 都统一用这个优先级分组,千万不要再分组,切忌。
SysTick_Init(72); //初始化延迟函数
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
/* LED 初始化 */
LED_GPIO_Config();
/*´串口初始化¯*/
USART_Config();
}
2.创建任务
创建任务有两种方法:一种是静态创建,另外一种就是动态创建。静态创建任务:使用xTaskCreateStatic() 函数创建。
静态创建任务是在编译时分配任务所需的内存空间。
创建任务时需要定义并初始化一个StaticTask_t类型的变量,该变量用于存储任务的相关信息。
静态创建任务的内存空间在任务整个运行期间都被任务所占用,直到任务被删除。
静态创建任务通常在应用程序的启动阶段进行,任务的数量是固定的,无法在运行时动态调整。
动态创建任务:
动态创建任务是在运行时通过动态内存分配函数(例如pvPortMalloc())来分配任务所需的内存空间。
创建任务时,不需要定义和初始化额外的变量,任务的相关信息直接存储在动态分配的内存中。
动态创建任务的内存空间可以在任务完成后释放,可以在运行时动态地创建和删除任务。
动态创建任务通过调用函数xTaskCreate()来实现,任务的数量可以在运行时根据需求进行动态调整。
本文采用的是动态创建任务的方式:该任务的功能便是使LED灯循环每隔0.5s进行亮灭操作,以及在上电之后通过串口发送“FreeRTOS点灯实验”至串口助手。
void LED_Task(void* parameter)
{
/*初始化串口 配置模式为115200 8-N-1,中断接收*/
USART_Config();
/* 发送一个字符串 */
printf("FreeRTOSLED点灯实验\r\n");
while (1)
{
LED1_ON; /*宏定义 digitalLo(LED1_GPIO_PORT,LED1_GPIO_PIN)将该引脚置为低电平 详情看下图 */
vTaskDelay(500); /* 延时500个tick */
LED1_OFF;
vTaskDelay(500); /* 延时500个tick */
}
}
因为我们采用的是动态创建任务的方法,所以在头文件FreeRTOSConfig当中的"FreeRTOS内存申请有关配置项中的支持动态申请的宏定义将其至为1" ,而后我们就能使用动态的方法来创建任务了。其次因为我们所使用的是C8T6内存并不是很大,所以我们系统所有总的堆大小宏定义改成8*1024。
3.函数声明
void AppTaskCreate(void);/* 用于创建任务 */
void LED_Task(void* Parameter);/* LED_Task任务实现 */
4.任务句柄
任务句柄是一个指针,用于指向一个任务,当任务创建好之后,它就具有了任务句柄。以后我们想要操作这个任务都需要通过这个任务句柄,如果是自身的任务操作自己,那么这个任务可以是NULL
/* 创建任务句柄 */
TaskHandle_t AppTaskCreate_Handle = NULL;
/* LED任务句柄*/
TaskHandle_t LED_Task_Handle = NULL;
5.动态创建任务
一个任务的三要素是任务主体函数,任务栈,任务控制块,通过xTaskCreate将三要素联系一起,让任务随时被系统启动。任务的优先级:自己添加,数字越大优先级越高,该任务相较于其它任务越先执行。
/***********************************************************************
* @ 函数名: AppTaskCreate
* @ 功能说明:为了方便管理,所有的任务创建函数都放在这个函数里面
* @ 参数: 无
* @ 返回值:无
**********************************************************************/
void AppTaskCreate(void)
{
taskENTER_CRITICAL(); //进入临界区
/*LED_Task任务 */
xTaskCreate((TaskFunction_t )LED_Task, /* 任务入口函数 */
(const char* )"LED_Task",/* 任务名字 */
(uint16_t )128, /* 任务栈大小 */
(void* )NULL, /* 任务入口函数参数 */
(UBaseType_t )2, /* 任务的优先级*/
(TaskHandle_t* )&LED_Task_Handle);/* 任务控制块指针 */
vTaskDelete(AppTaskCreate_Handle); //删除AppTaskCreat任务
taskEXIT_CRITICAL(); /退出临界区
任务创建函数的位置必须位于临界区之内,否则任务将无法正常执行。
6.任务运行
int main(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值默认值为pdPASS */
/* ¯开发板硬件初始化 */
BSP_Init();
/*创建APPTaskCreate任务 */
xReturn = xTaskCreate((TaskFunction_t )AppTaskCreate, /* 任务入口函数 */
(const char* )"AppTaskCreate",/* 任务名字*/
(uint16_t )512, /* 堆栈大小 */
(void* )NULL,/*任务函数入口参数*/
(UBaseType_t )1, /* 任务的优先级 */
(TaskHandle_t* )&AppTaskCreate_Handle);/* 任务句柄*/
/* 启动任务调度 */
if(pdPASS == xReturn)
vTaskStartScheduler(); /* 启动任务 开启调度 */
else
return -1;
while(1); /* 正常不会执行到这 */
}
必要的头文件
下载至C8T6后,按下最小系统板的rest键便可观察到实验现象。