打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
RTT系统启动流程分析

一般了解一份代码大多从启动部分开始,同样这里也采用这种方式,先寻找启动的源头。以 MDK-ARM 为例,MDK-ARM 的用户程序入口为 main() 函数,位于 main.c 文件中。系统启动后先从汇编代码 startup_stm32f103xe.s 开始运行,然后跳转到 C 代码,进行 RT-Thread 系统功能初始化,最后进入用户程序入口 main()。

下面我们来看看在 components.c 中定义的这段代码:

  1. //components.c 中定义
  2. /* re-define main function */
  3. int $Sub$$main(void)
  4. {
  5. rt_hw_interrupt_disable();
  6. rtthread_startup();
  7. return 0;
  8. }

 在这里 $Sub$$main 函数仅仅调用了 rtthread_startup() 函数。RT-Thread 支持多种平台和多种编译器,而 rtthread_startup() 函数是 RT-Thread 规定的统一入口点,所以 $Sub$$main 函数只需调用 rtthread_startup() 函数即可。例如采用 GNU GCC 编译器编译的 RT-Thread,就是直接从汇编启动代码部分跳转到 rtthread_startup() 函数中,并开始第一个 C 代码的执行的。在 components.c 的代码中找到 rtthread_startup() 函数,我们将可以看到 RT-Thread 的启动流程:

  1. int rtthread_startup(void)
  2. {
  3. rt_hw_interrupt_disable();
  4. /* board level initalization
  5. * NOTE: please initialize heap inside board initialization.
  6. */
  7. rt_hw_board_init();
  8. /* show RT-Thread version */
  9. rt_show_version();
  10. /* timer system initialization */
  11. rt_system_timer_init();
  12. /* scheduler system initialization */
  13. rt_system_scheduler_init();
  14. #ifdef RT_USING_SIGNALS
  15. /* signal system initialization */
  16. rt_system_signal_init();
  17. #endif
  18. /* create init_thread */
  19. rt_application_init();
  20. /* timer thread initialization */
  21. rt_system_timer_thread_init();
  22. /* idle thread initialization */
  23. rt_thread_idle_init();
  24. /* start scheduler */
  25. rt_system_scheduler_start();
  26. /* never reach here */
  27. return 0;
  28. }

这部分启动代码,大致可以分为四个部分

1. 初始化与系统相关的硬件;

2. 初始化系统内核对象,例如定时器,调度器;

3. 初始化系统设备,这个主要是为 RT-Thread 的设备框架做的初始化;

4. 初始化各个应用线程,并启动调度器。

在这里我要做几点说明, 因为官方文档在这里讲解的比较少,比较难理解:

1. 首先来说说$Sub$$main和$Super$$main 函数的用法

这是一种特殊模式:用于有一个已经存在且不能被改变的函数的情况(比如不能更改的库函数);使用这两个模式可以帮原函数打补丁,如存在一个函数foo();

$Sub$ $foo :定义的新功能函数,在foo()函数之前/后使用$Sub$ $foo 可以添加一些新的程序代码。

$Super$ $foo :就是原始的未修补的foo函数,使用这个$Super$ $foo函数将直接跳转到foo()函数。

下面以stm32f10xxx的int main(void)函数为例:

(1)  上电后,运行启动代码startup_stm32f10xxx.s

(2)  从系统初始化(SystemInit)开始执行,将函数地址赋给R0寄存器,跳转到R0地址执行并返回此处。

(3)  将__main函数地址给R0,将函数地址赋给R0,跳转到R0地址执行,不返回。

 

(4)  跳转到$Sub$$main(自己定义该函数)。

  1. #if defined (__CC_ARM)
  2.      extern int $Super$$main(void);
  3.   /* re-define main function */
  4.   int $Sub$$main(void)
  5.   {
  6.     preWork() ;      // do somthing before call main
  7.        $Super$$main();      //  跳转到 main() 
  8.     return 0;
  9.   }
  10. #endif

讲到这里我们来看看代码中关于这个得用法:

首先在components.c文件中

这里表示,这个函数在main函数之前运行,那么这个函数首先关闭了中断,然后再是rttread系统的启动函数。在该文件下还有

 

$Super$$main()函数表示将跳转到main函数运行。系统之所以这样的做法是,把用户的main函数和系统的main函数分开,系统的main函数比用户的main函数更前执行,这样就可以避免接触底层,注重应用层开发。

2.接着我们详细来介绍一下系统的运行过程:

(1)我们就不分析汇编代码了,直接从c文件入手,首先进入的是components.c文件中的int $Sub$$main(void)函数,该函数首先运行rt_hw_interrupt_disable()函数, 该函数失能中断

(2)接着运行rtthread_startup()函数,该函数对系统做了初始化,首先rt_hw_interrupt_disable()对失能了硬件中断,为啥要失能两次?? 有待思考, 接着rt_hw_board_init() 板级的初始化,rt_show_version()函数打印了系统的版本号 rt_system_timer_init()函数初始化了系统的定时器。rt_system_scheduler_init()初始化系统调度器。rt_system_signal_init()初始化信号量 ,rt_application_init() 函数是应用初始化,我们具体来看看这个函数

(3)rt_application_init(): 首先定义了一个rt的事件结构体变量,然后调用rt_thread_create创建了一个指向main_thread_entry函数的事件,最后启动了这个事件

(4)我们接着看看main_thread_entry函数,这个函数首先初始化了components, 然后调用了main函数,这里应该不能马上调用,因为系统还没有跑起来,只有等系统调用了,才能运行,分析到这我们就不分析了,接着就分析rt_thread_idle_init函数了, 这是初始化idle,至于这个是啥  我暂时也不知道, 然后再rt_system_scheduler_start 系统调度开始了,上面我们创建了一个main函数的事件, 这就可以运行了

 

用户入口代码

上面的启动代码基本上可以说都是和 RT-Thread 系统相关的,那么用户如何加入自己的应用程序的初始化代码呢?RT-Thread 将 main 函数作为了用户代码入口,只需要在 main 函数里添加自己的代码即可。

  1. int main(void)
  2. {
  3. /* user app entry */
  4. return 0;
  5. }

提示

注:为了在进入 main 程序之前,完成系统功能初始化,可以使用 $sub$$ 和 $super$$ 函数标识符在进入主程序之前调用另外一个例程,这样可以让用户不用去管 main() 之前的系统初始化操作。详见 ARM® Compiler v5.06 for µVision® armlink User Guide

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
源码解读·RT-Thread操作系统从开机到关机
STM32F103 RTT从零开始(二)——RTT系统中点亮LED
关于RT-Thread的启动问题
STM32 & RT-Thread的逆向入门
eCos启动流程解析
基于Tricore架构的RT-Thread移植
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服