返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >FreeRTOS进阶之空闲任务示例完全解析
  • 510
分享到

FreeRTOS进阶之空闲任务示例完全解析

2024-04-02 19:04:59 510人浏览 八月长安
摘要

目录1.释放内存2. 处理空闲优先级任务3.执行空闲任务钩子函数4.低功耗tickless模式当RTOS调度器开始工作后,为了保证至少有一个任务在运行,空闲任务被自动创建,占用最低优

当RTOS调度器开始工作后,为了保证至少有一个任务在运行,空闲任务被自动创建,占用最低优先级(0优先级)。

   xReturn = xTaskCreate( prvIdleTask,
                         "IDLE",configMINIMAL_STACK_SIZE,
                         (void * ) NULL,
                         (tskIDLE_PRioRITY | portPRIVILEGE_BIT ),
                         &xIdleTaskHandle);

空闲任务是FreeRTOS不可缺少的任务,因为FreeRTOS设计要求必须至少有一个任务处于运行状态。我们来看一下空闲任务要做的工作。

1.释放内存

从V9.0版本开始,如果一个任务删除另外一个任务,被删除任务的堆栈和TCB立即释放。如果一个任务删除自己,则任务的堆栈和TCB和以前一样,通过空闲任务删除。所以空闲任务开始就会检查是否有任务删除了自己,如果有的话,空闲任务负责删除这个任务的TCB和堆栈空间。

2. 处理空闲优先级任务

当使用抢占式内核,相同优先级的任务使用时间片方式获得CPU权限。如果有任务与空闲任务共享一个优先级,并且宏configIDLE_SHOULD_YIELD设置为1,那么空闲任务不必等到时间片耗尽再进行任务切换。

所以空闲任务检查空闲优先级下的就绪列表中是否有多个任务,有的话则执行任务切换,让用户任务获得CPU权限。

宏configIDLE_SHOULD_YIELD控制任务在空闲优先级中的行为。仅在满足下列条件后,才会起作用。

  • 使用抢占式内核调度
  • 用户任务使用空闲优先级。

通过时间片共享同一个优先级的多个任务,如果共享的优先级大于空闲优先级,并假设没有更高优先级任务,这些任务应该获得相同的处理器时间。

但如果共享空闲优先级时,情况会稍微有些不同。当configIDLE_SHOULD_YIELD为1时,其它共享空闲优先级的用户任务就绪时,空闲任务立刻让出CPU,用户任务运行,这样确保了能最快响应用户任务。处于这种模式下也会有不良效果(取决于你的程序需要),描述如下:

图中描述了四个处于空闲优先级的任务,任务A、B和C是用户任务,任务I是空闲任务。上下文切换周期性的发生在T0、T1…T6时刻。当用户任务运行时,空闲任务立刻让出CPU,但是,空闲任务已经消耗了当前时间片中的一定时间。这样的结果就是空闲任务I和用户任务A共享一个时间片。用户任务B和用户任务C因此获得了比用户任务A更多的处理器时间。

可以通过下面方法避免:

  • 如果合适的话,将处于空闲优先级的各单独的任务放置到空闲钩子函数中;
  • 创建的用户任务优先级大于空闲优先级;
  • 设置IDLE_SHOULD_YIELD为0;

设置configIDLE_SHOULD_YIELD为0将阻止空闲任务为用户任务让出CPU,直到空闲任务的时间片结束。这确保所有处在空闲优先级的任务分配到相同多的处理器时间,但是,这是以分配给空闲任务更高比例的处理器时间为代价的。

3.执行空闲任务钩子函数

空闲任务钩子是一个函数,这个函数由用户来实现,RTOS规定了函数的名字和参数,这个函数在每个空闲任务周期都会被调用。

要创建一个空闲钩子:

  • 设置FreeRTOSConfig.h 文件中的configUSE_IDLE_HOOK 为1;
  • 定义一个函数,函数名和参数如下所示:
void vApplicationIdleHook(void ); 

这个钩子函数不可以调用会引起空闲任务阻塞的api函数(例如:vTaskDelay()、带有阻塞时间的队列和信号量函数),在钩子函数内部使用协程是被允许的。

使用空闲钩子函数设置CPU进入省电模式是很常见的。

4.低功耗tickless模式

通常情况下,FreeRTOS回调空闲任务钩子函数(需要设计者自己实现),在空闲任务钩子函数中设置微处理器进入低功耗模式来达到省电的目的。因为系统要响应系统节拍中断事件,因此使用这种方法会周期性的退出、再进入低功耗状态。如果系统节拍中断频率过快,则大部分电能和CPU时间会消耗在进入和退出低功耗状态上。

FreeRTOS的tickless空闲模式会在空闲周期时停止周期性系统节拍中断。停止周期性系统节拍中断可以使微控制器长时间处于低功耗模式。移植层需要配置外部唤醒中断,当唤醒事件到来时,将微控制器从低功耗模式唤醒。

微控制器唤醒后,会重新使能系统节拍中断。由于微控制器在进入低功耗后,系统节拍计数器是停止的,但我们又需要知道这段时间能折算成多少次系统节拍中断周期,这就需要有一个不受低功耗影响的外部时钟源,即微处理器处于低功耗模式时它也在计时的,这样在重启系统节拍中断时就可以根据这个外部计时器计算出一个调整值并写入RTOS 系统节拍计数器变量中。

空闲任务的源代码如下所示,其中宏portTASK_FUNCTION翻译出来为:

void prvIdleTask(void * pvParameters)。

static portTASK_FUNCTION( prvIdleTask,pvParameters ){  (void ) pvParameters; for(;; ) {  prvCheckTasksWaitingTermination(); #if( configUSE_PREEMPTION == 0 ) {taskYIELD(); } #endif #if( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) {if(listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) >( UBaseType_t ) 1 ){ taskYIELD();} } #endif #if( configUSE_IDLE_HOOK == 1 ) {externvoid vApplicationIdleHook( void );vApplicationIdleHook(); } #endif #if( configUSE_TICKLESS_IDLE != 0 ) { TickType_txExpectedIdleTime;xExpectedIdleTime= prvGetExpectedIdleTime();if(xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ){ vTaskSuspendAll(); {  configASSERT(xNextTaskUnblockTime >= xTickCount ); xExpectedIdleTime= prvGetExpectedIdleTime(); if(xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) {portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime ); } } (void ) xTaskResumeAll();} } #endif }}static portTASK_FUNCTION( prvIdleTask,pvParameters )
{
	 
	 (void ) pvParameters;
	 for(;; )
	 {
		   
		   prvCheckTasksWaitingTermination();
 
		   #if( configUSE_PREEMPTION == 0 )
		   {
				
				taskYIELD();
		   }
		   #endif
		   #if( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
		   {
				
				if(listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) >( UBaseType_t ) 1 )
				{
						 taskYIELD();
				}
		   }
		   #endif
 
		   #if( configUSE_IDLE_HOOK == 1 )
		   {
				externvoid vApplicationIdleHook( void );
 
				
				vApplicationIdleHook();
		   }
		   #endif
 
		   #if( configUSE_TICKLESS_IDLE != 0 )
		   {
		   TickType_txExpectedIdleTime;
 
				
				xExpectedIdleTime= prvGetExpectedIdleTime();
 
				if(xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
				{
					 vTaskSuspendAll();
					 {
						   
						   configASSERT(xNextTaskUnblockTime >= xTickCount );
						   xExpectedIdleTime= prvGetExpectedIdleTime();
 
						   if(xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
						   {
								portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime );
						   }
					 }
					 (void ) xTaskResumeAll();
				}
		   }
		   #endif
	 }
}

以上就是FreeRTOS进阶之空闲任务示例完全解析的详细内容,更多关于FreeRTOS进阶空闲任务的资料请关注编程网其它相关文章!

--结束END--

本文标题: FreeRTOS进阶之空闲任务示例完全解析

本文链接: https://lsjlt.com/news/145551.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • FreeRTOS进阶之空闲任务示例完全解析
    目录1.释放内存2. 处理空闲优先级任务3.执行空闲任务钩子函数4.低功耗tickless模式当RTOS调度器开始工作后,为了保证至少有一个任务在运行,空闲任务被自动创建,占用最低优...
    99+
    2024-04-02
  • FreeRTOS进阶之任务通知示例完全解析
    目录前言1.发送通知1.1 xTaskGenericNotify()1.2 vTaskNotifyGiveFromISR()1.3 xTaskGenericNotifyFromISR...
    99+
    2024-04-02
  • FreeRTOS进阶之任务创建完全解析
    目录前言1.创建任务堆栈和任务TCB2.初始化任务TCB必要的字段3.初始化任务堆栈4.进入临界区5.当前任务数量增加16.为第一次运行做必要的初始化7.更新当前正在运行的任务TCB...
    99+
    2024-04-02
  • FreeRTOS进阶之队列示例完全解析
    目录前言1.队列创建函数2.入队2.1 xQueueGenericSend()2.2 xQueueGenericSendFromISR ()3.出队前言 FreeRTOS提供了多种任...
    99+
    2024-04-02
  • FreeRTOS进阶之任务切换完全分析
    目录FreeRTOS任务切换过程代码分析运行FreeRTOS过程FreeRTOS任务切换过程 FreeRTOS任务相关的代码大约占总代码的一半左右,这些代码都在为一件事情而努力,即找...
    99+
    2024-04-02
  • FreeRTOS进阶信号量示例的完全解析
    目录前言1.信号量创建1.1.创建二进制信号量1.2.创建计数信号量1.3创建互斥量1.4创建递归互斥量2.释放信号量2.1 xSemaphoreGive()2.2xSemaphor...
    99+
    2024-04-02
  • FreeRTOS进阶内存管理示例完全解析
    目录前言1. heap_1.c1.1内存申请:pvPortMalloc() 函数源码为:1.2获取当前未分配的内存堆大小:xPortGetFreeHeapSize()1.3其它函数2...
    99+
    2024-04-02
  • FreeRTOS进阶之系统延时完全解析
    目录1. 相对延时函数vTaskDelay()2. 绝对延时函数vTaskDelayUntil()3.小结FreeRTOS提供了两个系统延时函数:相对延时函数vTaskDelay()...
    99+
    2024-04-02
  • FreeRTOS进阶系统节拍时钟示例的完全解析
    目录前言1.调度器正常情况2.调度器挂起情况3.自动任务切换前言 操作系统的运行是由系统节拍时钟驱动的。 在FreeRTOS中,我们知道系统延时和阻塞时间都是以系统节拍时钟周期为单位...
    99+
    2024-04-02
  • freertos实时操作系统空闲任务阻塞延时示例解析
    目录前言空闲任务阻塞延时SysTick实验现象前言 阻塞态:如果一个任务当前正在等待某个外部事件,则称它处于阻塞态。 rtos中的延时叫阻塞延时,即任务需要延时的时候,会放弃CPU的...
    99+
    2024-04-02
  • Nodejs进阶之服务端字符编解码和乱码处理的示例分析
    这篇文章将为大家详细讲解有关Nodejs进阶之服务端字符编解码和乱码处理的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。写在前面在web服务端开发中,字符的编解码...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作