干货 | STM32上实现驱动注册initcall机制

Posted 嵌入式大杂烩

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了干货 | STM32上实现驱动注册initcall机制相关的知识,希望对你有一定的参考价值。

原文:https://blog.csdn.net/ziqi5543/article/details/102478126

一、前言

上一节嵌入式中实现应用层和硬件层分层管理我们实现了代码应用层和硬件层的分离管理,但是代码中还存在一个问题,每个硬件如LED控制,GPIO口需要初始化,初始化函数bsp_led_init();这个函数需要在主函数中调用初始化,类似这样:

void bsp_init(void)

    bsp_rcc_init();
    bsp_tick_init();
    bsp_led_init();
    bsp_usart_init();

这样存在的问题是:当有很对驱动,加入100个硬件驱动,我们只用到了了50个,剩下的源文件不参与编译,此时如果忘记将主函数中的相应初始化删除,就会报错。这样操作很麻烦,不能很好的实现单个驱动文件的隔离。

那么现在就提供解决此问题的方式。这个方式源自于Linux内核--initcall机制。具体讲解网络上很多,在此不在详细说明。

可阅读:

keil 之Image:

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

linux的initcall机制(针对编译进内核的驱动) :

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

二、代码

头文件:

#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

源文件:

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

在主进程中调用void do_init_call(void)进行驱动初始化,驱动注册初始化时调用:

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

举个例子:

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

这样头文件中就没有有对外的接口函数了。

三、代码

gitee:

https://gitee.com/schuck/cola_os

girhub:

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

温馨提示

由于微信公众号近期改变了推送规则,如果您想经常看到我们的文章,可以在每次阅读后,在页面下方点一个「赞」或「在看」,这样每次推送的文章才会第一时间出现在您的订阅列表里。

免责声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。

往期推荐:

分享一份嵌入式软件工具清单!

易懂 | 手把手教你编写你的第一个上位机

基于STM32的BootLoader的OTA远程升级

花了两天时间整理了STM32中的一些C语言知识点!

干货 | 嵌入式OTA升级实现原理

分享一个实用的、可应用于单片机的内存管理模块

C语言、嵌入式位操作精华技巧大汇总

嵌入式大杂烩周记 | 第 1 期

C语言、嵌入式中几个非常实用的宏技巧

分享一个自用的、极简的log模块!

分享一个很酷的IDE!软工必备

在公众号聊天界面回复1024,可获取嵌入式资源;回复 m ,可查看文章汇总。

点击阅读原文,查看更多分享。

以上是关于干货 | STM32上实现驱动注册initcall机制的主要内容,如果未能解决你的问题,请参考以下文章

在 STM32 板上实现 SSI 从接口

STM32上实现点灯(固件库方式)

在 STM32F411 Discovery 上实现 HD44780 LCD 时调试 HardFault

如何在stm32上实现tcp/ip协议

在STM32上实现NTFS之1:NTFS初识与准备工作

在STM32上实现NTFS之2:磁盘知识基础与NTFS结构