本文简单介绍了mtk-lk阶段的启动流程。
1.crt0.S的_start跳转到kmain执行
.section ".text.boot" .globl _start _start: ...... bl kmain
2.kmain函数在kernel/main.c中定义
void kmain(void) { //初始化线程系统,初始化run_queue& thread链表,初始化bootstrap线程,并标记为当前线程 thread_init_early(); //设置异常向量表基地址,使能mmu和neon,neon为多媒体应用优化设计 arch_early_init(); //平台相关初始化,中断、uart、gpio、wdt、i2c、pmic等,很多在preloader阶段已经完成的无需重复初始化 platform_early_init(); //目标板子前期初始化,这里并未定义 target_early_init(); //调用构造函数,调用.ctors段中的函数,使用objdump反汇编lk文件,并不存在.ctors段,这里直接跳过 call_constructors(); //初始化堆空间,插入空闲堆空间,并进行整合,减少碎片化 heap_init(); //timer线程初始化,这里跳过这步 thread_init(); //初始化dpc线程,调用dpc_queue将callback函数加入线程中,有时间触发时,线程会顺序执行回调函数 dpc_init();
//初始化timer_queue,并设置每隔10ms产生中断调用timer_tick函数 timer_init(); #if (!ENABLE_NANDWRITE) //创建并执行bootstrap2线程 dprintf(SPEW, "creating bootstrap completion thread\n"); thread_resume(thread_create("bootstrap2", &bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE)); //退出临界区,使能中断 exit_critical_section(); //标记当前线程为空闲状态,即bootstrap线程空闲 thread_become_idle(); #else bootstrap_nandwrite(); #endif }
- platform_early_init
void platform_early_init(void) {
//初始化gic controller platform_init_interrupts();
//timer前期初始化 platform_early_init_timer();
//gpio设置为default状态 mt_gpio_set_default();
//串口初始化,从bootarg中获取串口和波特率并进行设置 uart_init_early();
//wdt初始化 mtk_wdt_init();
//i2c初始化,preloader阶段已经完成,这里忽略 i2c_hw_init();
//pmic初始化,preloader阶段完成,这里忽略 pmic_init(); }
- call_constructors,遍历.ctors(__ctor_list到__ctor_end)段中所有的函数,并执行,通过objdump反编译lk并不存在.ctors段,这里直接忽略
static void call_constructors(void) { void **ctor; ctor = &__ctor_list; while(ctor != &__ctor_end) { void (*func)(void); func = (void (*)())*ctor; func(); ctor++; } }
- heap_init,堆初始化
void heap_init(void) { LTRACE_ENTRY; //设置堆空间范围 th