MTk kernel启动流程
MTk kernel启动流程
late_initcall
所有的__init函数在区段.initcall.init中还保存了一份函数指针,在初始化时内核会通过这些函数指针调用这些__init函数指针,并在整个初始化完成后,释放整个init区段(包括.init.text,.initcall.init等)。
注意,这些函数在内核初始化过程中的调用顺序只和这里的函数指针的顺序有关,和1)中所述的这些函数本身在.init.text区段中的顺序无关。initcall.init区段分成7个子区段,分别是
.initcall1.init
.initcall2.init
.initcall3.init
.initcall4.init
.initcall5.init
.initcall6.init
.initcall7.init当需要把函数fn放到.initcall1.init区段时,只要声明core_initcall(fn);即可。
其他的各个区段的定义方法分别是:
core_initcall(fn) --->.initcall1.init
postcore_initcall(fn) --->.initcall2.init
arch_initcall(fn) --->.initcall3.init
subsys_initcall(fn) --->.initcall4.init
fs_initcall(fn) --->.initcall5.init
device_initcall(fn) --->.initcall6.init
late_initcall(fn) --->.initcall7.init
在内核中,不同的init函数被放在不同的子区段中,因此也就决定了它们的调用顺序。这样也就解决了一些init函数之间必须保证一定的调用顺序的问题。按照include/linux/init.h文件所写的,我在驱动里偿试了这样两种方式:
__define_initcall("7", fn);
late_initcall(fn);
都可以把我的驱动调整到最后调用。实际上上面两个是一回事:
#define late_initcall(fn)__define_initcall("7", fn)
linux中把initcall分成了若干种类,主要用来区别不同的initcall的调用次序,由于initcall中的调用次序是随机的,所以不能保证某些重要的初始化先运行。分成了以下几个initcall,按执行顺序先后排列:
pure_initcall:最先运行的,不依赖于任何其他初始化函数。
core_initcall
core_initcall_sync
postcore_initcall
postcore_initcall_sync
arch_initcall
arch_initcall_sync
subsys_initcall
subsys_initcall_sync
fs_initcall
fs_initcall_sync
rootfs_initcall
device_initcall
device_initcall_sync
late_initcall
late_initcall_sync。
如:
Kernel/include/linux/init.h
178 #define __define_initcall(level,fn,id)\
179 static initcall_t __initcall_##fn##id __used \
180 __attribute__((__section__(".initcall" level".init"))) = fn
181
182 /*
183 * Early initcalls run before initializing SMP.
184 *
185 * Only for built-in code, not modules.
186 */
187 #define early_initcall(fn) __define_initcall("early",fn,early)
188
189 /*
190 * A "pure" initcall has no dependencies on anything else, andpurely
191 * initializes variables that couldn't be statically initialized.
192 *
193 * This only exists for built-in code, not for modules.
194 */
195 #define pure_initcall(fn) __define_initcall("0",fn,0)
196
197 #define core_initcall(fn) __define_initcall("1",fn,1)
198 #define core_initcall_sync(fn) __define_initcall("1s",fn,1s)
199 #define postcore_initcall(fn) __define_initcall("2",fn,2)
200 #define postcore_initcall_sync(fn) __define_initcall("2s",fn,2s)
201 #define arch_initcall(fn) __define_initcall("3",fn,3)
202 #define arch_initcall_sync(fn) __define_initcall("3s",fn,3s)
203 #define subsys_initcall(fn) __define_initcall("4",fn,4)
204 #define subsys_initcall_sync(fn) __define_initcall("4s",fn,4s)
205 #define fs_initcall(fn) __define_initcall("5",fn,5)
206 #define fs_initcall_sync(fn) __define_initcall("5s",fn,5s)
207 #define rootfs_initcall(fn) __define_initcall("rootfs",fn,rootfs)
208 #define device_initcall(fn) __define_initcall("6",fn,6)
209 #define device_initcall_sync(fn) __define_initcall("6s",fn,6s)
210 #define late_initcall(fn) __define_initcall("7",fn,7)
211 #define late_initcall_sync(fn) __define_initcall("7s",fn,7s)
Meditek kernel启动:
platform/mt6592/kernel/core/board.c
board_init()调mt_board_init();
./platform/mt6592/kernel/core/core.c
111 #ifdef MTK_TABLET_PLATFORM
112 MACHINE_START(MT6592,MTK_TABLET_PLATFORM)
113 #else
114 MACHINE_START(MT6592,"MT6592")
115 #endif
116 .atag_offset = 0x00000100,
117 .map_io = mt_map_io,
118 .init_irq = mt_init_irq,
119 .timer = &mt_timer,
120 .init_machine = mt_init,
121 .fixup = mt_fixup,
122 .restart =arm_machine_restart,
123 .reserve = mt_reserve,
124 MACHINE_END
kernel/arch/arm/include/asm/mach/arch.h中定义MACHINE_START
#defineMACHINE_START(_type,_name) \
static conststruct machine_desc __mach_desc_##_type \__used \__attribute__((__section__(".arch.info.init")))= { \
.nr = MACH_TYPE_##_type, \
.name = _name,#defineMACHINE_END \
};
MACHINE_START主要是定义了"structmachine_desc"的类型,放在 section(".arch.info.init"),是初始化数据,Kernel起来之后将被丢弃。
117 .map_io = mt_map_io,
这里会把一组平台相关的物理地址(比如总线地址、设备基地址)映射到一组固定虚拟地址上,这组虚拟地址在整个内核空间可见
106 void __init mt_map_io(void)
107 {
108 iotable_init(mt_io_desc, ARRAY_SIZE(mt_io_desc));
109 }iotable_init定义位于:Kernel/arch/arm/mm/mmu.c785 * Create the architecture specific mappings786 */787 void __init iotable_init(struct map_desc*io_desc, int nr)788 {789 struct map_desc *md;790 struct vm_struct *vm;791792 if (!nr)793 return;794795 vm = early_alloc_aligned(sizeof(*vm) * nr, __alignof__(*vm));796797 for (md = io_desc; nr; md++, nr--) {798 create_mapping(md, false);799 vm->addr = (void *)(md->virtual & PAGE_MASK);800 vm->size = PAGE_ALIGN(md->length + (md->virtual &~PAGE_MASK));801 vm->phys_addr = __pfn_to_phys(md->pfn);802 vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;803 vm->flags |= VM_ARM_MTYPE(md->type);804 vm->caller = iotable_init;805 vm_area_add_early(vm++);806 }807 }
118 .init_irq = mt_init_irq,
platform/mt6592/kernel/core/irq.c1054 void __initmt_init_irq(void)
1055 {
1056 spin_lock_init(&irq_lock);
1057 mt_gic_dist_init();
1058 mt_gic_cpu_init();
1059 }
119 .timer = &mt_timer,
platform/mt6592/kernel/core/tmer.c
50struct sys_timer mt_timer = {
51 .init = mt_timer_init,
52};
121 .fixup = mt_fixup,
platform/mt6592/kernel/core /mt_devs.c
对memory的一个fix。
122 .restart = arm_machine_restart,kernel/arch/arm/kernel/process.cvoid arm_machine_restart(char mode, const char *cmd)
146 {
147 /* Flush the console to make sure allthe relevant messages make it
148 * out to theconsole drivers */
149 arm_machine_flush_console();
150
151 /* Disableinterrupts first */
152 local_irq_disable();
153 local_fiq_disable();
154
155 /*
156 * Tell the mmsystem that we are going to reboot -
157 * we may need itto insert some 1:1 mappings so that
158 * soft bootworks.
159 */
160 setup_mm_for_reboot();
161
162 /* When l1 isdisabled and l2 is enabled, the spinlock cannot get the lock,
163 * so we need todisable the l2 as well. by Chia-Hao Hsu
164 */
165 outer_flush_all();
166 outer_disable();
167 outer_flush_all();
168
169 /* Clean andinvalidate caches */
170 flush_cache_all();
171
172 /* Turn offcaching */
173 cpu_proc_fin();
174
175 /* Push out anyfurther dirty data, and ensure cache is empty */
176 flush_cache_all();
177
178 /*
179 * Now call thearchitecture specific reboot code.
180 */
181 arch_reset(mode,cmd);
183 /*
184 * Whoops - thearchitecture was unable to reboot.
185 * Tell the user!
186 */
187 mdelay(1000);
188 printk("Reboot failed -- System halted\n");
189 while (1);
190 }
123 .reserve = mt_reserve,
platform/mt6592/kernel/core /mt_devs.c
主要是对memory的一个预留。
platform/mt6592/kernel/core /mt_devs.c主要实现以下函数:
HW_TP_Init mt_board_init is_pmem_range mtk_get_max_DRAM_size get_phys_offset get_text_region mt_reserve
For example1:(led)
在mt_board_init();
/注册设备信息,例如:***/
#if defined(CONFIG_MTK_LEDS)retval= platform_device_register(&mt65xx_leds_device);if(retval != 0)returnretval;printk("bei:deviceLEDS register\n");
#endifstatic struct platform_device mt65xx_leds_device = {.name= "leds-mt65xx",.id= -1
};
驱动设备匹配如下:匹配driver name :“leds-mt65xx”,
/platform/mt6592/kernel/drivers/leds/leds.c
./kernel/drivers/leds/leds_drv.c
602 static struct platform_drivermt65xx_leds_driver = {
603 .driver = {
604 .name ="leds-mt65xx",
605 .owner = THIS_MODULE,
606 },
607 .probe = mt65xx_leds_probe,
608 .remove = mt65xx_leds_remove,
609 //.suspend = mt65xx_leds_suspend,
610 .shutdown =mt65xx_leds_shutdown,
611 };
再继续就是进入我们熟悉的probe函数,这里不再赘述!
MTk kernel启动流程相关推荐
- 【SemiDrive源码分析】【X9芯片启动流程】30 - AP1 Android Kernel 启动流程 start_kernel 函数详细分析(一)
[SemiDrive源码分析][X9芯片启动流程]30 - AP1 Android Kernel 启动流程 start_kernel 函数详细分析(一) 一.Android Kernel 启动流程分析 ...
- kernel启动流程-start_kernel的执行_8.cpio initrd解包
目录 1. 前言 2. rootfs挂载 3.populate_rootfs 4.GotName的处理 参考文档 1. 前言 本专题文章承接之前<kernel启动流程_head.S的执行> ...
- [kernel 启动流程] 前篇——vmlinux.lds分析
https://blog.csdn.net/ooonebook/article/details/52690132 以下例子都以project X项目tiny210(s5pv210平台,armv7架构) ...
- I.MX6ULL_Linux_系统篇(21) kernel启动流程
链接脚本 vmlinux.lds 要分析 Linux 启动流程,同样需要先编译一下 Linux 源码,因为有很多文件是需要编译才会生成的.首先分析 Linux 内核的连接脚本文件 arch/arm/k ...
- kernel启动流程-head.S的执行_3.preserve_boot_args
1.前言 kernel版本:5.10 平台:arm64 本专题主要基于<arm64_linux head.S的执行流程>系列文章,前者是基于3.18,本专题针对的是内核5.10.主要分析h ...
- kernel启动流程-head.S的执行_4.el2_setup
目录 1.前言 2. el2_setup 选择栈 判断当前的异常级别 设置EL2端模式 设置EL0/EL1的端模式 VHE支持 Hyp configuration access physical ti ...
- Kernel 启动流程梳理
内核生命周期 uboot 打印完 Starting kernel . . .,就完成了自己的使命,控制权便交给了 kernel 的第一条指令,也就是下面这个函数 init/main.c asmlink ...
- uboot流程——uboot启动流程
[uboot] (第五章)uboot流程--uboot启动流程 2016年11月07日 20:12:07 阅读数:2230 以下例子都以project X项目tiny210(s5pv210平台,arm ...
- Linux Kernel系列一:开篇和Kernel启动概要
前言 近期几个月将Linux Kernel的大概研究了一下,以下须要进行深入具体的分析.主要将以S3C2440的一块开发板为硬件实体.大概包含例如以下内容: 1 bootloader分析,以uboot ...
- [uboot] (第五章)uboot流程——uboot启动流程
以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为例 [uboot] uboot流程系列: [project X] tiny210(s5pv210)上电启动流程( ...
最新文章
- 日本人真会玩!3天众筹60万元来造“机器猫”,会说话摇尾巴的那种
- 2021宁夏高考成绩查询电话,2021宁夏高考成绩什么时候几点可以查
- SVN专题(Visual SVN Server + TortoiseSVN + Visual SVN)
- golang java rpc_golang两种调用rpc的方法
- MySQL操作之JSON数据类型操作详解
- CYQ.Data 轻量数据访问层(四) 构造数据单元列
- gradle 引入jar时自动引入父依赖_原创 | 看完此文,你对Gradle的理解又升级了
- 计算机考研专业基础知识视频教程链接
- hdu 6015 Gameia(树上博弈)
- 慢慢人生路,学点Jakarta基础-集合类
- mysql插入用户 5.7_mysql 5.7 用户添加与权限管理
- Windows10下设置开机自启动自己的程序
- Mysql同环比计算详解
- word插入分隔符的方法
- php 测试网站打开速度,JS如何测试目标网站的打开响应速度
- 菜鸟编程:python中实现中英文文字或单词计数(wordcount)
- 任务并行库(Task Parellel Library)parallel.for parallel.foreach、List、ConcurrentBag 并行集合、线程安全结合
- oracle pga建议值,对SGA和PGA的优化建议
- 2020春招补录全过程
- maya如何查看资源大纲_maya大纲视图(Outliner),MAYA
热门文章
- python程度员要学很多英语吗_为什么程序员应该学好英语?
- 如何将bmp转化为jpg,bmp转jpg方法
- SAP中销售发货及开票引发的会计成本与收入配比原则问题的实例分析
- STM32片上Flash读写的一些重要知识
- html修改progress背景色,html5 progress标签如何更改进度条颜色?progress进度条详解...
- 江阴:智慧融入城市血液,打造创新发展新名片
- 个人小程序 给头像戴圣诞帽
- 汉字文化杂志汉字文化杂志社汉字文化编辑部2022年第11期目录
- 《Machine Learning in Action》—— 浅谈线性回归的那些事
- ligerui combobox ajax,LigerUI中使用ligerComboBox生成多选下拉框