内核启动流程
Posted 四季帆
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了内核启动流程相关的知识,希望对你有一定的参考价值。
1. 链接脚本
liteos_a的链接脚本路径如下:
OpenHarmony/kernel/liteos_a/tools/build/liteos_llvm.ld
链接脚本的内容如下:
ENTRY(reset_vector)
INCLUDE board.ld
INPUT(libuserinit.O)
SECTIONS
{
#各种段定义,此处全部省略
}
链接脚本中指定了kernel的入口为reset_vector。
2. 入口函数(reset_vector)实现
函数reset_vector是一个汇编函数,其定义在arch/arm/arm/src/startup/reset_vector_up.S中,reset_vector函数主要做了以下几件事:
.global reset_vector
.type reset_vector,function
reset_vector:
/* do some early cpu setup: i/d cache disable, mmu disabled 关闭cache和mmu*/
mrc p15, 0, r0, c1, c0, 0
bic r0, #(1<<12)
bic r0, #(1<<2 | 1<<0)
mcr p15, 0, r0, c1, c0, 0
/* if we need to relocate to proper location or not ,镜像重定位*/
adr r4, __exception_handlers /* r4: base of load address */
ldr r5, =SYS_MEM_BASE /* r5: base of physical address */
subs r12, r4, r5 /* r12: delta of load address and physical address */
beq reloc_img_to_bottom_done /* if we load image at the bottom of physical address */
clear_bss: /* 清bss段 */
ldr r1, =__bss_start
ldr r2, =__bss_end
mov r0, #0
bl main /* 跳转到main */
和Linux kernel的汇编阶段极其相似,对SOC做一些必须且早的设置,其余功能在C文件中实现。
3. main函数
分析的主干思路:main ---> OsMain ---> OsSystemInit ---> OsSystemInitTaskCreate ---> SystemInit。
//OpenHarmony/kernel/liteos_a/platform/main.c
LITE_OS_SEC_TEXT_INIT INT32 main(VOID)
{
PRINT_RELEASE("\\nmain core booting up...\\n");
······
uwRet = OsMain(); //在OsMain中做了大量的初始化动作
CPU_MAP_SET(0, OsHwIDGet());
OsStart();
}
OsMain()函数中做了大量的初始化动作,与Linux kernel中的start_kernel类似,不同的是,liteos_a中大多数初始化动作都定义了宏来控制,也就是说不需要的初始化动作可以通过配置宏定义来去掉,即liteos_a的控制粒度比Linux kernel更精细。
//OpenHarmony/kernel/liteos_a/kernelcommon/los_config.c
LITE_OS_SEC_TEXT_INIT INT32 OsMain(VOID)
{
#ifdef LOSCFG_SHELL_DMESG
ret = OsDmesgInit(); //dmesg相关初始化
if (ret != LOS_OK) {
return ret;
}
#endif
#if (LOSCFG_PLATFORM_HWI == YES)
OsHwiInit(); //应该是硬件相关的初始化
#endif
OsExcInit();
······
ret = OsTickInit(g_sysClock, LOSCFG_BASE_CORE_TICK_PER_SECOND); //OS心跳初始化(定时器相关初始化)
if (ret != LOS_OK) {
return ret;
}
#ifdef LOSCFG_DRIVERS
uart_init(); //串口初始化
#endif
ret = OsTaskInit();
if (ret != LOS_OK) {
PRINT_ERR("OsTaskInit error\\n");
return ret;
}
ret = OsSysMemInit();
if (ret != LOS_OK) {
PRINT_ERR("OsSysMemInit error\\n");
return ret;
}
SyscallHandleInit();
#if (LOSCFG_KERNEL_SMP == YES)
(VOID)OsMpInit();
#endif
#ifdef LOSCFG_KERNEL_PIPE
OsDriverPipeInit();
#endif
ret = OsSystemInit(); //注意这里是没有通过宏来控制的 --->
if (ret != LOS_OK) {
return ret;
}
ret = OomTaskInit();
if (ret != LOS_OK) {
return ret;
}
return LOS_OK;
}
OpenHarmony/kernel/liteos_a/kernel/common/los_config.c
UINT32 OsSystemInit(VOID)
{
UINT32 ret;
#ifdef LOSCFG_COMPAT_LINUXKPI
g_pstSystemWq = create_workqueue("system_wq");
#endif
ret = OsSystemInitTaskCreate(); //初始化任务 --->
······
return 0;
}
STATIC UINT32 OsSystemInitTaskCreate(VOID)
{
UINT32 taskID;
TSK_INIT_PARAM_S sysTask;
(VOID)memset_s(&sysTask, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S));
sysTask.pfnTaskEntry = (TSK_ENTRY_FUNC)SystemInit; //任务的入口函数
sysTask.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE;
sysTask.pcName = "SystemInit";
······
return LOS_TaskCreate(&taskID, &sysTask);
}
SystemInit()函数是具体单板相关的代码,以hi3516dv300为例,SystemInit()函数的实现在OpenHarmony/vendor/hisi/hi35xx/hi3516dv300/module_init/src/system_init.c中
void SystemInit(void)
{
#ifdef LOSCFG_DRIVERS_MMC
dprintf("MMC dev init ...");
extern int SD_MMC_Host_init(void);
SD_MMC_Host_init(); //MMC host初始化
#endif
#ifdef LOSCFG_DRIVERS_USB
dprintf("usb init ...\\n");
usb_init(HOST, 0); //usb初始化
#endif
#ifdef LOSCFG_PLATFORM_ROOTFS
dprintf("OsMountRootfs start ...\\n");
OsMountRootfs(); //挂载根文件系统
dprintf("OsMountRootfs end ...\\n");
#endif
······
if (OsUserInitProcess()) { //创建用户init进程
PRINT_ERR("Create user init process faialed!\\n");
return;
}
dprintf("cat log shell end\\n");
return;
}
以上是关于内核启动流程的主要内容,如果未能解决你的问题,请参考以下文章