Implement driver registration initcall mechanism on STM32

Reprint: Implementing driver registration initcall mechanism on STM32

1. Code

The separation management of the code application layer and the hardware layer has been achieved, but there is still a problem in the code. Each hardware, such as LED control, GPIO port needs to be initialized, and the initialization function bsp_led_init(); this function needs to be initialized by calling the main function, similar to this :

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

The problem with this is: when there are many pairs of drivers and 100 hardware drivers are added, we only use 50, and the remaining source files do not participate in compilation. At this time, if you forget to delete the corresponding initialization in the main function, it will Report an error. This operation is very troublesome and cannot effectively isolate a single driver file.

So now the way to solve this problem is provided. This method originates from the Linux kernel-initcall mechanism. There are many detailed explanations on the Internet, so I won’t go into details here.

Can read:

Image of keil:

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

Linux initcall mechanism (for drivers compiled into the kernel):

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

2. Code

head File:


#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

Source File:


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

Call void do_init_call(void) in the main process to initialize the driver. Call when the driver is registered and initialized:

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

for example:


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

In this way, there are no external interface functions in the header file.

3. Code

gitee:

https://gitee.com/schuck/cola_os

github:

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

4. Interpretation of header files


#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

Guess you like

Origin blog.csdn.net/weixin_42640280/article/details/128939653