• 9 开源鸿蒙OpenHarmony上电的第一行代码,boot代码简述


    开源鸿蒙OpenHarmony上电的第一行代码,boot代码简述

    作者将狼才鲸
    日期2024-03-12

    • 上电的第一行代码是硬件复位中断的入口,也就是RAM零地址的代码,属于boot代码的一部分

    • 芯片启动流程 - 内核概述

    • 内核代码具体的细节,ARM Cortex-M可以参考LiteOS-M,ARM Cortex-A可以参考LiteOS-A或者Linux内核

    • 本来芯片上电后的第一行代码应该是能在源码中看到的,但是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
    
    • 1
    • 2
    • 3
    jim@ubuntu:~/openHarmony$ cat kernel/liteos_m/arch/arm/cortex-m4/gcc/los_interrupt.c 
    
    #include 
    #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) */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 这个复位中断里会一级一级往后调用,你建个工程在代码里面一步步跳转就可以溯源了。
  • 相关阅读:
    深入了解Redis:配置文件、动态修改和安全设置
    Codeforces Round #821(Div.2) (A-D2) 题解
    常见的8个JMeter压测问题
    nginx学习(2)
    ASCHIP_ISP Tool 工具 使用与更新
    记一次 .NET 某手术室行为信息系统 内存泄露分析
    Linux系统(CentOS7)上安装MYSQL8.x
    我在华为度过的 “两辈子”(学习那些在大厂表现优秀的人)
    刷题之Leetcode283题(超级详细)
    侯捷 C++ STL标准库和泛型编程 —— 3 容器(序列式容器)
  • 原文地址:https://blog.csdn.net/qq582880551/article/details/136650270