接触RT-Thread有一段时间了,之前一段时间学习了RT-Thread内核方面的知识,但总归有点走马观花的意思,没仔细琢磨,就略过了。今天开始打算将RT-Thread系统重新温习一遍,对操作系统有更深刻的理解。
话不多说,接下来将讲述RT-Thread的系统启动流程。(RT-Thread官方已经给了比较详细的教程,所以在此主要添加一些自己的理解)
在开始之前,需要准备必须的工具,准备工具:keil、RT-Thread 官方提供的软件仿真例程
启动流程概述
在讲解之前,先上rt-thread系统启动的主体步骤:
- 系统首先进入汇编文件startup_stm32f103xe.s开始运行,主要调用**SystemInit **和 __main函数;
- 然后跳转到c代码,进行rt-thread系统功能初始化,主要在于理解$ Sub $$ main函数和 $ Super$ $函数对main函数执行前的补丁修复过程。
- 启动main函数。
1. 汇编代码部分
系统启动后首先进入汇编代码startup_stm32f103xe.s这个文件,这个部分并没有在点击dubug后出现,是因为已经执行完了。
这部分代码通常是对芯片进行必要的初始化,比如FLASH和RAM的始终初始化等,然后跳转到用户flash区域运行用户代码。
用户flash地址从0x08000000开始,并且cortexM规定其用户FLASH区域的最前面必须是一张中断向量表,所以说STM32的0x08000000开始是一张中断向量表,下面是摘自startup_stm32f103xe.s向量表的部分代码,可以看到向量表中的第一项是一个栈起始地址,第二项是复位向量地址。

开机之后会自动进入复位异常,通常叫上电复位过程,上电复位处理的模式是特权级线程模式。由于在特权模式下堆栈指针将使用MSP,所以很容易理解为什么向量表第一项是栈地址了吧,向量表第一项指定了栈起始地址首先被自动加载到MSP,第二项指向了复位模式的地址,然后被自动加载到PC并运行,然后就会跳转到Reset handler部分的代码,如下所示:

可以看到在Reset handler模式下,首先运行SystemInit函数,完成一些初始化;然后跳转到__main函数,进行进入main函数前的准备,主要是进行初始化ram和堆栈等操作,这部分想详细了解的话请参考这篇博客,他写的很详细,我看完很受启发,执行完__main函数之后就进入到了C代码部分。
这样,汇编代码的部分已经介绍完了。
2. 进入main函数(主进程)前的操作
在经历过系统自动上电复位之后,正式进入了我们所能看到的部分,编译之后点击debug按钮,可以看到程序跳转到了一个$ Sub$$main内,如下图所示:(components.c )

在解释该函数中执行的两个函数之前,首先需要说明一下,给main添加前缀 $Sub $ $,是作为一个新功能函数,可以将原有函数劫持下来,并在之后的程序运行中加上 $Super $ $前缀来重新调用原始函数。
好了,再说回 $ Sub $ $main函数,可以看到该函数将首先调用rt_hw
_interrupt_disable()函数,主要是为了清除所有硬件中断,然后调用rtthread_startup()函数,主要讲解该函数。
打开该函数,如下所示:

呃呃呃,至于为什么再次调用了一次rt_hw_interrupt_disable()函数,个人认为其实可以去掉其中任意一个,这样调用两次是为了保险起见(个人愚见,欢迎大神们来纠正)。
到了这里是不是会产生疑问,刚刚不是说如果需要执行main函数,需要之后的程序运行中加上 $Super $ $前缀来重新调用原始函数吗?那这个 $Super $ $main()函数在哪里?
莫急,请听我一一讲述,其实我们已经调用过这个函数了,在哪里呢?首先看到上图所示蓝色框框中的函数rt_application_init(),先看看它的源代码:

从上面的源码可以看到,该创建了一个main的进程,该进程的入口函数被红色框框起来了,叫main_thread_entry,我们现在去找一下它,代码如下所示:

好家伙,找到了,然后一切都明了了,原来main进程入口函数中调用了 $ Super $ $main()函数,因为定义了__CC_ARM(表明使用ARM编译器),所以会执行 $Super $ $main()函数,然后接下来顺利的跳转到我们自己定义的main()函数中进行执行,这样一个流程走完,我们知道了其实main函数只是系统运行的其中一个进程,只不过此进程为主进程,只能有一个。
3. 启动main函数
上面的程序都走完了,就到了我们自己定义的main函数中了,接下来就可以尽情发挥了~
int main(void)
{
led();
return 0;
}
参考资料
- 嵌入式实时操作系统 RT-Thread设计与实现
- 源码解读·RT-Thread操作系统从开机到关机
本文深入剖析RT-Thread实时操作系统启动流程,从汇编初始化、C代码功能配置到主进程启动,涵盖SystemInit、rt-thread_startup等关键函数解读。
2482

被折叠的 条评论
为什么被折叠?



