概述
前面几篇讲了ZYNQ7000的启动过程,包括BootRom和FSBL的代码逻辑,其中关于FSBL代码对启动模式为JTAG被动启动没有进行分析,本篇将通过将JTAG的功能和通过Xilinx SDK烧写镜像文件到flash来顺道把FSBL中的JTAG代码部分给讲解下。
1.JTAG
ZYNQ7000系列SOC通过标准的JTAG(IEEE1149.1)调试接口提供调试访问通道。在内部,SOC期间实现了PS端通过DAP(debug access port )控制器实现访问ARM,通过标准的TAP(test access port)控制器访问PL端。ARM DAP作为Arm CoreSight调试架构的一部分,允许用户利用行业标准的第三方调试工具进行调试。
下图展示了JTAG 的系统框图,在BootROM完成后将控制权移交给用户软件(启动FSBL),JTAG链就会自动启用,假设引导过程为非安全模式,这允许从用户软件入口点进行调试。
1.1 JTAG主要特性:
JTAG的主要特性有:
1) JTAG 1149.1 支持边界扫描
2) JTAG 1149.1 遵从TAP控制器:一个JTAG TAP控制器和一个ARM DAP控制器
3)AMD TAP控制器针对ZYNQ7000系列 唯一的IDCODE
4)支持IEEE1532可编程系统可配置 (in-system-configurable (ISC))设备
包括:
eFuse programming
BBRAM programming
XADC access
5)flash 编程
6)AMD逻辑分析仪调试支持
7)使用ARM DAP控制器访问Arm 片上调试和跟踪(CoreSight) 架构
8)通过DAP-AP端口间接访问PS地址空间
9)使用PS中的MIO或PL中的EMIO进行外部跟踪捕获
我们在这里知道通过JTAG可以直接操作flash和内存即可。
备注:eFUSE的全名是"Electrically Programmable Read-Only Memory Fuse",它是一种电可编程只读存储器。eFUSE是一种用于存储固定信息的存储器,它的主要特点是一旦编程后就无法再进行擦除或修改,类似于传统的只读存储器(ROM)的功能。eFUSE(熔断保护)通常是硬件特性,而不是预置的软件特性,eFUSE是一种一次性可编程的硬件存储器,用于存储固定的数据或配置信息,例如设备序列号、密钥、硬件配置等。
2.FSBL 代码JTAG模式
2.1 借助JTAG可以直接访问内存地址的功能,仿真器可以直接跳过BootRom对内存直接进行Program来加载ps7_init.tcl或应用至OCM或者DDR。
我们在使用仿真器进行debug时,ps7_init.tcl执行FSBL的等效代码,并走的JTAG分支,而这个分支最终状态只是让处理器进入WFE模式(参见2.2),并在应用程序elf加载到DDR中运行。JTAG模式下,处理器是处于挂起状态,而控制权是由JTAG控制(这也是为什么JTAG叫从模式的原因,因为处理器没有控制权)。红字部分也进行了说明。
2.2 FSBL JTAG模式分支代码
对应的JTAG模式分支,我们看FSBL的代码会发现JTAG模式的代码没有什么内容,就是调用汇编FsblHandoffJtagExit接口使能cache和mmu就进入WFE休眠了,而这正式释放处理器控制权的操作,以方便仿真器JTAG控制。
/*
* JTAG BOOT MODE
*/
if (BootModeRegister == JTAG_MODE) {
fsbl_printf(DEBUG_GENERAL,"Boot mode is JTAG\r\n");
RegVal = Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_STS_OFFSET);
/** If bitstream was loaded in jtag boot mode prior to running FSBL */
if(RegVal & XDCFG_IXR_PCFG_DONE_MASK)
{
#ifdef PS7_POST_CONFIG
ps7_post_config();
/*
* Unlock SLCR for SLCR register write
*/
SlcrUnlock();
#endif
}
/*
* Stop the Watchdog before JTAG handoff
*/
#ifdef XPAR_XWDTPS_0_BASEADDR
XWdtPs_Stop(&Watchdog);
#endif
/*
* Clear our mark in reboot status register
*/
ClearFSBLIn();
/*
* SLCR lock
*/
SlcrLock();
FsblHandoffJtagExit();
}
FsblHandoffJtagExit:
mcr 15,0,r0,cr7,cr5,0 /* Invalidate Instruction cache */
mcr 15,0,r0,cr7,cr5,6 /* Invalidate branch predictor array */
dsb
isb /* make sure it completes */
ldr r4, =0
mcr 15,0,r4,cr1,cr0,0 /* disable the ICache and MMU */
isb /* make sure it completes */
Loop:
wfe
b Loop
2.2 使用SDK烧写镜像文件
当我们通过SDK烧写镜像文件到flash,如果外部启动模式引脚可以进行配置,那么我们可以通过配置外部启动引脚电平然后执行上电复位(POR)实现采集启动模式保存到启动模式寄存器进入FSBL的JTAG分支;另外如果外部启动模式引脚不方便配置,我们也可以直接更改FSBL代码添加BootModeRegister = JTAG_MODE代码时,BootRom会在启动FSBL后走JTAG分支,并通过SDK选择该FSBL代码生成的elf实现代码下载,而直接用FSBL代码下载镜像到flash会失败。
我们现在想想这是什么原因,这是因为如果FSBL不运行JTAG分支,那么JTAG直接加载FSBL代码到OCM会执行nor flash分支,而该分支中运行的操作是将flash中的bit文件(暂存)和应用程序搬移到DDR中,与我们要进行的将镜像Boot.bin 烧写到 flash冲突,导致下载失败。