FreeRTOS总结
前言
信号量是操作系统中重要的一部分,信号量一般用来进行资源管理和任务同步,FreeRTOS
中信号量又分为二值信号量、计数型信号量、互斥信号量和递归互斥信号量。
所有的信号量都是使用队列来实现的
提示:以下是本篇文章正文内容,下面案例可供参考
一、信号量简介
**1.**信号量常常用于控制对共享资源的访问和任务同步。
eg、某个停车场有
100 个停车位,这 100 个停车位大家都可以用,对于大家来说这 100 个停车位就是共享资源。
假设现在这个停车场正常运行,你要把车停到这个这个停车场肯定要先看一下现在停了多少车
了?还有没有停车位?当前停车数量就是一个信号量,具体的停车数量就是这个信号量值,当
这个值到 100 的时候说明停车场满了。停车场满的时你可以等一会看看有没有其他的车开出停
车场,当有车开出停车场的时候停车数量就会减一,也就是说信号量减一,此时你就可以把车
停进去了,你把车停进去以后停车数量就会加一,也就是信号量加一。这就是一个典型的使用
信号量进行共享资源管理的案例,在这个案例中使用的就是计数型信号量。
信号量用于控制共享资源访问的场景相当于一个上锁机制,代码只有获得了这个锁的钥匙
才能够执行。
**2、**信号量的另一个重要的应用场合就是任务同步,用于任务与任务或中断与任务之间的同步。
在执行中断服务函数的时候可以通过向任务
发送信号量来通知任务它所期待的事件发生了,当退出中断服务函数以后在任务调度器的调度
下同步的任务就会执行。在编写中断服务函数的时候我们都知道一定要快进快出,中断服务函
数里面不能放太多的代码,否则的话会影响的中断的实时性。
二、二值信号量
1.简介
二值信号量通常用于互斥访问或同步,二值信号量和互斥信号量非常类似,但是还是有一
些细微的差别,互斥信号量拥有优先级继承机制,二值信号量没有优先级继承。因此二值信号
另更适合用于同步(任务与任务或任务与中断的同步),而互斥信号量适合用于简单的互斥访问。
和队列一样,信号量 API 函数允许设置一个阻塞时间,阻塞时间是当任务获取信号量的时候由于信号量无效从而导致任务进入阻塞态的最大时钟节拍数。如果多个任务同时阻塞在同一一个信号量上的话那么优先级最高的哪个任务优先获得信号量,这样当信号量有效的时候高优先级的任务就会解除阻塞状态。
二值信号量其实就是一个只有一个队列项的队列,这个特殊的队列要么是满的,要么是空的。
2.二值信号量的使用
1.创建二值信号量
vSemaphoreCreateBinary ()
动态创建 二 值 信 号 量 , 这 个 是 老 版 本
FreeRTOS 中使用的创建二值信号量的 API 函
数。(已经不使用了)
xSemaphoreCreateBinary()
动态创建二值信号量,新版 FreeRTOS 使用此
函数创建二值信号量。
xSemaphoreCreateBinaryStatic() 静态创建二值信号量。
函数xSemaphoreCreateBinary()
使用此函数创建二值信号量的话信号量所需要的 RAM 是由 FreeRTOS 的内存管理部分来动态分配的。此函数创建好的二值信号量默认是空的,也就是说刚创建好的二值信号量使用函数 xSemaphoreTake()是获取不到的
SemaphoreHandle_t xSemaphoreCreateBinary( void )
返回值
NULL:二值信号量创建失败
其他值:创建成功的二值信号量的句柄
2、释放二值信号量
xSemaphoreGive() 任务级信号量释放函数
xQueueGiveFromISR()。中断级信号量释放函数
1、函数 xSemaphoreGive()
此函数用于释放二值信号量、技术型信号量或互斥信号量
阻塞时间为 0(宏 semGIVE_BLOCK_TIME 为 0),入队方式采用的后向入队。
BaseType_t xSemaphoreGive( xSemaphore )
参数:
xSemaphore:要释放的信号量句柄。
返回值:
pdPASS: 释放信号量成功。
errQUEUE_FULL: 释放信号量失败。
2、函数 xSemaphoreGiveFromISR()
此函数用于在中断中释放信号量,此函数只能用来释放二值信号量和计数型信号量,绝对不能用来在中断服务函数中释放互斥信号量!
BaseType_t xSemaphoreGiveFromISR( SemaphoreHandle_t xSemaphore,
BaseType_t * pxHigherPriorityTaskWoken)
参数:
xSemaphore: 要释放的信号量句柄。
pxHigherPriorityTaskWoken: 标记退出此函数以后是否进行任务切换,这个变量的值由这
三个函数来设置的,用户不用进行设置,用户只需要提供一
个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退
出中断服务函数之前一定要进行一次任务切换。
返回值:
pdPASS: 释放信号量成功。
errQUEUE_FULL: 释放信号量失败。
3、获取信号量
xSemaphoreTake() 任务级获取信号量函数
xSemaphoreTakeFromISR() 中断级获取信号量函数
同释放信号量的 API 函数一样,不管是二值信号量、计数型信号量还是互斥信号量,它们都使用以上两个函数获取信号量。
1、函数xSemaphoreTake()
此函数用于获取二值信号量、计数型信号量或互斥信号量
BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore,
TickType_t xBlockTime)
参数:xSemaphore:要获取的信号量句柄。
xBlockTime: 阻塞时间。
返回值:
pdTRUE: 获取信号量成功。
pdFALSE: 超时,获取信号量失败。
2、函数 xSemaphoreTakeFromISR ()
此函数用于在中断服务函数中获取信号量,此函数用于获取二值信号量和计数型信号量,
绝 对 不 能 使 用 此 函 数 来 获 取 互 斥 信 号 量 ! 此 函 数 是 一 个 宏 , 真 正 执 行 的 是 函 数
xQueueReceiveFromISR (),此函数原型如下:
BaseType_t xSemaphoreTakeFromISR(SemaphoreHandle_t xSemaphore,
BaseType_t * pxHigherPriorityTaskWoken)
参数:
xSemaphore: 要获取的信号量句柄。
pxHigherPriorityTaskWoken: 标记退出此函数以后是否进行任务切换,这个变量的值由这
三个函数来设置的,用户不用进行设置,用户只需要提供一
个变量来保存这个值就行了。当此值为 pdTRUE 的时候在退
出中断服务函数之前一定要进行一次任务切换。
返回值:
pdPASS: 获取信号量成功。
pdFALSE: 获取信号量失败。
三、二值信号量实验
总结
信号量很重要,今天学的只是一小部分,继续加油!