一、实验目标
创建四个动态任务,栈空间大小均为128字。startTask、Task1、Task2、Task3。startTask仅运行一次,负责互斥信号量的创建,task1、task2、task3任务的创建,startTask任务的删除。Task1(低优先级)负责互斥信号量的获取后绝对延时3S后释放。Task2(中优先级)负责串口打印运行状态。Task3(高优先级)负责互斥信号量的获取后绝对延时1S后释放。
注:本实验基于正点原子FreeRTOS教程的学习总结。
二、实验准备
1.FreeRTOS的Keil动态任务创建与删除程序
2.STM3F407开发板
3.互斥信号量介绍
互斥信号量是具有优先级继承的二值信号量,可以降低优先级翻转带来的影响,但不能彻底解决。
优先级继承:当低优先级的任务先获取到互斥信号量,高优先级的任务获取互斥信号量时,会将低优先级的优先级提升到高优先级任务一样的优先级(优先级上升)。
互斥信号量创建时,会主动释放一次信号量。
4.所需API函数介绍
使用的API函数主要有互斥信号量动态创建函数、计数值获取函数。信号量释放函数、信号量获取函数与二值信号量的相同,可以在上一章查看。
互斥信号量动态创建函数xSemaphoreCreateMutex(),创建成功返回值为互斥信号量句柄,创建失败返回NULL。
#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
5.信号量相关定义
首先在freertos_demo.c中添加头文件:
#include "semphr.h"
其次定义互斥信号量的句柄:
//互斥信号量定义
SemaphoreHandle_t Mutex_Semaphore_Handle;//定义互斥信号量句柄
在FreeRTOSConfig.h中开启宏定义。
#define configUSE_MUTEXES 1 /* 1: 使能互斥信号量, 默认: 0 */
三、代码编写
3.1修改start_task的任务函数内容
start_task实现计数型信号量创建、两个任务创建、start_task任务删除。
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); /* 进入临界区 */
Mutex_Semaphore_Handle = xSemaphoreCreateMutex();//创建互斥信号量,主动式释放一次
if(Mutex_Semaphore_Handle != NULL) printf("互斥信号量创建成功\r\n");
/* 创建任务1 */
xTaskCreate((TaskFunction_t )task1,
(const char* )"task1",
(uint16_t )TASK1_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK1_PRIO,
(TaskHandle_t* )&Task1Task_Handler);
/* 创建任务2 */
xTaskCreate((TaskFunction_t )task2,
(const char* )"task2",
(uint16_t )TASK2_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK2_PRIO,
(TaskHandle_t* )&Task2Task_Handler);
/* 创建任务3 */
xTaskCreate((TaskFunction_t )task3,
(const char* )"task3",
(uint16_t )TASK3_STK_SIZE,
(void* )NULL,
(UBaseType_t )TASK3_PRIO,
(TaskHandle_t* )&Task3Task_Handler);
vTaskDelete(StartTask_Handler); /* 删除开始任务 */
taskEXIT_CRITICAL(); /* 退出临界区 */
}
3.2修改Task1的任务函数内容
Task1低优先级 获取信号量后,绝对延时3S后释放信号量。
/* task1 低优先级 获取信号量后,死延时3S后释放信号量*/
void task1(void *pvParameters)
{
while(1)
{
printf("low_task获取信号量\r\n");
xSemaphoreTake(Mutex_Semaphore_Handle,portMAX_DELAY);
printf("low_task正在运行\r\n");
delay_ms(3000);
printf("low_task释放信号量\r\n");
xSemaphoreGive(Mutex_Semaphore_Handle);
vTaskDelay(1000);//相对延时
}
}
3.3修改Task2的任务函数内容
Task2实现中优先级 打印。
/* task2 中优先级 打印 */
void task2(void *pvParameters)
{
BaseType_t err;
while(1)
{
printf("middle_task正在运行\r\n");
vTaskDelay(1000);//相对延时
}
}
3.4修改Task3的任务函数内容
Task3实现高优先级 获取信号量后,死延时1s后释放。
/* task3 高优先级 获取信号量后,绝对延时1s后释放 */
void task3(void *pvParameters)
{
BaseType_t err;
while(1)
{
printf("high_task获取信号量\r\n");
xSemaphoreTake(Mutex_Semaphore_Handle,portMAX_DELAY);
printf("high_task正在运行\r\n");
delay_ms(1000);
printf("high_task释放信号量\r\n");
xSemaphoreGive(Mutex_Semaphore_Handle);
vTaskDelay(1000);//相对延时
}
}
四、实验现象
实验现象如下所示。可以看到系统初始化显示互斥型信号量创建成功。首先高优先级的任务抢占,成功获取互斥信号量进行运行。接着中优先级任务抢占。再接着低优先级的任务抢占,并延时,此时高优先级任务抢占并获取不到信号量。
可以看到标注部分,低优先级的任务优先级继承,先于中优先级任务执行。执行完毕后高优先级任务执行。

617

被折叠的 条评论
为什么被折叠?



