最近拿到了明远智睿 的EK314开发板,以前主要用2440,眼界过于狭隘,借此机会练习下。

http://lornyin.top/?p=106 原文地址
首先看看它的板级文件

/arch/arm/mach-mx6/board-myimx6ek314.c

在他的末尾指定了map_io、init_irq、init_machine、timer等初始化函数,MACHINE_START是个宏定义,他的展开我列了出来

MACHINE_START(MYIMX6EK314, "MYZR i.MX6 Evaluation Kit ( MXM 314 )").boot_params = MX6_PHYS_OFFSET + 0x100,.fixup = fixup_mxc_board,.map_io = mx6_map_io,.init_irq = mx6_init_irq,.init_machine = mx6_sabresd_board_init,.timer = &mx6_sabresd_timer,.reserve = mx6q_sabresd_reserve,
MACHINE_ENDMACHINE_START(MYIMX6EK314, "MYZR i.MX6 Evaluation Kit ( MXM 314 )").boot_params = MX6_PHYS_OFFSET + 0x100,.fixup = fixup_mxc_board,.map_io = mx6_map_io,.init_irq = mx6_init_irq,.init_machine = mx6_sabresd_board_init,.timer = &mx6_sabresd_timer,.reserve = mx6q_sabresd_reserve,
MACHINE_END`#define MACHINE_START(_type,_name)         \
static const struct machine_desc __mach_desc_##_type    \__used                         \__attribute__((__section__(".arch.info.init"))) = {    \.nr     = MACH_TYPE_##_type,        \.name       = _name,`#define MACHINE_END                \
};

// 使用 attribute ((packed)) ,让编译器取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐,
// 这样子两边都需要使用 attribute ((packed))取消优化对齐,就不会出现对齐的错位现象。

这里的话,是定义了一个struct machine_desc __mach_desc__MYIMX6EK314 的结构体

这个结构体存放的段是.arch.info.init,这里注意一下,后边匹配machine_desc的时候就是到这个段中寻找,然后根据nr的值匹配。

这里的machine_desc指定的初始化函数的调用分别在以下阶段

void __init setup_arch(char **cmdline_p)
{struct machine_desc *mdesc;unwind_init();setup_processor();mdesc = setup_machine_fdt(__atags_pointer);if (!mdesc)mdesc = setup_machine_tags(machine_arch_type);machine_desc = mdesc;machine_name = mdesc->name;if (mdesc->soft_reboot)reboot_setup("s");.....................parse_early_param();sanity_check_meminfo();arm_memblock_init(&meminfo, mdesc);paging_init(mdesc);      // ->paging_init(mdesc)->devicemaps_initrequest_standard_resources(mdesc);...................early_trap_init();if (mdesc->init_early)mdesc->init_early();      //init_early:
}void __init setup_arch(char **cmdline_p)
{struct machine_desc *mdesc;unwind_init();setup_processor();mdesc = setup_machine_fdt(__atags_pointer);if (!mdesc)mdesc = setup_machine_tags(machine_arch_type);machine_desc = mdesc;machine_name = mdesc->name;if (mdesc->soft_reboot)reboot_setup("s");.....................parse_early_param();sanity_check_meminfo();arm_memblock_init(&meminfo, mdesc);paging_init(mdesc);      // ->paging_init(mdesc)->devicemaps_initrequest_standard_resources(mdesc);...................early_trap_init();if (mdesc->init_early)mdesc->init_early();      //init_early:
}

init_irq:
/init/main.c/start_kernel(void)->init_IRQ()->machine_desc->init_irq()
(mdesc) ->devicemaps_init() -> mdesc->map_io()
time_init:
start_kernel() –> time_init()->system_timer = machine_desc->timer;system_timer->init()

init_machine:

他是用了arch/arm/kernel/setup.c

@729
static int __init customize_machine(void)
{/* customizes platform devices, or adds new ones */if (machine_desc->init_machine)machine_desc->init_machine();return 0;
}
arch_initcall(customize_machine);static int __init customize_machine(void)
{/* customizes platform devices, or adds new ones */if (machine_desc->init_machine)machine_desc->init_machine();return 0;
}
arch_initcall(customize_machine);

这个arch_initcall 执行了machine_desc->init_machine(),那么arch_initcall 是何时调用的呢?

在main.c ->do_basic_setup();->do_initcalls();中

static void __init do_initcalls(void)
{initcall_t *fn;for (fn = __early_initcall_end; fn < __initcall_end; fn++)do_one_initcall(*fn);
}static void __init do_initcalls(void)
{initcall_t *fn;for (fn = __early_initcall_end; fn < __initcall_end; fn++)do_one_initcall(*fn);
}

这里的一个for循环do_one_initcall,调用了所有的 xxxx_initcall,在include/linux/init.h 中

以下代码是对标号进行处理,方便统一调用
`#define pure_initcall(fn) __define_initcall(“0”,fn,0)

#define core_initcall(fn) __define_initcall("1",fn,1)
#define core_initcall_sync(fn) __define_initcall(“1s”,fn,1s)
#define postcore_initcall(fn) __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn) __define_initcall(“2s”,fn,2s)
#define arch_initcall(fn) __define_initcall("3",fn,3)
#define arch_initcall_sync(fn) __define_initcall(“3s”,fn,3s)
#define subsys_initcall(fn) __define_initcall("4",fn,4)
#define subsys_initcall_sync(fn) __define_initcall(“4s”,fn,4s)
#define fs_initcall(fn) __define_initcall("5",fn,5)
#define fs_initcall_sync(fn) __define_initcall(“5s”,fn,5s)
#define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn) __define_initcall(“6”,fn,6)
#define device_initcall_sync(fn) __define_initcall("6s",fn,6s)
#define late_initcall(fn) __define_initcall(“7”,fn,7)
`#define late_initcall_sync(fn) __define_initcall(“7s”,fn,7s)

`#define __initcall(fn) device_initcall(fn)

`#define pure_initcall(fn) __define_initcall(“0”,fn,0)

#define core_initcall(fn) __define_initcall("1",fn,1)
#define core_initcall_sync(fn) __define_initcall(“1s”,fn,1s)
#define postcore_initcall(fn) __define_initcall("2",fn,2)
#define postcore_initcall_sync(fn) __define_initcall(“2s”,fn,2s)
#define arch_initcall(fn) __define_initcall("3",fn,3)
#define arch_initcall_sync(fn) __define_initcall(“3s”,fn,3s)
#define subsys_initcall(fn) __define_initcall("4",fn,4)
#define subsys_initcall_sync(fn) __define_initcall(“4s”,fn,4s)
#define fs_initcall(fn) __define_initcall("5",fn,5)
#define fs_initcall_sync(fn) __define_initcall(“5s”,fn,5s)
#define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
#define device_initcall(fn) __define_initcall(“6”,fn,6)
#define device_initcall_sync(fn) __define_initcall("6s",fn,6s)
#define late_initcall(fn) __define_initcall(“7”,fn,7)
`#define late_initcall_sync(fn) __define_initcall(“7s”,fn,7s)

`#define __initcall(fn) device_initcall(fn)

`#define __define_initcall(level,fn,id) \
static initcall_t _initcall##fn##id __used \
attribute((section(“.initcall” level “.init”))) = fn

initcall_t 的原型是typedef int (*initcall_t)(void); 就是个函数指针

__define_initcall就是把函数指针指向xxx_initcall() ,对应我们的初始化函数

而属性 attribute((section())) 则表示把对象放在一个这个由括号中的名称所指代的section中。

所以__define_initcall的含义是:

1) 声明一个名称为_initcall##fn的函数指针;

2) 将这个函数指针初始化为fn;

3) 编译的时候需要把这个函数指针变量放置到名称为 “.initcall” level “.init”的section中。

这个section是在/include/asm-generic/vmlinux.lds.h中

`#define INITCALLS                          \
    *(.initcallearly.init)                      \
    VMLINUX_SYMBOL(__early_initcall_end) = .;           \
    *(.initcall0.init)                      \
    *(.initcall0s.init)                     \
    *(.initcall1.init)                      \
    *(.initcall1s.init)                     \
    *(.initcall2.init)                      \
    *(.initcall2s.init)                     \
    *(.initcall3.init)                      \
    *(.initcall3s.init)                     \
    *(.initcall4.init)                      \
    *(.initcall4s.init)                     \
    *(.initcall5.init)                      \
    *(.initcall5s.init)                     \
    *(.initcallrootfs.init)                     \
    *(.initcall6.init)                      \
    *(.initcall6s.init)                     \
    *(.initcall7.init)                      \
    *(.initcall7s.init)#define INIT_CALLS \
       VMLINUX_SYMBOL(__initcall_start) = .; \
       INITCALLS \
       VMLINUX_SYMBOL(__initcall_end) = .;#define INITCALLS                           \
    *(.initcallearly.init)                      \
    VMLINUX_SYMBOL(__early_initcall_end) = .;           \
    *(.initcall0.init)                      \
    *(.initcall0s.init)                     \
    *(.initcall1.init)                      \
    *(.initcall1s.init)                     \
    *(.initcall2.init)                      \
    *(.initcall2s.init)                     \
    *(.initcall3.init)                      \
    *(.initcall3s.init)                     \
    *(.initcall4.init)                      \
    *(.initcall4s.init)                     \
    *(.initcall5.init)                      \
    *(.initcall5s.init)                     \
    *(.initcallrootfs.init)                     \
    *(.initcall6.init)                      \
    *(.initcall6s.init)                     \
    *(.initcall7.init)                      \
    *(.initcall7s.init)'#define INIT_CALLS \
       VMLINUX_SYMBOL(__initcall_start) = .; \
       INITCALLS \
       VMLINUX_SYMBOL(__initcall_end) = .;

而这些SECTION里的函数在初始化时被顺序执行(init内核线程->do_basic_setup()[main.C#778]->do_initcalls())。

程序(init/main.c文件do_initcalls()函数)do_initcalls()把.initcallXX.init中的函数按顺序都执行一遍。

linux板级初始化相关推荐

  1. Uboot 板级初始化流程and so on

    -------------------------- 本文以U-boot 2018.09源码 mips mt7621进行举例说明. 此预期的理论初始化流程适用于全U-boot和SPL(Secondar ...

  2. at91sam9260ek的板级、irq初始化-小试牛刀

    话不多说,先上代码. //code path:arch/arm/mach-at91/board-sam9260ek.c MACHINE_START(AT91SAM9260EK, "Atmel ...

  3. linux x86板级文件,Linux driver 板级文件跟踪一般方法

    /*********************************************************************************** * Linux driver ...

  4. 使用yocto搭建 i.MX8QXP Linux 4.14.98_ga 板级开发包编译环境

    1.1 下载板级开发包 https://www.nxp.com/support/developer-resources/run-time-software/i.mx-developer-resourc ...

  5. linux 为开发板添加板级文件config.h

    新的板子  需要在之前的板子基础上 做一些改动  首先就是要配置自己的板级文件 参考陈富林博客 这个写的很详细 https://www.cnblogs.com/chenfulin5/p/6393415 ...

  6. i.MX6 u-boot 怎么确定板级头文件

    /*********************************************************************** i.MX6 u-boot 怎么确定板级头文件* 说明: ...

  7. OpenBoard的板级支持包(BSP)开发召集令

    OpenBoard的板级支持包(BSP)开发召集令 什么是"板级支持包"? 在嵌入式系统中,Board Support Package(简称BSP,中译板支持包)是实现特定的支持代 ...

  8. 【原创】MIPS中断系统的板级验证及实例测试

    "五一"假期前后这约五天时间,终于将MIPS中断系统进行了板级验证及实例测试.因为老师给的交叉编译工具不会用,所以测试代码完全用MIPS汇编编写.使用MARS而没有用QtSpim, ...

  9. DPDK在Linux用户级执行环境中执行EAL

    目录 在Linux用户级执行环境中进行EAL 初始化和核心启动 关机和清理 多进程支持 内存映射发现和内存保留 支持外部分配的内存 每个核心和共享变量 日志 CPU功能识别 用户空间中断事件 黑名单 ...

最新文章

  1. html5添加随机率,HTML5 canvas  绘制随机曲线 并实现放大功能
  2. 序列化流与反序列化流
  3. 记一次T-SQL查询优化 索引的重要性
  4. AGC034 F - RNG and XOR
  5. 模态框里使IMG的Src能动态显示
  6. gridview行号
  7. inno setup 另一个程序正在使用此文件_STEP 7-MicroWIN SMART程序的上传与下载方式
  8. php目录遍历漏洞复现,nginx解析漏洞,配置不当,目录遍历漏洞环境搭建、漏洞复现...
  9. LLVM每日谈之一 LLVM是什么
  10. 我什么时候应该使用懒惰 <T> ?
  11. Emacs一个键绑定多个命令
  12. error: L6002U: Could not open file .\objects\startup_stm32f10x_hd.o
  13. iOS 模拟器下载与安装
  14. cs1.6服务器弹道优化,cs1.6弹道优化参数
  15. excel做ns流程图_如何制作传统流程图和NS流程图教程详解.ppt
  16. synchronized锁升级之重量级锁
  17. 电脑桌面云便签怎么设置短信提醒便签事项?
  18. 朱老师ARM裸机学习笔记(四):S5PV210启动过程详解
  19. 专转本-计算机二级习题2
  20. python @符号

热门文章

  1. 英利1500伏光伏组件系列亮相美国
  2. tomcat 绑定 ip 及域名,限制非法域名访问
  3. 智能识别技术对电子警察设备的影响
  4. 史陶比尔与机器人之父
  5. 最优化5-8章重点(考试点全)
  6. 计算机专业课的教学准备,计算机专业课程教学中的分层教学模式
  7. 正则表达式里转义字符_五分钟搞定正则表达式,如果没搞定,再加两分钟
  8. 如何将MATLAB程序发布为独立的不依赖MATLAB环境可执行的程序包(基于Matlab R2015b版 )
  9. 微信支付配置参数:支付授权目录、回调支付URL
  10. 最大连续子矩阵和算法