硬汉嵌入式论坛

 找回密码
 立即注册
查看: 377|回复: 4
收起左侧

[其它] 小白疑惑,关于将初始化函数放进内存段的问题,也就是关于initcall的问题

[复制链接]
回帖奖励 10 个金币 回复本帖可获得 5 个金币奖励! 每人限 1 次(中奖概率 80%)

1

主题

3

回帖

6

积分

新手上路

积分
6
发表于 2023-8-14 18:20:17 | 显示全部楼层 |阅读模式
我目前在移植cola os到自己的项目中,然后里面有个类似于linux将初始化函数放入内存段中执行的源码。
我使用的是GNUC编译器,现在困惑我的是 extern initcall_t __initcall_start[]; 和 extern initcall_t __initcall_end[];
  • 这两个变量从哪里来?该如何定义?
  • 需要写链接脚本吗,如果需要该怎么写?

例如我现在有`init_1()`和`init_2()`两个函数需要放进内存段执行。
源码如下:
/* initcall.c */
void do_init_call(void)
{
//GNUC编译器
    extern initcall_t __initcall_start[];
    extern initcall_t __initcall_end[];

    initcall_t *start = __initcall_start;
    initcall_t *end = __initcall_end;
    initcall_t *fn;

    for (fn = start; fn < end; fn++)
    {
        usb_printf("initcall fn 0x%x\r\n", fn);
        (*fn)();
    }
}
//===============================================

/* initcall.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);
//===============================================




回复

使用道具 举报

1

主题

3

回帖

6

积分

新手上路

积分
6
 楼主| 发表于 2023-8-14 18:24:21 | 显示全部楼层
为了看的更清楚,我把代码重新粘一下
[C] 纯文本查看 复制代码
void do_init_call(void)
{
    extern initcall_t __initcall_start[];
    extern initcall_t __initcall_end[];

    initcall_t *start = __initcall_start;
    initcall_t *end = __initcall_end;
    initcall_t *fn;

    for (fn = start; fn < end; fn++)
    {
        usb_printf("initcall fn 0x%x\r\n", fn);
        (*fn)();
    }
}



[C] 纯文本查看 复制代码
#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) //传感器初始化
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
106660
QQ
发表于 2023-8-15 14:45:35 | 显示全部楼层

回帖奖励 +5 个金币

反应到MDK上,就是这个东西。

MDK获取未使用RAM空间首地址方法
https://www.armbbs.cn/forum.php? ... 1353&fromuid=58
(出处: 硬汉嵌入式论坛)
回复

使用道具 举报

1

主题

3

回帖

6

积分

新手上路

积分
6
 楼主| 发表于 2023-8-15 15:11:21 | 显示全部楼层
eric2013 发表于 2023-8-15 14:45
反应到MDK上,就是这个东西。

MDK获取未使用RAM空间首地址方法

确实是这个东西,每个编译器还不一样。我后来又看了看源码的issues,有人说是因为代码不支持AC6编译,搞得我很懵。感觉问题应该不是不支持,而是没有指定初始化函数的内存段start地址和end地址。
回复

使用道具 举报

1

主题

3

回帖

6

积分

新手上路

积分
6
 楼主| 发表于 2023-8-15 17:19:09 | 显示全部楼层
大概懂了吧,应该是需要在链接脚本里加上
[C] 纯文本查看 复制代码
SECTIONS
{
  .initcalls :
  {
    . = ALIGN(4);
    __initcall_start = .;
    KEEP (*(.initcall0init))
    KEEP (*(.initcall1init))
    KEEP (*(.initcall2init))
    KEEP (*(.initcall3init))
    __initcall_end = .;
    . = ALIGN(4);
  } >FLASH
}

__initcall_start和__initcall_end是使用链接脚本里的符号。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-4-29 01:07 , Processed in 0.217235 second(s), 31 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表