美文网首页
semphr.h文件

semphr.h文件

作者: huojusan | 来源:发表于2019-07-30 19:43 被阅读0次
    /*
        FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
        All rights reserved
    */
    
    #ifndef SEMAPHORE_H
    #define SEMAPHORE_H
    
    #ifndef INC_FREERTOS_H
        #error "include FreeRTOS.h" must appear in source files before "include semphr.h"
    #endif
    
    #include "queue.h"
    
    typedef QueueHandle_t SemaphoreHandle_t;
    
    #define semBINARY_SEMAPHORE_QUEUE_LENGTH    ( ( uint8_t ) 1U )
    #define semSEMAPHORE_QUEUE_ITEM_LENGTH      ( ( uint8_t ) 0U )
    #define semGIVE_BLOCK_TIME                  ( ( TickType_t ) 0U )
    //----------------------------------------------------------------------------------
    /** 创建二值信号量(有参,传递句柄)
     * <pre>vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )</pre>
    
     * 用法例程:
    
     SemaphoreHandle_t xSemaphore = NULL;
    
     void vATask( void * pvParameters ) //任务函数入口
     {
        // 调用vSemaphoreCreateBinary ()之前,信号量无法使用
        // 这是一个宏,所以直接传入变量。
        vSemaphoreCreateBinary( xSemaphore );
    
        if( xSemaphore != NULL )
        {
            // 成功创建了信号量。
            // 现在可以使用信号量了。
        }
     }
     </pre>
     * \defgroup 创建二值信号量的API
     * \ingroup Semaphores
     */
    #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
        #define vSemaphoreCreateBinary( xSemaphore )                                                                                            \
            {                                                                                                                                   \
                ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE );    \
                if( ( xSemaphore ) != NULL )                                                                                                    \
                {                                                                                                                               \
                    ( void ) xSemaphoreGive( ( xSemaphore ) );                                                                                  \
                }                                                                                                                               \
            }
    #endif
    
    /** 创建二值信号量(无参,返回句柄)
     * SemaphoreHandle_t xSemaphoreCreateBinary( void )
    
     * Example usage:
    
     SemaphoreHandle_t xSemaphore = NULL;
    
     void vATask( void * pvParameters )
     {
        // 调用xSemaphoreCreateBinary()之前,信号量无法使用
        // 这是一个宏,所以直接传入变量。
        xSemaphore = xSemaphoreCreateBinary();
    
        if( xSemaphore != NULL )
        {
            // 成功创建了信号量。
            // 现在可以使用信号量了。
        }
     }
     * 这种类型的信号量可以用于任务或在中断和任务之间。
     */
    #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
        #define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE )
    #endif
    
    /**
     * SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )
     * 静态创建一个新的二进制信号量实例,并返回一个句柄可以引用新的信号量。
     * 
     * Example usage:
     <pre>
     SemaphoreHandle_t xSemaphore = NULL;
     StaticSemaphore_t xSemaphoreBuffer;
    
     void vATask( void * pvParameters )
     {
        // 调用xSemaphoreCreateBinary()之前信号量无法使用
        // 信号量的数据结构将放在变量xSemaphoreBuffer中,它的地址被传递到函数中。
        // 函数的参数不是NULL,因此函数不会尝试任何值动态内存分配,因此函数不会返回。
        
        xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer );
    
        // 其余的任务代码放在这里。
     }
     */
    #if( configSUPPORT_STATIC_ALLOCATION == 1 )
        #define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE )
    #endif /* configSUPPORT_STATIC_ALLOCATION */
    
    
    
    /**  在中断中获取一个信号量
     xSemaphoreTakeFromISR(
                              SemaphoreHandle_t xSemaphore,
                              BaseType_t *pxHigherPriorityTaskWoken
                          )
     *
     * 信号量必须是通过调用xsemaphorestatebinary()或xSemaphoreCreateCounting ()创建的。
     * 这个宏可以从ISR中使用,但是要从ISR中获取信号量,并不是常见的操作。互斥信号量不能在中断中使用!!!!
     *
     * @param xSemaphore 信号量句柄,这是创建信号量时返回的句柄。
     *
     * @param pxHigherPriorityTaskWoken :
     * xSemaphoreTakeFromISR()将把*pxHigherPriorityTaskWoken设置为pdTRUE,如果接收信号量导致任务解阻塞,并且解阻塞任务的优先级高于当前正在运行的任务。
     * 如果xSemaphoreTakeFromISR()将这个值设置为pdTRUE,那么应该在中断退出之前请求上下文切换。
     *
     */
    #define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken )  xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) )
    
    
    
    /** 创建互斥信号量
     * SemaphoreHandle_t xSemaphoreCreateMutex( void )  //创建一个新的互斥类型信号量实例,并返回新的互斥量句柄。
     *
     * 在FreeRTOS实现内部,互斥信号量使用一个互斥体结构存储在其中的块内存, 如果使用xsemaphoreatemutex()创建互斥对象,则在xsemaphoreatemutex()函数中会动态分配自动生成所需的内存
     * 如果使用xsemaphoreatemutexstatic()创建互斥对象,那么应用程序编写器必须提供内存。 因此,xsemaphoreatemutexstatic()允许在不使用任何动态内存分配的情况下创建互斥体。
     *
     * 使用这个函数创建的互斥对象可以使用xSemaphoreTake()和xSemaphoreGive()宏访问。 
     * 不能使用xSemaphoreTakeRecursive()和xSemaphoreGiveRecursive()宏。
     * 
     * 这种类型的信号量使用优先级继承机制,因此当不再需要信号量时,“获取take”该信号量的任务必须始终“释放give”该信号量。
     * 互斥类型信号量不能从中断服务例程中使用。
     *
     * Example usage:
    
     SemaphoreHandle_t xSemaphore;
    
     void vATask( void * pvParameters )
     {
        // 在调用xsemaphoreatemutex()之前,不能使用信号量。
        // 这是一个宏,所以直接传入变量。
        xSemaphore = xSemaphoreCreateMutex();
    
        if( xSemaphore != NULL )
        {
            // 成功创建了信号量。
            // 现在可以使用信号量了。
        }
     }
     */
    #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
        #define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX )
    #endif
    
    /**
     * 创建静态互斥信号量
     * SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )
     *
     * 创建一个新的互斥锁类型信号量实例,并返回一个句柄,通过该句柄可以引用新的互斥锁。
     *
     * 使用这个函数创建的互斥对象可以使用xSemaphoreTake()和xSemaphoreGive()宏访问。不能使用xSemaphoreTakeRecursive()和xSemaphoreGiveRecursive()宏。 
     * 这种类型的信号量使用优先级继承机制,因此当不再需要信号量时,“接收”该信号量的任务必须始终“返回”该信号量。
     *
     * 互斥类型信号量不能从中断服务例程中使用。
     *
     * Example usage:
    
     SemaphoreHandle_t xSemaphore;
     StaticSemaphore_t xMutexBuffer;
    
     void vATask( void * pvParameters )
     {
        // 互斥体在创建之前不能使用。静态创建不尝试动态内存分配。
        xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer );
    
        // 由于没有执行动态内存分配,xSemaphore不能为空,
        // 所以没有必要检查它。
     }
    
     */
     #if( configSUPPORT_STATIC_ALLOCATION == 1 )
        #define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) )
    #endif /* configSUPPORT_STATIC_ALLOCATION */
    
    
    /**创建动态递归互斥信号量
     * SemaphoreHandle_t  xSemaphoreCreateRecursiveMutex( void )
     *
     * 创建一个新的递归互斥锁类型信号量实例,并返回一个句柄,通过该句柄可以引用新的递归互斥锁。
     *
     * 使用这个宏创建的互斥对象可以使用xSemaphoreTakeRecursive()和xSemaphoreGiveRecursive()宏访问。  
     * 不能使用xSemaphoreTake()和xSemaphoreGive()宏。
     *
     * 递归使用的互斥量可以由所有者反复“获取”。直到所有者为每个成功的“take”请求调用xSemaphoreGiveRecursive(),互斥量才会再次可用。
     * 例如,如果一个任务成功地“接受”了5次相同的互斥锁,那么这个互斥锁将不会对任何其他任务可用,直到它也恰好“给出”了5次互斥锁。
     *
     * 这种类型的信号量使用优先级继承机制,所以是任务“获取”一个信号量必须始终“返回”该信号量,一旦该信号量不再是必需的。
     *
     * 互斥类型信号量不能从中断服务例程中使用。
     *
     * Example usage:
    
     SemaphoreHandle_t xSemaphore;
    
     void vATask( void * pvParameters )
     {
        // 在调用xsemaphoreatemutex()之前,不能使用信号量。
        xSemaphore = xSemaphoreCreateRecursiveMutex();
    
        if( xSemaphore != NULL )
        {
            // 成功创建了信号量。现在可以使用信号量了。
        }
     }
     */
    #if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
        #define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX )
    #endif
    
    
    /**创建静态递归互斥信号量
     * SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )
     *
     * 创建一个新的递归互斥锁类型信号量实例,并返回一个句柄,通过该句柄可以引用新的递归互斥锁。
     *
     * 使用这个宏创建的互斥对象可以使用xSemaphoreTakeRecursive()和xSemaphoreGiveRecursive()宏访问。
     * 不能使用xSemaphoreTake()和xSemaphoreGive()宏。
     * 
     * 这种类型的信号量使用优先级继承机制,因此当不再需要信号量时,“接收take”该信号量的任务必须始终“返回give”该信号量。
     *
     * Example usage:
    
     SemaphoreHandle_t xSemaphore;
     StaticSemaphore_t xMutexBuffer;
    
     void vATask( void * pvParameters )
     {
        // 这里使用xsemaphoreaterecursivemutexstatic()创建递归互斥量。
        // xMutexBuffer的地址被传递到函数中,并保存互斥数据结构——因此不会尝试动态内存分配。
        xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer );
    
        // 由于没有执行动态内存分配,xSemaphore不能为空,不需要检测。
     }
     */
    #if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) )
        #define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore )
    #endif /* configSUPPORT_STATIC_ALLOCATION */
    
    
    
    /** 创建计数信号量。
     * SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )
     *
     * 创建一个新的计数信号量实例,并返回一个句柄,通过该句柄可以引用新的计数信号量。
     *
     * 在许多使用场景中,使用直接到任务的通知代替计数信号量会更快、更节省内存
     *
     * 计数信号量通常用于两种情况:
     *
     * 1) 事件计数
     *
     * 在这个使用场景中,事件处理程序将在每次事件发生时“给出give”一个信号量(增加信号量计数值),
     * 而处理程序任务将在每次处理事件时“接受take”一个信号量(减少信号量计数值)。
     * 因此,count值是已发生的事件数与已处理的事件数之间的差值。在这种情况下,希望初始计数值为零。 
     *
     * 2) 资源管理
     *
     * 在这个使用场景中,count值指示可用资源的数量。要获得对资源的控制,任务必须首先获得一个信号量——减少信号量计数值。
     * 当计数值为零时,没有空闲资源。当任务使用资源完成时,它“返回give”信号量——增加信号量计数值。
     * 在这种情况下,希望初始计数值等于最大计数值,表示所有资源都是空闲的。
     *
     * @param uxMaxCount 可以达到的最大计数值。当信号量达到这个值时,它就不能再被“给定give”了。
     *
     * @param uxInitialCount 创建信号量时分配给它的计数值。
     *
     * Example usage:
    
     SemaphoreHandle_t xSemaphore;
    
     void vATask( void * pvParameters )
     {
        SemaphoreHandle_t xSemaphore = NULL;
    
        // 在调用xsemaphoatecounting()之前,不能使用信号量。
        // 信号量可以计数的最大值应该是10,分配给计数的初始值应该是0。
        xSemaphore = xSemaphoreCreateCounting( 10, 0 );
    
        if( xSemaphore != NULL )
        {
            // 成功创建了信号量。现在可以使用信号量了。
        }
     }
     */
    #if( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
        #define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) )
    #endif
    
    
    
    /** 创建计数静态信号量。
     * SemaphoreHandle_t  xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer )
     *
     * 创建一个新的计数信号量实例,并返回一个句柄,通过该句柄可以引用新的计数信号量。
     *
     * 在许多使用场景中,使用直接到任务的通知代替计数信号量会更快、更节省内存!
    
     * 计数信号量通常用于两种情况:
     *
     * 1) 事件计数
     *
     *    在这个使用场景中,事件处理程序将在每次事件发生时“给出”一个信号量(增加信号量计数值),而处理程序任务将在每次处理事件时“接受”一个信号量(减少信号量计数值)。
     *    因此,count值是已发生的事件数与已处理的事件数之间的差值。在这种情况下,希望初始计数值为零。
     *     
     * 2) 资源管理。
     *
     *    在这个使用场景中,count值指示可用资源的数量。要获得对资源的控制,任务必须首先获得一个信号量 ———— 减少信号量计数值。
     *    要获得对资源的控制,任务必须首先获得一个信号量——减少信号量计数值。
     *    当计数值为零时,没有空闲资源。当任务使用资源完成时,它“give”信号量 ———— 增加信号量计数值。
     *    在这种情况下,希望初始计数值等于最大计数值,表示所有资源都是空闲的。
     *
     * @param uxMaxCount 可以达到的最大计数值。当信号量达到这个值时,它就不能再被“给定”了。
     *
     * @param uxInitialCount 创建信号量时分配给它的计数值。
     *
     * @param pxSemaphoreBuffer 必须指向StaticSemaphore_t类型的变量,然后该变量将用于保存信号量的数据结构,从而消除动态分配内存的需要。
     *
     * @return 如果成功创建了计数信号量,则返回创建的计数信号量的句柄。如果pxSemaphoreBuffer为NULL,则返回NULL。
     *
     * Example usage:
    
    
     SemaphoreHandle_t xSemaphore;
     StaticSemaphore_t xSemaphoreBuffer;
    
     void vATask( void * pvParameters )
     {
        SemaphoreHandle_t xSemaphore = NULL;
    
        // 在创建信号量之前不能使用计数信号量。由xSemaphoreCreateCountingStatic()创建计数信号量。
        // 信号量可以计数的最大值为10,而分配给该计数的初始值为0。 传入xSemaphoreBuffer的地址,并将用于保存信号量结构,因此不会使用动态内存分配。
        xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer );
    
        // 没有尝试内存分配,因此xSemaphore不能为空,不需要检查它的值。
     }
     */
    #if( configSUPPORT_STATIC_ALLOCATION == 1 )
        #define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) )
    #endif /* configSUPPORT_STATIC_ALLOCATION */
    
    
    
    /**
     * 删除一个信号量。这个函数必须小心使用。例如,如果互斥对象由任务持有,则不要删除互斥对象类型信号量。
     *
     * @param xSemaphore 要删除的信号量的句柄。
     */
    #define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) )
    
    
    
    /**
     * TaskHandle_t  xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );
     *
     * 如果xMutex确实是一个互斥锁类型信号量,返回当前互斥锁持有者。
     * 如果xMutex不是互斥锁类型信号量,或者互斥锁可用(不是由任务持有),则返回NULL。
     *
     * 注意:这是确定调用任务是否是互斥锁持有者的好方法,但不是确定互斥锁持有者身份的好方法,因为持有者可能在函数退出和测试返回值之间发生变化。
     */
    #define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) )
    
    
    /**
     * UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore ); //返回信号量当前的计数值
     *
     * 如果信号量是一个计数信号量,那么uxSemaphoreGetCount()返回它的当前计数值。
     * 如果信号量是二进制信号量,那么uxSemaphoreGetCount()在信号量可用时返回1,在信号量不可用时返回0。
     */
    #define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) )
    
    #endif /* SEMAPHORE_H */
    

    相关文章

      网友评论

          本文标题:semphr.h文件

          本文链接:https://www.haomeiwen.com/subject/uubgrctx.html