FreeRTOS系列

您所在的位置:网站首页 递归的作用与意义 FreeRTOS系列

FreeRTOS系列

2023-12-26 08:17| 来源: 网络整理| 查看: 265

递归互斥信号量 1. 递归互斥信号量

递归互斥信号量是一种特殊的互斥信号量,已经获取了互斥信号量的任务不能再次获取这个互斥信号量,但是递归互斥信号量不同;已经获取了递归互斥信号量的任务可以再次获取这个递归互斥信号量(即可以嵌套使用),且次数不限。

递归互斥信号量也有优先级继承的问题。一个任务获取了多少次递归互斥信号量就必须释放多少次。比如,若某个任务成功获取了3次递归互斥量,那么该任务也需要同样释放3次递归信号量。同互斥信号量一样,递归互斥信号量不能用在中断服务函数中

2. 递归互斥信号量的API函数 2.1 创建递归互斥信号量 /********************动态创建递归互斥信号量**********************************************/ SemaphoreHandle_t xSemaphoreCreateRecursiveMutex(void) /********************静态创建递归互斥信号量**********************************************/ SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic(StaticSemaphore_t * pxSemaphoreBuffer) //参数:pxSemaphoreBuffer 指向一个StaticSemaphore_t类型的变量,用来保存信号量结构体 /***********************************************************************************/ 返回值:创建成功返回互斥信号量句柄;失败返回NULL

动态递归互斥信号量创建函数是一个宏,最终是通过xQueueCreateMutex()函数来完成,其源码如下:

#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) #define xSemaphoreCreateRecursiveMutex() \ xQueueCreateMutex(queueQUEUE_TYPE_RECURSIVE_MUTEX) #endif

xQueueCreateMutex函数的源码分析,可参考互斥信号量章节3.1的介绍

2.2 释放递归互斥信号量

递归互斥信号量有专门的释放函数:xSemaphoreGiveRecursive()

/********************递归互斥信号量释放*************************************/ BaseType_t xSemaphoreGiveRecursive(SemaphoreHandle_t xMutex) /************************************************************************/ 返回值:释放成功返回pdPASS;释放失败返回pdFAIL

递归互斥信号量释放函数是一个宏,最终调用xQueueGiveMutexRecursive()函数,源码如下示:

#define xSemaphoreGiveRecursive(xMutex) xQueueGiveMutexRecursive((xMutex)) /**************xQueueGiveMutexRecursive()函数*********************/ BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex ){ BaseType_t xReturn; Queue_t * const pxMutex = ( Queue_t * ) xMutex; /* 检查递归互斥信号量是不是被当前任务获取 */ if(pxMutex->pxMutexHolder == (void *)xTaskGetCurrentTaskHandle()){ ( pxMutex->u.uxRecursiveCallCount )--;//用来记录递归信号量被释放的次数 /* uxRecursiveCallCount为0时,说明是最后一次释放 */ if(pxMutex->u.uxRecursiveCallCount == (UBaseType_t) 0){ /* 此时调用xQueueGenericSend完成真正的释放 */ (void)xQueueGenericSend(pxMutex,NULL,queueMUTEX_GIVE_BLOCK_TIME,queueSEND_TO_BACK); } else{ mtCOVERAGE_TEST_MARKER(); } xReturn = pdPASS;//释放成功 } else{ xReturn = pdFAIL;//不是被当前任务获取,释放失败 } return xReturn; } 2.3 获取递归互斥信号量

递归互斥信号量有专门的获取函数:xSemaphoreTakeRecursive()

/********************递归互斥信号量获取*******************************************/ BaseType_t xSemaphoreTakeRecursive(SemaphoreHandle_t xMutex//要获取的信号量句柄 TickType_t xBlockTime)//阻塞时间 /******************************************************************************/ 返回值:获取成功返回pdPASS;释放失败返回pdFALSE

递归互斥信号量获取函数是一个宏,最终调用xQueueTakeMutexRecursive()函数,源码如下示:

#if( configUSE_RECURSIVE_MUTEXES == 1 ) #define xSemaphoreTakeRecursive( xMutex, xBlockTime ) \ xQueueTakeMutexRecursive(( xMutex ), ( xBlockTime )) #endif /**************xQueueTakeMutexRecursive()函数*********************/ BaseType_t xQueueTakeMutexRecursive(QueueHandle_t xMutex,TickType_t xTicksToWait){ BaseType_t xReturn; Queue_t * const pxMutex = ( Queue_t * ) xMutex; /* 检查当前任务是不是递归互斥信号量的拥有者 */ if(pxMutex->pxMutexHolder == (void *) xTaskGetCurrentTaskHandle()){ ( pxMutex->u.uxRecursiveCallCount )++;//若是,表示本次是重复获取信号量 xReturn = pdPASS; } else{//如果任务是第一次获取信号量,就需要调用以下函数完成真正的信号量获取 xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE ); /* 第一次获取信号量成功后,将uxRecursiveCallCount加1 */ if( xReturn != pdFAIL ){ ( pxMutex->u.uxRecursiveCallCount )++; } else{ traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ); } } return xReturn; } 3. 递归互斥信号量的应用实例

本实例介绍递归互斥信号量的使用。使用STM32CubeMX将FreeRTOS移植到工程中,创建优先级为高中低的三个任务、一个递归互斥信号量

High_Task:高优先级任务,会获取递归互斥信号量2次,获取成功后进行相应的处理,处理完后释放递归互斥信号量两次Middle_Task:中优先级任务,简单的应用任务Low_Task:低优先级任务,会获取递归互斥信号量,获取成功后进行相应的处理,处理完后释放递归互斥信号量。但是任务信号量的时间比高优先级任务占用的时间要长 3.1 STM32CubeMX设置 RCC设置外接HSE,时钟设置为72MPC0/PC1设置为GPIO推挽输出模式、上拉、高速、默认输出电平为高电平USART1选择为异步通讯方式,波特率设置为115200Bits/s,传输数据长度为8Bit,无奇偶校验,1位停止位;激活FreeRTOS,添加任务,设置任务名称、优先级、堆栈大小、函数名称等参数

在这里插入图片描述

动态创建递归互斥信号量

在这里插入图片描述

使用FreeRTOS操作系统,一定要将HAL库的Timebase Source从SysTick改为其他定时器,选好定时器后,系统会自动配置TIM输入工程名,选择路径(不要有中文),选择MDK-ARM V5;勾选Generated periphera initialization as a pair of ‘.c/.h’ files per IP ;点击GENERATE CODE,生成工程代码 3.2 MDK-ARM软件编程 添加High_Task、Middle_Task、Low_Task任务函数代码 /******************HighTask**************************/ void HighTask(void const * argument){ for(;;){ vTaskDelay(500); printf("High task take RecursiveMutex1\r\n"); xSemaphoreTakeRecursive(RecursiveMutexHandle,portMAX_DELAY); printf("High task running...!\r\n"); printf("High task take RecursiveMutex2\r\n"); xSemaphoreTakeRecursive(RecursiveMutexHandle,portMAX_DELAY); printf("High task running...!\r\n"); HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_1); printf("High task give RecursiveMutex1\r\n"); xSemaphoreGiveRecursive(RecursiveMutexHandle); printf("High task give RecursiveMutex2\r\n"); xSemaphoreGiveRecursive(RecursiveMutexHandle); vTaskDelay(500); } } /******************MiddleTask***********************/ void MiddleTask(void const * argument){ for(;;){ printf("Middle task running!\r\n"); HAL_GPIO_TogglePin(GPIOC,GPIO_PIN_0); vTaskDelay(1000); } } /******************LowTask**************************/ void LowTask(void const * argument){ for(;;){ printf("Low task take RecursiveMutex\r\n"); xSemaphoreTakeRecursive(RecursiveMutexHandle,portMAX_DELAY); printf("Low task running...!\r\n"); for(int i=0;i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3