FreeRTOS学习笔记——空闲任务prvIdleTask

文章目录

    • 任务创建
    • 任务的内容
      • 推荐阅读

任务创建

prvIdleTask任务,是由任务调度函数vTaskStartScheduler创建的,任务优先级0,任务堆栈深度由配置选项configMINIMAL_STACK_SIZE定义。

void vTaskStartScheduler(void)
{/* 其他代码*//* Add the idle task at the lowest priority. */xReturn = xTaskCreate(prvIdleTask,configIDLE_TASK_NAME,configMINIMAL_STACK_SIZE,(void *) NULL,portPRIVILEGE_BIT, &xIdleTaskHandle); /* 其他代码*/
}

任务的内容

这里贴上源码,然后对源码做解析。

static portTASK_FUNCTION(prvIdleTask, pvParameters)
{/* Stop warnings. */(void) pvParameters;/** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE* SCHEDULER IS STARTED. **//* In case a task that has a secure context deletes itself, in which case* the idle task is responsible for deleting the task's secure context, if* any. */portALLOCATE_SECURE_CONTEXT(configMINIMAL_SECURE_STACK_SIZE);for(; ;){/* See if any tasks have deleted themselves - if so then the idle task* is responsible for freeing the deleted task's TCB and stack. */prvCheckTasksWaitingTermination();#if (configUSE_PREEMPTION == 0){/* If we are not using preemption we keep forcing a task switch to* see if any other task has become available.  If we are using* preemption we don't need to do this as any task becoming available* will automatically get the processor anyway. */taskYIELD();}#endif /* configUSE_PREEMPTION */#if ((configUSE_PREEMPTION == 1) && (configIDLE_SHOULD_YIELD == 1)){/* When using preemption tasks of equal priority will be* timesliced.  If a task that is sharing the idle priority is ready* to run then the idle task should yield before the end of the* timeslice.** A critical region is not required here as we are just reading from* the list, and an occasional incorrect value will not matter.  If* the ready list at the idle priority contains more than one task* then a task other than the idle task is ready to execute. */if(listCURRENT_LIST_LENGTH(&(pxReadyTasksLists[ tskIDLE_PRIORITY ])) > (UBaseType_t) 1){taskYIELD();}else{mtCOVERAGE_TEST_MARKER();}}#endif /* ((configUSE_PREEMPTION == 1) && (configIDLE_SHOULD_YIELD == 1)) */#if (configUSE_IDLE_HOOK == 1){extern void vApplicationIdleHook(void);/* Call the user defined function from within the idle task.  This* allows the application designer to add background functionality* without the overhead of a separate task.* NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,* CALL A FUNCTION THAT MIGHT BLOCK. */vApplicationIdleHook();}#endif /* configUSE_IDLE_HOOK *//* This conditional compilation should use inequality to 0, not equality* to 1.  This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when* user defined low power mode  implementations require* configUSE_TICKLESS_IDLE to be set to a value other than 1. */#if (configUSE_TICKLESS_IDLE != 0){TickType_t xExpectedIdleTime;/* It is not desirable to suspend then resume the scheduler on* each iteration of the idle task.  Therefore, a preliminary* test of the expected idle time is performed without the* scheduler suspended.  The result here is not necessarily* valid. */xExpectedIdleTime = prvGetExpectedIdleTime();if(xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP){vTaskSuspendAll();{/* Now the scheduler is suspended, the expected idle* time can be sampled again, and this time its value can* be used. */configASSERT(xNextTaskUnblockTime >= xTickCount);xExpectedIdleTime = prvGetExpectedIdleTime();/* Define the following macro to set xExpectedIdleTime to 0* if the application does not want* portSUPPRESS_TICKS_AND_SLEEP() to be called. */configPRE_SUPPRESS_TICKS_AND_SLEEP_PROCESSING(xExpectedIdleTime);if(xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP){traceLOW_POWER_IDLE_BEGIN();portSUPPRESS_TICKS_AND_SLEEP(xExpectedIdleTime);traceLOW_POWER_IDLE_END();}else{mtCOVERAGE_TEST_MARKER();}}(void) xTaskResumeAll();}else{mtCOVERAGE_TEST_MARKER();}}#endif /* configUSE_TICKLESS_IDLE */}
}
  • portTASK_FUNCTION是一个宏定义,专门用来定义任务函数,如下图。
    在这里插入图片描述

  • portALLOCATE_SECURE_CONTEXT(configMINIMAL_SECURE_STACK_SIZE);
    portALLOCATE_SECURE_CONTEXT是一个用于在 FreeRTOS 中分配安全上下文的函数,一般用在使用了TrustZone 技术的系统中。通过分配和初始化安全堆栈,它为非安全任务提供了必要的支持,以便在需要时与安全区域进行交互。

    TrustZone技术是由ARM公司开发的一种硬件安全技术,旨在通过将处理器和系统资源分为安全和非安全两部分来增强系统的安全性。它广泛应用于需要高安全性的嵌入式系统中,如智能手机、物联网设备和支付系统。

  • prvCheckTasksWaitingTermination();
    检查是否有需要释放内存的被删除任务,当有任务调用函数vTaskDelete()删除自身的话,此任务就会添加到列表xTasksWaitingTermination中。函数prvCheckTasksWaitingTermination()会检查列表xTasksWaitingTermination是否为空,如果不为空的话就依次将列表中所有任务对应的内存释放掉(任务控制块 TCB 和任务堆栈的内存)。

  • 使用抢占式内核并且 configIDLE_SHOULD_YIELD 为 1,说明空闲任务需要让出时间片给同优先级的其他就绪任务。

  • 检查优先级为tskIDLE_PRIORITY(空闲任务优先级)的就绪任务列表是否为空,如果不为空的话就调用函数taskYIELD()进行一次任务切换。

  • 如果使能了空闲任务钩子函数的话就执行这个钩子函数,空闲任务钩子函数的函数名为vApplicationIdleHook(),这个函数需要用户自行编写!在编写这个这个钩子函数的时候一定不能调用任何可以阻塞空闲任务的 API 函数。通常,使用这个空闲钩子函数设置CPU进入低功耗模式。

  • 剩下的都是Tickless模式的代码
    configUSE_TICKLESS_IDLE不为 0,说明使能了 FreeRTOS 的低功耗 Tickless 模式。

    一般而言,在RTOS中为了降低功耗。运行空闲任务时需要进入低功耗模式,在处理应用层任务时需要将处理器从低功耗模式中唤醒。一般会在空闲任务的钩子函数中执行低功耗相关处理,比如设置处理器进入低功耗模式、关闭其他外设时钟、降低系统主频等。

    但FreeRTOS中的时钟是由滴答定时器(一般频率为1000Hz)来提供的,这会导致当处理器进入低功耗模式时会被滴答定时器中断频繁唤醒,导致低功耗模式作用大大降低。因此引入了Tickless模式——当处理器进入空闲任务周期后,就关闭滴答定时器中断,只有当其他中断发生或者其他任务需要处理的时候,处理器才会被从低功耗模式中唤醒。

    但这将面临两个问题: 其一是关闭系统节拍中断会导致系统节拍计数器停止,系统时钟就会停止。 FreeRTOS 的系统时钟是依赖于系统节拍中断(滴答定时器中断)的,如果关闭了系统节拍中断的话就会导致系统时钟停止运行,这是绝对不允许的!解决方法为–记录下系统节拍中断的关闭时间,当系统节拍中断再次开启运行的时候补上这段时间,因此这段时间也称为补偿时间。这时候就需要另外一个定时器来记录这段补偿时间,而F103是继续采用滴答定时器来完成这个功能。

    其二是当处理器进入睡眠模式之后,除了及时响应中断外,还需要响应应用层的就绪任务,但是中断可以唤醒睡眠模式,应用层任务却不能主动将处理器从睡眠中唤醒。为了解决上述问题,采用记录处理器在进入低功耗模式之前的待运行任务阻塞时间(也称为低功耗持续时间),FreeRTOS中提供了prvGetExpectedIdleTime()函数来获取这段时间。

推荐阅读

空闲任务与钩子函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/90065.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/90065.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初识卷积神经网络CNN

卷积神经网络CNN 全连接神经网络存在的问题: 输入的形式应该是列向量,但是卷积神经网络中的输入是图像(2D矩阵),那么就需要对图片进行展平处理,原本图像中蕴含的空间等信息就被打乱了输入的特征多了,那么神经元的参数就会很多&…

高层功能架构详解 - openExo

高层功能架构详解1. 系统整体结构与模块化设计2. 两大核心类:ExoData 与 ExoA. ExoDataB. ExoC. 数据结构的层级关系3. 多微控制器协作与BLE通信4. 主控软件运行流程(主循环伪代码)5. 架构优点小结6. 与 Code Structure 的关系实用建议1. 系统…

【西北工业大学公开课】导引系统原理(全61讲)周军 -个人笔记版 5000字

【严正声明】此文档为个人笔记:仅供个人与同学参考学习,记录学习过程,严谨商业转载,或商业售卖!感谢西北工业大学公开课知识分享,公开资料开源!视频链接:【【西北工业大学】导引系统…

《命令行参数与环境变量:从使用到原理的全方位解析》

前言 当我们在终端输入 ls -l /home 查看目录详情,或用 gcc -o hello hello.c 编译代码时,或许很少思考:这些空格分隔的 “指令 选项 路径” 是如何被程序识别的?为什么 PATH 变量能让系统找到可执行文件,而 HOME 变…

C++设计模式:单例模式 (现代C++主流实现方式Meyer‘s Singleton + 使用CRTP模板化)

文章目录单例模式创建单例类饿汉式or懒汉式现代C单例模式的主流实现方式——Meyers Singleton使用 CRTP 模板化单例类单例模式 单例模式是指程序中只需要一个实例化对象,在全局作用域或整个代码架构中,此对象只被实例化一次,就可以达到在整个…

Eureka 和 Nacos

一、基本介绍EurekaEureka 是 Netflix 公司开发的一款基于 REST 风格的服务注册与发现组件,专为分布式系统设计。它遵循 AP 原则(可用性、分区容错性优先),强调在网络分区等异常情况下的服务可用性,是 Spring Cloud Ne…

文件IO笔试题

目录前言一、核心概念:二、关键操作步骤:三、为什么需要文件IO?四、常见类型:五、标准IO源码六、笔试真题和练习1.代码实现1代码实现22.代码实现3.代码实现4.代码实现5.代码实现七、总结前言 文件IO(文件输入/输出&am…

前端学习 5:DFT

DFT技术 DFT (design for testability):指在设计系统和电路的同时,考虑测试的需求,通过增加一定的硬件开销,获得最大可测性的设计过程。(因为增加了硬件,所以也带来了不足&#xff…

最长递增子序列(LIS)问题详解

最长递增子序列LIS问题详解一、问题定义与核心特征1.1 问题描述1.2 核心特征二、基础解法:动态规划(DP)2.1 解法思路2.2 Java代码实现2.3 复杂度分析三、优化解法:二分查找贪心3.1 核心思路3.2 二分查找的作用3.3 Java代码实现代码…

什么是HTTP长连接、短连接?谁更能抗DoS攻击?

想象你在快餐店点餐: 你:“一个汉堡”收银员:“好的,15元”交易结束,你离开队伍你想加杯可乐,重新排队你:“一杯可乐”收银员:“好的,8元”再次离开… 这种每次沟通后立即…

微软徽标认证是什么?如何快速获取驱动签名?

在Windows系统中安装硬件驱动时,是否遇到过“无法验证发布者”的警告?这正是驱动数字签名在背后发挥作用。对于软件开发者而言,驱动数字签名不仅是系统兼容性的保障,更是企业品牌信任度的核心。一、驱动数字签名的核心作用驱动数字…

Apache Ignite缓存基本操作

这段内容主要讲解了 Apache Ignite 中缓存(IgniteCache)的基本操作,包括获取缓存、创建缓存、销毁缓存、执行原子操作以及异步操作等。下面我将用中文对这些内容进行详细解释,帮助你更好地理解。一、获取缓存实例(Gett…

最新基于R语言结构方程模型分析与实践技术应用

现代统计学理论和方法的不断完善,使科研工作对统计方法的要求也越来越高,面对纷繁复杂的数据,如何选择最为合适的数据分析方法已成为科研工作者,尤其是广大刚处于科研生涯起步阶段的研究生们最为棘手问题。随着科学的发展&#xf…

物联网_TDengine_EMQX_性能测试

一、Tdengine接口开发文档 1、数据库 1.创建数据库 URL /dp/createdb/ method post 请求示例 {"db_name":"demo01" // 必填 }响应示例 // 成功 {"code": 1,"data": {"成功创建数据库": "demo04"},"error…

从分析到优化:Amazon Q CLI 助力 EKS 网络调用链剖析与运维实践

1. 引言 在 Amazon EKS(Elastic Kubernetes Service)环境中,理解从 ALB(Application Load Balancer)到 Pod 的完整网络调用链对运维人员至关重要。本文将展示如何利用 Amazon Q CLI 这一 AI 助手工具,通过…

Class10简洁实现

Class10简洁实现 import torch from torch import nn from d2l import torch as d2l# 输入为28*28,输出为10类,第1、2隐藏层256神经元 num_inputs, num_outputs, num_hiddens1, num_hiddens2 784, 10, 256, 256 # 第1个隐藏层丢弃率为0.2,第…

【多线程篇22】:ConcurrentHashMap的并发安全原理剖析

文章目录一、HashMap 的“不安全”:问题的根源1. 数据结构回顾 (JDK 1.8)2. 并发下的致命缺陷:put 操作二、ConcurrentHashMap 的安全之道 (JDK 1.8)1. 核心数据结构2. 安全的 put 操作:分场景精细化加锁3. 安全的 size() 计算:并…

【Java + Vue 实现图片上传后 导出图片及Excel 并压缩为zip压缩包】

系统环境: Java JDK:1.8.0_202 Node.js:v12.2.0 Npm:6.9.0 Java后端实现 Controller /*** xxxx-导出* param response 返回信息体* param files 上传的图片文件* param param1 参数1* param param2 参数2*/PostMapping("/ex…

安科瑞:能源微电网助力工业园区“绿色”发展

朱以真近日,厦门市工业和信息化局印发工业园区绿色智慧微电网建设,拟开展全市工业园区绿色智慧微电网试点通知,那么对于如何实现绿色园区的建设是今天的话题。对工业园区绿色智慧微电网建设需求,其核心价值体现在“源-网-荷-储-充…

VUE2 学习笔记3 v-on、事件修饰符、键盘事件

事件处理v-on用于事件交互。语法:v-on:要绑定的事件“事件触发时执行的函数” (函数这里可以写括号,也可以不写,没有影响)简写::事件触发时要执行的函数,在Vue配置参数中,通过method…