MSM8909+Android5.1.1启动流程(3)---kmain()

MSM8909+Android5.1.1启动流程(3)---kmain()

 

1.     thread_init_early()

// get us into some sort of thread context

       thread_init_early();

让我们进入某种线程上下文,初始化线程系统,此函数只被调用一次。主要的工作如下:

(1)  初始化运行队列list_initialize(&run_queue[i])

(2)  初始化线程列表list_initialize(&thread_list)

(3)  创建一个线程来覆盖当前的运行状态,并初始化次线程的结构体。

/* create a thread to cover the currentrunning state */
       thread_t*t = &bootstrap_thread;
       init_thread_struct(t,"bootstrap");
 
/* half construct this thread, since we'realready running */
       t->priority= HIGHEST_PRIORITY;
       t->state= THREAD_RUNNING;
       t->saved_critical_section_count= 1;
       list_add_head(&thread_list,&t->thread_list_node);
       current_thread= t;

2.     arch_early_init()

做一些关闭cache,使能MMU的arm相关工作。

void arch_early_init(void)
{
       /*turn off the cache */
       arch_disable_cache(UCACHE);
 
       /*set the vector base to our exception vectors so we dont need to double map at 0*/
#if ARM_WITH_MMU
       arm_mmu_init();
 
#endif
 
       /*turn the cache back on */
       arch_enable_cache(UCACHE);
 
#if ARM_WITH_NEON
       /*enable cp10 and cp11 */
       uint32_tval;
       __asm__volatile("mrc     p15, 0, %0, c1, c0,2" : "=r" (val));
       val|= (3<<22)|(3<<20);
       __asm__volatile("mcr     p15, 0, %0, c1, c0,2" :: "r" (val));
 
       /*set enable bit in fpexc */
       __asm__volatile("mrc  p10, 7, %0, c8, c0,0" : "=r" (val));
       val|= (1<<30);
       __asm__volatile("mcr  p10, 7, %0, c8, c0,0" :: "r" (val));
#endif
}

3.     platform_early_init()

平台的早期初始化

void platform_early_init(void)
{
       board_init();
       platform_clock_init();
       qgic_init();
       qtimer_init();
}

3.1  board_init()

void board_init()
{
       platform_detect();
       target_detect(&board);//对于msm8909是空函数,在platform_detect()实现
       target_baseband_detect(&board);//填充board->baseband = BASEBAND_MSM;
}
 

platform_detect()

 

Smem:共享内存

struct smem {
       structsmem_proc_comm proc_comm[4];
       unsignedversion_info[32];
       structsmem_heap_info heap_info;
       structsmem_alloc_info alloc_info[SMEM_MAX_SIZE];
};

共享内存对应的结构体

 

SMEM :sharedmemory,是高通平台各子系统共享信息的一种机制,通过SMEM机制,PBL可以将信息传递给SBL1,SBL1可以将信息传递给RPM、LK。下面分析一个SMEM信息传递的具体实现过程。

 

Platform id信息

SBL1会将board levelplatform id信息通过SMEM机制保存,LK在启动过程中会自动platform detect,检测当前平台board infor信息,然后填充board结构体实例的值

struct board_data {
       uint32_tplatform;
       uint32_tfoundry_id;
       uint32_tplatform_version;
       uint32_tplatform_hw;
       uint32_tplatform_subtype;
       uint32_ttarget;
       uint32_tbaseband;
       structboard_pmic_data pmic_info[MAX_PMIC_DEVICES];
       uint32_tplatform_hlos_subtype;
};
 

根据检测到的board infor加载相应的device tree。

 

3.2  platform_clock_init()

调用clk_init(msm_clocks_msm8909,ARRAY_SIZE(msm_clocks_msm8909))初始化时钟查询表

/* Clock lookup table */
static struct clk_lookup msm_clocks_msm8909[]=
{
       CLK_LOOKUP("sdc1_iface_clk",gcc_sdcc1_ahb_clk.c),
       CLK_LOOKUP("sdc1_core_clk",  gcc_sdcc1_apps_clk.c),
 
       CLK_LOOKUP("sdc2_iface_clk",gcc_sdcc2_ahb_clk.c),
       CLK_LOOKUP("sdc2_core_clk",  gcc_sdcc2_apps_clk.c),
 
       CLK_LOOKUP("uart1_iface_clk",gcc_blsp1_ahb_clk.c),
       CLK_LOOKUP("uart1_core_clk",  gcc_blsp1_uart1_apps_clk.c),
       …
}


3.3  qgic_init()

QGIC:Qualcomm GenericInterrupt Controller高通通用中断控制器

初始化QGIC,包括初始化QGIC的分配器(distributor)和初始化CPU具体的控制器。

 

3.4  qtimer_init()

获取定时器的频率

4.     target_early_init()

这里就是串口初始化uart_dm_init(1, 0,BLSP1_UART0_BASE)---> uart_dm_init()

从时钟查找表msm_clocks_msm8909[]串口并配置其时钟频率、配置GPIO为串口、配置串口寄存器等。

 

5.     bs_set_timestamp(BS_BL_START)

设置时间戳,这里的bs指boot stats,引导统计。

 

6.     call_constructors()

构造函数相关初始化

bootloader的构造器一般完成的是初始化设备对象的操作,由于不同的系统在bootloader阶段需要初始化的设备不同,所以需要用户自己调用这些初始化函数。

 

根据函数名称,就是字面意思——调用构造器,构造器是定义在__ctor_list和__ctor_end之间的函数指针。至于__ctor_list和__ctor_end之间有哪些函数你可以看编译之后输出的map文件,或者链接脚本里面可能也有定义。

 

7.     heap_init()

启动内核堆。

 

8.     __stack_chk_guard_setup()

负责生成canary值

http://toutiao.com/a6244754891979129089/

 

9.     thread_init()

初始化线程系统。

 

10.  dpc_init()

dpc:DelayedProcedure Call 延迟过程调用的缩写,初始化dpc系统,相关事件初始化、创建名字为dpc的线程并调用。

 

11.  timer_init()

初始化lk定时器。

 

12.  bootstrap2

thread_resume(thread_create("bootstrap2",&bootstrap2, NULL, DEFAULT_PRIORITY, DEFAULT_STACK_SIZE));
 
// enable interrupts
exit_critical_section();
 
// become the idle thread
thread_become_idle();


创建名字为bootstrap2的线程并调用,调用thread_become_idle()让当前线程处于idle状态。

 

后面接着学习线程bootstrap2。

相关文章