本帖最后由 slmxiaodai 于 2023-3-9 23:41 编辑
3 RT-Thread启动流程剖析在使用rt-thread-master提供的lpc55s69_nxp _evk工程时,发现其结构跟我原来移植RT-Thread系统有些区别,我原来是将RT-Thread系统源码移植到工程后,直接在main()函数中调用rtthread_startup()来启动rt-thread系统。而示例工程为了在执行main()函数之前完成对RT-Thread系统的初始化,使用了 MDK 的扩展功能 $Sub$$ 和 $Super$$。
1. 关于$Super$$和$Sub$$ 的用法 MDK的help文件描述如下: (1)$Super$$foo :指向原始的未修补的foo函数,使用$Super$$foo函数将直接跳转到原始foo()函数。 (2)$Sub$$foo :指向替换原始foo函数的新的函数,使用$Sub$$foo可以在原始foo函数之前/后添加程序代码。 $Sub$$main 可以先调用一些要补充在 main 之前的功能函数(这里添加 RT-Thread 系统启动,进行系统一系列初始化),再调用$Super$$main转到 main() 函数执行,这样可以让用户不用去管 main() 之前的系统初始化操作。 components.c文件中
,启动RT-Thread。
通俗理解:在main(void)函数之前先执行$Sub$$main(void)函数。
$Super$$main(void)执行真正的main(void)函数
。 注意: (1)void $Sub$$main(void)和intmain(void)可以不放在同一个C文件中,就算放在同一文件中也没有先后顺序之分; (2)extern int $Super$$main(); /* for ARMCC. */必须要有,且位于$Super$$main();调用之前,可以放在$Sub$$main(void)函数内,也可以放在函数外; (3)$Super$$与$Sub$$基本是要成对使用; (4)需要特定编译器才支持该符号,比如MDK; (5)$Super$$与$Sub$$不只用于main()函数,也可以用于其他函数; (6)$Super$$Fun();函数之后还可以写代码且能够被执行,此处相当于整体把Fun()函数替换进来,执行完Fun()后接着往下执行,相当于$Sub$$Fun()变成了真正的Fun()。 (7)可以用于给某个函数打补丁,而不破坏原来的程序结构。
RT-Thread启动过程的流程如下(通过打桩测试验证):
串口打印信息如下:
启动过程中创建了5个线程:main、timer、tidle0、mmcsd、tshell。 启动文件:工程结果Libraries文件夹下的startup_LPC55S69_cm33_core0.s。 在rt-thread工程中,程序执行完__main函数并不是跳转到main()函数,而是跳转到conmponent.c中的$Sub$$main函数。因为 RT-Thread 使用MDK编译器自带的 $Sub$$ 和 $Super$$这两个符号来扩展了main 函数,使用 $Sub$$main 可以在执行 main 之前先执行 $Sub$$main,在$Sub$$main 函数中我们可以先执行一些预操作,预操作执行完成后通过调用 $Super$$main 来执行 main() 函数。 总结:rtthread工程启动流程
启动文件—>__main函数—>$ Sub$$main函数—>rtthread_startup函数—>启动调度器—>C中main()函数。
|