RT-Thread

RT-Thread

RT-Thread 版权属于上海睿赛德电子科技有限公司,于 2006年 1月首次发布,初始版 本号为0.1.0,经过 10来年的发展,如今主版本号已经升级到3.0,累计开发者达到数百万, 在各行各业产品中装机量达到了惊人的2000多万,占据国产RTOS的鳌头。


在接触RT-Thread之前我已经深入学习过FreeRTOS实时操作系统,感觉这些操作系统的形式都大差不差,自认为无非是各种功能的函数名字不一样,时间片的实现,启动流程有些许不同。

RT-Thread和FreeRTOS类似,都拥有线程管理(在RT-Thread中叫线程,在FreeRTOS中叫任务),消息队列,信号量(二值,计数),互斥量,事件,软件定时器,内存管理,中断管理。比

FreeRTOS多了个邮箱(目前看来根据野火的源码分析,感觉和消息队列功能差不多)。


 启动流程

接下来讲一下RT-Thread的启动流程

当你拿到一个移植好的 RT-Thread工程的时候,你去看 main函数,只能在 main函数 里面看到创建线程和启动线程的代码,硬件初始化,系统初始化,启动调度器等信息都看 不到

那是因为RT-Thread拓展了main函数,在main函数之前把这些工作都做好了。

我们知道,在系统上电的时候第一个执行的是启动文件里面由汇编编写的复位函数 Reset_Handler。复位函数的最后会调用 C 库函数__main,__main 函数的主要工作是初始化系统的堆和栈,最后调用 C 中 的main函数,从而去到C的世界。

执行完__main之后,并不是跳转到C 中的main函数,而是跳转到component.c中的$Sub$$main函数,这是为什么?因为RT Thread使用编译器(这里仅讲解KEIL,IAR或者GCC稍微有点区别,但是原理是一样的) 自带的$Sub$$和$Super$$这两个符号来扩展了main函数。

使用$Sub$$main可以在执行 main之前先执行$Sub$$main,在$Sub$$main函数中我们可以先执行一些预操作,当做完这 些预操作之后最终还是要执行main函数。

这个就通过调用$Super$$main来实现。当需要扩展的函数不是main的时候,只需要将main换成你要扩展的函数名即可,即$Sub$$function 和$Super$$function。(mdk的扩展功能)


首先执行$Sub$$main函数,在其中包含的内容有:

  1. 关闭中断,除了硬FAULT和NMI可以响应外,其它统统关掉。
  2.  执行rtthread_startup()函数。

rtthread_startup()函数

RT-Thread 启动的时候会调用一个名为 rt_hw_board_init()的函数, 从函数名称我们可以知道它是用来初始化开发板硬件的,需要把硬件相关的初始化都放在 rt_hw_board_int()函数里面完成,比如时钟,比如串口等,具体初 始化什么由用户选择。

当这些硬件初始化好之后,RT-Thread 才继续往下启动,(就是把各种外设初始化放在这个函数之中去执行),RT-Thread该函数需要我们在board.c中自己编写。


由图片可见,在rtthread_startup()函数中先是关闭中断,板级硬件初始化。打印RT-Thread的版本号(要想成功打印,必须重映射一个控制台到rt_kprintf函数  )后面进行定时器,调度器,信号的初始化

最终创建一个初始线程。这个初始线程类似于FREERTOS中的创建任务的任务,就是在这个任务中去创建工程所用到的所有的任务。


RT-Thread的启动流程是这样的: 即先创建一个初始线程,等调度器启动之后,在这个初始线程里面创建各种应用线程,当 所有应用线程都成功创建好后,初始线程就把自己关闭。那么这个初始线程就在 rt_application_init()里面创建。

该函数也在component.c里面定义,我们可以去component.c中修改,一般情况下是在rt_application_init()中创建main主函数的线程,在main主函数线程中去创建其他的线程,其中硬件各种外设的初始化已经在rt_hw_board_int()中完成了,所以main主函数中只需要去创建其他的线程就可以了。


rt_application_init()函数     

在这个函数中判断使用静态还是动态方法创建main线程,也就是void  main_thread_entry(void*parameter),并初始化相关参数。


void  main_thread_entry(void*parameter)

在main主函数线程中除了调用rt_components_init()函数进行 RT-Thread的组件初始化外,最终是调用main的扩展函数$Super$$main()回到main函数。

这个是必须的,因为我们一开始在进入main函数之前,通过$Sub$$main()函数扩展了main 函数,做了一些硬件初始化,RTOS系统初始化的工作,当这些工作做完之后最终还是要 回到main函数,那只能通过调用$Super$$main()函数来实现。$Sub$$和$Super$$是MDK 自带的用来扩展函数的符号,通常是成对使用。


main函数执行到最后,通过LR寄存器指定的链接地址退出,在 创建main线程的时候,线程栈对应LR寄存器的内容是rt_thread_exit()函数,在 rt_thread_exit里面会把main线程占用的内存空间都释放掉。

至此,结束了,RT-Thread的整个启动流程。

在我看来这也是RT-Thread和FreeRTOS的主要区别。


重映射串口到rt_kprintf函数

在RT-Thread中,有一个打印函数rt_kprintf()供用户使用,方便在调试的时候输出各 种信息。如果要想使用rt_kprintf(),则必须将控制台重映射到rt_kprintf(),这个控制台可以 是串口、CAN、USB、以太网等输出设备,用的最多的就是串口,


SysTick_Handler()

这一部分是rtthread用于更新时基,实现时间片的功能代码。将这一部分直接放在SysTick_Handler()中执行。


在线程里面的延时函数必须使用RT-Thread里面提供的延时函数,并 不能使用我们裸机编程中的那种延时。这两种的延时的区别是RT-Thread里面的延时是阻 塞延时,

即调用rt_thread_delay()函数的时候,当前线程会被挂起,调度器会切换到其它就 绪的线程,从而实现多线程。如果还是使用裸机编程中的那种延时,那么整个线程就成为 了一个死循环,如果恰好该线程的优先级是最高的,那么系统永远都是在这个线程中运行, 根本无法实现多线程。

该特性在所有操作系统都是一样的,可以在所有外设初始化的时候使用delay,在任务或者线程中只能使用操作系统提供的延时函数。

关于RT-Thread的其他系统功能,其实和FreeRTOS差不多,总而言之还是去查询API函数的使用方法在工程中。感觉掌握了一款实时操作系统其他的操作系统入门相对来说也更加容易了。

共勉,绝望之为虚妄,正与希望相对。我的理解是现实有多绝望的同时,希望就有多大!

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

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

相关文章

C++ 并发编程指南(5)线程状态及切换

文章目录 一、多线程状态及切换1、线程状态2、状态切换 前言&#xff1a; C中的线程状态及切换是操作系统和C线程库&#xff08;如POSIX线程或C11及之后的<thread>库&#xff09;共同管理的。线程的状态和切换是多线程编程中的重要概念&#xff0c;下面将简要介绍C线程的…

【Linux取经路】守护进程

文章目录 一、前台进程和后台进程二、Linux 的进程间关系三、setsid——将当前进程设置为守护进程四、daemon——设置为守护进程五、结语 一、前台进程和后台进程 Linux 中每一次用户登录都是一个 session&#xff0c;一个 session 中只能有一个前台进程在运行&#xff0c;键盘…

国产工业级实时数据库

项目功能描述 Mars数据库的核心功能在于其能够高效地处理来自工业现场的大量传感器数据。它通过简化的可视化配置&#xff0c;允许用户轻松接入各种传感器&#xff0c;并进行数据记录和逻辑处理。Mars数据库在单机模式下支持高达120万个传感器信号的接入&#xff0c;而其分布式…

Python Excel 指定内容修改

需求描述 在处理Excel 自动化时,财务部门经常有一个繁琐的场景,需要读取分发的Excel文件内容复制到汇总Excel文件对应的单元格内,如下图所示: 这种需求可以延申为,财务同事制作一个模板,将模板发送给各员工,财务同事需收取邮件将员工填写的excel文件下载到本机,再类似…

Java Web学习笔记15——DOM对象

DOM&#xff1a; 概念&#xff1a;Document Object Model&#xff1a; 文档对象模型 将标记语言的各个组成部分封装为对应的对象&#xff1a; Document: 整个文档对象 Element&#xff1a;元素对象 Attribute&#xff1a; 属性对象 Text&#xff1a;文本对象 Comment&a…

【Linux取经路】信号的发送与保存

文章目录 一、重新理解发送信号二、信号的保存、阻塞信号的概念三、信号集操作函数3.1 sigprocmask3.2 sigpending 四、阻塞信号代码验证五、结语 一、重新理解发送信号 进程通过位图来实现对普通信号&#xff08;1-31号信号&#xff09;的保存&#xff0c;该位图保存在进程的…

冯喜运:6.7今日黄金原油行情分析及独家操作策略

【黄金消息面分析】&#xff1a;周三&#xff08;6月5日&#xff09;&#xff0c;金价回升逾1.2%&#xff0c;收盘报每盎司2,355.49美元&#xff0c;全面收复前一交易日的跌幅。周三当天前公布的美国民间就业数据弱于预期&#xff0c;增强了美联储将在今年晚些时候降息的预期&a…

多表连接查询和子查询

一、连接查询 连接查询是SQL语言最强大的功能之一&#xff0c;它可以执行查询时动态的将表连接起来&#xff0c;然后从中查询数据。 1.1、连接两表的方法 在SQL中连接两表可以有两种方法&#xff0c;一种是无连接规则连接&#xff0c;另一种是有连接规则连接。 无连接规则连…

PbootCms微信小程序官网模版/企业官网/社交电商官网/网络工作室/软件公司官网

在数字化时代&#xff0c;企业网站已成为吸引潜在客户、提升企业形象、和扩大品牌影响力的必备工具。因此&#xff0c;一个优秀的企业网站模板显得尤为重要。 企业官网的内容框架通常都包含企业形象、产品或服务类型、信息展示等部分&#xff0c;设计师需要借助和企业形象契合…

初学者如何对大模型进行微调?

粗略地说&#xff0c;大模型训练有四个主要阶段&#xff1a;预训练、有监督微调、奖励建模、强化学习。 预训练消耗的时间占据了整个训练pipeline的99%&#xff0c;其他三个阶段是微调阶段&#xff0c;更多地遵循少量 GPU 和数小时或数天的路线。预训练对于算力和数据的要求非…

【vue3|第6期】如何正确地更新和替换响应式对象reactive

日期&#xff1a;2024年6月5日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xff…

区间预测 | Matlab实现QRCNN-GRU-Attention分位数回归卷积门控循环单元注意力机制时序区间预测

区间预测 | Matlab实现QRCNN-GRU-Attention分位数回归卷积门控循环单元注意力机制时序区间预测 目录 区间预测 | Matlab实现QRCNN-GRU-Attention分位数回归卷积门控循环单元注意力机制时序区间预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现QRCNN-GRU-…

eNSP学习——配置RIP的版本兼容、定时器和协议优先级

目录 主要命令 原理概述 实验内容 实验拓扑 实验目的 实验编址 实验步骤 1、基本配置 2、配置RIP协议的版本兼容 3、配置RIP的定时器 4&#xff0e;配置RIP协议优先级 需要eNSP各种配置命令的点击链接自取&#xff1a;华为&#xff45;NSP各种设备配置命令大全PDF版…

二重,三重积分和曲面,曲线积分的关系和区别

这是我在学习完曲面曲线积分概念后容易和二重三重积分混淆而大概总结和区分了一下&#xff0c;如果有错误请大佬指出&#xff0c;多谢&#xff01;&#xff01;&#xff01;

CopilotKit:开源 Copilot 框架,部署应用内 AI 代理,使用 Langchain 自动执行任何任务!

原文链接&#xff1a;&#xff08;更好排版、视频播放、社群交流、最新AI开源项目、AI工具分享都在这个公众号&#xff01;&#xff09; CopilotKit&#xff1a;开源 Copilot 框架&#xff0c;部署应用内 AI 代理&#xff0c;使用 Langchain 自动执行任何任务&#xff01; &am…

WPS表格插件方方格子【凑数】功能:选出和等于固定数字的数

文章目录 后来发现可以下载方方格子插件&#xff0c;使用【凑数】功能https://ffcell.lanzouj.com/iwhfc1kjhayh【凑数】快速【凑数】 导师让沾发票&#xff0c;需要选出若干个数额的发票&#xff0c;使它们的和等于一个指定数。不知道怎么办了&#xff0c;查了一下&#xff0c…

SOA的发展历史

1.SOA的发展历程 回顾SOA发展历程&#xff0c;我们把其大致分为了三个阶段&#xff0c;下面将分别介绍每个阶段的重要标准和规范。 1.1.萌芽阶段 这一阶段以XML技术为标志&#xff0c;时间大致从20世纪90年代末到21世纪初。XML系W3C所建&#xff0c;源自流行的标准通用标记语…

Xcode 打包报错Command PhaseScriptExecution failed with a nonzero exit code

解决办法: 1、在Xcode项目中 Pods -> Targets Support Files -> Pods-项目名 -> Pods-项目名-frameworks 中(大约在第44行) 加上 -f 2、CocoaPods版本太旧了,可以尝试升级CocoaPods版本 使用sudo gem update cocoapods更新cocoapods&#xff0c;问题将在1.12.1版本已…

shell的编程方式

文章目录 变量俩种方式第一种方式第二种方式 取消变量数组创建数组获取数组元素的方式 read输出的方式限制输入的方式 流程控制方式for循环输出的方式第一种方式第二种方式while循环输出的方式select选择输出的方式 判断方式判断的四种方式第一种方式第二种方式第三种方式 算术…

Docker笔记-解决非交互式运行python时print不输出的问题

换句话来说就是在docker中如何不会python的print 只需要在启动时&#xff0c;不让python缓冲其输出。 关键命令如下&#xff1a;PYTHONUNBUFFERED1 如下&#xff1a; docker run -e PYTHONUNBUFFERED1 <your_image> 下面解释下-e "-e"选项的全称是"…