Proceso de inicio de RT-Thread (notas de estudio)

Este artículo hace referencia a [Wildfire EmbedFire] "Implementación de kernel de subprocesos RT y desarrollo de aplicaciones: basado en STM32", que solo se usa como una nota de estudio personal. Para obtener contenido y pasos más detallados, consulte el texto original (puede descargarlo del Centro de descarga de datos de Wildfire)

Cuando obtiene un proyecto RT-Thread trasplantado, va a la función principal, solo puede ver el código para crear hilos e iniciar hilos, inicialización de hardware, inicialización del sistema e iniciar el programador en la función principal. Eso es porque RT-Thread extiende la función principal y hace todo el trabajo antes de la función principal.

--original

Función de reinicio Reset_Handler

Después de encender el sistema, la primera función es la función de reinicio en el archivo de inicio. Este archivo de inicio está escrito en lenguaje ensamblador. La función de reinicio llamará a la función de biblioteca C. __mainEl trabajo principal de esta función es inicializar el montón del sistema. y apilar, y finalmente llamar a la main()función para entrar.El mundo del lenguaje C.

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

$Sub$$función principal

El texto original decía que después de la ejecución de un solo paso __main, saltaría a component.cla $Sub$$main()función, pero __maindespués de un solo paso, fui directamente a la main()función (esto puede deberse a que mi operación no está en su lugar).

En el compilador de Keil, existe un par de símbolos, y pueden extender una función, como el uso $Sub$$puede ejecutarse antes de la ejecución , y luego llamarse para cambiar a la función.$Super$$$Sub$$main()main()$Sub$$main()$Super$$main()main()

Estas son component.calgunas de las funciones en (para el compilador Keil)

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. */
}

función rtthread_startup()

$Sub$$main()Solo hay una función en la función del paso anterior rtthread_startup(), y toda la inicialización de RT-Thread se implementa en esta función.

Entre ellos, rt_hw_board_init()esta función se ha tocado muchas veces y se define board.cpara inicializar el firmware subyacente.

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;
}

función rt_application_init()

rt_application_init()Se crea un subproceso en la función, que es un subproceso inicial. Cuando todos los subprocesos de la aplicación se crean correctamente, el subproceso inicial se cierra solo. La última línea de la función llama a la rt_thread_startup()función. Aunque sabemos que la función de esta función es iniciar el subproceso, el subproceso no se inicia en este momento, porque la rtthread_startup()última línea de la función de nivel superior (ver arriba) rt_system_scheduler_start()no se ha iniciado. aún no se ha ejecutado y el subproceso del sistema aún no ha comenzado a programarse.

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);
}

función main_thread_entry()

La siguiente es la función de entrada del subproceso inicial, la función principal es inicializar el componente y finalmente $Super$main()volver a llamar a main()la función.

#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
}

función principal

main()La función se llama a través del subproceso inicial. Como se mencionó anteriormente, el subproceso inicial debe cerrarse solo más tarde, lo que significa que main()después de que se ejecuta la función, todo el sistema es main()irrelevante. Esto es muy diferente del sistema bare metal. main()Hay una función en el sistema bare metal, por lo que la función no deja de ejecutarse while(1)después de encender el microcontrolador , mientras que RT-Thread (y algunos otros RTOS) no contienen un bucle infinito . , en cambio, es la creación e inicialización de un montón de subprocesos.main()main()


En este punto, básicamente se ha presentado todo el proceso de inicio de RT-Thread. main()No se discutirá aquí cómo funciona el sistema una vez que se completa la operación.

Supongo que te gusta

Origin blog.csdn.net/weixin_43772810/article/details/123656826
Recomendado
Clasificación