开源鸿蒙OpenHarmony上电的第一行代码,boot代码简述
作者 | 将狼才鲸 |
---|---|
日期 | 2024-03-12 |
-
上电的第一行代码是硬件复位中断的入口,也就是RAM零地址的代码,属于boot代码的一部分
-
内核代码具体的细节,ARM Cortex-M可以参考LiteOS-M,ARM Cortex-A可以参考LiteOS-A或者Linux内核
- LiteOS-M内核介绍
- LiteOS-A内核介绍
- Linux5.10内核鸿蒙特供版
- 当前代码中编译器Cortex-M3只支持Keil,Cortex-M4支持GCC
-
本来芯片上电后的第一行代码应该是能在源码中看到的,但是OpenHarmony中使用了ARM的CMSIS官方库,也就是说上电时的第一行代码已经融合进编译器里面去了,所以你看不到,只能看到第二行代码,那就是 Reset_Handler() 复位中断函数
- RAM的0地址就是第一行代码,同时也是reset复位中断的入口,在这里的代码只有一个目的,那就是复位中断进来后立马调用 Reset_Handler() 函数,这里既可以调用汇编的reset函数,也可以调用C语言函数。
-
搜索 Reset_Handler 这个函数,这是上电后执行的第二行代码
arm/cortex-m4/gcc/los_interrupt.c: hwiForm[1] = (HWI_PROC_FUNC)Reset_Handler; /* [1] reset */
arm/cortex-m3/keil/los_startup.s:Reset_Handler
-
ARM官方CMSIS的API一般都是NVIC_开头的函数,和上电后先调用的函数有:
- HalHwiInit ArchInit LOS_KernelInit kal/cmsis/cmsis_liteos2.c osKernelInitialize
jim@ubuntu:~/openHarmony/kernel/liteos_m/arch/arm/cortex-m3/keil$ ls
los_arch_atomic.h los_arch_interrupt.h los_atomic.S los_dispatch.S los_interrupt.c los_timer.c
los_arch_context.h los_arch_timer.h los_context.c los_exc.S los_startup.s
jim@ubuntu:~/openHarmony$ cat kernel/liteos_m/arch/arm/cortex-m4/gcc/los_interrupt.c
#include <stdarg.h>
#include "securec.h"
#include "los_context.h"
#include "los_arch_interrupt.h"
#include "los_hook.h"
#include "los_task.h"
#include "los_sched.h"
#include "los_memory.h"
#include "los_membox.h"
#if (LOSCFG_CPUP_INCLUDE_IRQ == 1)
#include "los_cpup.h"
#endif
/* ****************************************************************************
Function : HalHwiInit
Description : initialization of the hardware interrupt
Input : None
Output : None
Return : None
**************************************************************************** */
LITE_OS_SEC_TEXT_INIT VOID HalHwiInit(VOID)
{
#if (LOSCFG_USE_SYSTEM_DEFINED_INTERRUPT == 1)
UINT32 index;
HWI_PROC_FUNC *hwiForm = (HWI_PROC_FUNC *)ArchGetHwiFrom();
hwiForm[0] = 0; /* [0] Top of Stack */
hwiForm[1] = (HWI_PROC_FUNC)Reset_Handler; /* [1] reset */
for (index = 2; index < OS_VECTOR_CNT; index++) { /* 2: The starting position of the interrupt */
hwiForm[index] = (HWI_PROC_FUNC)HalHwiDefaultHandler;
}
/* Interrupt vector table location */
SCB->VTOR = (UINT32)(UINTPTR)hwiForm;
#endif
#if (__CORTEX_M >= 0x03U) /* only for Cortex-M3 and above */
NVIC_SetPriorityGrouping(OS_NVIC_AIRCR_PRIGROUP);
#endif
return;
}
/* ======== */
jim@ubuntu:~/openHarmony/third_party$ cat cmsis/Device/ARM/ARMCM55/Source/startup_ARMCM55.c
/*----------------------------------------------------------------------------
Reset Handler called on controller reset
*----------------------------------------------------------------------------*/
__NO_RETURN void Reset_Handler(void)
{
__set_PSP((uint32_t)(&__INITIAL_SP));
__set_MSPLIM((uint32_t)(&__STACK_LIMIT));
__set_PSPLIM((uint32_t)(&__STACK_LIMIT));
#if defined (__ARM_FEATURE_CMSE) && (__ARM_FEATURE_CMSE == 3U)
__TZ_set_STACKSEAL_S((uint32_t *)(&__STACK_SEAL));
#endif
SystemInit(); /* CMSIS System Initialization */
__PROGRAM_START(); /* Enter PreMain (C library entry point) */
}
- 这个复位中断里会一级一级往后调用,你建个工程在代码里面一步步跳转就可以溯源了。