RT-THREAD启动解析

疑问

RT-THREAD的DEMO工程在添加所有文件编译之后,完全没有用户自己去调用HAL库的代码,甚至连main函数里面都是空的,竟然可以正常运行。
当然是RT-THREAD做了其他操作来达到运行的效果。

启动解析

RESET之后第一时间的运行的是main函数虽然main函数里面是空,但是并不代表RT-THREAD没有运行代码

main函数重定向

先运行\$Sub$$main,来进行初始化,这样做的目的是为了适应不同的编译器,有些编译器的入口并不是main函数
在app初始化时再重新回调我们自己定义的main函数。

#ifdef __ARMCC_VERSION
extern int $Super$$main(void);
/* re-define main function */
int $Sub$$main(void)
{
    rtthread_startup();
    return 0;
}

\$Sub$$功能使用

板级初始化

在重定向main函数之后,会调用rt_hw_board_init来初始化board的功能,不同的板子实现方式不一样,现在我们这个函数是在drv_common.c这个文件里面实现,当然有些人在board.c里面实现也是没有问题,而且这个函数定义用的是RT_WEAK的类型,可重新定义。从源码中我们可以看出这个函数也是真正调用了相应的初始化代码。

RT_WEAK void rt_hw_board_init()
{
#ifdef BSP_SCB_ENABLE_I_CACHE
    /* Enable I-Cache---------------------------------------------------------*/
    SCB_EnableICache();
#endif

#ifdef BSP_SCB_ENABLE_D_CACHE
    /* Enable D-Cache---------------------------------------------------------*/
    SCB_EnableDCache();
#endif

    /* HAL_Init() function is called at the beginning of the program */
    HAL_Init();

    /* System clock initialization */
    SystemClock_Config();

    /* Heap initialization */
#if defined(RT_USING_HEAP)
    rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
#endif

    /* Pin driver initialization is open by default */
#ifdef RT_USING_PIN
    rt_hw_pin_init();
#endif

    /* USART driver initialization is open by default */
#ifdef RT_USING_SERIAL
    rt_hw_usart_init();
#endif

    /* Set the shell console output device */
#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
    rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif

    /* Board underlying hardware initialization */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif
}

宏添加初始化操作

rt_components_board_init这个函数调用了用户独有的板级初始化代码,而调用的方式不是显示地调用,而是使用section定义的方式,将初始化函数定在相近的代码区,然后用函数指针的方式去调用相应的初始化函数。
具体的section操作可参考其他教程。
RT-Thread定义了很多相近的宏用于初始化以及添加新的线程(INIT_APP_EXPORT)来进行直接加任务,而不需要显示调用。

/* board init routines will be called in board_init() function */
#define INIT_BOARD_EXPORT(fn)           INIT_EXPORT(fn, "1")

/* pre/device/component/env/app init routines will be called in init_thread */
/* components pre-initialization (pure software initialization) */
#define INIT_PREV_EXPORT(fn)            INIT_EXPORT(fn, "2")
/* device initialization */
#define INIT_DEVICE_EXPORT(fn)          INIT_EXPORT(fn, "3")
/* components initialization (dfs, lwip, ...) */
#define INIT_COMPONENT_EXPORT(fn)       INIT_EXPORT(fn, "4")
/* environment initialization (mount disk, ...) */
#define INIT_ENV_EXPORT(fn)             INIT_EXPORT(fn, "5")
/* application initialization (rtgui application etc ...) */
#define INIT_APP_EXPORT(fn)             INIT_EXPORT(fn, "6")

通过以上的方式,完成板级初始化,同时创建主任务及空闲任务,开始系统的运行与调度。

总结

RT-THREAD通过重定向及宏的定义进行初始化,使代码本身更新的清晰可扩展性极好。理解之后还是一个很好的设计。

posted @ 2022-10-19 20:07  cau_par  阅读(135)  评论(0编辑  收藏  举报