Implementar el mecanismo de llamada inicial de registro del controlador en STM32

Reimpresión: Implementación del mecanismo de llamada inicial de registro de controladores en STM32

1. Código

Se ha logrado la gestión de separación de la capa de aplicación de código y la capa de hardware, pero todavía hay un problema en el código: cada hardware, como el control LED, el puerto GPIO, debe inicializarse y la función de inicialización bsp_led_init(); esto La función debe inicializarse llamando a la función principal, similar a esta:

void bsp_init(void)
{
    
    
    bsp_rcc_init();
    bsp_tick_init();
    bsp_led_init();
    bsp_usart_init();
}

El problema con esto es: cuando hay muchos pares de controladores y se agregan 100 controladores de hardware, solo usamos 50 y los archivos fuente restantes no participan en la compilación. En este momento, si olvida eliminar la inicialización correspondiente en el función principal, informará un error. Esta operación es muy problemática y no puede aislar eficazmente un único archivo de controlador.

Ahora se proporciona la manera de resolver este problema. Este método se origina en el mecanismo de llamada inicial del kernel de Linux. Hay muchas explicaciones detalladas en Internet, por lo que no entraré en detalles aquí.

Puedo leer:

Imagen de keil:

https://www.cnblogs.com/idle_man/archive/2010/12/18/1910158.html

Mecanismo de llamada inicial de Linux (para controladores compilados en el kernel):

https://www.cnblogs.com/downey-blog/p/10486653.html

2. Código

Archivo de cabeza:


#ifndef _COLA_INIT_H_
#define _COLA_INIT_H_
 
 
#define  __used  __attribute__((__used__))
 
typedef void (*initcall_t)(void);
 
#define __define_initcall(fn, id) \
    static const initcall_t __initcall_##fn##id __used \
    __attribute__((__section__("initcall" #id "init"))) = fn; 
 
#define pure_initcall(fn)       __define_initcall(fn, 0) //可用作系统时钟初始化  
#define fs_initcall(fn)         __define_initcall(fn, 1) //tick和调试接口初始化
#define device_initcall(fn)     __define_initcall(fn, 2) //驱动初始化
#define late_initcall(fn)       __define_initcall(fn, 3) //其他初始化
    
 
void do_init_call(void);
    
#endif

Archivo fuente:


#include "cola_init.h"
 
 
 
void do_init_call(void)
{
    
    
    extern initcall_t initcall0init$$Base[];
    extern initcall_t initcall0init$$Limit[];
    extern initcall_t initcall1init$$Base[];
    extern initcall_t initcall1init$$Limit[];
    extern initcall_t initcall2init$$Base[];
    extern initcall_t initcall2init$$Limit[];
    extern initcall_t initcall3init$$Base[];
    extern initcall_t initcall3init$$Limit[];
    
    initcall_t *fn;
    
    for (fn = initcall0init$$Base;
            fn < initcall0init$$Limit;
            fn++)
    {
    
    
        if(fn)
            (*fn)();
    }
    
    for (fn = initcall1init$$Base;
            fn < initcall1init$$Limit;
            fn++)
    {
    
    
        if(fn)
            (*fn)();
    }
    
    for (fn = initcall2init$$Base;
            fn < initcall2init$$Limit;
            fn++)
    {
    
    
        if(fn)
            (*fn)();
    }
    
    for (fn = initcall3init$$Base;
            fn < initcall3init$$Limit;
            fn++)
    {
    
    
        if(fn)
            (*fn)();
    }
       
}

Llame a void do_init_call(void) en el proceso principal para inicializar el controlador. Llame cuando el controlador esté registrado e inicializado:

 pure_initcall(fn)        //可用作系统时钟初始化  
 fs_initcall(fn)          //tick和调试接口初始化
 device_initcall(fn)      //驱动初始化
 late_initcall(fn)

Por ejemplo:


static void led_register(void)
{
    
    
    led_gpio_init();
    led_dev.dops = &ops;
    led_dev.name = "led";
    cola_device_register(&led_dev);
}
 
device_initcall(led_register);

De esta manera, no hay funciones de interfaz externa en el archivo de encabezado.

3. Código

casa rural:

https://gitee.com/schuck/cola_os

github:

https://github.com/sckuck-bit/cola_os

4. Interpretación de archivos de encabezado.


#ifndef _COLA_INIT_H_
#define _COLA_INIT_H_
 
#define  __used  __attribute__((__used__)) //使用__used__属性
 
typedef void (*initcall_t)(void);   //定义函数指针类型
 
#define __define_initcall(fn, id) \   //定义注册函数宏
 
// 定义函数指针,函数指针名为:__initcall_##fn##id ,例如fn = test,id = 0; 
//则函数指针名为__initcalltest0;
    static const initcall_t __initcall_##fn##id __used \ 
 
//说明函数指针存储位置,在自定义段中。
    __attribute__((__section__("initcall" #id "init"))) = fn;  
 
 
#define pure_initcall(fn)       __define_initcall(fn, 0) //可用作系统时钟初始化  
#define fs_initcall(fn)         __define_initcall(fn, 1) //tick和调试接口初始化
#define device_initcall(fn)     __define_initcall(fn, 2) //驱动初始化
#define late_initcall(fn)       __define_initcall(fn, 3) //其他初始化
    
 
void do_init_call(void);
    
#endif

Supongo que te gusta

Origin blog.csdn.net/weixin_42640280/article/details/128939653
Recomendado
Clasificación