一、二值信号量简介
二值信号量通常用于互斥访问或同步,二值信号量和互斥信号量非常类似,但是还是有一些细微的差别,互斥信号量拥有优先级继承机制,二值信号量没有优先级继承。因此二值信号另更适合用于同步(任务与任务或任务与中断的同步),而互斥信号量适合用于简单的互斥访问。和队列一样,信号量API函数允许设置一个阻塞时间,阻塞时间是当任务获取信号量的时候由于信号量无效从而导致任务进入阻塞态的最大时钟节拍数。如果多个任务同时阻塞在同一个信号量上的话那么优先级最高的那个任务优先获得信号量,这样当信号量有效的时候高优先级的任务就会解除阻塞状态。二值信号量其实就是一个只有一个队列项的队列,这个特殊的队列要么是满的,要么是空的,这不正好就是二值的吗?任务和中断使用这个特殊队列不用在乎队列中存的是什么消息,只需要知道这个队列是满的还是空的。可以利用这个机制来完成任务与中断之间的同步。在实际应用中通常会使用一个任务来处理MCU的某个外设,比如网络应用中,一般最简单的方法就是使用一个任务去轮询的查询MCU的ETH(网络相关外设,如STM32的以太网MAC)外设是否有数据,当有数据的时候就处理这个网络数据。这样使用轮询的方式是很浪费CPU资源的,而且也阻止了其他任务的运行。最理想的方法就是当没有网络数据的时候网络任务就进入阻塞态,把CPU让给其他的任务,当有数据的时候网络任务才去执行。现在使用二值信号量就可以实现这样的功能,任务通过获取信号量来判断是否有网络数据,没有的话就进入阻塞态,而网络中断服务函数(大多数的网络外设都有中断功能,比如STM32的MAC专用DMA中断,通过中断可以判断是否接收到数据)通过释放信号量来通知任务以太网外设接收到了网络数据,网络任务可以去提取处理了。网络任务只是在一直的获取二值信号量,它不会释放信号量,而中断服务函数是一直在释放信号量,它不会获取信号量。在中断服务函数中发送信号量可以使用函数xSemaphoreGiveFromISR(),也可以使用任务通知功能来替代二值信号量,而且使用任务通知的话速度更快,代码量更少。使用二值信号量来完成中断与任务同步的这个机制中,任务优先级确保了外设能够得到及时的处理,这样做相当于推迟了中断处理过程。也可以使用队列来替代二值信号量,在外设事件的中断服务函数中获取相关数据,并将相关的数据通过队列发送给任务。如果队列无效的话任务就进入阻塞态,直至队列中有数据,任务接收到数据以后就开始相关的处理过程。下面几
个步骤演示了二值信号量的工作过程。
1、二值信号量无效

在上图中任务Task通过函数xSemaphoreTake()获取信号量,但是此时二值信号量无效,所以任务Task进入阻塞态。
2、中断释放信号量

此时中断发生了,在中断服务函数中通过函数xSemaphoreGiveFromISR()释放信号量,因此信号量变为有效。
3、任务获取信号量成功

本文详细介绍了FreeRTOS中的二值信号量,包括其工作原理、用途及与互斥信号量的区别。二值信号量常用于任务与中断同步,通过获取和释放操作实现任务调度。创建、释放、获取信号量的API函数也在文中逐一解析,帮助理解如何在任务和中断服务函数中正确使用二值信号量。
——二值信号量&spm=1001.2101.3001.5002&articleId=120940988&d=1&t=3&u=e6fd6c77b81548889ae5fd3a66f4c1e1)
3379

被折叠的 条评论
为什么被折叠?



