1. 概述
多核启动时,通常CPU0作为主CPU,其它CPU均为从CPU,设备上电后主CPU先启动完成,再由主CPU给从CPU上电,并通知从CPU从指定的程序入口开始执行;通常情况下,单板初始化阶段由SPL、ATF、UBOOT三部分程序完成,下面就各部分的工作流程展开介绍;
2. 主CPU启动过程
主CPU启动流程如下图所示,系统上电后开始执行SPL程序,在SPL中对必要的基础外设进行初始化,并根据配置从FLASH或者SD卡等存储介质中load UBOOT版本到内存中,通常ATF版本和UBOOT版本打包在一起;UBOOT版本load完成后跳转到ATF开始执行,ATF程序的入口函数为bl31_entrypoint,ATF完成SMC相关命令注册后,从EL3切换到EL2状态执行UBOOT程序,UBOOT的入口函数为_start,和SPL的入口函数相同,这是因为SPL和UBOOT这部分代码共用,部分代码用编译宏区分;UBOOT初始化完成后进入到main_loop,这个时候可以进入UBOOT命令行,也可以启动os;至此,主CPU已经可以正常工作;
3. 从CPU启动过程
主CPU通过发送psci_cpu_on的SMC消息,通知ATF给从CPU上电,并唤醒从CPU从指定入口函数开始执行,入口函数指针作为psci_cpu_on消息参数传入;从CPU上电起来后从SPL程序的入口_start开始执行,完成基本初始化后,根据cpuid的判断分流,进入到从CPU的代码分支执行,循环读取CPU_RELEASE_ADDR寄存器,如果非0,则跳转到该地址开始执行,这个寄存器在ATF中赋值为plat_secondary_cpus_bl31_entry函数指针,ATF中会继续跳转到PLAT_SEC_ENTRY执行,这个地址在ATF中被赋值为bl31_warm_entrypoint,然后将psci_cpu_on传入的程序入口函数作为上下文切换的ELR,使用ERET指令完成EL3到EL2的程序跳转,如果时Linux操作系统,最终会跳转到sencondary_entry函数;