作者:付汉杰,<a href="mailto:hankf@xilinx.com">hankf@xilinx.com</a>,文章转载自:<a id="link_3" href="https://forums.xilinx.com/t5/%E5%B5%8C%E5%85%A5%E5%BC%8F-%E5%B7%A5%E5%8…;
MPSoC A53执行的第一条代码定义在BSP工程的目录\psu_cortexa53_0\libsrc\standalone_v7_0\src\asm_vectors.S里。
去掉Xen相关代码后,简化如下:
<pre>
.org 0
.section .vectors, "a"
_vector_table:
.set VBAR, _vector_table
.org VBAR
b _boot
.org (VBAR + 0x200)
b SynchronousInterruptHandler
.org (VBAR + 0x280)
b IRQInterruptHandler
.org (VBAR + 0x300)
b FIQInterruptHandler
.org (VBAR + 0x380)
b SErrorInterruptHandler
</pre>
上述代码的地址,由《ARM® Architecture Reference Manual,ARMv8, for ARMv8-A architecture profile》(ARM DDI 0487C)定义,可以参考Table D1-7 Vector offsets from vector table base address。
EL0的Synchronous offset是0x0。其他EL级别,Synchronous offset是0x200,IRQ or vIRQ offset是0x280, FIQ or vFIQ offset是0x300, SError or vSError offset是0x380,
MPSoC A53启动后,在EL0,执行的第一条代码是“b _boot”。
符号_boot的定义在BSP工程的目录\psu_cortexa53_0\libsrc\standalone_v7_0\src\boot.S里。简化后的代码如下。
<pre>
/* this initializes the various processor modes */
_prestart:
_boot:
mov x0, #0
... ...
mov x30, #0
#if 0 //dont put other a53 cpus in wfi
//Which core am I
// ----------------
mrs x0, MPIDR_EL1
and x0, x0, #0xFF //Mask off to leave Aff0
cbz x0, OKToRun //If core 0, run the primary init code
EndlessLoop0:
wfi
b EndlessLoop0
#endif
OKToRun:
mrs x0, currentEL
cmp x0, #0xC
beq InitEL3
cmp x0, #0x4
beq InitEL1
b error // go to error if current exception level is neither EL3 nor EL1
</pre>
InitEL3/InitEL1会设置reset vector address,Invalidate cache,设置stack pointer。
执行上述代码后,会执行“bl _startup”。
符号_startup的定义在BSP工程的目录\psu_cortexa53_0\libsrc\standalone_v7_0\src\xil-crt0.S里。符号_startup先清除SBSS和BSS段,然后运行global constructors,再跳到C语言的定义在文件xfsbl_main.c里的入口函数main。
FSBL的main()里的调用关系是XFsbl_Initialize()->XFsbl_SystemInit()->XFsbl_HookPsuInit()->psu_init().。
psu_init由Vivado导出,含有芯片的管脚、pll、DDR初始化,主要代码如下。
<pre>
psu_init(void)
{
status &= psu_mio_init_data();
status &= psu_pll_init_data();
status &= psu_clock_init_data();
status &= psu_ddr_init_data();
status &= psu_ddr_phybringup_data();
status &= psu_peripherals_init_data();
status &= init_serdes();
init_peripheral();
status &= psu_peripherals_powerdwn_data();
status &= psu_afi_config();
}
</pre>
上述流程,可以在SDK里双击应用程序的ELF文件,查看应用程序的反汇编文件确认。