RT-Thread简介及启动流程分析
阅读引言: 最近在学习RT-Thread的内部机制,觉得这个启动流程和一些底层原理还是挺重要的, 所以写下此文。
目录
1, RT-Thread简介
2,RT-Thread任务的几种状态
3, 学习资源推荐
4, 启动流程分析开始
1, RT-Thread简介
RT-Thread是一个来自中国的开源、中英文双语的实时操作系统(RTOS),它适用于各种资源受限的嵌入式系统。自2006年由熊谱翔(Bernard Xiong)创建以来,RT-Thread已经发展成为一个功能丰富、高度可伸缩、完全开源的实时操作系统。
以下是RT-Thread的一些主要特性:
-
实时性能:RT-Thread提供了高实时性能,能够满足嵌入式系统对实时性的需求。
-
可伸缩性:系统设计为可伸缩,可以运行在从几百字节内存的简单嵌入式设备到拥有大量内存的复杂系统。
-
组件丰富:RT-Thread拥有丰富的组件库,包括文件系统、TCP/IP网络协议栈、设备驱动框架等。
-
易用性:RT-Thread提供了简洁明了的API设计,易于学习和使用。
-
开源社区:拥有活跃的开源社区,众多开发者和公司贡献代码和组件。
-
跨平台:支持多种处理器架构,如ARM Cortex-M、Cortex-R、Cortex-A系列,以及MIPS、x86、XTensa等。
-
工具链支持:与多种编译器和集成开发环境(IDE)兼容,如Keil、IAR、GCC等。
-
软件包生态:RT-Thread Studio提供了丰富的软件包管理,方便开发者快速集成和使用。
-
文档和教程:提供详细的文档和教程,帮助开发者快速上手。
-
商业友好:RT-Thread的BSD许可协议非常友好,允许商业和个人用户免费使用和修改。
RT-Thread适用于各种嵌入式应用场景,包括智能家居、智能穿戴、智能安防、工业自动化、车载设备等。它的设计目标是为嵌入式开发提供稳定、高效、易用的解决方案。
2,RT-Thread任务的几种状态
状态 | 特点 |
---|---|
初始状态 | 创建完任务还未开启任务调度器, 此时任务就属于此种状态 |
就绪状态 | 启动调度器后, 任务属于此种状态 |
挂起(阻塞) | 任务因为等待某种资源而阻塞 |
运行 | 运行 |
关闭 | 线程退出 |
- 初始状态
当线程刚开始创建还没开始运行时就处于初始状态:
使用rt_thread_init()创建,但是未调用rt_thread_startup使它就绪
使用rt_thread_create()创建,但是未调用rt_thread_startup使它就绪
- 就绪状态
这个线程完全准备好了,随时可以运行:只是还轮不到它:这时它就处于就绪态(Ready)。
在下面几种情况下,线程都处于就绪状态:
我们创建线程后,使用rt_thread_startup()函数使它进入就绪态。
它在运行过程中,被更高优先级的线程抢占了,这时它处于就绪状态。
它在运行过程中,轮到同优先级的线程运行了,这时它处于就绪状态。
它因为等待某些资源而没有运行,别的线程或者中断函数把它唤醒了,这时它处于就绪状态。
- 运行状态
当处于就绪状态的线程运行时,它就处于运行状态。
- 挂起状态
在日常生活的例子中,母亲在电脑前跟同事沟通时,如果同事一直没回复,那么母亲的工作就被卡住了、被堵住了、处于挂起状态。
重点在于:母亲在等待。
在RTOS中创建多个任务后, 如果别的这些任务中优先级最高的任务(线程)在循环执行过程中不调用休眠相关的函数让出CPU的资源, 那么比它优先级低的任务根本呢不会执行。
在实际产品中,我们不会让一个线程一直运行,而是使用"事件驱动"的方法让它运行:
线程要等待某个事件,事件发生后它才能运行
在等待事件过程中,它不消耗CPU资源
在等待事件的过程中,这个线程就处于挂起状态, 就是阻塞状态
在挂起状态的线程,它可以等待两种类型的事件:
时间相关的事件
可以等待一段时间:我等2分钟
也可以一直等待,直到某个绝对时间:我等到下午3点
同步事件:这事件由别的线程,或者是中断程序产生
例子1:线程A等待线程B给它发送数据
例子2:线程A等待用户按下按键
同步事件的来源有很多(这些概念在后面会细讲):
信号量(semaphores)
互斥量(mutexe)
事件集(event)
在等待一个同步事件时,可以加上超时时间。比如等待队里数据,超时时间设为10ms:
10ms之内有数据到来:成功返回
10ms到了,还是没有数据:超时返回
- 关闭状态
当线程运行结束时,将处于关闭状态:
可由运行状态正常退出,进入关闭状态
或者通过线程删除函数进入关闭状态
rt_err_t rt_thread_detach(),用来删除使用rt_thread_init()创建的线程
rt_err_t rt_thread_delete(),用来删除使用rt_thread_create()创建的线程
在进入关闭状态时,线程所占据的资源(比如栈)不会立即释放,需等到空闲进程运行时才能清理。在这两个删除任务的函数内部实现是将任务控制块从不同的状态链表中进行搬移, 实际在回收任务控制块和任务栈的任务是在操作系统的空闲任务中做的。
3, 学习资源推荐
FreeRTOS
RT-Thread
没有系统学习过RTOS的兄弟建议去学第一个, 正点原子推出的FreeRTOS教程, 讲得很仔细, 很底层。
4, 启动流程分析开始
追一下代码: 这里简单补充一下一般mcu的启动流程, 一般在固化程序运行完成之后就到了启动代码, 不太明白为什么mcu启动的第一个处理的函数(符号)是复位处理的可以去看我之前写的这篇文章: http://t.csdnimg.cn/DUkKK
Reset_Handler:
; Reset handler
Reset_Handler PROCEXPORT Reset_Handler [WEAK] @导出Reset_Handler符号, 别的源文件可见IMPORT __main @导入编译器生成的__main引导函数IMPORT SystemInit @导入SystemInit函数符号LDR R0, =SystemInit @初始化时钟等BLX R0 LDR R0, =__mainBX R0ENDP
mcu上电之后执行完固化的引导程序之后, 会根据拨码开关的指示来存储器中取出指令执行, 执行的指令的开始是启动代码, 启动代码中的第一个函数符号是复位处理, 在复位处理中调用到了SystemInit函数, 接下来到了SystemInit函数了。
SystemInit:
/*** @brief Setup the microcontroller system* Initialize the Embedded Flash Interface, the PLL and update the * SystemCoreClock variable.* @note This function should be used only after reset.* @param None* @retval None*/
void SystemInit (void)
{/* Reset the RCC clock configuration to the default reset state(for debug purpose) *//* Set HSION bit */RCC->CR |= 0x00000001U;/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#if !defined(STM32F105xC) && !defined(STM32F107xC)RCC->CFGR &= 0xF8FF0000U;
#elseRCC->CFGR &= 0xF0FF0000U;
#endif /* STM32F105xC */ /* Reset HSEON, CSSON and PLLON bits */RCC->CR &= 0xFEF6FFFFU;/* Reset HSEBYP bit */RCC->CR &= 0xFFFBFFFFU;/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */RCC->CFGR &= 0xFF80FFFFU;#if defined(STM32F105xC) || defined(STM32F107xC)/* Reset PLL2ON and PLL3ON bits */RCC->CR &= 0xEBFFFFFFU;/* Disable all interrupts and clear pending bits */RCC->CIR = 0x00FF0000U;/* Reset CFGR2 register */RCC->CFGR2 = 0x00000000U;
#elif defined(STM32F100xB) || defined(STM32F100xE)/* Disable all interrupts and clear pending bits */RCC->CIR = 0x009F0000U;/* Reset CFGR2 register */RCC->CFGR2 = 0x00000000U;
#else/* Disable all interrupts and clear pending bits */RCC->CIR = 0x009F0000U;
#endif /* STM32F105xC */#if defined(STM32F100xE) || defined(STM32F101xE) || defined(STM32F101xG) || defined(STM32F103xE) || defined(STM32F103xG)#ifdef DATA_IN_ExtSRAMSystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM */
#endif #ifdef VECT_TAB_SRAMSCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#elseSCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
建议各位先看一些大型工程代码的时候使用SourceInsight。总结一下Systeminit函数做了啥, 初始化Flash, 系统时钟。
RTOS的启动, 需要在特定的编译环境下才能成功, 举个例子
在绝大多数的编程语言中, 数字、字母、下划线是构成字符串的要求, 这种写法防到标准C语言语法中肯定就报错了, 只是在嵌入式C语言中, 可以根据不同的平台, 不同的应用场景将编译器修改配套, 这样就不会报错了。
在复位处理中, 当SystemInit执行完之后, 会接着调用编译器提供的__main引导函数, 找到函数的main函数入口, 从而去执行用户代码。在这里有一点特殊的是, __main引导找到的函数是 $Sub$$main, 所有接下来我们该去分析一下 $Sub$$main做了什么了。
int rtthread_startup(void)
{rt_hw_interrupt_disable();/* board level initialization* NOTE: please initialize heap inside board initialization.*/rt_hw_board_init();/* show RT-Thread version */rt_show_version();/* timer system initialization */rt_system_timer_init();/* scheduler system initialization */rt_system_scheduler_init();#ifdef RT_USING_SIGNALS/* signal system initialization */rt_system_signal_init();
#endif/* create init_thread */rt_application_init();/* timer thread initialization */rt_system_timer_thread_init();/* idle thread initialization */rt_thread_idle_init();/* start scheduler */rt_system_scheduler_start();/* never reach here */return 0;
}
可以看到在这个函数中还是做了蛮多事情的, 但是主要的就两个函数。
看一下这两个源文件的实现
可以看到比较核心的是创建了一个主线程, 要不先去看看这个主线程干了啥?
可以看到, 在初始化一些系统组件之后, 调用到了我们的main函数。
具体任务切换是如何切的就要看cpu架构了, 本质通过一些链表, 定时器, 找到需要运行的任务, 将正在运行的任务和需要运行的任务进行一次上下文切换。
到此, RT-Thread启动流程就大致的分析完成了。
相关文章:
RT-Thread简介及启动流程分析
阅读引言: 最近在学习RT-Thread的内部机制,觉得这个启动流程和一些底层原理还是挺重要的, 所以写下此文。 目录 1, RT-Thread简介 2,RT-Thread任务的几种状态 3, 学习资源推荐 4, 启动流程分…...
MCU嵌入式AI开发笔记-视频笔记同步更新
MCU嵌入式AI开发笔记 抖音B站等站点笔记视频同步更新 01嵌入式AI大的方向 STM32跑神经网络 http://news.eeworld.com.cn/mp/EEWorld/a134877.jspx 为什么可以在STM32上面跑神经网络?简而言之就是使用STM32CubeMX中的X-Cube-AI扩展包将当前比较热门的AI框架进行C代码的转化,…...
DoIP——step2:车辆发现
文章目录 前言一、IP地址配置1.1 AutoIP1.2 DHCP1.3 DoIP实体的IP地址配置流程二、车辆发现车辆声明报文内容如下:前言 完成诊断设备到车辆的物理连接并通过激活线使能诊断连接后边缘节点将会将连接状态传递至应用层,在开始车辆发现过程之前,需要先进行各自的IP地址配置,获…...
【动态规划】0-1背包问题
【动态规划】0-1背包问题 题目:现在有四个物品,背包总容量为8,背包最多能装入价值为多少的物品? 我的图解 表格a【i】【j】表示的是容量为j的背包装入前i个物品的最大价值。 拿a【1】【1】来说,它的值就是背包容量为1,只考虑…...
WordPress 高级缓存插件 W3 Total Cache Pro 详细配置教程
说起来有关 WordPress 缓存插件明月已经发表过不少文章了,但有关 W3 Total Cache Pro 这个 WordPress 高级缓存插件除了早期【网站缓存插件 W3 Total Cache,适合自己的才是最好的!】一文后就很少再提及了,最近因为明月另一个网站【玉满斋】因为某些性能上的需要准备更换缓存…...
每日一题——Python实现PAT乙级1012 数字分类(举一反三+思想解读+逐步优化)五千字好文
一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 代码优点 代码缺点 时间复杂度 空间复杂度 代码改进建议 我要更强 哲…...
Unity2D游戏制作入门 | 13 ( 之人物三段攻击 )
上期链接:Unity2D游戏制作入门 | 12(之人物受伤和死亡的逻辑动画)-CSDN博客 上期我们聊了人物的受伤和死亡的逻辑和动画,我们主要学习了事件的执行,即我们在人物受伤时可能会触发很多的事件,比如触发人物受伤的动画以及播放音乐等…...
DAY04 HTMLCSS
文章目录 一 表单(1) 数字控件(2) 颜色控件(3) 日期控件(4) 月份控件(5) 星期控件(6) 搜索控件(7) 范围控件 二 浮动框架三 结构化标签四 CSS1 CSS概述2 CSS的编写位置1. inline style 行内样式2. inner style 内部样式3. outer style 外部样式4. 小结 3 CSS选择器1. 通用选择器…...
Linux_理解程序地址空间和页表
目录 1、进程地址空间示意图 2、验证进程地址空间的结构 3、验证进程地址空间是虚拟地址 4、页表-虚拟地址与物理地址 5、什么是进程地址空间 6、进程地址空间和页表的存在意义 6.1 原因一(效率性) 6.2 原因二(安全性) …...
NAND闪存市场彻底复苏
在全球内存市场逐渐走出阴霾、迎来复苏曙光之际,日本存储巨头铠侠(Kioxia)凭借敏锐的市场洞察力和及时的战略调整,成功实现了从生产紧缩到全面复苏的华丽转身。这一转变不仅彰显了企业在逆境中的生存智慧,也为全球半导…...
过拟合与正则化
Location Beijing 过拟合 对于一个模型 A A A,解向量空间为 θ \theta θ,误差函数用式1表示 J ( θ ) J a c c [ y θ ( x ) − y ] 2 (1) J(\theta)J_{acc}[y_\theta(x)-y]^2\tag{1} J(θ)Jacc[yθ(x)−y]2(1) 首先我们考虑用模型 A A A拟合下…...
VMware挂载NAS存储异常处理
问题概述 由于非法关机或恢复,NFS存储可能会出现以下问题: 数据存储处于挂起状态或无法正常识别。虚拟机的配置文件或虚拟磁盘仍然注册在异常数据存储上。系统误认为有虚拟机在使用该数据存储。 问题对策 下面是详细的排查步骤和解决对策:…...
Redis 7.x 系列【4】命令手册
有道无术,术尚可求,有术无道,止于术。 本系列Redis 版本 7.2.5 源码地址:https://gitee.com/pearl-organization/study-redis-demo 文章目录 1. 说明2. 命令手册2.1 Generic2.2 数据类型2.2.1 String2.2.2 Hash2.2.3 List2.2.4 S…...
走进Elasticsearch
什么是ES 是一个分布式、RESTful风格的搜索和数据分析引擎 中文参考文档: 《Elasticsearch中文文档》 | Elasticsearch 技术论坛 elasticSearch官网: Functions and Operators | Elasticsearch Guide [7.11] | Elastic查询方式 Kibana查询(原…...
QT TCP服务器和客户端示例程序
下面是一个简单的 Qt TCP 服务器和客户端示例,演示了如何使用 vSetDriver、vSetListener 和 vTcpServerStart 函数。假设 vSetDriver 和 vSetListener 是你定义的自定义函数。 TCP 服务器部分 tcpserver.h #ifndef TCPSERVER_H #define TCPSERVER_H#include <QT…...
Xlua三方库Android编译出错解决办法
Xlua三方库Android编译出错解决办法 最近听老师的热更教程,讲到xlua编译android平台会报错,也是看了老师的博客,按照方法去解决,然而问题并没有解决。应该是因为代码更新或者版本不一样,在此简单记录一下解决过程。 参…...
美国犹他州立大学《Nature Geoscience》(IF=18)!揭示草本植物对土壤有机碳的重要贡献!
随着全球变暖的影响越来越显著,碳固定成为了一个备受关注的话题。在这个背景下,热带草原被认为是一个潜在的碳固定区域。然而,目前的研究主要关注于在热带草原中种植树木,以期望增加土壤有机碳含量。但是,热带草原中的…...
高考专业抉择计算机专业热度不减,兴趣、实力与挑战并存。
作为一名即将步入大学校门的高考生,我对于计算机相关专业是否仍是热门选择感到困惑。在过去几年里,计算机科学与技术、人工智能、网络安全、软件工程等专业一直备受追捧,吸引了无数学生。然而,随着市场竞争加剧和市场饱和度提高&a…...
Flask-RQ
Flask-RQ库教程 Flask-RQ 是一个用于在 Flask 应用中集成 RQ(Redis Queue)的扩展。RQ 是一个简单的 Python 库,用于将任务排入 Redis 队列并异步执行这些任务。这对于处理长时间运行的任务(如发送电子邮件、生成报告等࿰…...
LeetCode 58. 最后一个单词的长度
LeetCode 58. 最后一个单词的长度 你一个字符串 s,由若干单词组成,单词前后用一些空格字符隔开。返回字符串中 最后一个 单词的长度。 单词 是指仅由字母组成、不包含任何空格字符的最大子字符串 示例 1: 输入:s “Hello World”…...
3阶段提交协议(3pc)
3阶段提交协议(3pc) 1 简介 三阶段提交协议是一个强一致、中心化的原子提交协议。解决了分布式事务、副本容错等分布式问题。其核心思想是将2PC的二阶段提交协议的“准备阶段”一分为二,形成了由CanCommit、PreCommit、DoCommit三个阶段组成…...
802.11中的各种帧
在无线网络中,802.11协议定义了三种类型的帧:管理帧(Management Frames)、控制帧(Control Frames)和数据帧(Data Frames)。每种类型的帧都有其特定的功能,帮助维护和管理…...
SAP PP学习笔记21 - 计划策略的Customize:策略组 > 策略 > 需求类型 > 需求类(消费区分,计划区分)
上面几章讲了MTS,MTO,ATO的计划策略。 本章来讲一下它的后台 Customize。 1,Customizeing:Planned Indep.Reqmts Management 这是配置计划策略的整个过程: - Requirements Type / Class 需求类型 / 需求类 - Plann…...
axure9设置组件自适应浏览器大小
问题:预览时不展示下方的滚动条 方法一:转化为动态面板 1.在页面上创建一个矩形 2.右键-转化为动态面板 3.双击进入动态面板设置 4.设置动态面板矩形的颜色 5.删除原来的矩形 6.关闭动态面板,点击预览 7.此时可以发现底部没有滚动条了 方法…...
示例:WPF中TreeView自定义TreeNode泛型绑定对象来实现级联勾选
一、目的:在绑定TreeView的功能中经常会遇到需要在树节点前增加勾选CheckBox框,勾选本节点的同时也要同步显示父节点和子节点状态 二、实现 三、环境 VS2022 四、示例 定义如下节点类 public partial class TreeNodeBase<T> : SelectBindable<…...
C++ explicit关键字的用法
在C中,explicit关键字用于构造函数和转换运算符,以防止隐式转换。它可以帮助我们避免意外的类型转换,从而提高代码的安全性和可读性。explicit关键字只能用于单参数构造函数和转换运算符。 使用explicit的场景 单参数构造函数: 当…...
51.Python-web框架-Django开始第一个应用的增删改查
目录 1.概述 2.创建应用 创建app01 在settings.py里引用app01 3.定义模型 在app01\models.py里创建模型 数据库迁移 4.创建视图 引用头 部门列表视图 部门添加视图 部门编辑视图 部门删除视图 5.创建Template 在app01下创建目录templates 部门列表模板depart.ht…...
Redis之线程IO模型
引言 Redis是个单线程程序!这点必须铭记。除了Redis之外,Node.js也是单线程,Nginx也是单线程,但是他们都是服务器高性能的典范。 Redis单线程为什么能够这么快! 因为他所有的数据都在内存中,所有的运算都…...
针对微电网中可时移,柔性,基础负荷的电价响应模型---代码解析
前言: 在上两篇帖子中,讲解了我对于粒子群算法的理解,站在巨人的肩膀上去回望:科研前辈们确实非常牛逼,所以它才成为了非常经典的算法。这篇帖子主要是想分享一下,对于微电网、电力系统的论文中,…...
git使用http协议时免密pull和push方法
1、创建文件 在项目目录下创建.git-credentials文件,内容如下,填入自己的用户名和密码即可,如果是gitlab,把地址换成自己的gitlab的地址即可。 https://{用户名}:{密码}github.com2、终端执行 git config --global credential.…...
专业集团门户网站建设方案/扬州网络优化推广
1 第2-3课:模板引擎 Thymeleaf 基础使用 1.1 模板引擎 模板引擎是为了使用户界面与业务数据(内容)分离而产生的,它可以生成特定格式的文档,用于网站的模板引擎就会生成一个标准的 HTML 文档。 模板引擎的实现方…...
如何复制wordpress主题/合肥关键词排名工具
小米公开亮度调校方法,友商请速度跟进除了 1.08 亿像素、高刷新率屏幕以及骁龙 865 处理器外,小米10 还有很多细节值得赞赏。比如小米在发布会上花了不少篇幅介绍的小米10 双光线传感器 4096 级别亮度调节方案。更精准、舒适的亮度调节让别家品牌的用户都…...
室内装修设计上海/深圳知名seo公司
二值化核心思想 设阈值,大于阈值的为0(黑)或255(白),使图像成为黑白图。 阈值可固定,也可自适应阈值。 自适应阈值一般为一点像素与这点为中心的区域像素平均值或者高斯分布加权和的比较&#x…...
如何做生鲜配送网站生意/湖北短视频搜索seo
想象一下,如果您企业的人力资源部门不仅可以使用数据来预测员工的敬业度,还能够知道员工什么时候可能会跳槽?而这就是HighGround公司的 创始人兼首席执行官Vip Sandhir想要通过该公司最新员工敬业度产品所实现的目标。通过创建能够直接从员工中挖掘数据…...
wordpress看板猫/网站推广与优化方案
题目描述 矩阵对角线 是一条从矩阵最上面行或者最左侧列中的某个元素开始的对角线,沿右下方向一直到矩阵末尾的元素。例如,矩阵 mat 有 6 行 3 列,从 mat[2][0] 开始的 矩阵对角线 将会经过 mat[2][0]、mat[3][1] 和 mat[4][2] 。 给你一个…...
wordpress 手机无法访问/产品软文案例
安装教程 1、首先在本站下载解压文件包,得到iso安装镜像文件,如图;资源地址:MathWorks MATLAB R2020a中文版 2、使用压缩软件解压ISO镜像文件,win10系统的话可以直接加载,直接运行【setup.exe】开始安装&a…...