FreeRTOS中断管理--计数信号量

计数信号量

正如可以将二值信号量视为长度为1的队列一样,将计数信号量视为长度大于1的队列。即:任务对队列中存储的数据不感兴趣,仅对队列中的项目数感兴趣。
如果要使用计数信号量,必须在FreeRTOSConfig.h中将configUSE_COUNTING_SEMAPHORES设置为1。
每次“给出”计数信号量时,都会使用其队列中的另一个空间。队列中的项目数是信号量的“计数”值。
计数信号量通常用于两件事:

  1. 计数事件
    在这种情况下,事件处理程序将在每次事件发生时“给予(give)”信号量,从而使信号的计数值在每次“给予”时增加。任务在每次处理事件时都会“获取”信号量-导致每次“获取”时信号量的计数值都会减少。计数值是已发生的事件数与已处理的事件数之间的差。这种机制如下图所示。
    FreeRTOS中断管理--计数信号量_第1张图片
    用于计数事件的计数信号量的初始计数值为零。
  2. 资源管理。
    在这种情况下,计数值指示可用资源的数量。要获得对资源的控制,任务必须首先获得一个信号量-减少该信号量的计数值。当计数值达到零时,将没有可用资源。当任务使用资源完成时,它将“给予”信号量-增加信号量的计数值。
    创建用于管理资源的计数信号量,以使它们的初始计数值等于可用资源的数量。

函数原型
SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount,UBaseType_t uxInitialCount);

FreeRTOS中断管理--计数信号量_第2张图片

示例2:使用一个计数信号同步任务与中断

/*在使用信号灯之前,必须显式创建它。在此示例中,创建了一个计数信号量。创建的信号量的最大计数值为10,初始计数值为0*/

xCountingSemaphore = xSemaphoreCreateCounting(10,0);

为了模拟在高频下发生的多个事件,将中断服务程序更改为在每个中断中多次“提供”信号量。每个事件都锁在信号量的计数值中。下列示例代码显示了修改后的中断服务例程。

static uint32_t ulExampleInterruptHandler(void)
{
	BaseType_t xHigherPriorityTaskWoken;


	/*xHigherPriorityTaskWoken参数必须初始化为pdFALSE,因为如果需要上下文切换,它将在中断安全API函数中设置为pdTRUE。*/
	xHigherPriorityTaskWoken = pdFALSE;
	/*多次“给予”信号量。第一个将取消阻止延迟的中断处理任务,接下来的“给与”操作将演示信号量将事件锁存,以允许延迟执行延迟任务的任务依次处理它们,而不会丢失事件。这将模拟处理器正在接收的多个中断,即使在这种情况下,事件是在单个中断发生时进行模拟的。*/
	
	xSemaphoreGiveFromISR(xCountingSemaphore,&xHigherPriorityTaskWoken);
	xSemaphoreGiveFromISR(xCountingSemaphore,&xHigherPriorityTaskWoken);
	xSemaphoreGiveFromISR(xCountingSemaphore,&xHigherPriorityTaskWoken);
	/*将xHigherPriorityTaskWoken值传递到portYIELD_FROM_ISR()。如果在xSemaphoreGiveFromISR()中将xHigherPriorityTaskWoken设置为pdTRUE,则调用portYIELD_FROM_ISR()将请求上下文切换。如果xHigherPriorityTaskWoken仍然是pdFALSE,则调用portYIELD_FROM_ISR()将无效。与大多数FreeRTOS端口不同,Windows端口要求ISR返回一个值-return语句位于Windows版本的portYIELD_FROM_ISR()中。*/
	
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

}

你可能感兴趣的:(FreeRTOS)