【FreeRTOS操作系统教程】第21章 FreeRTOS计数信号量

标签:
fatfsfreertosstemwinstm32usb |
分类: FreeRTOS |
第21章
FreeRTOS 计数信号量
本章节开始讲解FreeRTOS任务间的同步和资源共享机制,计数信号量。FreeRTOS中计数信号量的源码实现是基于消息队列实现的。
本章教程配套的例子含Cortex-M3内核的STM32F103和Cortex-M4内核的STM32F407以及F429。
21.1 信号量
21.2 计数信号量API函数
21.3 实验例程说明(任务间通信)
21.4 实验例程说明(中断方式通信)
21.5
21.1 信号量
21.1.1 信号量的概念及其作用
信号量(semaphores)是20世纪60年代中期Edgser Dijkstra发明的。使用信号量的最初目的是为了给共享资源建立一个标志,该标志表示该共享资源被占用情况。这样,当一个任务在访问共享资源之前,就可以先对这个标志进行查询,从而在了解资源被占用的情况之后,再来决定自己的行为。
实际的应用中,信号量的作用又该如何体现呢?比如有个30人的电脑机房,我们就可以创建信号量的初始化值是30,表示30个可用资源,不理解的初学者表示信号量还有初始值?是的,信号量说白了就是共享资源的数量。另外我们要求一个同学使用一台电脑,这样每有一个同学使用一台电脑,那么信号量的数值就减一,直到30台电脑都被占用,此时信号量的数值就是0。如果此时还有几个同学没有电脑可以使用,那么这几个同学就得等待,直到有同学离开。有一个同学离开,那么信号量的数值就加1,有两个就加2,依此类推。刚才没有电脑用的同学此时就有电脑可以用了,有几个同学用,信号量就减几,直到再次没有电脑可以用,这么一个过程就是使用信号量来管理共享资源的过程。
平时使用信号量主要实现以下两个功能:
(1)两个任务之间或者中断函数跟任务之间的同步功能,这个和前面章节讲解的事件标志组是类似的。其实就是共享资源为1的时候。
(2)多个共享资源的管理,就像上面举的机房上机的例子。
针对这两种功能,FreeRTOS分别提供了二值信号量和计数信号量,其中二值信号量可以理解成计数信号量的一种特殊形式,即初始化为仅有一个资源可以使用,只不过FreeRTOS对这两种都提供了API函数,而像RTX,uCOS-II和III是仅提供了一个信号量功能,设置不同的初始值就可以分别实现二值信号量和计数信号量。当然,FreeRTOS使用计数信号量也能够实现同样的效果。
实际上信号量还有很多其它用法,而且极具挑战性,可以大大的开拓大家的视野,有兴趣的同学可以阅读一下《The Little Book Of Semaphores》,作者是Allen B. Downy。
本章节主要为大家讲解计数信号量。
21.1.2 FreeRTOS 任务间计数信号量的实现
任务间信号量的实现是指各个任务之间使用信号量实现任务的同步或者资源共享功能。下面我们通过如下的框图来说明一下FreeRTOS计数信号量的实现,让大家有一个形象的认识。
运行条件:
u
u
运行过程描述如下:
u
u
上面就是一个简单的FreeRTOS任务间计数信号量的使用过程。
21.1.3 FreeRTOS 中断方式计数信号量的实现
FreeRTOS中断方式信号量的实现是指中断函数和FreeRTOS任务之间使用信号量。信号量的中断方式主要是用于实现任务同步,与前面章节讲解事件标志组中断方式是一样的。
下面我们通过如下的框图来说明一下FreeRTOS中断方式信号量的实现,让大家有一个形象的认识。

运行条件:
u
u
运行过程描述如下:
u
u
u
上面就是一个简单的FreeRTOS中断方式信号量同步过程。实际应用中,中断方式的消息机制要注意以下四个问题:
u
u
u
u
l
l
l
l
21.2计数信号量API函数
使用如下18个函数可以实现FreeRTOS的信号量(含计数信号量,二值信号量和互斥信号):
(1)
关于这18个函数的讲解及其使用方法可以看FreeRTOS在线版手册:
这里我们重点的说以下4个函数:
(2)
(3)
(4)
因为本章节配套的例子使用的是这4个函数。
21.2.1 函数xSemaphoreCreateCounting
函数原型:
SemaphoreHandle_t
xSemaphoreCreateCounting
函数描述:
函数xSemaphoreCreateCounting
u
u
u
使用这个函数要注意以下问题:
1.
#define
xSemaphoreCreateCounting
xQueueCreateCountingSema
函数xQueueCreateCountingSema
2.
#define
configUSE_COUNTING_SEMAPHORES
使用举例:
static
SemaphoreHandle_t
static void AppObjCreate (void)
{
}
21.2.2函数xSemaphoreGive
函数原型:
xSemaphoreGive( SemaphoreHandle_t xSemaphore );
函数描述:
函数xSemaphoreGive用于在任务代码中释放信号量。
u
u
使用这个函数要注意以下问题:
1.
#define
xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, \
queueSEND_TO_BACK )
2.
3.
4.
使用举例:
static
SemaphoreHandle_t
static void vTaskTaskUserIF(void *pvParameters)
{
}
21.2.3函数xSemaphoreGiveFromISR
函数原型:
xSemaphoreGiveFromISR
函数描述:
函数xSemaphoreGiveFromISR用于中断服务程序中释放信号量。
u
u
u
使用这个函数要注意以下问题:
1.
#define
2.
3.
4.
使用举例:
static
SemaphoreHandle_t
static void TIM2_IRQHandler (void)
{
}
21.2.4函数xSemaphoreTake
函数原型:
xSemaphoreTake( SemaphoreHandle_t xSemaphore,
函数描述:
函数xSemaphoreTake用于在任务代码中获取信号量。
u
u
u
使用这个函数要注意以下问题:
1.
2.
3.
使用举例:
static
SemaphoreHandle_t
static void vTaskMsgPro(void *pvParameters)
{
}
21.3实验例程说明(任务间通信)
21.3.1STM32F103开发板实验
配套例子:
V4-319_FreeRTOS实验_计数信号量
实验目的:
1.
2.
实验内容:
1.
2.
3.
FreeRTOS的配置:
FreeRTOSConfig.h文件中的配置如下:
#if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
#endif
#define
configUSE_PREEMPTION
#define
configUSE_IDLE_HOOK
#define
configUSE_TICK_HOOK
#define
configCPU_CLOCK_HZ
#define
configTICK_RATE_HZ
#define
configMAX_PRIORITIES
#define
configMINIMAL_STACK_SIZE
#define
configTOTAL_HEAP_SIZE
#define
configMAX_TASK_NAME_LEN
#define
configUSE_TRACE_FACILITY
#define
configUSE_16_BIT_TICKS
#define
configIDLE_SHOULD_YIELD
#define
configUSE_COUNTING_SEMAPHORES
#define
configGENERATE_RUN_TIME_STATS
#define
configUSE_STATS_FORMATTING_FUNCTIONS
#define
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
#define
portGET_RUN_TIME_COUNTER_VALUE()
//#define
portALT_GET_RUN_TIME_COUNTER_VALUE
#define
configUSE_CO_ROUTINES
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
#define
INCLUDE_vTaskPrioritySet
#define
INCLUDE_uxTaskPriorityGet
#define
INCLUDE_vTaskDelete
#define
INCLUDE_vTaskCleanUpResources
#define
INCLUDE_vTaskSuspend
#define
INCLUDE_vTaskDelayUntil
#define
INCLUDE_vTaskDelay
#ifdef __NVIC_PRIO_BITS
#else
#endif
#define
configLIBRARY_LOWEST_INTERRUPT_PRIORITY
#define
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
FreeRTOS任务调试信息(按K1按键,串口打印):
上面截图中打印出来的任务状态字母B, R, D, S对应如下含义:
#define
tskBLOCKED_CHAR
#define
tskREADY_CHAR
#define
tskDELETED_CHAR
#define
tskSUSPENDED_CHAR
程序设计:
u
vTaskUserIF任务
vTaskLED任务
vTaskMsgPro任务 :2048字节
vTaskStart任务
任务栈空间是在任务创建的时候从FreeRTOSConfig.h文件中定义的heap空间中申请的
#define
configTOTAL_HEAP_SIZE
u
u
int main(void)
{
}
u
硬件外设的初始化是在bsp.c文件实现:
void bsp_Init(void)
{
}
u
static void AppTaskCreate (void)
{
}
u
static void AppObjCreate (void)
{
}
u
static void vTaskTaskUserIF(void *pvParameters)
{
}
static void vTaskLED(void *pvParameters)
{
}
static void vTaskMsgPro(void *pvParameters)
{
}
static void vTaskStart(void *pvParameters)
{
}