/*
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 */
网友评论