优先级翻转
互斥信号量概念及其应用
一、解决优先级翻转的问题
当高优先级任务去剥夺了低优先级任务的cpu使用权时,信号量如果被低优先级任务占有,高优先级任务处于阻塞态,临时提高低优先级任务的优先级。——互斥信号量的第一个特性
二值信号量一般用于信号同步
二值信号量主要做一些信号同步,任何一个任务都可以发送二值信号量,同时解除一个等待获取的任务的阻塞状态。1,只适合用于同步,2、二值信号量不是单个任务独有。
任务独占资源
互斥信号量的两个特性:
1、优先级继承
2、任务独占资源(这个资源是指什么资源?CPU使用权?)
FreeRTOS互斥信号量
mutex:常规信号量 ——隐患:会死锁
recursivemutex:递归的互斥信号量:解决死锁。
互斥信号量工作原理
递归互斥信号量解决死锁问题
普通互斥信号量锁死问题:当第一次使用互斥信号量的时候,如果再次使用互斥信号量,就相当于函数把自己挂起。互斥信号量只能在自己的任务中被使用被释放。调用两次就会一直处于阻塞状态。
递归互斥信号量解决死锁问题
互斥信号量函数应用
实验解决优先级翻转
功能需求:
API详解
xSemaphoreCreateMutex()
xSemaphoreGetMutexHolder()
递归互斥信号量函数应用
死锁现象:
2、API
xSemaphoreCreateRecursiveMutex()
xSemaphoreTakeRecursive()
xSemaphoreGiveRecursive()
实验验证()
使能USE_RECURSIVE_UTEXES()
创建递归信号量
高优先级任务
void High_Task(void const * argument)
{
/* USER CODE BEGIN High_Task */
/* Infinite loop */
for(;;)
{
printf("High Task Take RecursiveMutex1\r\n");
if(xSemaphoreTakeRecursive(myRecursiveMutexHandle,portMAX_DELAY) == pdPASS){
printf("High Task is Runing\r\n");
}
printf("High Task Take RecursiveMutex2\r\n");
if(xSemaphoreTakeRecursive(myRecursiveMutexHandle,portMAX_DELAY) == pdPASS){
printf("High Task is Runing\r\n");
}
printf("High Task Give RecursiveMutex1\r\n");
xSemaphoreGiveRecursive(myRecursiveMutexHandle);
printf("High Task Give RecursiveMutex2\r\n");
xSemaphoreGiveRecursive(myRecursiveMutexHandle);
osDelay(500);
}
/* USER CODE END High_Task */
}
中等优先级任务
void Led_Task(void const * argument)
{
/* USER CODE BEGIN Led_Task */
/* Infinite loop */
for(;;)
{
printf("Normal Task is Runing\r\n");
osDelay(500);//1ms时基
}
/* USER CODE END Led_Task */
}
低优先级任务
void Delay_Task(void const * argument)
{
/* USER CODE BEGIN Delay_Task */
uint32_t i;
/* Infinite loop */
for(;;)
{
printf("Low Task Take RecursiveMutex\r\n");
if(xSemaphoreTakeRecursive(myRecursiveMutexHandle,portMAX_DELAY) == pdPASS){
printf("Low Task is Runing\r\n");
}
for(i=0;i<2000000;i++){
taskYIELD();
}
printf("Low Task Give RecursiveMutex\r\n");
xSemaphoreGiveRecursive(myRecursiveMutexHandle);
osDelay(500);
}
/* USER CODE END Delay_Task */
}
互斥信号量的原理
互斥信号量的创建
互斥信号量初始化
#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
#define xSemaphoreCreateMutex()
xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
#endif
QueueHandle_t xQueueCreateMutex( const uint8_t ucQueueType )
{
Queue_t *pxNewQueue;
const UBaseType_t uxMutexLength = ( UBaseType_t ) 1, uxMutexSize = ( UBaseType_t ) 0;
//创建消息队列
/*
队列长度:1
队列大小:0
队列类型:queueQUEUE_TYPE_MUTEX
*/
pxNewQueue = ( Queue_t * ) xQueueGenericCreate( uxMutexLength, uxMutexSize, ucQueueType );
//初始化互斥信号量->其实就是初始化消息队列的控制块
prvInitialiseMutex( pxNewQueue );