FreeRTOS系列

2023-10-27

1. 多任务系统

1.1 前后台系统

单片机裸机开发时,一般都是在main函数里面用while(1)做一个大循环来完成所有的处理,循环中调用相应的函数完成所需的处理。有时也需要在中断中完成一些处理。相对于多任务系统而言,这就是单人单任务系统也称作前后台系统,中断服务函数作为前台程序,while(1)作为后台程序,如下图示

在这里插入图片描述

1.2 抢占式多任务系统

多任务系统会把一个大问题分而治之,把大问题划分成很多个小问题,逐步的把小问题解决掉,大问题也就随之解决了,这些小问题可以单独的作为一个小任务来处理。多个任务带来了一个新的问题,即究竟哪个任务先运行,哪个任务后执行?完成这个功能的东西在RTOS系统中叫做任务调度器。不同的系统其任务调度器的实现方法也不同,比如FreeRTOS是一个抢占式的实时多任务系统,那么其任务调度器也是抢占式的,其运行过程如下图示

在这里插入图片描述
从图中可以看出,高优先级的任务可以打断低优先级任务的运行而取得CPU的使用权。高优先级的任务执行完成以后重新把CPU的使用权归还给低优先级的任务,这就是抢占式任务系统的基本原理

2. FreeRTOS任务

在使用RTOS的时候一个实时应用可以作为一个独立的任务。每个任务都有自己的运行环境,不依赖于系统中其他的任务或者RTOS调度器。任何一个时间点只能有一个任务运行,具体运行哪个任务是由RTOS调度器来决定的,RTOS调度器因此就会重复的开启、关闭每个任务。任务不需要了解RTOS调度器的具体行为,RTOS调度器的职责是确保当一个任务开始执行的时候其上下文环境(寄存器值,堆栈内容等)和任务上一次退出的时候相同。为了做到这一点,每个任务都必须有个堆栈,当任务切换的时候将上下文环境保存在堆栈中,这样当任务再次执行的时候就可以从堆栈中取出上下文环境,任务恢复运行

2.1 任务状态

FreeRTOS中的任务有下面几种状态

  • 运行态:当任务正在运行时,处于运行态;处于运行态的任务就是当前正在使用处理器的任务
  • 就绪态:已经准备就绪,可以运行的任务;有同优先级或更高优先级的任务正在运行占用CPU
  • 阻塞态:任务正在等待某个外部事件即处于阻塞态;阻塞态有超时时间,若超时会退出阻塞态
  • 挂起态:进入挂起态后也不能被调度器调用进入运行态;挂起态的任务没有超时时间

任务状态之间的转换如下图

在这里插入图片描述

2.2 任务优先级

每个任务都可以分配一个从0 ~ (configMAX_PRIORITIES - 1)的优先级,configMAX_PRIORITIES在文件FreeRTOSConfig.h中定义,可以通过STM32CubeMX中FreeRTOS下的MAX_PRIORITIES参数进行配置。MAX_PRIORITIES可以为任意值,但是考虑到RAM的消耗,最好设置为一个满足应用的最小值

优先级数字越低表示任务的优先级越低,0的优先级最低,configMAX_PRIORITIES - 1的优先级最高。空闲任务的优先级最低,为0

2.3 任务实现

在使用FreeRTOS的过程中,要使用xTaskCreate()或xTaskCreateStatic()来创建任务,这两个函数的第一个参数pxTaskCode,就是这个任务的任务函数。任务函数就是完成本任务工作的函数。FreeRTOS官方给出的任务函数模板如下:

void vATaskFunction(void *pvParameters)		//根据实际情况定义任务名;返回类型一定要为void类型
{
	for(;;)		//代表一个循环
	{
		任务应用程序;	//任务代码
		vTaskDelay();	//延时函数,不一定会用到
	}
	vTaskDelete(NULL);	//任务函数一般不允许跳出循环,如果一定要跳出的话在跳出循环后一定要删除此任务
}

2.4 任务控制块

FreeRTOS的每个任务都有一些属性需要存储,FreeRTOS把这些属性集合到一起用一个结构体来表示,这个结构体叫做任务控制块:TCB_t,在使用函数xTaskCreate()创建任务的时候就会自动的给每个任务分配一个任务控制块。此结构体在文件task.c中有定义,如下:

typedef struct tskTaskControlBlock
{
	volatile StackType_t	*pxTopOfStack;	/*任务堆栈栈顶*/

	#if ( portUSING_MPU_WRAPPERS == 1 )
		xMPU_SETTINGS	xMPUSettings;		/*MPU相关设置*/
	#endif

	ListItem_t			xStateListItem;		/*状态列表项*/
	ListItem_t			xEventListItem;		/*事件列表项*/
	UBaseType_t			uxPriority;			/*任务优先级*/
	StackType_t			*pxStack;			/*任务堆栈起始地址*/
	char				pcTaskName[ configMAX_TASK_NAME_LEN ];	/*任务名字*/

	#if ( portSTACK_GROWTH > 0 )
		StackType_t		*pxEndOfStack;		/*任务堆栈栈底*/
	#endif

	#if ( portCRITICAL_NESTING_IN_TCB == 1 )
		UBaseType_t		uxCriticalNesting;	/*临界区嵌套深度*/
	#endif

	#if ( configUSE_TRACE_FACILITY == 1 )
		UBaseType_t		uxTCBNumber;		/*debug的时候用到*/
		UBaseType_t		uxTaskNumber;		/*trace的时候用到*/
	#endif

	#if ( configUSE_MUTEXES == 1 )
		UBaseType_t		uxBasePriority;		/*任务基础优先级,优先级反转时用到*/
		UBaseType_t		uxMutexesHeld;		/*任务获取到的互斥信号量个数*/
	#endif

	#if ( configUSE_APPLICATION_TASK_TAG == 1 )
		TaskHookFunction_t pxTaskTag;
	#endif

	#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )	//与本地存储有关
		void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
	#endif

	#if( configGENERATE_RUN_TIME_STATS == 1 )
		uint32_t		ulRunTimeCounter;	/*用来记录任务运行总时间*/
	#endif

	#if ( configUSE_NEWLIB_REENTRANT == 1 )
		struct	_reent xNewLib_reent;		/*定义一个newlib结构体变量*/
	#endif

	#if( configUSE_TASK_NOTIFICATIONS == 1 )	/*任务通知相关变量*/
		volatile uint32_t ulNotifiedValue;		/*任务通知值*/
		volatile uint8_t ucNotifyState;			/*任务通知状态*/
	#endif

	/* 用来标记任务是动态创建还是静态创建*/
	#if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
		uint8_t	ucStaticallyAllocated; 		/*静态创建此变量为pdTURE;动态创建此变量为pdFALSE*/
	#endif

	#if( INCLUDE_xTaskAbortDelay == 1 )
		uint8_t ucDelayAborted;
	#endif

} tskTCB;

/*新版本的任务控制块重命名为TCB_t,本质上还是tskTCB,主要考虑旧版本的兼容*/
typedef tskTCB TCB_t;

2.5 任务堆栈

FreeRTOS之所以能正确的恢复一个任务的运行就是因为有任务堆栈在保驾护航,任务调度器在进行任务切换的时候会将当前任务的现场(CPU寄存器值等)保存在此任务的任务堆栈中,等到此任务下次运行的时候就会先用堆栈中保存的值来恢复现场,恢复现场以后任务就会接着从上次中断的地方开始运行

创建任务的时候需要给任务指定堆栈,若使用xTaskCreate()动态创建任务,任务堆栈会由函数xTaskCreate()自动创建;若使用xTaskCreateStatic()静态创建任务,就需要自行定义任务堆栈,将堆栈首地址作为函数的参数puxStackBuffer传递给函数,如下:

TaskHandle_t xTaskCreateStatic(	TaskFunction_t pxTaskCode,
								const char * const pcName,
								const uint32_t ulStackDepth,
								void * const pvParameters,
								UBaseType_t uxPriority,
								StackType_t * const puxStackBuffer,		//需要自定义,并将堆栈首地址传递给此参数
								StaticTask_t * const pxTaskBuffer )

不论是使用动态还是静态方法创建任务,创建任务都需要指定任务堆栈大小。任务堆栈的数据类型为StackType_t,其本质是uint32_t,在portmacro.h文件中由定义,如下:

#define portSTACK_TYPE	uint32_t
....
typedef portSTACK_TYPE StackType_t;

可见StackType_t类型的变量为4个字节,因此任务的实际堆栈大小就是我们所定义的4倍

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FreeRTOS系列 的相关文章

  • 基于HAL库的FREERTOS----------二.任务API函数

    任务API函数览概 CUBEMX对 做了API的封装 很多 的函数没有封装到位 可以用原函数调用 任务API函数分别介绍 1 uxTaskPriorityGet 此函数用来获取指定任务的优先级 要使用此函数的话宏 INCLUDE uxTas
  • 【FreeRTOS 信号量】互斥信号量

    互斥信号量与二值信号量类似 但是互斥信号量可以解决二值信号量出现的优先级翻转问题 解决办法就是优先级继承 普通互斥信号量创建及运行 参阅安富莱电子demo 互斥信号量句柄 static SemaphoreHandle t xMutex NU
  • FreeRTOS 软件定时器的使用

    FreeRTOS中加入了软件定时器这个功能组件 是一个可选的 不属于freeRTOS内核的功能 由定时器服务任务 其实就是一个定时器任务 来提供 软件定时器是当设定一个定时时间 当达到设定的时间之后就会执行指定的功能函数 而这个功能函数就叫
  • 【FreeRTOS开发问题】FreeRTOS内存溢出

    FreeRTOS内存溢出 如下图所示 FreeRTOS编译完成后可以看到 系统提示无法分配内存到堆 Objects Template axf Error L6406E No space in execution regions with A
  • freeRTOS手册 第六章 . 中断管理

    如果我对本翻译内容享有所有权 允许任何人复制使用本文章 不会收取任何费用 如有平台向你收取费用与本人无任何关系 第六章 中断管理 章节介绍和范围 事件 嵌入式实时系统必需对环境中的事件做出响应 比如 外部网络设备收到一个发送给TCP IP栈
  • FreeRTOS+CubeMX系列第一篇——初识FreeRTOS

    文章目录 一 关于FreeRTOS 二 FreeRTOS的特点 三 如何在CubeMX上配置FreeRTOS 四 FreeRTOS文档资料 五 同系列博客 一 关于FreeRTOS 1 什么是FreeRTOS FreeRTOS是一个迷你的实
  • FreeRTOS_中断

    传送门 博客汇总帖 传送门 Cortex M3 中断 异常 传送门 Cortex M3笔记 基础 笔记内容参考 正点原子的FreeRTOS开发手册 cortex m3权威指南 Cortex M3和Cortex M4权威指南等 文中stm32
  • FreeRTOS临界段和开关中断

    http blog sina com cn s blog 98ee3a930102wg5u html 本章教程为大家讲解两个重要的概念 FreeRTOS的临界段和开关中断 本章教程配套的例子含Cortex M3内核的STM32F103和Co
  • FreeRTOS,串口中断接收中使用xQueueOverwriteFromISR()函数,程序卡死在configASSERT

    原因 UART的中断优先级设置的太高 高于了configMAX SYSCALL INTERRUPT PRIORITY宏定义的安全中断等级 UART的中断等级小于等于宏定义的优先等级即可
  • stm32f103zet6移植标准库的sdio驱动

    sdio移植 st官网给的标准库有给一个用于st出的评估板的sdio外设实现 但一是文件结构有点复杂 二是相比于国内正点原子和野火的板子也有点不同 因此还是需要移植下才能使用 当然也可以直接使用正点原子或野火提供的实例 但为了熟悉下sdio
  • FreeRTOS之软件定时器

    FreeRTOS之软件定时器 声明 本人按照正点原子的FreeRTOS例程进行学习的 欢迎各位大佬指责和批评 谢谢 include sys h include delay h include usart h include led h in
  • FreeRTOS笔记(一)简介

    这个笔记主要依据韦东山freertos快速入门系列记录 感谢韦东山老师的总结 什么是实时操作系统 操作系统是一个控制程序 负责协调分配计算资源和内存资源给不同的应用程序使用 并防止系统出现故障 操作系统通过一个调度算法和内存管理算法尽可能把
  • FreeRTOS轻量级同步--任务通知

    1 简介 在FreeRTOS的配置参数中的configUSE TASK NOTIFICATIONS宏打开 一般RTOS会默认打开 如图1所示 图1 notify宏开关 RTOS在创建任务时 会创建一个32位的通知值ulNotifiedVal
  • FreeRTOS笔记(二)

    FreeRTOS笔记 二 静态任务 文章目录 FreeRTOS笔记 二 静态任务 一 任务定义 二 任务创建 2 1 定义任务栈 2 2 定义任务函数 2 3 定义任务控制块 2 4 实现任务创建函数 三 实现就绪列表 3 1 定义就绪列表
  • FreeRTOS临界段

    1 临界段 在访问共享资源时不希望被其他任务或者中断打断的代码 这段要执行的代码称为临界段代码 2 设置临界段的目的 保护共享资源 例如 全局变量 公共函数 不可重入函数 函数里面使用 了一些静态全局变量 malloc 等 保护外设的实时性
  • FreeRTOS任务基础知识

    多任务系统 对于单任务系统 每个任务的优先级都是相同的 多任务将一个大问题分成小问题 每个小任务完成的时间很短 看起来像同时完成 多任务系统通过任务调度器来安排任务优先顺序 FreeROTS根据是一个抢占式的实时多任务系统 高优先级的任务可
  • 使用 GCC 编译器的 ARM 内核的堆栈回溯(当存在 MSP 到 PSP 切换时)

    核心 ARM Cortex M4 编译器 GCC 5 3 0 ARM EABI 操作系统 免费 RTOS 我正在使用 gcc 库函数 Unwind Reason Code Unwind Backtrace Unwind Trace Fn v
  • 当一个任务写入变量而其他任务读取该变量时,我们是否需要信号量?

    我正在研究 freeRtos 并且我有一个名为 x 的变量 现在 每秒只有一个任务正在写入该变量 而其他任务正在读取该变量值 我需要用互斥锁来保护变量吗 如果变量为 32 位或更小 并且其值是独立的并且不与任何其他变量一起解释 则不需要互斥
  • 如何更改 FreeRTOS 中任务的最大可用堆大小?

    我通过以下方式在任务中创建元素列表 l dllist pvPortMalloc sizeof dllist dlllist 有 32 字节大 我的嵌入式系统有 60kB SRAM 所以我希望系统可以轻松处理我的 200 个元素列表 我发现在
  • GNU Arm Cortex m4 上的 C++ 异常处理程序与 freertos

    2016 年 12 月更新现在还有一个关于此行为的最小示例 https community nxp com message 862676 https community nxp com message 862676 我正在使用带有 free

随机推荐

  • [c#][process]下发单个以及同时多条adb指令

    库 using System Diagnostics private Process cmd process 下发单条adb指令 代码示例 private string GetAdbCommandsArguments string cmds
  • fiddler设置只抓取某个网址的信息

    1 前提 在使用fiddler进行抓包过程中 如果想只抓取某一个地址下的请求 可以如下设置 2 设置 1 打开fiddler 选择过滤器 2 选择仅显示以下主机 3 点击 动作 选择 现在运行筛选器 4 打开百度 输入信息 进行搜索 查看抓
  • 字符分割算法研究

    字符分割 定义 以字符串的形式分割字符 达到将验证码分割的效果 从定位得到的车牌图像中分离出单个字符 包括汉字 字母和数字等 的图像 以便于字符分割 初步了解 行切分 字切分 参考范例 车牌识别 主要算法解析 改进的连通域分割法 版面分割是
  • 线程池基础知识

    1 为什么要使用线程池 线程池用什么用 创建线程和销毁线程的花销是比较大的 这些时间有可能比处理业务的时间还要长 这样频繁的创建线程和销毁线程 再加上业务工作线程 消耗系统资源的时间 可能导致系统资源不足 我们可以把创建和销毁的线程的过程去
  • Linux 将本地文件上传Linux服务器, 即ssh 命令上传本地文件

    利用ssh传输文件 在linux下一般用scp这个命令来通过ssh传输文件 1 从服务器上下载文件scp username servername path filename var www local dir 本地目录 例如scp root
  • supervisor托管配置nginx

    前言 阅读本文档前 请先了解如何安装配置supervisor和nginx 以下是相关学习文档 超全面 CentOS7 安装及配置supervisor CentOS 安装及配置nginx 配置 1 创建supervisor托管配置文件 详细如
  • oracle导库报959,IMP-00003: 遇到 ORACLE 错误 959

    导入前先要建好表空间和用户 建议你导出的时候按用户导出 不要用sys全部导出来还有在导入的时候需要指定导入到哪个用中去 给个操作手顺吧 我今天刚弄完的 1 导出 exp user user dbname owner user file pa
  • opencv之初学

    浅浅地记录一下自己学习opencv的过程吧 我有想毕业之后从事图像处理方面的工作 所以就从现在学起 争取明年秋招时能拿到offer吧 1 下载opencv opencv有很多的版本 我大概在网上搜了一下它的下载过程 需要在Visual St
  • UE4中文本文件配置文件Json文件XML文件的读写

    虚幻引擎中提供了与平台无关的文件读写与访问接口 通过调用 可以完成一些文件的读写 比如文本文件 配置文件 json文件 xml文件等 完成文件读写 首先需要获取文件路径等相关信息 对调用这些操作 我们需要包含头文件PlatformFilem
  • stm32水质检测系统(TDS检测,水温检测,PH检测,wifi上传,上位机显示)

    一 硬件材料清单 1 STM32核心板 2 OLED显示屏 3 PH传感器 4 TDS传感器 5 DS18B02水温传感器 6 ESP8266 二 实现的功能 1 数据的实时检测 2 本地OLED数据实时刷新 3 远程终端上位机数据显示刷新
  • Flask系列 路由系统

    Flask路由系统细分 from flask import Flask app Flask name app route def index return ok if name main app run 从这个简单的代码入口 来剖析一下路由
  • SpringIOC和AOP概念原理

    springIOC概念和原理 控制反转 把对象创建和对象之间的调用过程 交给Spring进行管理 使用IOC目的 为了耦合度降低 IOC思想是基于IOC容器完成 IOC容器底层就是对象工厂 Spring提供了IOC容器2中实现方式 俩个接口
  • 利用强化学习进行股票操作实战(一)

    利用强化学习进行股票操作实战 今天开始利用强化学习实现股票操作 我在网上找了一个简单的强化学习进行股票操作的例子 并在此基础上进行了小改动 首先讲下建模的思路 当模型发出买入指令时 我们一次性全部买入 当模型发出卖出指令时则一次性全部卖出
  • Swift 中 10 个震惊小伙伴的单行代码

    作者 uraimo 原文链接 原文日期 2016 01 06译者 bestswifter 校对 numbbbbb 定稿 小锅 几年前 函数式编程的复兴正值巅峰 一篇介绍 Scala 中 10 个单行函数式代码的博文在网上走红 很快地 一系列
  • qnx 设备驱动开发_2021年起奥迪车将换装Linux系统 此前为QNX

    车东西5月21日消息 外媒Forbes报道 奥迪官方宣布到2021年 会对旗下多款车型的信息娱乐系统进行升级换代 此前 奥迪旗下车型的信息娱乐系统基于QNX研发而来 未来将更换为Linux系统 升级后的奥迪信息娱乐系统 最大的亮点在于增加的
  • xcode,ios单元测试网络请求 AFNetworking 无法引入

    单元测试引入AFNetworking 同需要在 Podfile 引入 platform ios 7 0 target MyDemoTests do pod AFNetworking gt 2 5 0 end 否则无法引入
  • C++11中enum class的使用

    枚举类型 enumeration 使我们可以将一组整型常量组织在一起 和类一样 每个枚举类型定义了一种新的类型 枚举属于字面值常量类型 C 包含两种枚举 限定作用域的和不限定作用域的 这里主要介绍限定作用域的 不限定作用域的使用可以参考 h
  • [亲测有效]QT生成项目时候,右下角显示红色构建进度条,但是不报错,且无法生成UI界面 的解决方法。

    最近用QT5 9时候 发现生成项目莫名的慢 即使是生成过的项目也要十几秒钟才能弹出UI界面 于是我就想换一个版本用一下 于是我选择了QT 5 6 1版本 但是我发现完成项目后 点击左下角的运行按钮 右下角显示红色进度条的构建过程 更为诡异的
  • OpenLayers绘制图形

    OpenLayers的显示构成由外向内为 ol Map 地图对象 ol layer Vector 图层对象layer Map含有多个layer 最终的显示效果是由多个layer叠加而成 ol source Vector和ol style S
  • FreeRTOS系列

    1 多任务系统 1 1 前后台系统 单片机裸机开发时 一般都是在main函数里面用while 1 做一个大循环来完成所有的处理 循环中调用相应的函数完成所需的处理 有时也需要在中断中完成一些处理 相对于多任务系统而言 这就是单人单任务系统也