编辑
2025-04-03
工作知识
0
请注意,本文编写于 64 天前,最后修改于 64 天前,其中某些信息可能已经过时。

目录

一、Start.S源码
二、解释重要步骤

我们知道系统的启动从start.S开始,对于RTEMS也一样,这里简单介绍一下RTEMS的start.S

一、Start.S源码

对于Start.S,抽离了一些没开的宏定义,代码如下:

#include <rtems/asm.h> #include <rtems/score/percpu.h> #include <bspopts.h> /* Global symbols */ .globl _start .section ".bsp_start_text", "ax" /* Start entry */ _start: mov x5, x1 /* machine type number or ~0 for DT boot */ mov x6, x2 /* physical address of ATAGs or DTB */ /* Initialize SCTLR_EL1 */ mov x0, XZR msr SCTLR_EL1, x0 mrs x0, CurrentEL // 这里是0x20,bit3,所以是EL1 cmp x0, #(1<<2) b.eq .L_el1_start .L_el1_start: bl _AArch64_Get_current_processor_for_system_start /* * Check that this is a configured processor. If not, then there is * not much that can be done since we do not have a stack available for * this processor. Just loop forever in this case. */ ldr x1, =_SMP_Processor_configured_maximum // 这里x获得了符合_SMP_Processor_configured_maximum的地址,_SMP_Processor_configured_maximum的值是1 ldr w1, [x1] // 把x1的值给w1,此时w1是1 cmp x1, x0 bgt .Lconfigured_processor .Lconfigured_processor: /* * Get current per-CPU control and store it in PL1 only Thread ID * Register (TPIDR_EL1). */ ldr x1, =_Per_CPU_Information // 这里_Per_CPU_Information是0,x1是_Per_CPU_Information的地址 add x1, x1, x0, lsl #PER_CPU_CONTROL_SIZE_LOG2 msr TPIDR_EL1, x1 //这里计算了per cpu,将el1下的线程结构指针设置到tpidr上,这里就是_Per_CPU_Information的地址 /* Calculate interrupt stack area end for current processor */ ldr x1, =_ISR_Stack_size //这里将stack大小0x2000的_ISR_Stack_size地址给x1 add x3, x0, #1 //这里x3是1 mul x1, x1, x3 //因为x1是0,所以乘法后是0 ldr x2, =_ISR_Stack_area_begin //这里栈的begin add x3, x1, x2 //将_ISR_Stack_area_begin+0x2000 /* Disable interrupts and debug */ msr DAIFSet, #0xa /* * SPx: the stack pointer corresponding to the current exception level * Normal operation for RTEMS on AArch64 uses SPx and runs on EL1 * Exception operation (synchronous errors, IRQ, FIQ, System Errors) uses SP0 */ ldr x1, =bsp_stack_exception_size // 设置bsp_stack_exception_size /* Switch to SP0 and set exception stack */ msr spsel, #0 mov sp, x3 // 设置sp,x3是之前计算的sp /* Switch back to SPx for normal operation */ msr spsel, #1 sub x3, x3, x1 /* Set SP1 stack used for normal operation */ mov sp, x3 // 设置sp,x3是之前计算的sp /* Stay in EL1 mode */ /* Read CPACR */ mrs x0, CPACR_EL1 /* Enable EL1 access permissions for CP10 */ orr x0, x0, #(1 << 20) /* Write CPACR */ msr CPACR_EL1, x0 isb /* Branch to start hook 1 */ bl bsp_start_hook_1 // 跳到bsp_start_hook_1 /* Branch to boot card */ mov x0, #0 bl boot_card //跳到 boot_card 这里调整的函数_AArch64_Get_current_processor_for_system_start如下: FUNCTION_ENTRY(_AArch64_Get_current_processor_for_system_start) /* Return the affinity level 0 reported by the MPIDR_EL1 */ mrs x0, mpidr_el1 # 获取cpu亲和性的值 and x0, x0, #0xff ret FUNCTION_END(_AArch64_Get_current_processor_for_system_start)

二、解释重要步骤

如上所述,已经在必要的地方添加了注释,其主要步骤如下:

  • 清空SCTLR_EL1
  • 获取CurrentEL
  • 获取MPIDR_EL1
  • 获取_SMP_Processor_configured_maximum 预设的值
  • 获取_Per_CPU_Information 预设的值
  • 将_Per_CPU_Information 和 获取MPIDR_EL1 的值计算,存放TPIDR_EL1
  • 设置stack大小为_ISR_Stack_size (0x2000)
  • 计算sp
  • 通过DAIFSet禁止中断
  • 通过CPACR_EL1判断FPEN
  • 跳转到hook1
  • 跳转到boot card