日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > linux >内容正文

linux

linux板级初始化

發(fā)布時(shí)間:2023/12/10 linux 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux板级初始化 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

最近拿到了明遠(yuǎn)智睿 的EK314開發(fā)板,以前主要用2440,眼界過于狹隘,借此機(jī)會(huì)練習(xí)下。

http://lornyin.top/?p=106 原文地址
首先看看它的板級(jí)文件

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

在他的末尾指定了map_io、init_irq、init_machine、timer等初始化函數(shù),MACHINE_START是個(gè)宏定義,他的展開我列了出來

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)) ,讓編譯器取消結(jié)構(gòu)在編譯過程中的優(yōu)化對(duì)齊,按照實(shí)際占用字節(jié)數(shù)進(jìn)行對(duì)齊,
// 這樣子兩邊都需要使用 attribute ((packed))取消優(yōu)化對(duì)齊,就不會(huì)出現(xiàn)對(duì)齊的錯(cuò)位現(xiàn)象。

這里的話,是定義了一個(gè)struct machine_desc __mach_desc__MYIMX6EK314 的結(jié)構(gòu)體

這個(gè)結(jié)構(gòu)體存放的段是.arch.info.init,這里注意一下,后邊匹配machine_desc的時(shí)候就是到這個(gè)段中尋找,然后根據(jù)nr的值匹配。

這里的machine_desc指定的初始化函數(shù)的調(diào)用分別在以下階段

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);

這個(gè)arch_initcall 執(zhí)行了machine_desc->init_machine(),那么arch_initcall 是何時(shí)調(diào)用的呢?

在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); }

這里的一個(gè)for循環(huán)do_one_initcall,調(diào)用了所有的 xxxx_initcall,在include/linux/init.h 中

以下代碼是對(duì)標(biāo)號(hào)進(jìn)行處理,方便統(tǒng)一調(diào)用
`#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); 就是個(gè)函數(shù)指針

__define_initcall就是把函數(shù)指針指向xxx_initcall() ,對(duì)應(yīng)我們的初始化函數(shù)

而屬性 attribute((section())) 則表示把對(duì)象放在一個(gè)這個(gè)由括號(hào)中的名稱所指代的section中。

所以__define_initcall的含義是:

1) 聲明一個(gè)名稱為_initcall##fn的函數(shù)指針;

2) 將這個(gè)函數(shù)指針初始化為fn;

3) 編譯的時(shí)候需要把這個(gè)函數(shù)指針變量放置到名稱為 “.initcall” level “.init”的section中。

這個(gè)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里的函數(shù)在初始化時(shí)被順序執(zhí)行(init內(nèi)核線程->do_basic_setup()[main.C#778]->do_initcalls())。

程序(init/main.c文件do_initcalls()函數(shù))do_initcalls()把.initcallXX.init中的函數(shù)按順序都執(zhí)行一遍。

總結(jié)

以上是生活随笔為你收集整理的linux板级初始化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。