介绍互斥信号量所用到的函数

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();
 }

总结

优先级翻转问题与优先级继承这个概念一定要理解清楚。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐