上一节讲了FSBL主要功能负责对PS端进行初始化、调用bitstream文件对PL端进行配置,加载应用或二级引导程序置DDR中并启动DDR,本节通过对FSBL代码进行分析深入理解代码。
参考资料
SDK版本:Release Version: 2018.3
一、FSBL代码过程
1.打开FSBL工程 fsbl_bsp->ps7_cortexa9_0->libsrc->standalone_v6_8->asm_vectors.S,即启动文件,这个文件生命了一个代码段,位于地址0处(而我们从《Xilinx ZYNQ 7000学习笔记一》知道BootRom最后执行就是跳转到0地址,即跳转到在OCM中执行的下面的FSBL代码)
开机后,PS自动开始执行0地址的指令,其第一句话就是一个跳转:B _boot
.org 0
.text
.globl _vector_table
.section .vectors
_vector_table:
B _boot
B Undefined
B SVCHandler
B PrefetchAbortHandler
B DataAbortHandler
NOP /* Placeholder for address exception vector*/
B IRQHandler
B FIQHandler
于是就跳转到boot.S中执行_boot标号下的代码了,(期间对包括DDR是否共享状态进行配置、使能了MMU和各级cache、中断初始化,当它执行完后,PS将具备执行C代码的能力),
我们对_boot标号的代码进行下简单分析:
_boot:
#if XPAR_CPU_ID==0 /* 表示当前FSBL是core0还是core1,我们对比分别用core0和core1创建FSBL,发现该宏XPAR_CPU_ID值分别会在工程中配置0或1 */
/* only allow cpu0 through */
mrc p15,0,r1,c0,c0,5
and r1, r1, #0xf
cmp r1, #0
beq CheckEFUSE
EndlessLoop0:
wfe
b EndlessLoop0
CheckEFUSE:
ldr r0,=EFUSEStaus
ldr r1,[r0] /* Read eFuse setting */
ands r1,r1,#0x80 /* Check whether device is having single core */
beq OKToRun
/* single core device, reset cpu1 */
ldr r0,=SLCRUnlockReg /* Load SLCR base address base + unlock register */
ldr r1,=SLCRUnlockKey /* set unlock key */
str r1, [r0] /* Unlock SLCR */
ldr r0,=SLCRCPURSTReg
ldr r1,[r0] /* Read CPU Software Reset Control register */
orr r1,r1,#0x22
str r1,[r0] /* Reset CPU1 */
ldr r0,=SLCRlockReg /* Load SLCR base address base + lock register */
ldr r1,=SLCRlockKey /* set lock key */
str r1, [r0] /* lock SLCR */
#elif XPAR_CPU_ID==1
/* only allow cpu1 through */
mrc p15,0,r1,c0,c0,5
and r1, r1, #0xf
cmp r1, #1
beq CheckEFUSE1
b EndlessLoop1
CheckEFUSE1:
ldr r0,=EFUSEStaus
ldr r1,[r0] /* Read eFuse setting */
ands r1,r1,#0x80 /* Check whether device is having single core */
beq OKToRun
EndlessLoop1:
wfe
b EndlessLoop1
#endif
XPAR_CPU_ID该宏值用来表示当前的FSBL代码是core0还是core1启动,这个是由我们创建FSBL选择core0还是core1工程决定的,我们以常用core0作为FSBL为例:双核运行后,针对core0会满足beq CheckEFUSE,结果就是core0继续标号CheckEFUSE运行,而core1不满足beq CheckEFUSE,将core1置为WFE休眠模式。反过来,如果我们创建FSBL是依据core1创建的,那么执行的结果就是core1干活儿core0进入WFE模式。(在这里我们知道,core1或者core0被置位为WFE休眠状态原来是FSBL启动后设定的啊)。EFUSEStaus寄存器是用来表示当前SOC是单核还是双核系统,为一次编程的非易失器件,我们是双核系统,会执行beq OKToRun,即执行下面标号OKToRun。
OKToRun:
mrc p15, 0, r0, c0, c0, 0 /* Get the revision */
and r5, r0, #0x00f00000
and r6, r0, #0x0000000f
orr r6, r6, r5, lsr #20-4
#ifdef CONFIG_ARM_ERRATA_742230
cmp r6, #0x22 /* only present up to r2p2 */
mrcle p15, 0, r10, c15, c0, 1 /* read diagnostic register */
orrle r10, r10, #1 << 4 /* set bit #4 */
mcrle p15,