【快速笔记】freeRTOS

news2024/11/13 14:44:05

第十八章 低功耗Tickless模式

在这里插入图片描述
睡眠模式:__WFI 中断唤醒 __WFE 事件唤醒 CPU CLK关闭
停止模式:RAM保持 中断唤醒

当 STM32F103 处于休眠模式的时候 Cortex-M3 内核停止运行,但是其他外设运行正常,
比如 NVIC、SRAM 等。
休眠模式的功耗比其他两个高,但是休眠模式没有唤醒延时,应用程
序可以立即运行。

停止模式基于 Cortex-M3 的深度休眠模式与外设时钟门控,在此模式下 1.2V 域的所有时钟
都会停止,PLL、HSI 和 HSE RC 振荡器会被禁止,但是内部 SRAM 的数据会被保留。调压器
可以工作在正常模式,也可配置为低功耗模式

相比于前面两种低功耗模式,待机模式的功耗最低。待机模式是基于 Cortex-M3 的深度睡
眠模式的

其中调压器被禁止。1.2V 域断电,PLL、HSI 振荡器和 HSE 振荡器也被关闭。除了
备份区域和待机电路相关的寄存器外,SRAM 和其他寄存器的内容都将丢失
退出待机模式的话会导致 STM32F1 重启

处理器处理空闲任务的时候就进入低功耗模式
FreeRTOS 就是通过在处理器处
理空闲任务的时候将处理器设置为低功耗模式来降低能耗

一般会在空闲任务的钩子函数中执行低功耗相关处理,
比如设置处理器进入低功耗模式、关闭其他外设时钟、降低系统主频等等

FreeRTOS 的系统时钟是由滴答定时器中断来提供的

Tickless 模式,当处理器进入空闲任务周期
以后就关闭系统节拍中断(滴答定时器中断),
只有当其他中断发生或者其他任务需要处理的时候处理器才会被从低功耗模式中唤醒

关闭了系统节拍中断的话就会导致系统时钟停止运行,这是绝对不允许的
该如何解决这个问题呢?
我们可以记录下系统节拍中断的关闭时间,
当系统节拍中断再次开启运行的时候补上这段时间就行

如果处理器在进入低功耗模式之前能够获取到还有多长时间运行下一个任务那么问题就迎刃而解了
我们只需要开一个定时器,定时器的定时周期设置为这个时间值就行了
定时时间到了以后产生定时中断,处理器不就从低功耗模式唤醒了

#define configUSE_TICKLESS_IDLE (1)

portSUPPRESS_TICKS_AND_SLEEP()

空闲任务是唯一可运行的任务,因为其他所有的任务都处于阻塞态或者挂起态

系统处于低功耗模式的时间至少大于 configEXPECTED_IDLE_TIME_BEFORE_SLEEP
个时钟节拍,
#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2

我们可以在 FreeRTOSConfig.h 中重新定义,此宏必须大于 2

portSUPPRESS_TICKS_AND_SLEEP()有个参数,此参数用来指定还有多长时间将有任务
进入就绪态,其实就是处理器进入低功耗模式的时长(单位为时钟节拍数)

滴答定时器的计数寄存器是 24 位

__disable_irq(); //关闭全部中断

__enable_irq();//开启全部中断

在真正的低功耗设计中不仅仅是将处理器设置到低功耗模式就行了,还需要做一些其他的
处理,比如:
● 将处理器降低到合适的频率,因为频率越低功耗越小,甚至可以在进入低功耗模式以后
关闭系统时钟。
● 修改时钟源,晶振的功耗肯定比处理器内部的时钟源高,进入低功耗模式以后可以切换
到内部时钟源,比如 STM32 的内部 RC 振荡器。
● 关闭其他外设时钟,比如 IO 口的时钟。
● 关闭板子上其他功能模块电源,这个需要在产品硬件设计的时候就要处理好,比如可以
通过 MOS 管来控制某个模块电源的开关,在处理器进入低功耗模式之前关闭这些模块的电源

宏 configPRE_SLEEP_PROCESSING ()和 configPOST_SLEEP_PROCESSING()
进入低功耗硬件操作。退出低功耗硬件操作

默认情况下 configEXPECTED_IDLE_TIME_BEFORE_SLEEP 为 2 个时钟节拍,并且最小
不能小于 2 个时钟节拍
进入低功耗的时最小时钟节拍数,设置为10,当进入低功耗时间大于10个系统时钟才允许进入

#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();

			if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
			{
				traceLOW_POWER_IDLE_BEGIN();
				portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );
				traceLOW_POWER_IDLE_END();
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}

从上面可以看出tickless不在空闲钩子函数中

第十九章 空闲任务

当 FreeRTOS 的调度器启动以后就会自动的创建一个空闲任务,这样就可以确保至少有一任务可以运行。
但是这个空闲任务使用最低优先级,0

如果某个任务要调用函数 vTaskDelete()删除自身,那么这个任务的任务控制块 TCB 和任务堆栈等这些由 FreeRTOS 系统自动分配的内存需要在空闲任务中释放掉
如果删除的是别的任务那么相应的内存就会被直接释放掉,不需要在空闲任务中释放

如果使能了空闲任务钩子函数的话就执行这个钩子函数,空闲任务钩子函数的函数名为 vApplicationIdleHook(),这个函数需要用户自行编写!在编写这个钩子函数的时候一定不能调用任何可以阻塞空闲任务的 API 函数

因此绝对不能在空闲任务钩子函数中调用任何可以阻塞空闲任务的 API 函数,比如 vTaskDelay(),或者其他带有阻塞时间的信号量或队列操作函数

  • 如果使用通用低功耗模式的话每个滴答定时器中断都会将处理器从低功耗模式中唤醒,反复的进入低功耗、退出低功耗
  • FreeRTOS 自带的 Tickless 模式更加合理有效

第二十章 内存管理

函数 pvPortMalloc()、vPortFree()
与函数 malloc()、free()的函数原型类似

  • 内存碎片是伴随着内存申请和释放而来的
  • 多次申请释放以后产生内存碎片

1. heap_1

当宏 configAPPLICATION_ALLOCATED_HEAP 为 1 的时候需要用户自行定义内存堆
否则的话由编译器来决定,默认都是由编译器来决定的
如果自己定义的话就可以将内存堆定义到外部 SRAM 或者 SDRAM 中
heap_1 实现起来就是当需要 RAM 的时候就从一个大数组(内存堆)中分一小块出来
heap_1 特性如下:
1、适用于那些一旦创建好任务、信号量和队列就再也不会删除的应用,实际上大多数的FreeRTOS 应用都是这样的
2、具有可确定性(执行所花费的时间大多数都是一样的),而且不会导致内存碎片。
3、代码实现和内存分配过程都非常简单,内存是从一个静态数组中分配到的,也就是适合于那些不需要动态内存分配的应用。

2. heap_2

heap_2 的特性如下:
1、可以使用在那些可能会重复的删除任务、队列、信号量等的应用中,要注意有内存碎片
产生!
2、如果分配和释放的内存 n 大小是随机的,那么就要慎重使用了

3.heap_3

4. heap_4

heap_4 提供了一个最优的匹配算法
heap_4 会将内存碎片合并成一个大的可用内存块,它提供了内存块合并算法
heap_4 特性如下:
1、可以用在那些需要重复创建和删除任务、队列、信号量和互斥信号量等的应用中。
2、不会像 heap_2 那样产生严重的内存碎片,即使分配的内存大小是随机的。
3、具有不确定性,但是远比 C 标准库中的 malloc()和 free()效率高。
heap_4 非常适合于那些需要直接调用函数 pvPortMalloc()和 vPortFree()来申请和释放内存
的应用,注意,我们移植 FreeRTOS 的时候就选择的 heap_4!
heap_4 也使用链表结构来管理空闲内存块,链表结构体与 heap_2 一样。heap_4 也定义了两个局部静态变量 xStart 和 pxEnd 来表示链表头和尾,其中 pxEnd 是指向 BlockLink_t 的指针。

5.heap_5

heap_5 使用了和 heap_4 相同的合并算法,内存管理实现起来基本相同,但是 heap_5 允许内存堆跨越多个不连续的内存段

至此,FreeRTOS 官方提供的 5 种内存分配方法已经讲完了,
heap_1 最简单,但是只能申请内存,不能释放。
heap_2 提供了内存释放函数,用户代码也可以直接调用函数 pvPortMalloc()和
vPortFree()来申请和释放内存,但是 heap_2 会导致内存碎片的产生!
heap_3 是对标准 C 库中的函数 malloc()和 free()的简单封装,并且提供了线程保护。
heap_4 相对与 heap_2 提供了内存合并功能,可以降低内存碎片的产生,我们移植 FreeRTOS 的时候就选择了 heap_4。
heap_5 基本
上和 heap_4 一样,只是 heap_5 支持内存堆使用不连续的内存块。

  • 内存泄露:
    在使用内存管理的时候最常遇到的一个问题就是内存泄露,
    内存泄露的原因是没有正确的释放内存!
    内存泄露严重的话应用可能因为申请不到合适的内存而导致死机

第七章 列表和列表项

freeRTOS大量用到列表和列表项
列表是 FreeRTOS 中的一个数据结构,概念上和链表有点类似

列表

/*
 * Definition of the type of queue used by the scheduler.
 * 调度器使用的队列类型的定义。
 */
typedef struct xLIST
{
	listFIRST_LIST_INTEGRITY_CHECK_VALUE//默认不开启				
	configLIST_VOLATILE UBaseType_t uxNumberOfItems;//列表项的数量
	ListItem_t * configLIST_VOLATILE pxIndex;//记录当前列表索引号			
	MiniListItem_t xListEnd;//表示列表结束							
	listSECOND_LIST_INTEGRITY_CHECK_VALUE//默认不开启				
} List_t;

uxNumberOfItems
pxIndex
xListEnd

列表项

就是存放在列表中的项目,FreeRTOS 提供了两种列表项:列表项和迷你列表项。这两个都在文件 list.h 中有定义

/*
 * Definition of the only type of object that a list can contain.
 */
struct xLIST_ITEM
{
	listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE			
	configLIST_VOLATILE TickType_t xItemValue;			//列表项值
	struct xLIST_ITEM * configLIST_VOLATILE pxNext;		//指向下一个列表项
	struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;	//指向前一个列表项
	void * pvOwner;									//记录列表项归谁所有
	void * configLIST_VOLATILE pvContainer;		    //记录列表项归哪个列表
	listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE			/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
};
typedef struct xLIST_ITEM ListItem_t;					/* For some reason lint wants this as two separate definitions. */

定义
ListItem_t xStateListItem;
创建一个任务以后
xStateListItem.pvOwner = 任务控制块地址
当任务就绪以后
xStateListItem.pvContainer = 就绪列表

迷你列表项

struct xMINI_LIST_ITEM
{
	listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE			/*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
	configLIST_VOLATILE TickType_t xItemValue;//列表项值
	struct xLIST_ITEM * configLIST_VOLATILE pxNext;//下一个列表
	struct xLIST_ITEM * configLIST_VOLATILE pxPrevious;//上一个列表
};
typedef struct xMINI_LIST_ITEM MiniListItem_t;

列表初始化

void vListInitialise( List_t * const pxList )
{
	/* The list structure contains a list item which is used to mark the
	end of the list.  To initialise the list the list end is inserted
	as the only list entry. */
	pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd );			/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */

	/* The list end value is the highest possible value in the list to
	ensure it remains at the end of the list. */
	pxList->xListEnd.xItemValue = portMAX_DELAY;

	/* The list end next and previous pointers point to itself so we know
	when the list is empty. */
	pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd );	/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */
	pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd );/*lint !e826 !e740 The mini list structure is used as the list end to save RAM.  This is checked and valid. */

	pxList->uxNumberOfItems = ( UBaseType_t ) 0U;

	/* Write known values into the list if
	configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
	listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
	listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
}

临界段

临界段代码也叫做临界区,是指那些必须完整运行,不能被打断的代码段
FreeRTOS 在进入临界段代码的时候需要关闭中断,当处理完临界段代码以后再打开中断

 taskENTER_CRITICAL()taskEXIT_CRITICAL() 、任务级的临界段代码保护
 
 taskENTER_CRITICAL_FROM_ISR()taskEXIT_CRITICAL_FROM_ISR(),中断级的临界段代码保护
 
#define taskENTER_CRITICAL() portENTER_CRITICAL()
#define taskEXIT_CRITICAL() portEXIT_CRITICAL()

#define portENTER_CRITICAL() vPortEnterCritical()
#define portEXIT_CRITICAL() vPortExitCritical()


开关中断

portENABLE_INTERRUPTS ()
portDISABLE_INTERRUPTS()

任务

在这里插入图片描述

延时函数

消息队列

也称消息队列
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

信号量

二值信号量
计数信号量
互斥信号量

软件定时器

事件标志组

EventBits_t 类型的变量可以存储 24 个事件位

任务通知

效率更高:FreeRTOS 的每个任务都有一个 32 位的通知值
FreeRTOS 的任务通知只能有一个接收任务

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

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

相关文章

【Linux】环境部署kafka集群

目录 一、kafka简介 1. 主要特点 2.组件介绍 3.消息中间件的对比 二、环境准备 1.Java环境 2.Zookeeper环境 3.硬件环境集群 三、Zookeeper的集群部署 1.下载zookeeper 2.部署zookeeper集群 &#xff08;1&#xff09;node1节点服务器 &#xff08;2&#xff09;no…

排序----希尔排序

void ShellSort(int* a, int n) {int gap n;while (gap > 1){// 1保证最后一个gap一定是1// gap > 1时是预排序// gap 1时是插入排序gap gap / 3 1;for (size_t i 0; i < n - gap; i){int end i;int tmp a[end gap];while (end > 0){if (tmp < a[end]){…

6.C_数据结构_查询_哈希表

概述 哈希表的查询是通过计算的方式获取数据的地址&#xff0c;而不是依次比较。在哈希表中&#xff0c;有一个键值key&#xff0c;通过一些函数转换为哈希表的索引值。 其中&#xff1a;这个函数被称为哈希函数、散列函数、杂凑函数&#xff0c;记为&#xff1a;H(key) 哈希…

MySQL 中的锁定粒度:理解与应用

在 MySQL 数据库的使用中&#xff0c;锁定粒度是一个至关重要的概念。它决定了数据库在并发控制中锁定的范围和程度&#xff0c;对数据库的性能和并发能力有着深远的影响。今天&#xff0c;我们就来深入了解一下 MySQL 中的锁定粒度是什么意思&#xff0c;并通过实际案例来更好…

鸿蒙开发之ArkUI 界面篇 十五 交叉轴对其方式

鸿蒙界面有两个容器一个是Colum、一个是Row&#xff0c;Colum主轴是垂直方向&#xff0c;交叉轴是水平方向&#xff0c;Row的主轴是水平方向&#xff0c;交叉轴是垂直方向&#xff0c;对应方向调整子控件的话&#xff0c;justifyContent调整的是主轴方向的子控件距离&#xff0…

论文阅读-《Attention is All You Need》

注意力就是一切 【要点】&#xff1a;论文提出了一种全新的网络架构——Transformer&#xff0c;完全基于注意力机制&#xff0c;无需使用循环和卷积&#xff0c;实现了在机器翻译任务上的性能提升和训练效率的显著提高。 【方法】&#xff1a;通过构建一个仅使用注意力机制的…

【高分系列卫星简介】

高分系列卫星是中国国家高分辨率对地观测系统&#xff08;简称“高分工程”&#xff09;的重要组成部分&#xff0c;旨在提供全球范围内的高分辨率遥感数据&#xff0c;广泛应用于环境监测、灾害应急、城市规划、农业估产等多个领域。以下是对高分系列卫星及其数据、相关参数和…

Java流程控制语句——条件控制语句详解(附有流程图)#Java条件控制语句有哪些?#if-else、switch

在 Java 编程中&#xff0c;条件控制语句用于控制程序的执行路径&#xff0c;决定根据某些条件来选择执行某段代码或跳过某段代码。它们是 Java 编程的重要组成部分&#xff0c;帮助开发者根据不同的输入、状态或数据流来编写更加灵活和动态的代码。在本文中&#xff0c;我们将…

利用git将项目上传到github

采用git而不是在pycharm中共享的原因&#xff1a;可能会出现上图报错 目录 1、创建github仓库2、在 git bash 中初始化Git仓库&#xff0c;添加文件&#xff0c;上传代码 1、创建github仓库 2、在 git bash 中初始化Git仓库&#xff0c;添加文件&#xff0c;上传代码

【C++】STL----list常见用法

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;C从小白到高手 &#x1f339;往期回顾&#x1f339;&#xff1a;[C]vector常见用法 &#x1f516; 流水不争&#xff0c;争的是滔滔不息。 文章目录 一、list的介绍li…

【C++】list容器的基本使用

一、list是什么 list的底层结构是带头双向循环链表。 相较于 vector 的连续线性空间&#xff0c;list 就显得复杂很多&#xff0c;它是由一个个结点构成&#xff0c;每个结点申请的空间并不是连续的&#xff0c;它的好处是每次插入或删除一个数据&#xff0c;就配置或释放一个…

WebServer:log

超时锁的编写 这个问题处于blockqueue.h文件中&#xff0c;内容如下&#xff1a; template<class T> bool BlockDeque<T>::pop(T& item, int timeout) {std::unique_lock<std::mutex> locker(mtx_);while(deq_.empty()) {if(condConsumer_.wait_for(lo…

内存泄漏

文章目录 内存泄漏发现问题topVisualVMArthas 原因分析代码层面并发请求 诊断问题MAT原理 –支配树获取运行时快照 内存泄漏 内存泄漏&#xff08;memory leak&#xff09;&#xff1a;在Java中如果不再使用一个对象&#xff0c;但是该对象依然在GC ROOT的引用链上&#xff0c;…

12.第二阶段x86游戏实战2-CE找基地址

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

全网最全:企业微信用户授权登录对接完整流程

Hello&#xff01;欢迎各位新老朋友来看小弟博客&#xff0c;祝大家事业顺利&#xff0c;财源广进&#xff01;&#xff01; 主题&#xff1a;企业微信用户授权与校验完整对接流程 一&#xff1a;构造第三方应用授权链接 如果第三方应用需要在打开的网页里面携带用户的身份信息…

吸尘器制造5G智能工厂物联数字孪生平台,推进制造业数字化转型

吸尘器制造行业&#xff0c;作为传统制造业的重要组成部分&#xff0c;也在积极探索如何通过先进技术实现生产模式的创新升级。5G智能工厂与物联数字孪生平台的融合应用&#xff0c;为吸尘器制造业的数字化转型铺设了一条高速通道&#xff0c;不仅极大地提升生产效率&#xff0…

华为---代理ARP简介及示例配置

目录 1. 概念 2. 前提条件 3. 使用环境 4. 工作过程 5. 优点 6. 缺点 7. 示例配置 7.1 示例场景 7.2基本配置 7.3 配置端口隔离 7.4 开启代理ARP 7.4.1 VLAN内代理ARP 7.4.2 VLAN间代理ARP 7.4.3路由式ARP代理 1. 概念 代理ARP&#xff08;Proxy ARP&#xff09;&…

GAMES202 作业1

参考&#xff1a;games202作业1 SM 首先是利用shadow map去生成尝试生成硬阴影。根据作业的要求 我们完成光源对物体的mvp矩阵 CalcLightMVP(translate, scale) {let lightMVP mat4.create();let modelMatrix mat4.create();let viewMatrix mat4.create();let projection…

Bigemap GIS Office 2024注册机 全能版地图下载软件

对于需要利用GIS信息进行编辑、设计的用户来说&#xff0c;Bigemap GIS Office占有重要地位。用户可以使用Bigemap GIS Office作为工具进行设计、分析、共享、管理和发布地理信息。Bigemap GIS Office能实现多种数据流转、嵌入、融合以及更多地为用户提供数据的增强处理及多种分…

文心一言 VS 讯飞星火 VS chatgpt (351)-- 算法导论24.1 2题

二、证明推论24.3。推论 24.3 的内容是设 G ( V , E ) G(V,E) G(V,E)是一带权重的源结点为 s s s的有向图&#xff0c;其权重函数为 ω : E → R ω:\boldsymbol{E→R} ω:E→R。假定图 G G G不包含从源结点 s s s可以到达的权重为负值的环路&#xff0c;则对于所有结点 v ∈ …