参考UG585 内容
下面这张图是ZYNQ启动的关键流程
1.POR表示硬件复位,不关心Power-up也就是说冷热启动都行。Nor-POR就是非POR复位,有点软件应用复位的意思。
2.POR复位会复位所有寄存器。并且采集 HardWare boot pin的状态。这点很关键,
3.是否使用PLL如何是就会把外部时钟输入到PLL进行倍频,获得比外部时钟更高跟稳定的CLK。
4.执行BootROM,它是在ZYNQ芯片内部的一块只读存储器,其中的代码不可以更改。可以理解为XILINX写死一段启动代码在ZYNQ芯片中。上电后完成POR的复位动作,第一条执行的代码就是BootRom的代码。
需要理解的几个关键点,boot的作用是初始化必要的硬件然后从程序存储的地方加载程序运行。像ZYNQ这样的SOC来说,是一个复杂的系统,有非常多的外设可以使用。可能有SD卡,FLASH等储存设备记录了代码,这点和MCU单片机有很大的不同。单片机的应用场合比较简单,只需要从片内的FLASH启动即可。ZYNQ的使用场景复杂的多,内部没有用户的flash。那么BootRom就需要判断,用户的代码存放在什么位置,然后去运行它。程序的运行一般需要RAM,也就是可以单字节访问的储存器。ZYNQ内部有一个RAM成为OCM。
OCM是On Chip Memory,可以理解为一个片内的RAM。RAM用来运行程序,如果这个RAM够用那么就不需要使用外部内存,比如DDR。
如果需要使用外部DDR等设备,需要对外部设备进行初始化,并且把程序复制到外部RAM中运行。也就是程序需要一块内存(RAM)来运行,称为运行域。为了把程序从存储域搬移到运行域需要加载程序。显然BootRom做了这个事情。
现在就是看如何去选择之前提到的储存器
上面这张表是必须要懂的表,MIO为PS的PIN,可以理解为和ARM 或者MCU一样就是芯片的引脚。POR复位后会硬件会采集这些引脚的状态。MIO8,7表示引脚的电平规则,因为电平的采集就会涉及到高低电平。那么ZYNQ的硬件需要知道硬件的电平规则。然后MIO6事故PLL是否旁路的选择。MIO5.4.3 是引导器件的选择,显然有JTAG,NOR,NAND,SPI,SD卡。上电后硬件就会采集引脚状态然后BOOTRom去对于的器件找FSBL(一段代码)中的引导头,然后进行运行域的初始化,就是代码搬移到OCM。
那么就会有一个问题,BootRom需要知道所搬移代码的信息,比如搬移多少代码上去,代码是否加密等等信息。所以需要和程序约定好一个格式告诉BootRom自己的信息。这个信息块就是BootRom Header。
FSBL 就是BootRom搬运代码的称呼,称为第一阶段引导程序。
所谓第一阶段第二阶段并不重要,其实就是套娃。
加密是什么,就是程序代码进行了加密,需要解密才能正常运行。
PL作为APU的一个外设,在BOOTRom或者用户代码中去初始化。
二 CODE
EQU:给数字常量取一个符号名,相当于C语言中的define
AREA:指示汇编程序汇编新的代码或数据段。
SPACE:分配内存空间
PRESERVE8:当前文件堆栈需按照8字节对齐
EXPORT:声明一个标号具有全局属性,可被外部的文件使用
DCD:以字为单位分配内存,要求4字节对齐,并要求初始化这些内存
PROC:定义子程序,与ENDP成对使用,表示子程序结束
MSR:Move to Special register from Register. 恢复到特殊寄存器
WEAK:弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,如果外部文件没有定义也不出错。要注意的是:这个不是ARM的指令,是编译器的,这里放在一起只是为了方便。
IMPORT:声明标号来自外部文件,跟C语言中的EXTERN关键字类似
B:跳转到一个标号ALIGN编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,缺省表示4字节对齐。要注意的是:这个不是ARM的指令,是编译器的,这里放在一起只是为了方便。
END:到达文件的末尾,文件结束
IF,ELSE,ENDIF:汇编条件分支语句,跟C语言的if else类似
————————————————
版权声明:本文为CSDN博主「烹小鲜啊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/denghuajing/article/details/128045438
在XXX_bsp中Libsrc->standalone->src->asm_vector.s为启动代码
.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
_vector_table
汇编语言源程序中若没有ORG伪指令,则程序执行时,指令代码被放到自由内存空间的CS:0处;若有ORG伪指令,编译器则把其后的指令代码放到ORG伪指令指定的偏移地址。两个ORG伪指令之间,除了指令代码,若有自由空间,则用0填充。
显然从地址0开始存放中断向量表_boot 表示_boot的地址
SVCHander 为系统调用,然后是最后的IRQ,FIQ
文件接下来是 中断处理函数
IRQHandler: /* IRQ vector handler */
stmdb sp!,{r0-r3,r12,lr} /* state save from compiled code*/
#if FPU_HARD_FLOAT_ABI_ENABLED
vpush {d0-d7}
vpush {d16-d31}
vmrs r1, FPSCR
push {r1}
vmrs r1, FPEXC
push {r1}
#endif
#ifdef PROFILING
ldr r2, =prof_pc
subs r3, lr, #0
str r3, [r2]
#endif
bl IRQInterrupt /* IRQ vector */
#if FPU_HARD_FLOAT_ABI_ENABLED
pop {r1}
vmsr FPEXC, r1
pop {r1}
vmsr FPSCR, r1
vpop {d16-d31}
vpop {d0-d7}
#endif
ldmia sp!,{r0-r3,r12,lr} /* state restore from compiled code */
subs pc, lr, #4 /* adjust return */
-boot的内容在BOOT.S中
通过3个汇编文件逐渐进入到main函数
对于FSBL的main函数究竟做了些什么
在mai中有个相当重要的代码
/* * Read bootmode register */ BootModeRegister =
Xil_In32(BOOT_MODE_REG); BootModeRegister &= BOOT_MODES_MASK;
读取Boot mode寄存器的内容
这边部分的内容我觉得就是POR复位后BOOTRom读取的引脚信息。
后面FSBL根据BootModeRegister 的启动方式去拷贝代码到OCM中运行。
包含原地址目的地址,长度。