前提
首先得新建一份RT_Thread 的工程,偌大且互相嵌套的文件结构让我第想起第一次用cubeMX配置32 。。。
开始
既然是看main,哪直接从main看起。
通过打开main的调用层次结构得出main的调用顺序是
entry() -> rtthread_startup() -> rt_application_init() -> main_thread_entry -> main()
entry()入口地址
rtthread_startup() (这个函数是RT_Thread规定的统一入口点。)
值得注意的是在rt_hw_board_init中初始化了串口,配置了系统时钟,将系统输入输出终端绑定到了这个串口。这在用RT_Studio新建工程时就开启了串口。后续若用cubemx进行配置则必须使能串口。这样在stm32xxx_config.h中就有定义使用串口的宏。
rt_application_init()
动态创建一个main函数的线程,也就是主线程,分配栈空间,把主线程的入口定义为main_thread_entry(),然后通过rt_thread_startup()启动该线程。
main_thread_entry()
组件初始化等等,最后调用main函数
最后找entry的入口,在stm32的启动文件里。
从启动文件开始,我用的是正点原子的stm32F103ZET6精英板.
搜索startup_stm32f103xe
/* Call the application's entry point.*/
正如注释一样,entry是应用程序的入口点。
更多细节
到此,main的启动过程分析完毕,里面还有很多细节。
比如我想知道外设是否有初始化,熟悉用cubeMX配置工程后脑子里免不了cubemx的哪一套结构(先进行一系列初始化后再直接使用的习惯)。
在 rtthread_startup()中的 rt_hw_board_init()
圈出来的哪一块进行了时钟源配置,模式是HSI,内部高速时钟。
看源代码对串口,pin引脚以及时钟进行了初始化。
/** * This function will initial STM32 board. */ void hw_board_init(char *clock_src, int32_t clock_src_freq, int32_t clock_target_freq) { extern void rt_hw_systick_init(void); extern void clk_init(char *clk_source, int source_freq, int target_freq); #ifdef SCB_EnableICache /* Enable I-Cache---------------------------------------------------------*/ SCB_EnableICache(); #endif #ifdef SCB_EnableDCache /* Enable D-Cache---------------------------------------------------------*/ SCB_EnableDCache(); #endif /* HAL_Init() function is called at the beginning of the program */ HAL_Init(); /* enable interrupt */ __set_PRIMASK(0); /* System clock initialization */ clk_init(clock_src, clock_src_freq, clock_target_freq); /* disbale interrupt */ __set_PRIMASK(1); rt_hw_systick_init(); /* Pin driver initialization is open by default */ #ifdef RT_USING_PIN extern int rt_hw_pin_init(void); rt_hw_pin_init(); #endif /* USART driver initialization is open by default */ #ifdef RT_USING_SERIAL extern int rt_hw_usart_init(void); rt_hw_usart_init(); #endif }
至此,结束。