介绍互斥信号量所用到的函数
1.互斥量创建函数
xSemaphoreCreateMutex()
功能:互斥量创建函数
参 数:void 无
返回值:返回一个互斥量句柄
2.互斥量获取函数
xSemaphoreTake( xSemaphore, xBlockTime )
参数:
xSemaphore:互斥量句柄
xBlockTime :
portMAX_DELAY 没有申请到资源阻塞,
0 申请到立马返回
3.互斥量释放函数
xSemaphoreGive( xSemaphore )
参数:
xSemaphore :互斥量句柄
4.模拟优先级翻转代码
模拟优先级翻转实验是在 FreeRTOS 中创建了三个任务与一个二值信号量,任务分别是高优先级任务,中优先级任务,低优先级任务, 用于模拟产生优先级翻转。
低优先级任 务在获取信号量的时候,被中优先级打断,中优先级的任务执行时间较长,因为低优先级还未释放信号量,那么高优先级任务就无法取得信号量继续运行,此时就发生了优先级翻 转,
#include "main.h"
static TaskHandle_t AppTaskCreate_Handle = NULL;/* 创建任务句柄 */
static TaskHandle_t LowPriority_Task_Handle = NULL;/* LowPriority_Task 任务句柄 */
static TaskHandle_t MidPriority_Task_Handle = NULL;/* MidPriority_Task 任务句柄 */
static TaskHandle_t HighPriority_Task_Handle = NULL;/* HighPriority_Task 任务句柄 */
SemaphoreHandle_t BinarySem_Handle =NULL;
static void AppTaskCreate(void);/* 用于创建任务 */
static void LowPriority_Task(void* pvParameters);/* LowPriority_Task 任务实现 */
static void MidPriority_Task(void* pvParameters);/* MidPriority_Task 任务实现 */
static void HighPriority_Task(void* pvParameters);/* MidPriority_Task 任务实现 */
static void BSP_Init(void);/* 用于初始化板载相关资源 */
int main(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
BSP_Init(); /* 开发板硬件初始化 */
printf("优先级翻转实验! \n");
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;
}
static void AppTaskCreate(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
taskENTER_CRITICAL(); //进入临界区
BinarySem_Handle = xSemaphoreCreateBinary();
if (NULL != BinarySem_Handle )
printf("BinarySem_Handle 二值信号量创建成功!\r\n");
xReturn = xSemaphoreGive( BinarySem_Handle );//给出二值信号量
/* 创建 LowPriority_Task 任务 */
xReturn = xTaskCreate((TaskFunction_t )LowPriority_Task, /* 任务入口函数 */
(const char* )"LowPriority_Task",/*任务名字 */
(uint16_t )512, /* 任务栈大小 */
(void* )NULL, /* 任务入口函数参数 */
(UBaseType_t )2, /* 任务的优先级 */
(TaskHandle_t* )&LowPriority_Task_Handle);/* 任务控制块指针 */
if (pdPASS == xReturn)
printf("创建 LowPriority_Task 任务成功!\r\n");
/* 创建 MidPriority_Task 任务 */
xReturn = xTaskCreate((TaskFunction_t )MidPriority_Task, /* 任务入口函数 */
(const char* )"MidPriority_Task",/*任务名字 */
(uint16_t )512, /* 任务栈大小 */
(void* )NULL,/* 任务入口函数参数 */
(UBaseType_t )3, /* 任务的优先级 */
(TaskHandle_t* )&MidPriority_Task_Handle);/* 任务控制块指针 */
if (pdPASS == xReturn)
printf("创建 MidPriority_Task 任务成功!\n");
/* 创建 HighPriority_Task 任务 */
xReturn = xTaskCreate((TaskFunction_t )HighPriority_Task, /* 任务入口函数 */
(const char* )"HighPriority_Task",/* 任务名字 */
(uint16_t )512, /* 任务栈大小 */
(void* )NULL,/* 任务入口函数参数 */
(UBaseType_t )4, /* 任务的优先级 */
(TaskHandle_t* )&HighPriority_Task_Handle);/*任务控制块指针 */
if (pdPASS == xReturn)
printf("创建 HighPriority_Task 任务成功!\n\n");
vTaskDelete(AppTaskCreate_Handle); //删除 AppTaskCreate 任务
taskEXIT_CRITICAL(); //退出临界区
}
static void LowPriority_Task(void* parameter)
{
static uint32_t i;
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
while (1) {
printf("LowPriority_Task 获取信号量\n");
//获取二值信号量 xSemaphore,没获取到则一直等待
xReturn = xSemaphoreTake(BinarySem_Handle,/* 二值信号量句柄 */
portMAX_DELAY); /* 等待时间 */
if (pdTRUE == xReturn)
printf("LowPriority_Task Runing\n\n");
for (i=0; i<2000000; i++) //模拟低优先级任务占用互斥量
{
taskYIELD();//发起任务调度
}
printf("LowPriority_Task 释放信号量!\r\n");
xReturn = xSemaphoreGive( BinarySem_Handle);//给出二值信号量
LED1_TOGGLE;
vTaskDelay(1000);
}
}
static void MidPriority_Task(void* parameter)
{
while (1)
{
printf("MidPriority_Task Runing\n");
vTaskDelay(1000);
}
}
static void HighPriority_Task(void* parameter)
{
BaseType_t xReturn = pdTRUE;/* 定义一个创建信息返回值,默认为 pdPASS */
while (1)
{
printf("HighPriority_Task 获取信号量\n");
//获取互斥量 MuxSem,没获取到则一直等待
xReturn = xSemaphoreTake(BinarySem_Handle,/* 二值信号量句柄 */
portMAX_DELAY); /* 等待时间 */
if (pdTRUE == xReturn)
printf("HighPriority_Task Runing\n");
LED1_TOGGLE;
printf("HighPriority_Task 释放信号量!\r\n");
xReturn = xSemaphoreGive( BinarySem_Handle);//给出二值信号量
vTaskDelay(1000);
}
}
static void BSP_Init(void)
{
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
LED_GPIO_Config();
USART_Config();
Key_GPIO_Config();
}
5.互斥量代码
互斥量实验是基于优先级翻转实验进行修改的,目的是为了测试互斥量的优先级继承机制是否有效
#include "main.h"
static TaskHandle_t AppTaskCreate_Handle = NULL;/* 创建任务句柄 */
static TaskHandle_t LowPriority_Task_Handle = NULL;/* LowPriority_Task 任务句柄 */
static TaskHandle_t MidPriority_Task_Handle = NULL;/* MidPriority_Task 任务句柄 */
static TaskHandle_t HighPriority_Task_Handle = NULL;/* HighPriority_Task 任务句柄 */
SemaphoreHandle_t MuxSem_Handle =NULL;
static void AppTaskCreate(void);/* 用于创建任务 */
static void LowPriority_Task(void* pvParameters);/* LowPriority_Task 任务实现 */
static void MidPriority_Task(void* pvParameters);/* MidPriority_Task 任务实现 */
static void HighPriority_Task(void* pvParameters);/* MidPriority_Task 任务实现 */
static void BSP_Init(void);/* 用于初始化板载相关资源 */
int main(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
BSP_Init(); /* 开发板硬件初始化 */
printf("互斥信号量实验! \n");
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;
}
static void AppTaskCreate(void)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
taskENTER_CRITICAL(); //进入临界区
MuxSem_Handle = xSemaphoreCreateMutex();
if (NULL != MuxSem_Handle)
printf("MuxSem_Handle 互斥量创建成功!\r\n");
xReturn = xSemaphoreGive( MuxSem_Handle );//给出互斥量
/* 创建 LowPriority_Task 任务 */
xReturn = xTaskCreate((TaskFunction_t )LowPriority_Task, /* 任务入口函数 */
(const char* )"LowPriority_Task",/*任务名字 */
(uint16_t )512, /* 任务栈大小 */
(void* )NULL, /* 任务入口函数参数 */
(UBaseType_t )2, /* 任务的优先级 */
(TaskHandle_t* )&LowPriority_Task_Handle);/* 任务控制块指针 */
if (pdPASS == xReturn)
printf("创建 LowPriority_Task 任务成功!\r\n");
/* 创建 MidPriority_Task 任务 */
xReturn = xTaskCreate((TaskFunction_t )MidPriority_Task, /* 任务入口函数 */
(const char* )"MidPriority_Task",/*任务名字 */
(uint16_t )512, /* 任务栈大小 */
(void* )NULL,/* 任务入口函数参数 */
(UBaseType_t )3, /* 任务的优先级 */
(TaskHandle_t* )&MidPriority_Task_Handle);/* 任务控制块指针 */
if (pdPASS == xReturn)
printf("创建 MidPriority_Task 任务成功!\n");
/* 创建 HighPriority_Task 任务 */
xReturn = xTaskCreate((TaskFunction_t )HighPriority_Task, /* 任务入口函数 */
(const char* )"HighPriority_Task",/* 任务名字 */
(uint16_t )512, /* 任务栈大小 */
(void* )NULL,/* 任务入口函数参数 */
(UBaseType_t )4, /* 任务的优先级 */
(TaskHandle_t* )&HighPriority_Task_Handle);/*任务控制块指针 */
if (pdPASS == xReturn)
printf("创建 HighPriority_Task 任务成功!\n\n");
vTaskDelete(AppTaskCreate_Handle); //删除 AppTaskCreate 任务
taskEXIT_CRITICAL(); //退出临界区
}
static void LowPriority_Task(void* parameter)
{
static uint32_t i;
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为 pdPASS */
while (1) {
printf("LowPriority_Task 获取信号量\n");
xReturn = xSemaphoreTake(MuxSem_Handle,/* 互斥量句柄 */
portMAX_DELAY); /* 等待时间 */
if (pdTRUE == xReturn)
printf("LowPriority_Task Runing\n\n");
for (i=0; i<2000000; i++) //模拟低优先级任务占用互斥量
{
taskYIELD();//发起任务调度
}
printf("LowPriority_Task 释放信号量!\r\n");
xReturn = xSemaphoreGive( MuxSem_Handle );//给出互斥量
LED1_TOGGLE;
vTaskDelay(1000);
}
}
static void MidPriority_Task(void* parameter)
{
while (1)
{
printf("MidPriority_Task Runing\n");
vTaskDelay(1000);
}
}
static void HighPriority_Task(void* parameter)
{
BaseType_t xReturn = pdTRUE;/* 定义一个创建信息返回值,默认为 pdPASS */
while (1)
{
printf("HighPriority_Task 获取信号量\n");
//获取互斥量 MuxSem,没获取到则一直等待
xReturn = xSemaphoreTake(MuxSem_Handle,/* 互斥量句柄 */
portMAX_DELAY); /* 等待时间 */
if (pdTRUE == xReturn)
printf("HighPriority_Task Runing\n");
LED1_TOGGLE;
printf("HighPriority_Task 释放信号量!\r\n");
xReturn = xSemaphoreGive( MuxSem_Handle );//给出互斥量
vTaskDelay(1000);
}
}
static void BSP_Init(void)
{
NVIC_PriorityGroupConfig( NVIC_PriorityGroup_4 );
LED_GPIO_Config();
USART_Config();
Key_GPIO_Config();
}
总结
优先级翻转问题与优先级继承这个概念一定要理解清楚。