FreeRTOS的事件组

news/2025/2/9 5:40:18 标签: 单片机, stm32

1 创建事件组 xEventGroupCreate

EventGroupHandle_t xEventGroupCreate( void )
{
EventGroup_t *pxEventBits;


    /* 分配事件组内存。*/
	pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) );
	if( pxEventBits != NULL )
	{
		pxEventBits->uxEventBits = 0;   // 初始化事件位为0
		vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );   // 初始化等待事件的任务列表
		traceEVENT_GROUP_CREATE( pxEventBits );
	}
	else
	{
		traceEVENT_GROUP_CREATE_FAILED();
	}

	return ( EventGroupHandle_t ) pxEventBits;
}

2 事件置位 xEventGroupSetBits

EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
{
ListItem_t *pxListItem, *pxNext;
ListItem_t const *pxListEnd;
List_t *pxList;
EventBits_t uxBitsToClear = 0, uxBitsWaitedFor, uxControlBits;
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
BaseType_t xMatchFound = pdFALSE;

	/* Check the user is not attempting to set the bits used by the kernel
	itself. */
	configASSERT( xEventGroup );
	configASSERT( ( uxBitsToSet & eventEVENT_BITS_CONTROL_BYTES ) == 0 );

    /* 获取事件列表头 */
	pxList = &( pxEventBits->xTasksWaitingForBits );
	/* 获取列表尾节点 */
	pxListEnd = listGET_END_MARKER( pxList ); /*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
	/* 挂起调度器 */
	vTaskSuspendAll();
	{
		traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );

       /* 获取头结点 */
		pxListItem = listGET_HEAD_ENTRY( pxList );

		/* Set the bits. */
		/* 设置事件标志位 */
		pxEventBits->uxEventBits |= uxBitsToSet;

		/* See if the new bit value should unblock any tasks. */
		/* 循环遍历整个列表项,直到列表头节点等于尾节点(指针) */
		while( pxListItem != pxListEnd )
		{
			pxNext = listGET_NEXT( pxListItem );  //获取下个列表项

			/* 获取当前列表项的值 */
			uxBitsWaitedFor = listGET_LIST_ITEM_VALUE( pxListItem );
			xMatchFound = pdFALSE; //标记是否找到需要处理的节点

			/* Split the bits waited for from the control bits. */
			/* 拆分 */
			uxControlBits = uxBitsWaitedFor & eventEVENT_BITS_CONTROL_BYTES;
			uxBitsWaitedFor &= ~eventEVENT_BITS_CONTROL_BYTES;

			if( ( uxControlBits & eventWAIT_FOR_ALL_BITS ) == ( EventBits_t ) 0 )
			{
				/* Just looking for single bit being set. */
					/* 或逻辑,等待位已经置位 */
				if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) != ( EventBits_t ) 0 )
				{
					xMatchFound = pdTRUE;
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			/* 表示所有等待的位都已经触发 */
			else if( ( uxBitsWaitedFor & pxEventBits->uxEventBits ) == uxBitsWaitedFor )
			{
				/* All bits are set. */
				xMatchFound = pdTRUE;
			}
			else
			{
				/* Need all bits to be set, but not all the bits were set. */
			}

			if( xMatchFound != pdFALSE )
			{
				/* The bits match.  Should the bits be cleared on exit? */
					/* 判断是否需要清除 */
				if( ( uxControlBits & eventCLEAR_EVENTS_ON_EXIT_BIT ) != ( EventBits_t ) 0 )
				{
					uxBitsToClear |= uxBitsWaitedFor;
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}

				/* Store the actual event flag value in the task's event list
				item before removing the task from the event list.  The
				eventUNBLOCKED_DUE_TO_BIT_SET bit is set so the task knows
				that is was unblocked due to its required bits matching, rather
				than because it timed out. */
				/* 把任务从事件列表中移除	*/
				( void ) xTaskRemoveFromUnorderedEventList( pxListItem, pxEventBits->uxEventBits | eventUNBLOCKED_DUE_TO_BIT_SET );
			}

			/* Move onto the next list item.  Note pxListItem->pxNext is not
			used here as the list item may have been removed from the event list
			and inserted into the ready/pending reading list. */
			pxListItem = pxNext;  //当前列表项指向下个,继续遍历
		}

		/* Clear any bits that matched when the eventCLEAR_EVENTS_ON_EXIT_BIT
		bit was set in the control word. */
		pxEventBits->uxEventBits &= ~uxBitsToClear;  //清除设置后的标志位
	}
	( void ) xTaskResumeAll();  //开启调度器

	return pxEventBits->uxEventBits;
}

3 等待标志位 xEventGroupWaitBits

EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait )
{
EventGroup_t *pxEventBits = ( EventGroup_t * ) xEventGroup;
EventBits_t uxReturn, uxControlBits = 0;
BaseType_t xWaitConditionMet, xAlreadyYielded;
BaseType_t xTimeoutOccurred = pdFALSE;

	/* Check the user is not attempting to wait on the bits used by the kernel
	itself, and that at least one bit is being requested. */
	configASSERT( xEventGroup );
	configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
	configASSERT( uxBitsToWaitFor != 0 );
	#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
	{
		configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
	}
	#endif

	vTaskSuspendAll();  //挂起调度器
	{
		/* 获取当前的事件标志位 */
		const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;

		/* Check to see if the wait condition is already met or not. */
		/* 检查是否触发 */
		xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );

		if( xWaitConditionMet != pdFALSE )
		{
			
			/* The wait condition has already been met so there is no need to
			block. */
			/* 已经触发 */
			uxReturn = uxCurrentEventBits;
			xTicksToWait = ( TickType_t ) 0;

			/* Clear the wait bits if requested to do so. */
			/* 清楚已经触发的标志 */
			if( xClearOnExit != pdFALSE )
			{
				pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		
		else if( xTicksToWait == ( TickType_t ) 0 )
		{
			/* 不需要超时,直接返回标志位. */
			uxReturn = uxCurrentEventBits;
		}
		else
		{

			/* 事件没有触发,并且需要超时*/
			if( xClearOnExit != pdFALSE )
			{
				uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}

			if( xWaitForAllBits != pdFALSE )
			{
				uxControlBits |= eventWAIT_FOR_ALL_BITS;
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}


			/* 把任务添加到事件列表中	*/
			vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );


			uxReturn = 0;

			traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
		}
	}
	xAlreadyYielded = xTaskResumeAll();  //恢复调度器	

	if( xTicksToWait != ( TickType_t ) 0 )
	{
		if( xAlreadyYielded == pdFALSE )
		{
			portYIELD_WITHIN_API();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}

		
		/* 任务已经恢复,则复位列表项中的值  复位为任务有优先级 */
		uxReturn = uxTaskResetEventItemValue();
        /* 是不是通过事件置位解除的任务 */
		if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
		{
			taskENTER_CRITICAL();  //进入临界段
			{
				/* The task timed out, just return the current event bit value. */
				uxReturn = pxEventBits->uxEventBits;    // 获取当前事件位

				/* It is possible that the event bits were updated between this
				task leaving the Blocked state and running again. */
				/* 判断是否已经置位 */
				if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
				{
					/* 如果需要清除,清除触发后的标志位 */
					if( xClearOnExit != pdFALSE )
					{
						pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
					}
					else
					{
						mtCOVERAGE_TEST_MARKER();
					}
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			taskEXIT_CRITICAL();

			/* Prevent compiler warnings when trace macros are not used. */
			xTimeoutOccurred = pdFALSE;
		}
		else
		{
			/* The task unblocked because the bits were set. */
		}

		/* The task blocked so control bits may have been set. */
		uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
	}
	traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );

	return uxReturn;
}

http://www.niftyadmin.cn/n/5845593.html

相关文章

uniapp中使用uCharts折线图X轴数据间隔显示

1、先看官网 https://www.ucharts.cn/ 2、设置代码 "xAxisDemo3":function(val, index, opts){if(index % 2 0){return val}else {return }}, 再在数据中引入设置好样式

Django开发入门 – 1.搭建基于Python Web框架Django的IDE开发环境

Django开发入门 – 1.搭建基于Python Web框架Django的IDE开发环境 Build A Integrated Development Environment(IDE) for Python Web Framework - django By JacksonML 1. 获取及安装最新版Python 打开Chrome浏览器,访问Python官网链接:https://www…

Windows下AMD显卡在本地运行大语言模型(deepseek-r1)

Windows下AMD显卡在本地运行大语言模型 本人电脑配置第一步先在官网确认自己的 AMD 显卡是否支持 ROCm下载Ollama安装程序模型下载位置更改下载 ROCmLibs先确认自己显卡的gfx型号下载解压 替换替换rocblas.dll替换library文件夹下的所有 重启Ollama下载模型运行效果 本人电脑配…

《Java核心技术 卷II》本地化的数字格式

数字格式 数字和货币的格式高度依赖locale。 格式化对象的集合,可以对java.text包中的数字进行格式化和解析。 格式化数字值 对特定locale的数字进行格式化的步骤: 得到Locale对象使用工厂方法得到一个格式器对象。使用这个格式器对象来完成格式化解析工…

AI知识库和全文检索的区别

1、AI知识库的作用 AI知识库是基于人工智能技术构建的智能系统,能够理解、推理和生成信息。它的核心作用包括: 1.1 语义理解 自然语言处理(NLP):AI知识库能够理解用户查询的语义,而不仅仅是关键词匹配。 …

kafka服务端之日志磁盘存储

文章目录 页缓存顺序写零拷贝 Kafka依赖于文件系统(更底层地来说就是磁盘)来存储和缓存消息 。 那么kafka是如何让自身在使用磁盘存储的情况下达到高性能的?接下来主要从3各方面详细解说。 页缓存 页缓存是操作系统实现的一种主要的磁盘缓存…

R包:ggalign调整和组合多个图形的R包

文章目录 介绍案例安装R包教程1教程2参考 介绍 这个包扩展了ggplot2,提供了用于对齐和组织多个图的高级工具,特别是那些自动重新排序观察结果的工具,比如树形图。它提供了对布局调整和情节注释的精细控制,使您能够创建复杂的、出…

模板方法模式(Template)

一、模板方法的定义: 在操作中定义业务逻辑框架,包含业务逻辑的方法就是模板方法,模板方法允许子类在不改变原有业务逻辑的流程下,对某些步骤进行扩展和修改; 是一种基于继承的代码复用技术,是一种类行为…