一、前言
每個(gè)硬件如LED控制,GPIO口需要初始化,初始化函數(shù)bsp_led_init();這個(gè)函數(shù)需要在主函數(shù)中調(diào)用初始化,類似這樣:
void bsp_init(void)
{
bsp_rcc_init();
bsp_tick_init();
bsp_led_init();
bsp_usart_init();
}
這樣存在的問(wèn)題是:
當(dāng)有很對(duì)驅(qū)動(dòng),加入100個(gè)硬件驅(qū)動(dòng),我們只用到了了50個(gè),剩下的源文件不參與編譯,此時(shí)如果忘記將主函數(shù)中的相應(yīng)初始化刪除,就會(huì)報(bào)錯(cuò)。這樣操作很麻煩,不能很好的實(shí)現(xiàn)單個(gè)驅(qū)動(dòng)文件的隔離。 那么現(xiàn)在就提供解決此問(wèn)題的方式。這個(gè)方式源自于Linux內(nèi)核--initcall機(jī)制。具體講解網(wǎng)絡(luò)上很多,在此不在詳細(xì)說(shuō)明。 可閱讀:
二、代碼
頭文件:
#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) //可用作系統(tǒng)時(shí)鐘初始化 #define fs_initcall(fn) __define_initcall(fn, 1) //tick和調(diào)試接口初始化 #define device_initcall(fn) __define_initcall(fn, 2) //驅(qū)動(dòng)初始化 #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)();
}
}
在主進(jìn)程中調(diào)用void do_init_call(void)進(jìn)行驅(qū)動(dòng)初始化,驅(qū)動(dòng)注冊(cè)初始化時(shí)調(diào)用:
pure_initcall(fn) //可用作系統(tǒng)時(shí)鐘初始化 fs_initcall(fn) //tick和調(diào)試接口初始化 device_initcall(fn) //驅(qū)動(dòng)初始化 late_initcall(fn)
舉個(gè)例子:
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);
這樣頭文件中就沒(méi)有有對(duì)外的接口函數(shù)了。
三、代碼
gitee:
https://gitee.com/schuck/cola_os
girhub:
https://github.com/sckuck-bit/cola_os
審核編輯:湯梓紅
-
led
+關(guān)注
關(guān)注
243文章
24596瀏覽量
690912 -
STM32
+關(guān)注
關(guān)注
2309文章
11162瀏覽量
373479 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4417瀏覽量
67524 -
代碼
+關(guān)注
關(guān)注
30文章
4968瀏覽量
73990 -
GPIO
+關(guān)注
關(guān)注
16文章
1328瀏覽量
56231
原文標(biāo)題:在STM32上實(shí)現(xiàn)驅(qū)動(dòng)注冊(cè)initcall機(jī)制
文章出處:【微信號(hào):c-stm32,微信公眾號(hào):STM32嵌入式開(kāi)發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
請(qǐng)問(wèn)基于GCC編譯器的initcall在STM32如何實(shí)現(xiàn)?
嵌入式linux 串口console注冊(cè)
Linux的platform機(jī)制開(kāi)發(fā)驅(qū)動(dòng)流程是怎么樣的?
Delphi教程之軟件注冊(cè)機(jī)制的建立
C#教程之注冊(cè)碼注冊(cè)機(jī)制
基于STM32單片機(jī)低功耗模式機(jī)制詳細(xì)解析
Linux內(nèi)核驅(qū)動(dòng)的platform機(jī)制是怎樣的
在STM32H743芯片上實(shí)現(xiàn)CAN通信的步驟
基于 RT-Thread 在 STM32 上實(shí)現(xiàn) USB 虛擬串口
嵌入式函數(shù)回調(diào)注冊(cè)機(jī)制的實(shí)現(xiàn)
什么是函數(shù)回調(diào)注冊(cè)機(jī)制?實(shí)現(xiàn)的大致步驟介紹
initcall實(shí)現(xiàn)原理和調(diào)試方法介紹
如何解決引入注冊(cè)機(jī)制問(wèn)題
基于表驅(qū)動(dòng)的健康監(jiān)控機(jī)制實(shí)現(xiàn)方法
在STM32上實(shí)現(xiàn)驅(qū)動(dòng)注冊(cè)initcall機(jī)制
評(píng)論