0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

RT-Thread记录(二、RT-Thread内核启动流程)

矜辰所致 来源:矜辰所致 作者:矜辰所致 2022-06-20 00:30 次阅读
在上一篇文章中,我们了解了RT-Thread的版本以及开发环境,使用RT-Thread Studio成功创建了一个工程。
但是要了解一个操作系统,内核的了解是必不可少的,
我们今天就在前面我们RT-Thread Studio工程基础之上讲一讲RT-Thread内核启动流程

RT-Thread启动流程

1、基础介绍
2、源码分析

2.1 汇编部分 — startup_xxxx.s说明
2.2 C部分 — rtthread_startup 说明
2.2.1 板级硬件初始化 — rt_hw_board_init
板级硬件初始化更新说明
2.2.2 RT-Thread 堆和栈空间说明(与FreeRTOS不同)
2.2.3 main线程创建 — rt_application_init
2.2.4 调度器说明

1、基础介绍

在裸机程序中,一般在 .s 文件中就跳转到 _main从而跳转到 main()函数启动,而 RT-Thread 启动会先跳转到其启动函数 rtthread_startup()进行一系列的必要的初始化,最后才跳转至 main()函数。

简单来说就是: 程序启动,通过 startup_xxxx.s 文件(汇编语言)跳转到 RT-Thread启动函数rtthread_startup() (C语言),再通过 rtthread_startup() 跳转到 main()(C语言)函数。

官方的图片很详细的表明了这个流程:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_5,color_FFFFFF,t_70,g_se,x_16#pic_center

在 RT-Thread 中,会把 main()函数 当成是一个线程。这个在 rtthread_startup() 就会将 main() 创建成一个线程,除此之外,rtthread_startup() 还会创建timer 线程 和 空闲线程 这两个线程。

结合上图,下面我们通过上篇文章创建的示例代码来说明一下这个流程。

2、源码分析

2.1 汇编部分 — startup_xxxx.s说明

打开RT-Thread Studio工程,在哪里找到 startup_xxxx.s 文件呢,看下面一张图:

在这里插入图片描述

我们找到了启动文件,可以打开查看,启动文件的说明我在我在另一篇博文有详细的介绍:

STM32的启动过程 — startup_xxxx.s文件解析(更新GCC环境下的启动文件分析)

已经讲解的比较详细了,这里我只把主要的简单说明一下。在上面推荐的博文中讲到过,GCC环境下面的启动,需要两个文件,一个是 startup_xxxx.s文件,还一个是 .ld链接文件,我们先看一下链接文件:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16



在以前讲过,GCC下的链接文件主要制定了入口函数,堆栈大小和数据段的整体布局。在上图中我们看到值定义了系统栈的大小,并没有定义堆大小。

这里为什么只定义系统栈?
虽然我们在其他博文说过,如果不用 malloc函数,不需要用到堆,这里没有定义是因为在后面初始化的时候会根据是否使用堆,来定义堆的大小。
在本文下面板级硬件初始化部分有介绍说明。

然后就简单来看一下 startup_xxxx.s文件,首先我们找到上电执行的第一个指令 Reset_Handler(芯片刚上电,就是上电复位,直接就会触发Reset_Handler):

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16


上图中所进行的操作不理解的可以查看博文:

STM32的内存管理相关(内存架构,内存管理,map文件分析)

完成数据搬运以后,就是系统基本的初始化,如下图:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16


完成基本初始化,MCU得以运行起来,就跳转到我们上面基础介绍里面说到的入口函数,如下图:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

通过上面的步骤,最终就从 .s 中的汇编跳转到了 C语言部分,通过入口函数跳转到 rtthread_startup函数,我们通过下面的介绍说明一下,进入rtthread_startup函数 后,RT-Thread 确实做了哪些工作。

2.2 C部分 — rtthread_startup 说明

在本文第一节基础介绍中通过官方的一张图表示了进入rtthread_startup后,所会进行的操作,我们上面也说明了工程是怎么进入 rtthread_startup 函数的,那么进入 rtthread_startup函数 后执行了哪些操作,如下图:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16


补充说明: 上图中的SMP相关,是与多核处理器有关的设置。

上面的过程很好理解,主要有做了以下工作:

1、基本的硬件初始化;

2、一定会创建main现 线程;

3、根据是否使用软件定时器创建 time r线程;

4、一定会创建 idle 线程;

5、初始化开启调度器;

其中有一些初始化我们可以更加深入的看看具体的操作:

2.2.1 板级硬件初始化 — rt_hw_board_init

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

在上图找那个,板级硬件初始化最后调用了rt_components_board_init()函数,这个函数如下:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

rt_components_board_init()函数会把所有 INIT_BOARD_EXPORT 的设备都初始化,这里暂时不介绍是如何实现的,但是有必要说明一下。

比如我们什么外设都没使能,但是使用到了串口1作为打印LOG的设备,所以串口1 必定会被使能,那么这个初始化就是在这里完成的,我们可以在工程 drivers 文件夹里的drv_usart.c 文件中查看到串口相关的初始化代码,我们可以看到如下图所示部分(此部分串口1 的说明有待确认,因为后期加了其他串口以后回头来看这个地方,并没有发现下图代码……):

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_17,color_FFFFFF,t_70,g_se,x_16


板级硬件初始化更新说明

对于上图提到的串口会使用 INIT_BOARD_EXPORT(rt_hw_usart_init),后续我反而并没有找到图示代码,也不知道是因为版本问题还是什么原因,这里需要补充说明一下:

硬件设备的初始化是在hw_board_init函数中的:

pYYBAGKueT-AT5aBAADBiQQ3Pqo300.png

2.2.2 RT-Thread 堆和栈空间说明(与FreeRTOS不同)

在上图中,有一点比较特殊,就是对 堆 空间的初始化,我们以前遇到的都是在启动文件中定义好堆栈空间,而我们上面分析 RT-Thread 启动文件的时候,只定义了栈空间,堆空间没有定义,其实是放在了这个地方:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

刚开始看到这里还有个疑问,HEAP 把余下 所有的 RAM 都使用了,按照以前的理解,系统栈应该是在最后面的位置的,这里是怎么回事?

关于 系统栈位置的问题,可以参考博文:RTOS的 任务栈 和 系统栈

上面我们通过源码看到的结论和 这篇博文说到的不一样(当时是用裸机和 FreeRTOS作为例子说明的),然后在 RT-Thread 下,系统栈的位置在什么地方,于是乎回头看了看定义数据段整体布局的链接文件:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_17,color_FFFFFF,t_70,g_se,x_16

通过链接文件我们可以推断 .stack 的位置,那么为了确认一下,我们可以查看程序编译过后的 .map文件:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

在 RAM 数据段我们可以查看数据存放的位置,找到关于 系统栈的位置部分:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

确认了在 RT-Thread 中,系统栈的位置是确实存放于 .data 段和 .bss 之间的,所以堆空间即便使用了余下全部的 ram 空间也是没有问题的。

2.2.3 main线程创建 — rt_application_init

在 RT-Thread 中,创建了一个名字为 "main" 的线程来调用 main() 函数,就是在rtthread_startup函数中的rt_application_init(),如下图:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

2.2.4 调度器说明

调度器是操作系统的核心知识,调度器是基于链表进行操作的,具体的原理将来会单独写一篇文章说明,这里我们就简单的过一遍,知道函数的用意。

rtthread_startup函数中,使用rt_system_scheduler_init();初始化调度器,rt_system_scheduler_start();开启调度器,开启调度器之后,线程之间就会根据一定的规则进行切换(时间片,优先级):

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

开启调度器后,会在就绪列表中找到最高优先级的线程,然后通过设置 线程指针(PSP),来跳转到对应的位置执行:

线程指针什么意思,可以参考博文:FreeRTOS记录(三、FreeRTOS任务调度原理解析_Systick、PendSV、SVC)

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA55-c6L6w5omA6Ie0,size_20,color_FFFFFF,t_70,g_se,x_16

至此,整个系统就正常跑起来了,然后用户运行自己想要做的事情,可以在 main 中设计自己的应用代码,或者创建线程。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    3

    文章

    1309

    浏览量

    39844
  • STM
    STM
    +关注

    关注

    1

    文章

    555

    浏览量

    42054
  • RT-Thread
    +关注

    关注

    31

    文章

    1148

    浏览量

    38867
收藏 人收藏

    评论

    相关推荐

    RT-Thread记录(一、版本开发环境及配合CubeMX)

    RT-Thread 学习记录的第一篇文章,RT-Thread记录(一、RT-Thread 版本、RT-T
    的头像 发表于 06-20 00:28 4477次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>记录</b>(一、版本开发环境及配合CubeMX)

    RT-Thread记录(三、RT-Thread线程操作函数)

    讲完了RT-Thread开发环境,启动流程启动以后当然是开始跑线程了,那么自然我们得学会如何创建线程以及线程的有关操作。
    的头像 发表于 06-20 00:31 5565次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>记录</b>(三、<b class='flag-5'>RT-Thread</b>线程操作函数)

    RT-Thread记录(十、全面认识 I/O 设备模型)

    学完 RT-Thread 内核,从本文开始熟悉了解 RT-Thread I/O 设备管理相关知识。
    的头像 发表于 06-30 10:38 3545次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>记录</b>(十、全面认识 I/O 设备模型)

    如何对RT-Thread内核有基本的了解?

    RT-Thread 的时钟管理以时钟节拍为基础,时钟节拍是 RT-Thread 操作系统中最小的时钟单位。
    的头像 发表于 07-19 10:12 6790次阅读
     如何对<b class='flag-5'>RT-Thread</b><b class='flag-5'>内核</b>有基本的了解?

    RT-Thread记录(五、RT-Thread 临界区保护)

    本文聊聊临界区,以及RT-Thread对临界区的处理
    的头像 发表于 06-20 16:06 4286次阅读
    <b class='flag-5'>RT-Thread</b><b class='flag-5'>记录</b>(五、<b class='flag-5'>RT-Thread</b> 临界区保护)

    从0到1教你写RT-Thread之新建工程

    仿真,然后我们再开始一步一步地教大家把 RT-Thread 内核从 0 到 1 写出来,让大家彻底搞懂 RT-Thread的内部实现和设计的哲学思想。最后我们再把 RT-Thread
    发表于 11-18 14:17 1166次阅读

    RT-Thread内核简介

    RT-Thread 启动流程5、RT-Thread 程序内存分布keil工程编译内存分布RT-thread studio 工程编译内存分布
    发表于 08-06 07:44

    【原创精选】RT-Thread征文精选技术文章合集

    及配合CubeMX)RT-Thread记录RT-Thread内核启动
    发表于 07-26 14:56

    RT-Thread快速入门之了解内核启动流程

    1、了解RT-Thread内核启动流程  内核是操作系统最基础也是最重要的部分。从本文开始进入 RT-
    发表于 09-05 17:01

    RT-Thread开发,如何有效学习RT-Thread的五个步骤

    RT-Thread推出RT-Thread Inside战略开放RT-Thread开发平台授权合作,与硬件十万个为什么合作首次推出第一款RT-Inside的开发板——iBox物联网开发套
    的头像 发表于 09-25 09:55 3.4w次阅读
    <b class='flag-5'>RT-Thread</b>开发,如何有效学习<b class='flag-5'>RT-Thread</b>的五个步骤

    RT-Thread学习笔记 RT-Thread的架构概述

    RT-Thread 简介 作为一名 RTOS 的初学者,也许你对 RT-Thread 还比较陌生。然而,随着你的深入接触,你会逐渐发现 RT-Thread 的魅力和它相较于其他同类型 RTOS
    的头像 发表于 07-09 11:27 3995次阅读
    <b class='flag-5'>RT-Thread</b>学习笔记 <b class='flag-5'>RT-Thread</b>的架构概述

    RT-Thread文档_RT-Thread 简介

    RT-Thread文档_RT-Thread 简介
    发表于 02-22 18:22 5次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> 简介

    RT-Thread文档_内核基础

    RT-Thread文档_内核基础
    发表于 02-22 18:28 0次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>内核</b>基础

    RT-Thread文档_内核移植

    RT-Thread文档_内核移植
    发表于 02-22 18:31 2次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>内核</b>移植

    RT-Thread文档_RT-Thread SMP 介绍与移植

    RT-Thread文档_RT-Thread SMP 介绍与移植
    发表于 02-22 18:31 7次下载
    <b class='flag-5'>RT-Thread</b>文档_<b class='flag-5'>RT-Thread</b> SMP 介绍与移植