rt-thread启动流程(最详细教程)

4 篇文章 0 订阅
订阅专栏

资料下载

RT-Thread Simulator 例程

操作流程

  1. 将上面的仿真例程下载并解压,通过MDK打开,编译,调试,并打开串口点击运行,就可以看到如下输出了:
    在这里插入图片描述
  2. 添加自己的 thread:在main()函数中添加即可,如下图:
    在这里插入图片描述

启动流程

  1. 首先是通过startup_stm32f103xe.s启动文件调用SystemInit(),系统初始化完成后,调用C库函数__main(),然后由__main()调用用户的main()函数。但是,由于ARMCC编译器的特性,可以在调用main()函数前插入一个$Sub$$main()函数(其他编译器也有类似特性)。rt-thread就是利用了这个特性,使所有的硬件、系统初始化都在$Sub$$main()函数完成,而不需要用户在main()中调用。
    在这里插入图片描述
  2. 接下来看看 rtthread_startup() 函数:
    在这里插入图片描述
  3. 我们进入到 rt_application_init() 函数去看一下:
    在这里插入图片描述
    在这里插入图片描述
  4. 以上就是系统的启动即初始化流程,以及实现自己的 thread 的操作流程。但是我们明明还有其他的 thread 在运行啊,比如上面图一中的tshelltidle线程,这两个线程又是从哪里启动的呢?
    在这里插入图片描述
  5. 首先,我们通过全局搜索tshell,看下这个这个thread是在哪里创建的:
#define FINSH_THREAD_NAME "tshell"

在这里插入图片描述
原来是在 shell.c 中的finsh_system_init()函数中创建了tshell线程,那理论上是不是就应该全局搜索在哪里调用了finsh_system_init()函数呢?确实是,但搜索后发现,这个函数没有被调用的记录,这又是为啥呢?

  1. 重点就在finsh_system_init()函数后面的一句:
INIT_APP_EXPORT(finsh_system_init);

查看定义如下(C语言中##起连接作用):
在这里插入图片描述
那么INIT_APP_EXPORT(finsh_system_init);这句翻译一下,就是:

INIT_EXPORT(finsh_system_init, "6");

再翻译一下,就是:

RT_USED const init_fn_t __rt_init_finsh_system_init SECTION(".rti_fn.6") = finsh_system_init;

这句就已经很清晰了吧,定义了一个变量__rt_init_finsh_system_init,变量类型为const init_fn_t(其中init_fn_t为函数指针),这个变量的值就是finsh_system_init()这个函数的起始地址,重点是:将这个函数起始地址放在了.rti_fn.6的段中!
分析到这里,就很容易再分析出另外几个宏定义的作用了:

INIT_BOARD_EXPORT(fn) : 将板子初始化函数起始地址放到.rti_fn.1的段中
INIT_PREV_EXPORT(fn) :将预初始化函数起始地址放到.rti_fn.2的段中
INIT_DEVICE_EXPORT(fn) :将设备初始化函数起始地址放到.rti_fn.3的段中
INIT_COMPONENT_EXPORT(fn) :将组件初始化函数起始地址放到.rti_fn.4的段中
INIT_ENV_EXPORT(fn) :将环境初始化函数起始地址放到.rti_fn.5的段中

这里再提醒一下,当在同一个段中放入多个变量时,这些变量会按照时间顺序依次往后排。

  1. 现在我们知道,tshell线程创建函数没有被直接调用,而是放在了一个特色的段中,那么这个段中的函数什么时候被执行的呢?这个我也没找到什么好的定位方法,只能从初始化函数依次看下来,然后发现,有这么一条函数调用链:

$Sub$$main() --> rtthread_startup() --> rt_application_init() --> main_thread_entry() --> rt_components_init()

在这里插入图片描述
通过以上代码,我们看到通过INIT_EXPORT()宏又定义了几个函数并放入了相应的段:

rti_start() --> .rti_fn.0
rti_board_start() --> .rti_fn.0.end
rti_board_end() --> .rti_fn.1.end
rti_end() --> .rti_fn.6.end

根据上面所定义段的命名,猜测一下这些段的地址关系应该是:

.rti_fn.0 --> .rti_fn.0.end --> .rti_fn.1 --> .rti_fn.1.end --> .rti_fn.2 --> .rti_fn.3 --> .rti_fn.4 --> .rti_fn.5 --> .rti_fn.6 --> .rti_fn.6.end

打开map文件看一下各个段的地址验证一下(由于我们例程中并没有使用到2-5这几个段,所以map中没有记录):
在这里插入图片描述

这里有个还有个疑问:各个段的地址是怎么确定的呢?由编译器指定还是由开发人员指定呢?
如果由编译器指定,那编译器又怎么知道哪个段需要放前面呢?如果由开发人员指定,又是在哪里指定的呢?

自问自答一下:我暂时没有找到什么资料,但是通过在代码中添加其他的段名进行各种尝试,发现段地址的由编译器决定的,而段的存放顺序是由段的名字按字母排序决定的!如下图:
在这里插入图片描述

接下来终于可以看看这些初始化函数是怎么调用的了:

/**
 * @brief  RT-Thread Components Initialization.
 */
void rt_components_init(void)
{
    volatile const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++)
    {
        (*fn_ptr)();
    }
}

通过以上函数中的for循环,直接将__rt_init_rti_board_end(即.rti_fn.1.end)__rt_init_rti_end(即.rti_fn.6.end)之间的所有初始化函数执行了一遍。当然,也就包括了在.rti_fn.6段中的finsh_system_init()函数了。

  1. 同理,通过以下的函数调用流程,可以将.rti_fn.1中的初始化函数也执行一遍:

$Sub$$main() --> rtthread_startup() --> rt_hw_board_init() --> rt_components_board_init()

/**
 * @brief  Onboard components initialization. In this function, the board-level
 *         initialization function will be called to complete the initialization
 *         of the on-board peripherals.
 */
void rt_components_board_init(void)
{
    volatile const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
    {
        (*fn_ptr)();
    }
}

通过以上函数中的for循环,直接将__rt_init_rti_board_start(即.rti_fn.0.end)__rt_init_rti_board_end(即.rti_fn.1.end)之间的所有初始化函数执行了一遍。而且,在rtthread_startup()函数中,rt_hw_board_init()函数是比rt_application_init()函数更早调用,这就保证了.rti_fn.1段中的函数要早于其他段中函数的执行。

  1. rt-thread的启动流程这就讲完啦,大家现在应该知道为什么要把这些初始化函数放在这么多个段中了吧?

因为在同一个段的函数执行顺序是由编译器决定的,如果我们需要指定顺序,只能通过在不同段中实现。

RT-ThreadRTT启动流程
肥宅快乐博客
11-17 2472
文章目录RTOS的俩种启动方式方式一:先创建所有线程,再调度方式二:在启动线程中,创建线程RTT的启动流程1.上电后首先执行的复位函数2.调用__main函数3.main函数的预操作`$Sub$$main`函数`rtthread_startup()`函数`rt_application_init()`函数`main_thread_entry`函数4.main函数中创建线程 RTOS的俩种启动方式 R...
rt-thread入门教程PPT
03-13
* RT-Thread启动过程包括 SystemInit()、Main()、SystemInit()、$Sub$$main()、rtthread_startup()、rt_application_init() 和 main_thread_entry * RT-Thread 的内存管理包括堆栈的概念 * RT-Thread 的应用场景...
RT-Thread 启动流程详解
weixin_42530814的博客
04-23 1634
RT-Thread启动流程是操作系统初始化和运行应用程序之前的关键步骤。系统启动入口:RT-Thread 规定的统一启动入口是函数。不同的平台和编译器可能会有不同的启动文件和入口点,但最终都会调用这个函数。硬件初始化:在函数中首先进行的是硬件的初始化,这通常包括 CPU、内存、外设等的初始化。系统堆初始化:硬件初始化之后,系统会初始化系统堆,这是为应用程序和其他软件组件提供内存分配的基础。打印版本信息:系统会打印出 RT-Thread 的版本信息,这对于调试和确认系统状态很有帮助。定时器初始化。
RT-Thread 启动流程
最新发布
qq_24093081的博客
09-01 508
系统启动后先从汇编代码 startup_stm32f103xe.s 开始运行,然后跳转到 C 代码,进行 RT-Thread 系统启动,最后进入用户程序入口函数 main()。rt_hw_board_init() 中完成系统时钟设置,为系统提供心跳、串口初始化,将系统输入输出终端绑定到这个串口,后续系统运行信息就会从串口打印出来。main() 函数是 RT-Thread 的用户代码入口,用户可以在 main() 函数里添加自己的应用。(4)初始化定时器线程、空闲线程,并启动调度器。扩展功能的使用,详见。
RTT(RT-Thread)内核启动流程详解
qq_25218501的博客
07-25 2324
启动的第一阶段从启动汇编代码开始执行,我们的编译环境一共有三种分别为MDK(如Keil5)、IAR、GCC(如VScode、CLion等),不同开发工具调用的函数都是不一样的,不过它们最终的结果都是进入到rtthread_startup函数里执行。我们使用的编译软件是RT Thread Stduio,它使用的是GCC编译环境,它执行完启动文件,然后经过入口函数entry()以后,最终调用了函数。
RT-Thread启动流程
qq_43460068的博客
09-24 1536
第二种我称之为小心翼翼,十分谨慎法,这种方法是在main函数中将硬件和RTOS系统初始化好,然后创建一个启动线程后就启动调度器,然后再启动线程里面在创建各种应用线程,当所有的线程都创建好之后,启动线程把自己删除,具体的伪代码实现如下。、应用线程的优先级比初始线程的优先级高,那创建完后立马去执行刚 刚创建的应用线程,当应用线程被阻塞时,继续回到初始线程被打断的地方继续往下执行, 直到所有应用线程创建完成,最后初始线程把自己关闭,完成自己的使命;到所有应用线程创建完成,最后初始线程把自己关闭,完成自己的使命。
RT-Thread OS的启动流程
weixin_34257076的博客
03-07 375
1、RT进入main之前, SystemInit函数初始化时钟。 2、main函数位于startup.c文件中。进行两个工作 系统开始前,rt_hw_interrupt_disable关闭所有中断。 之后使用rtthread_startup启动RTThread 3、函数rtthread_startup()完成的工作: 1、调用函数rt_hw_board_init 完成板子初始化工作 2、...
rt-thread-3.1.3_rtthread_RT-Thread_nano_rtthreadopenocd_RT-Threa
09-30
在"rtthread nano"的模板中,你可以找到这些核心功能的实现,适合于资源有限的嵌入式设备。线程调度是操作系统的核心部分,它决定了程序中的各个任务如何在处理器上交替执行。在RT-Thread Nano中,线程按照优先级...
RT-thread相关介绍与面试问题+答案
03-05
RT-thread的初始化过程主要包括硬件初始化、内核对象初始化、创建主线程以及启动调度器等步骤。这些步骤通过定义在链接脚本中的初始化函数表实现,确保了系统的稳定启动和可靠运行。 - **初始化顺序**: - INIT_...
RT-thread移植指南-RISC-V.docx
09-24
- **RT-thread启动流程**:调整RT-thread启动代码,使其适应RISC-V的启动过程,通常包括初始化内存管理、调度器和基本系统服务。 - **配置宏、全局符号的适配**:根据RISC-V的特性修改RT-thread的配置宏和全局...
RT-Thread-MicroPython 用户手册.pdf
09-17
RT-Thread MicroPython 开发手册》是一份详细介绍如何在RT-Thread操作系统上使用MicroPython的用户手册。RT-Thread是一个流行的开源实时操作系统,而MicroPython则是Python编程语言的一个轻量级实现,适用于资源...
RT-Thread教程
06-26
RT thread教程,网友写的,还算详细
RT-Thread最全入门教程
11-27
国产最优秀的嵌入式实时操作系统RT-ThreadRT-Thread是一个实时的内核(全抢占优先级调度,调度器时间复杂度O(1)),但在发展过程中,RT-Thread实时操作系统得到了来自全国嵌入式开发工程师的鼎力支持,为RT-Thread添砖加瓦,现在它不仅仅是一款高效、稳定的实时核心,也是一套面向嵌入式系统的软件平台,覆盖了全抢占的实时操作系统内核,小巧而与底层具体实现无关的文件系统,轻型的TCP/IP协议栈以及轻型的多窗口多线程图形用户界面。
RT-Thread系列--启动过程
coderma的博客
01-16 538
RT-Thread启动过程分析
RT-Thread启动流程
booksyhay的专栏
12-09 823
其中,rt_application_init()函数会创建“main”线程,线程函数为main_thread_entry(),该函数会调用用户的main()函数。最后,调用rt_system_scheduler_start()启动调度器。后面,rt_thread_idle_init()函数会创建idle线程。
rt_thread启动流程
weixin_38931060的博客
03-17 485
启动流程: 1:执行$sub$$main函数,此函数为main扩展函数,就相当于是在main函数里面进行操作,只是他是在执行main函数之前执行。   在components.c文件中有定义: /* $Sub$$main 函 数 */ int $Sub$$main(void) { rtthread_startup(); return 0; } 在这里 $Sub$$main 函数调用了 rtthread_startup() 函数,其中rtthread_startup() 函数的代码如下所示: int rtt
RT-Thread(一)--系统启动过程
FourLeafCloverLLLS的博客
05-01 4183
今天5月1号,趁着四天假期,我选择好好提升自己,打算这四天学习一个物联网操作系统,物联网时代的到来,mcu上的物联网操作系统,就变得尤为重要,上周在ST峰会上看到了阿里的著作,被深深的吸引住了。立下flag,一:好好学习英语 二:学习两门的物联网联网技术:蓝牙mesh和lora组网 三:学习一门物联网操作系统 四:接触物联网云平台搭建 。本来是想学习阿里的AliOS Things...
写文章

热门文章

  • 1.1 解惑:运放的输入输出电压范围 36603
  • 热电偶工作原理图解 31081
  • part-7 共模抑制比CMRR 21518
  • part-1 输入偏置电流和输入失调电流 14795
  • SecureCRT简单设置 10589

分类专栏

  • STM32 6篇
  • 嵌入式 11篇
  • CortexM内核 1篇
  • Linux 3篇
  • python 4篇
  • FreeRTOS 1篇
  • 电机 1篇
  • mysql 1篇
  • C语言 13篇
  • docker 1篇
  • container 1篇
  • shell 1篇
  • stm32h743iit6 1篇
  • rt-thread 4篇
  • RTOS 1篇
  • JavaScript 1篇
  • 51单片机 1篇
  • VBA 3篇
  • Excel 5篇
  • vim 1篇
  • kicad 1篇
  • PCB 1篇
  • git 1篇
  • 算法 4篇
  • 传感器 1篇
  • 软考 1篇
  • 嵌入式系统设计师 1篇
  • QT 2篇
  • 数据库 1篇
  • 数据结构 1篇
  • 信号处理 1篇
  • C++ 3篇
  • 运放参数的详解 13篇
  • 运算放大器设计(31节) 3篇
  • 代码插件效果测试 2篇

最新评论

  • 通过PWM控制串行LED灯

    weixin_43846432: typedef enum { LED_DEAL_OK, // 操作成功 LED_HAL_ERR, // HAL库操作错误 LED_HANDLE_ERR, // LED句柄错误 LED_GET_DATA_OK // 获取数据成功 } LEDStatusTypeDef; 这个结构体是这么定义的吗?

  • ST-LINK 每次下载完程序后就断开连接,必须重新拔插才能再次下载

    暖男排狗后面: 6,神仙大佬

  • SecureCRT简单设置

    刘有余香: 在File里面有Hex View

  • 利用STM32的LR寄存器调试HardFault错误

    ForesterX: 。。。。。。你这还不如截几个图

  • 通过PWM控制串行LED灯

    shadow3D: 以上方式是输出指定数量指定占空比PWM波形,通过STM32定时器的RepetitionCounter参数,好像还可以输出指定数量指定频率的PWM波形。

最新文章

  • 嵌入式PID算法总结
  • MDK-ARM 编译后 MAP 文件分析
  • BeagleBone Black入门总结
2024年9篇
2023年26篇
2022年7篇
2021年7篇
2020年25篇
2017年34篇

目录

目录

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

玻璃钢生产厂家四川商场美陈市场价山东玻璃钢小品雕塑公司浙江玻璃钢青蛙雕塑常德玻璃钢胸像雕塑河南室内商场美陈生产公司玻璃钢雕塑断裂怎么修复玻璃钢抽象雕塑造价玻璃钢雕塑打磨喷漆中上海大型商场创意商业美陈经验商场美陈氛围布置公众号南宁佛像玻璃钢雕塑优势美陈特色商场阳江玻璃钢动物雕塑要求玻璃钢雕塑培训班哪家好重庆户外装饰玻璃钢美陈雕塑徐州玻璃钢雕塑景观设计大型玻璃钢花盆销售企业襄凡玻璃钢雕塑厂周口动物玻璃钢雕塑制作唐县玻璃钢雕塑工艺品厂异形雕塑玻璃钢鞍山玻璃钢雕塑邯郸标识标牌玻璃钢雕塑商场美陈注意事项抽象玻璃钢雕塑找哪家山西抽象玻璃钢雕塑多少钱玻璃钢大型雕塑设计贵不贵北京常用商场美陈多少钱玻璃钢雕塑定制设计公司玻璃钢巨型动物雕塑香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化