干货 | 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
温馨提示
由于微信公众号近期改变了推送规则,如果您想经常看到我们的文章,可以在每次阅读后,在页面下方点一个「赞」或「在看」,这样每次推送的文章才会第一时间出现在您的订阅列表里。
免责声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。
往期推荐:
在公众号聊天界面回复1024,可获取嵌入式资源;回复 m ,可查看文章汇总。
点击阅读原文,查看更多分享。
以上是关于干货 | STM32上实现驱动注册initcall机制的主要内容,如果未能解决你的问题,请参考以下文章