RT-Thread startup process (study notes)

This article refers to [Wildfire EmbedFire] "RT-Thread Kernel Implementation and Application Development - Based on STM32", which is only used as a personal study note. For more detailed content and steps, please check the original text (you can download it from the Wildfire Data Download Center)

When you get a transplanted RT-Thread project, you go to the main function, you can only see the code for creating threads and starting threads, hardware initialization, system initialization, and starting the scheduler in the main function. not. That's because RT-Thread extends the main function and does all the work before the main function.

--original

Reset_Handler reset function

After the system is powered on, the first function is the reset function in the startup file. This startup file is written in assembly language. The reset function will call the C library function __main. The main work of this function is to initialize the system's heap and stack, and finally call the main()function to enter. The world of C language.

Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main
                IMPORT  SystemInit
                LDR     R0, =SystemInit
                BLX     R0               
                LDR     R0, =__main
                BX      R0
                ENDP

$Sub$$main function

The original text said that after the single-step execution __main, it will jump to component.cthe $Sub$$main()function in, but __mainafter I single-stepped, I went directly to the main()function (this may be because my operation is not in place).

In Keil's compiler, there exists a pair of symbols, and they can extend a function, such as using $Sub$$can be executed before execution , and then called to switch into the function.$Super$$$Sub$$main()main()$Sub$$main()$Super$$main()main()

Here are component.csome of the functions in (for the Keil compiler)

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

/* the system main thread */
void main_thread_entry(void *parameter)
{
    
    
    extern int main(void);
    extern int $Super$$main(void);

#ifdef RT_USING_COMPONENTS_INIT
    /* RT-Thread components initialization */
    rt_components_init();
#endif
    /* invoke system main function */
    $Super$$main(); /* for ARMCC. */
}

rtthread_startup() function

$Sub$$main()There is only one function in the previous step function rtthread_startup(), and all the initialization of RT-Thread is implemented in this function.

Among them, rt_hw_board_init()this function has been touched many times and is defined in board.cto initialize the underlying firmware.

int rtthread_startup(void)
{
    
    
    rt_hw_interrupt_disable();

    /* board level initialization
     * NOTE: please initialize heap inside board initialization.
     */
    rt_hw_board_init();

    /* show RT-Thread version */
    rt_show_version();

    /* timer system initialization */
    rt_system_timer_init();

    /* scheduler system initialization */
    rt_system_scheduler_init();

    /* create init_thread */
    rt_application_init();

    /* timer thread initialization */
    rt_system_timer_thread_init();

    /* idle thread initialization */
    rt_thread_idle_init();

    /* start scheduler */
    rt_system_scheduler_start();

    /* never reach here */
    return 0;
}

rt_application_init() function

rt_application_init()A thread is created in the function, which is an initial thread. When all application threads are successfully created, the initial thread closes itself. The last line of the function calls the rt_thread_startup()function. Although we know that the function of this function is to start the thread, the thread is not started at this time, because the rtthread_startup()last line of the upper-level function (see above) has rt_system_scheduler_start()not yet been executed, and the system thread has not yet started scheduling.

void rt_application_init(void)
{
    
    
    rt_thread_t tid;

#ifdef RT_USING_HEAP
    tid = rt_thread_create("main", main_thread_entry, RT_NULL,
                           RT_MAIN_THREAD_STACK_SIZE, RT_MAIN_THREAD_PRIORITY, 20);
    RT_ASSERT(tid != RT_NULL);
#else
    rt_err_t result;

    tid = &main_thread;
    result = rt_thread_init(tid, "main", main_thread_entry, RT_NULL,
                            main_stack, sizeof(main_stack), RT_MAIN_THREAD_PRIORITY, 20);
    RT_ASSERT(result == RT_EOK);

    /* if not define RT_USING_HEAP, using to eliminate the warning */
    (void)result;
#endif

    rt_thread_startup(tid);
}

main_thread_entry() function

The following is the entry function of the initial thread, the main function is to initialize the component, and finally call $Super$main()back to main()the function.

#ifndef RT_USING_HEAP
/* if there is not enable heap, we should use static thread and stack. */
ALIGN(8)
static rt_uint8_t main_stack[RT_MAIN_THREAD_STACK_SIZE];
struct rt_thread main_thread;
#endif

/* the system main thread */
void main_thread_entry(void *parameter)
{
    
    
    extern int main(void);
    extern int $Super$$main(void);

#ifdef RT_USING_COMPONENTS_INIT
    /* RT-Thread components initialization */
    rt_components_init();
#endif
    /* invoke system main function */
#if defined(__CC_ARM) || defined(__CLANG_ARM)
    $Super$$main(); /* for ARMCC. */
#elif defined(__ICCARM__) || defined(__GNUC__)
    main();
#endif
}

main() function

main()The function is called through the initial thread. As mentioned earlier, the initial thread needs to be closed by itself later, which means that main()after the function runs, the whole system is main()irrelevant. This is very different from the bare metal system. main()There is one function in the bare metal system, so the function does not stop running while(1)after the microcontroller is powered on, while RT-Thread (and some other RTOS) does not contain an infinite loop, instead is the creation and initialization of a bunch of threads.main()main()


At this point, the entire startup process of RT-Thread has basically been introduced. main()How the system operates after the operation is completed will not be discussed here.

Guess you like

Origin blog.csdn.net/weixin_43772810/article/details/123656826