El simulador del simulador RT-Thread admite el mecanismo de inicialización automática

Prefacio

  • El mecanismo de inicialización automática de RT-Thread es muy fácil de usar, pero el simulador en bsp no lo admite.
  • Estudié el mecanismo de inicialización automática y descubrí que el simulador de PC también se puede inicializar automáticamente.

 

proceso de investigación

  • Para ejecutar el simulador bsp, use vs2019.
  • Encontrado: INIT_BOARD_EXPORT INIT_COMPONENT_EXPORT, sin efecto
  • El análisis del código encontró que el simulador del lado de la PC no es compatible de forma predeterminada:
/* initialization export */
#ifdef RT_USING_COMPONENTS_INIT
typedef int (*init_fn_t)(void);
#ifdef _MSC_VER /* we do not support MS VC++ compiler */
    #define INIT_EXPORT(fn, level)
#else
  • Después de algunas búsquedas, verificación y análisis, se encuentra que el mecanismo de inicialización automática es el siguiente:
  1. Necesita usar la sección (sección, sección), deje que el compilador coloque el puntero de la función en él
  2. __attribute __ ((section (x))) no es compatible con VS2019 (_MSC_VER)
  3. Encuentre la operación de la sección basada en VS2019 _MSC_VER para realizar la inicialización automática
  4. MSH_CMD_EXPORT, admite el funcionamiento de la sección del simulador y se utiliza para exportar la función MSH CMD

 

Operación basada en la sección VS2019:

    #pragma section(".rti_fn.$0")
    #define INIT_EXPORT_LEVEL0(fn)                \
        __declspec(allocate(".rti_fn.$0")) const init_fn_t __rt_init_##fn = fn
  • ¿Por qué no usarlo directamente: (nivel ".rti_fn."), Porque el error de compilación

 

Modifica el código

rtdef.h modificación

/* initialization export */
#ifdef RT_USING_COMPONENTS_INIT
typedef int (*init_fn_t)(void);
#ifdef _MSC_VER /* we do not support MS VC++ compiler */
    #pragma section(".rti_fn.$0")
    #pragma section(".rti_fn.$1")
    #pragma section(".rti_fn.$2")
    #pragma section(".rti_fn.$3")
    #pragma section(".rti_fn.$4")
    #pragma section(".rti_fn.$5")
    #pragma section(".rti_fn.$6")
    #pragma section(".rti_fn.$0.end")
    #pragma section(".rti_fn.$1.end")
    #pragma section(".rti_fn.$6.end")

    #define INIT_EXPORT_LEVEL0(fn)                                                  \
            __declspec(allocate(".rti_fn.$0")) const init_fn_t __rt_init_##fn = fn
    #define INIT_EXPORT_LEVEL0_END(fn)                                                  \
            __declspec(allocate(".rti_fn.$0.end")) const init_fn_t __rt_init_##fn = fn
    #define INIT_EXPORT_LEVEL1_END(fn)                                                  \
            __declspec(allocate(".rti_fn.$1.end")) const init_fn_t __rt_init_##fn = fn
    #define INIT_EXPORT_LEVEL6_END(fn)                                                  \
            __declspec(allocate(".rti_fn.$6.end")) const init_fn_t __rt_init_##fn = fn
    #define INIT_EXPORT_LEVEL1(fn)                                                  \
            __declspec(allocate(".rti_fn.$1")) const init_fn_t __rt_init_##fn = fn
    #define INIT_EXPORT_LEVEL2(fn)                                                  \
            __declspec(allocate(".rti_fn.$2")) const init_fn_t __rt_init_##fn = fn
    #define INIT_EXPORT_LEVEL3(fn)                                                  \
            __declspec(allocate(".rti_fn.$3")) const init_fn_t __rt_init_##fn = fn
    #define INIT_EXPORT_LEVEL4(fn)                                                  \
            __declspec(allocate(".rti_fn.$4")) const init_fn_t __rt_init_##fn = fn
    #define INIT_EXPORT_LEVEL5(fn)                                                  \
            __declspec(allocate(".rti_fn.$5")) const init_fn_t __rt_init_##fn = fn
    #define INIT_EXPORT_LEVEL6(fn)                                                  \
            __declspec(allocate(".rti_fn.$6")) const init_fn_t __rt_init_##fn = fn
#else
    #if RT_DEBUG_INIT
        struct rt_init_desc
        {
            const char* fn_name;
            const init_fn_t fn;
        };
        #define INIT_EXPORT(fn, level)                                                       \
            const char __rti_##fn##_name[] = #fn;                                            \
            RT_USED const struct rt_init_desc __rt_init_desc_##fn RT_SECTION(".rti_fn." level) = \
            { __rti_##fn##_name, fn};
    #else
        #define INIT_EXPORT(fn, level)                                                       \
            RT_USED const init_fn_t __rt_init_##fn RT_SECTION(".rti_fn." level) = fn
    #endif
#endif
#else
#define INIT_EXPORT(fn, level)
#endif

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

/* pre/device/component/env/app init routines will be called in init_thread */
/* components pre-initialization (pure software initilization) */
#ifdef _MSC_VER
#define INIT_PREV_EXPORT(fn)           INIT_EXPORT_LEVEL2(fn)
#else
#define INIT_PREV_EXPORT(fn)            INIT_EXPORT(fn, "2")
#endif

/* device initialization */
#ifdef _MSC_VER
#define INIT_DEVICE_EXPORT(fn)           INIT_EXPORT_LEVEL3(fn)
#else
#define INIT_DEVICE_EXPORT(fn)          INIT_EXPORT(fn, "3")
#endif

/* components initialization (dfs, lwip, ...) */
#ifdef _MSC_VER
#define INIT_COMPONENT_EXPORT(fn)           INIT_EXPORT_LEVEL4(fn)
#else
#define INIT_COMPONENT_EXPORT(fn)       INIT_EXPORT(fn, "4")
#endif

/* environment initialization (mount disk, ...) */
#ifdef _MSC_VER
#define INIT_ENV_EXPORT(fn)           INIT_EXPORT_LEVEL5(fn)
#else
#define INIT_ENV_EXPORT(fn)             INIT_EXPORT(fn, "5")
#endif

/* appliation initialization (rtgui application etc ...) */
#ifdef _MSC_VER
#define INIT_APP_EXPORT(fn)           INIT_EXPORT_LEVEL6(fn)
#else
#define INIT_APP_EXPORT(fn)             INIT_EXPORT(fn, "6")
#endif

modificación de components.c:

static int rti_start(void)
{
    return 0;
}
#ifdef _MSC_VER
INIT_EXPORT_LEVEL0(rti_start);
#else
INIT_EXPORT(rti_start, "0");
#endif

static int rti_board_start(void)
{
    return 0;
}
#ifdef _MSC_VER
INIT_EXPORT_LEVEL0_END(rti_board_start);
#else
INIT_EXPORT(rti_board_start, "0.end");
#endif

static int rti_board_end(void)
{
    return 0;
}
#ifdef _MSC_VER
INIT_EXPORT_LEVEL1_END(rti_board_end);
#else
INIT_EXPORT(rti_board_end, "1.end");
#endif

static int rti_end(void)
{
    return 0;
}
#ifdef _MSC_VER
INIT_EXPORT_LEVEL6_END(rti_end);
#else
INIT_EXPORT(rti_end, "6.end");
#endif

/**
 * RT-Thread Components Initialization for board
 */
void rt_components_board_init(void)
{
#if RT_DEBUG_INIT
    int result;
    const struct rt_init_desc *desc;
    for (desc = &__rt_init_desc_rti_board_start; desc < &__rt_init_desc_rti_board_end; desc ++)
    {
        rt_kprintf("initialize %s", desc->fn_name);
        result = desc->fn();
        rt_kprintf(":%d done\n", result);
    }
#else
    volatile const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_start; fn_ptr < &__rt_init_rti_board_end; fn_ptr++)
    {
        if (*fn_ptr != RT_NULL)
            (*fn_ptr)();
    }
#endif
}

/**
 * RT-Thread Components Initialization
 */
void rt_components_init(void)
{
#if RT_DEBUG_INIT
    int result;
    const struct rt_init_desc *desc;

    rt_kprintf("do components initialization.\n");
    for (desc = &__rt_init_desc_rti_board_end; desc < &__rt_init_desc_rti_end; desc ++)
    {
        rt_kprintf("initialize %s", desc->fn_name);
        result = desc->fn();
        rt_kprintf(":%d done\n", result);
    }
#else
    volatile const init_fn_t *fn_ptr;

    for (fn_ptr = &__rt_init_rti_board_end; fn_ptr < &__rt_init_rti_end; fn_ptr ++)
    {
        if (*fn_ptr != RT_NULL)
            (*fn_ptr)();
    }
#endif
}
#endif   /* RT_USING_COMPONENTS_INIT */

 

Habilitar: RT_USING_COMPONENTS_INIT

La definición de implementación de Kconfig se puede configurar

 

En el simulador: application.c, agregue:

void rt_init_thread_entry(void *parameter)
{
    rt_kprintf("Hello RT-Thread!\n");
    rt_components_board_init();
    rt_components_init();
    platform_init();
    mnt_init();

 

Agregue rutinas de prueba de inicialización automática:

#include <rtthread.h>

int func_a1(void)
{
    rt_kprintf("%s: init ok!\n", __func__);
    return 0;
}

int func_a2(void)
{
    rt_kprintf("%s: init ok!\n", __func__);
    return 0;
}

int func_a3(void)
{
    rt_kprintf("%s: init ok!\n", __func__);
    return 0;
}

int func_a4(void)
{
    rt_kprintf("%s: init ok!\n", __func__);
    return 0;
}

int func_a5(void)
{
    rt_kprintf("%s: init ok!\n", __func__);
    return 0;
}

int func_a6(void)
{
    rt_kprintf("%s: init ok!\n", __func__);
    return 0;
}

int func_a7(void)
{
    rt_kprintf("%s: init ok!\n", __func__);
    return 0;
}

int func_a8(void)
{
    rt_kprintf("%s: init ok!\n", __func__);
    return 0;
}

INIT_BOARD_EXPORT(func_a1);
INIT_PREV_EXPORT(func_a2);
INIT_DEVICE_EXPORT(func_a3);
INIT_COMPONENT_EXPORT(func_a4);
INIT_ENV_EXPORT(func_a5);
INIT_APP_EXPORT(func_a6);
INIT_DEVICE_EXPORT(func_a7);
INIT_ENV_EXPORT(func_a8);

 

Verificación funcional

  • Compilado (el último código RT-Thread: report timegm no está definido, comenta primero)
  • correr:

 \ | /
- RT -     Thread Operating System
 / | \     4.0.3 build Mar 13 2021
 2006 - 2021 Copyright by rt-thread team
Hello RT-Thread!
func_a1: init ok!
func_a2: init ok!
func_a3: init ok!
func_a7: init ok!
func_a4: init ok!
func_a5: init ok!
func_a8: init ok!
func_a6: init ok!
finsh shell already init.
dfs already init.
File System on root initialized!
[E/DFS] There is no space to mount this file system (elm).
File System on sd initialization failed!
msh />
  • Encontré la función de inicialización automática y la ejecuté. Algunas funciones ejecutadas manualmente se pueden comentar.

 

para resumir

  • Necesita comprender el funcionamiento de la sección en el entorno VS (Visual Studio).
  • Puede utilizar las herramientas del lado de la PC: OD, Die y otras herramientas para analizar el archivo PE y comprender el contenido de la sección del archivo ejecutable generado
  • Utilice el archivo exe generado por la descompilación OD para encontrar la dirección y la sección de la función

2021-02-12_204437.png

  • Utilice Die para ver la sección del archivo exe

2021-03-13_195445.png

2021-03-13_195504.png

Supongo que te gusta

Origin blog.csdn.net/tcjy1000/article/details/114760526
Recomendado
Clasificación