当前位置:网站首页>Implementing the driver registration initcall mechanism on stm32

Implementing the driver registration initcall mechanism on stm32

2022-06-13 04:54:00 qq_ thirty-nine million two hundred and eighty thousand seven h

  Reprint :STM32 Implement driver registration on initcall Mechanism   

One 、 Code

         It realizes the separation management of code application layer and hardware layer , But there is a problem in the code , Each hardware such as LED control ,GPIO The port needs to be initialized , Initialization function bsp_led_init(); This function needs to be initialized in the main function , Like this :

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

The problem with that is : When there are very few drivers , Join in 100 Hardware drivers , We only used 50 individual , The remaining source files do not participate in compilation , At this point, if you forget to delete the corresponding initialization in the main function , You're going to report a mistake . It's a lot of trouble , The isolation of a single driver file cannot be well realized .

So now is the time to provide a solution to this problem . This method comes from Linux kernel --initcall Mechanism . There are many specific explanations on the Internet , I will not elaborate here .

Can be read :

keil And Image:

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

linux Of initcall Mechanism ( For drivers compiled into the kernel ) :

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

Two 、 Code

The header 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) // Can be used as system clock initialization   
#define fs_initcall(fn)         __define_initcall(fn, 1) //tick And debug interface initialization 
#define device_initcall(fn)     __define_initcall(fn, 2) // Drive initialization 
#define late_initcall(fn)       __define_initcall(fn, 3) // Other initialization 
    
 
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)();
    }
       
}

Called in the main process void do_init_call(void) Perform driver initialization , When the driver registration is initialized, call :

 pure_initcall(fn)        // Can be used as system clock initialization   
 fs_initcall(fn)          //tick And debug interface initialization 
 device_initcall(fn)      // Drive initialization 
 late_initcall(fn) 

for instance :

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 is no external interface function in the header file .

3、 ... and 、 Code

gitee:

https://gitee.com/schuck/cola_os

girhub:

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

Four 、 Header file interpretation

#ifndef _COLA_INIT_H_
#define _COLA_INIT_H_
 
#define  __used  __attribute__((__used__)) // Use __used__ attribute 
 
typedef void (*initcall_t)(void);   // Define function pointer type 
 
#define __define_initcall(fn, id) \   // Define register function macros 

//  Define function pointers , The function pointer is named :__initcall_##fn##id , for example fn = test,id = 0; 
// Then the function pointer is named __initcalltest0;
    static const initcall_t __initcall_##fn##id __used \ 

// Description of function pointer storage location , In the custom segment .
    __attribute__((__section__("initcall" #id "init"))) = fn;  

 
#define pure_initcall(fn)       __define_initcall(fn, 0) // Can be used as system clock initialization   
#define fs_initcall(fn)         __define_initcall(fn, 1) //tick And debug interface initialization 
#define device_initcall(fn)     __define_initcall(fn, 2) // Drive initialization 
#define late_initcall(fn)       __define_initcall(fn, 3) // Other initialization 
    
 
void do_init_call(void);
    
#endif 

reference :
C In language "#" and "##" Usage of

__attribute_unused__ and __attribute_used__ The role of

gcc Of __attribute__ Compile properties

原网站

版权声明
本文为[qq_ thirty-nine million two hundred and eighty thousand seven h]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202280518241997.html