码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-03-01 23:23:59      阅读:263      评论:0      收藏:0      [点我收藏+]

标签:mit   begin   timer   lang   模块   一个   函数指针   priority   pre   

在嵌入式学习工作中经常初始化一个硬件就写一个初始化函数,基本都要到主函数中调用进行初始化,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();
    }
}    

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

标签:mit   begin   timer   lang   模块   一个   函数指针   priority   pre   

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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!