利用__attribute__((section("name")))构建初始化函数表

在嵌入式学习工作中经常初始化一个硬件就写一个初始化函数,基本都要到主函数中调用进行初始化,main函数都要改变。当利用__attribute__((section("name")))这个属性就可以构造一个初始化函数表,这样每次初始化一个硬件啥的就不用到main函数中去调用初始化函数。式在RTT初始化函数和Linux初始化驱动模块也是类似这样做的。

attribute的用法

http://www.keil.com/support/man/docs/armcc/armcc_chr1359124982450.htm

代码

  • 头文件
#ifndef _HARDWARE_INIT_H_
#define _HARDWARE_INIT_H_

#if defined(__CC_ARM) || defined(__CLANG_ARM)   /* ARMCC Complier */
    #define INIT_SECTION(x)      __attribute__((section(x)))
    #define INIT_USED            __attribute__((used))
#elif defined(__ICCARM__)                      /* IAR ARMCC Complier */

#elif defined(__GNUC__)                        /* GNUC Complier */

#else
    #error "not support tool chain"
#endif

typedef void (*init_func)(void);

typedef struct{
    init_func _init_func;
}init_func_t;

#define INIT_EXPORT(handler)                                                      INIT_USED init_func_t _init_##handler##_func INIT_SECTION("INIT_LIST") =  \          //INIT_LIST自定义段名
    {                                                                                 handler,                                                                  }

void sys_init(void);

#endif
  • 源文件
    在MDK中使用下面方式获得自定义段的起始和终止地址。
static init_func_t *init_list_begin;
static init_func_t *init_list_end;

void sys_init(void)
{
    init_func_t *index;
#if defined(__CC_ARM) || defined(__CLANG_ARM)
    extern const int INIT_LIST$$Base;
    extern const int INIT_LIST$$Limit;
    init_list_begin = (init_func_t *)&INIT_LIST$$Base;   //获得段起始地址
    init_list_end   = (init_func_t *)&INIT_LIST$$Limit;  //获得结束段地址
#elif defined(__ICCARM__)                      /* IAR ARMCC Complier */

#elif defined(__GNUC__)                        /* GNUC Complier */

#endif
    for(index = init_list_begin; index < init_list_end; index++)
    {
        index->_init_func();
    }
}
  • 初始化函数使用INIT_EXPORT修饰
void MY_USART_Init(void)
{
    __MY_USART_Init(115200);
}
INIT_EXPORT(MY_USART_Init);

用INIT_EXPORT修饰过的函数都会定义一个函数指针在自定义的section——INIT_LIST,这个自定义的段由编译器静态分配。

  • 主函数中调用sys_init()
 int main(void)
 {
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级

    sys_init(); 

    while(1)
    {
        software_timer_main_loop();
    }
}    

原文地址:https://www.cnblogs.com/AresGuangjie/p/12392892.html

时间: 2024-11-14 11:47:49

利用__attribute__((section("name")))构建初始化函数表的相关文章

链接加载文件gcc __attribute__ section

在阅读源代码的过程中,发现一个头文件有引用: /** The address of the first device table entry. */ extern device_t devices[]; /** The address after the last device table entry. */ extern device_t devices_end[]; /** The address of the first "driver_t". */ extern driver_

关于C++中虚函数表存放位置的思考

其实这是我前一段时间思考过的一个问题,是在看<深入探索C++对象模型>这本书的时候我产生的一个疑问,最近在网上又看到类似的帖子,贴出来看看: 我看到了很多有意思的答案,都回答的比较好,下面贴出一些具有代表性的: Answer 1: Answer 2: 我们都知道,虚函数是多态机制的基础,就是在程序在运行期根据调用的对象来判断具体调用哪个函数,现在我们来说说它的具体实现原理,主要说一下我自己的理解,如果有什么不对的地方请指正在每个包含有虚函数的类的对象的最前面(是指这个对象对象内存布局的最前面,

C++虚函数表剖析

关键词:虚函数.虚表,虚表指针,动态绑定,多态 一.概述 为了实现C++的多态,C++使用了一种动态绑定的技术. 这个技术的核心是虚函数表(下文简称虚表).本文介绍虚函数表是怎样实现动态绑定的. 二.类的虚表 每一个包括了虚函数的类都包括一个虚表. 我们知道,当一个类(A)继承还有一个类(B)时.类A会继承类B的函数的调用权.所以假设一个基类包括了虚函数,那么其继承类也可调用这些虚函数,换句话说,一个类继承了包括虚函数的基类.那么这个类也拥有自己的虚表. 我们来看下面的代码. 类A包括虚函数vf

C++中的虚函数表是什么时期建立的?(阿里内推面试题)

虚函数表是在什么时期建立的? 最近参加阿里巴巴公司的内推,面试官问了“虚函数表是在什么时期建立的?”.因为以前对虚函数表的理解不够多,所以就根据程序构建(Build)的四个过程(预编译.编译.汇编和链接),推导出虚函数表应该是在编译器确定的,原因如下: 1)预编译器主要处理那些源代码文件中的以“#”开始的预编译指令,如“#include”.“#define”.很明显这个过程可以排除. 2)汇编器是将编译器生成的汇编代码转变成机器可以执行的指令,每一个汇编语句几乎都对应一条机器指令.汇编过程相对于

C++虚函数表理解

一,思维模式图 二,代码验证 class A { public: A(int x) { fProtected = x; } float GetFProtected() { return fProtected; } public: float fpublic = 2.3f; //c++11支持了初始化,但不能使用auto string sname = "liqi"; CMyNumOperator<int>* on = new CMyNumOperator<int>

C++中3种多态实现机制之虚函数表

上期我们简单的讲解了利用RTTI来实现多肽,这期我们就来聊聊利用虚函数的方法来实现多肽. 1.什么是虚函数 在某基类中声明为 virtual 并在一个或多个派生类中被重新定 义的成员函数,用法格式为:virtual 函数返回类型 函数名(参数表) {函数体}:,实现多态性,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数 2.实现多肽的条件 简单的说就是:基类的指针或引用指向子类对象,当子类中成员函数和基类成员函数:函数名相同,参数列表相同,返回值相同,并且基类该函数为虚函数时,基类

【欧拉函数表】POJ2478-Farey Sequence

[题目大意] 求∑φ(i)(1<=i<=N). [思路] 欧拉函数具有如下的重要推论: 当b是素数时 性质①若b|a,有φ(ab)=φ(a)*b: 性质②若b不|a,有φ(ab)=φ(a)*(b-1). 由此可以得出递推求欧拉函数表的方法: 对于当前φ(i),若未被修改过,这说明它是素数,加入素数表. 对于每个i,枚举小于它的所有素数j.利用性质1和性质2求出φ(ij) 1 #include<iostream> 2 #include<cstdio> 3 #include

C++学习 - 虚表,虚函数,虚函数表指针学习笔记

虚函数 虚函数就是用virtual来修饰的函数.虚函数是实现C++多态的基础. 虚表 每个类都会为自己类的虚函数创建一个表,来存放类内部的虚函数成员. 虚函数表指针 每个类在构造函数里面进行虚表和虚表指针的初始化. 下面看一段代码: // // main.cpp // VirtualTable // // Created by Alps on 15/4/14. // Copyright (c) 2015年 chen. All rights reserved. // #include <iostr

虚函数表存放在哪里

from: here 1.虚函数表是全局共享的元素,即全局仅有一个. 2.虚函数表类似一个数组,类对象中存储vptr指针,指向虚函数表.即虚函数表不是函数,不是程序代码,不肯能存储在代码段. 3.虚函数表存储虚函数的地址,即虚函数表的元素是指向类成员函数的指针,而类中虚函数的个数在编译时期可以确定,即虚函数表的大小可以确定,即大小是在编译时期确定的,不必动态分配内存空间存储虚函数表,所以不再堆中. 根据以上特征,虚函数表类似于类中静态成员变量.静态成员变量也是全局共享,大小确定. 所以我推测虚函