发新帖我要提问
12
返回列表
打印

FreeRTOS信号量

[复制链接]
楼主: keer_zu
手机看帖
扫描二维码
随时随地手机跟帖
21
keer_zu|  楼主 | 2021-12-15 14:12 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
3.6.3  递归信号量创建过程分析
        这里只分析动态创建互斥信号量函数 xSemaphoreCreateRecursiveMutex (),此函数是个宏,
定义如下:
#define xSemaphoreCreateRecursiveMutex()
xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
可以看出,真正干事的是函数 xQueueCreateMutex(),互斥信号量的创建也是用的这个函数,
只是在创建递归互斥信号量的时候类型选择为 queueQUEUE_TYPE_RECURSIVE_MUTEX。具
体的创建过程参考 14.8.3 小节。

3.6.4  释放递归互斥信号量
        递归互斥信号量有专用的释放函数:xSemaphoreGiveRecursive(),此函数为宏,如下:
#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) )
    函 数 的 参 数 就 是 就 是 要 释 放 的 递 归 互 斥 信 号 量 , 真 正 的 释 放 是 由 函 数
    xQueueGiveMutexRecursive()来完成的,此函数代码如下:
    BaseType_t xQueueGiveMutexRecursive( QueueHandle_t xMutex )
    {
        BaseType_t xReturn;
        Queue_t * const pxMutex = ( Queue_t * ) xMutex;
                                                    configASSERT( pxMutex );
        //检查递归互斥信号量是不是被当前任务获取的,要释放递归互斥信号量的任务肯定是当
        //前正在运行的任务。 因为同互斥信号量一样,递归互斥信号量的获取和释放要在同一个
        //任务中完成!如果当前正在运行的任务不是递归互斥信号量的拥有者就不能释放!
        if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() )  (1)
        {
            traceGIVE_MUTEX_RECURSIVE( pxMutex );
        ( pxMutex->u.uxRecursiveCallCount )--;  (2)
        if( pxMutex->u.uxRecursiveCallCount == ( UBaseType_t ) 0 ) (3)
        {
            ( void ) xQueueGenericSend( pxMutex, NULL, \ (4)
            queueMUTEX_GIVE_BLOCK_TIME, queueSEND_TO_BACK );
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }
        xReturn = pdPASS; (5)
    }
    else
    {
        xReturn = pdFAIL; (6)
        traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex );
    }
    return xReturn;
}
(1)、哪个任务获取到的递归互斥信号量,哪个任务就释放!要释放递归互斥信号量的任务 肯定是当前正在运行的任务。检查这个任务是不是递归互斥信号量的拥有者,如果不是的话就 不能完成释放。
(2)、uxRecursiveCallCount 减一,uxRecursiveCallCount 用来记录递归信号量被获取的次数。 由于递归互斥信号量可以被一个任务多次获取,因此在释放的时候也要多次释放,但是只有在 最后一次释放的时候才会调用函数xQueueGenericSend()完成释放过程,其他的时候只是简单的 将 uxRecursiveCallCount 减一即可。
(3)、当 uxRecursiveCallCount 为 0 的时候说明是最后一次释放了。
(4)、如果是最后一次释放的话就调用函数 xQueueGenericSend()完成真正的释放过程。阻塞 时间是queueMUTEX_GIVE_BLOCK_TIME,宏 queueMUTEX_GIVE_BLOCK_TIME 为 0。
(5)、递归互斥信号量释放成功,返回 pdPASS。
(6)、递归互斥信号量释放未成功,返回 pdFAIL。
由于递归互斥信号量可以被一个任务重复的获取,因此在释放的时候也要释放多次,但是
只有在最后一次释放的时候才会调用函数 xQueueGenericSend()完成真正的释放。其他释放的话
只是简单的将 uxRecursiveCallCount 减一。



使用特权

评论回复
22
keer_zu|  楼主 | 2021-12-15 14:12 | 只看该作者
3.6.5  获取递归互斥信号量
        递归互斥信号量的获取使用函数 xSemaphoreTakeRecursive(),此函数是个宏,定义如下:
#define xSemaphoreTakeRecursive( xMutex, xBlockTime )
    xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) )
        函数第一个参数是要获取的递归互斥信号量句柄,第二个参数是阻塞时间。真正的获取过 程是由函数             xQueueTakeMutexRecursive()来完成的,此函数如下:
BaseType_t xQueueTakeMutexRecursive( QueueHandle_t xMutex, //要获取的信号量
                                                                TickType_t xTicksToWait )//阻塞时间
{
    BaseType_t xReturn;
    Queue_t * const pxMutex = ( Queue_t * ) xMutex;
    configASSERT( pxMutex );
    traceTAKE_MUTEX_RECURSIVE( pxMutex );
    if( pxMutex->pxMutexHolder == ( void * ) xTaskGetCurrentTaskHandle() )  (1)
    {
        ( pxMutex->u.uxRecursiveCallCount )++;  (2)
        xReturn = pdPASS;
    }
    else
    {
        xReturn = xQueueGenericReceive( pxMutex, NULL, xTicksToWait, pdFALSE );  (3)
        if( xReturn != pdFAIL )
        {
            ( pxMutex->u.uxRecursiveCallCount )++;  (4)
        }
        else
        {
            raceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex );
        }
    }
        return xReturn;
}
(1)、判断当前要获取递归互斥信号量的任务是不是已经是递归互斥信号量的拥有者。通过 这一步就可以判断出当前任务是第一次获取递归互斥信号量还是重复获取。
(2)、如果当前任务已经是递归互斥信号量的拥有者,那就说明任务已经获取了递归互斥信 号量,本次是重复获取递归互斥信号量,那么就简单的将 uxRecursiveCallCount 加一,然后返回 pdPASS 表示获取成功。
(3)、如果任务是第一次获取递归互斥信号量的话就需要调用函数 xQueueGenericReceive() 完成真正的获取过程。
(4)、第一次获取递归互斥信号量成功以后将 uxRecursiveCallCount 加一。

使用特权

评论回复
23
keer_zu|  楼主 | 2021-12-15 17:36 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则