参考链接:
ZYNQ上无DDR加载应用
官方参考步骤
ZYNQ 无DDR 启动
1 fsbl_bsp 相关修改
1.1 Translation_table.s
该文件位于E: …\fsbl_bsp\ps7_cortexa9_0\libsrc\standalone_v7_0\src 目录下
在文件第203-206 行内容屏蔽掉 并添加两段代码
原内容如下:
.rept 0x0020 /* 0xfc000000 - 0xfdffffff (Linear QSPI - XIP) */
.word SECT + 0xc0a /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b1, B=b0 */
.set SECT, SECT+0x100000
.endr
修改后文本内容如下:
#if 0
.rept 0x0020 /* 0xfc000000 - 0xfdffffff (Linear QSPI - XIP) */
.word SECT + 0xc0a /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b1, B=b0 */
.set SECT, SECT+0x100000
.endr
#endif
.rept 0x0007 /* 0xfc000000 - 0xfc6fffff (Linear QSPI - XIP) */
.word SECT + 0xc0a /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b1, B=b1 */
.set SECT, SECT+0x100000
.endr
.rept 0x0019 /* 0xfc700000 - 0xfdffffff (Linear QSPI - XIP) */
.word SECT + 0x15de2 /* S=b0 TEX=b101 AP=b11, Domain=b0, C=b0, B=b0 */
.set SECT, SECT+0x100000
.endr
增加的代码使用了QSPI内部的存储空间,用于执行FSBL,这里将QSPI配置为线性模式,分为2段XIP,7MB和25MB。这与后面提到的产生BIN文件时使用XIP模块相对应,同时0XFC000000这个地址将会用在fsbl的lscript.ld中。
1.2 xil_exception.c
向向量表条目添加了XVtable 属性。
该文件第93行
原内容为:
XExc_VectorTableEntry XExc_VectorTable[XIL_EXCEPTION_ID_LAST + 1] =
添加 XVtable 属性 修改后如下:
XExc_VectorTableEntry XExc_VectorTable[XIL_EXCEPTION_ID_LAST + 1] __attribute__ ((section("XVtable"))) =
以上为 fsbl_bsp 修改内容
2 fsbl 相关修改
2.1main.c
2.1.1 添加头文件
原文第138行 添加头文件
#include "xil_cache_l.h"
#include "xl2cc.h"
2.1.2 添加 preload_func 和 copy 函数及一些宏定义等 具体内容如下:
添加在 221 行 main() 函数前面即可 该函数将应用程序代码加载到缓存中并锁定它。
添加内容如下:
#ifdef DDRLESS_SYSTEM
#define XPAR_PS7_DDR_0_S_AXI_BASEADDR
#define WAY_SIZE 65536
#define MAX_NUM_WAYS 8
/*****************************************************************************/
/**
*
* This function is used to preload and lock data in to L2 Cache.
*
*
* @param None.
*
* @return
* - XST_SUCCESS to indicate success
* - XST_FAILURE.to indicate failure
*
* @note
*
****************************************************************************/
int preload_funct(unsigned int uiSrcAddress, unsigned int uiSize)
{
// static unsigned int uiAlreadyProgrammed;
unsigned int i=0;
// unsigned int uiNumofWays=0;
// unsigned int uiVariable=0;
// unsigned int uiValue0=0;
// unsigned int uiValue1=0;
fsbl_printf(DEBUG_GENERAL,"\n\rInside Preload Functions \n\r");
// Disable FIQ and IRQ interrupt
Xil_ExceptionDisableMask(XIL_EXCEPTION_ALL);
/*
* UnLock Data and Instruction from way 1 to7 and unlock Data and instruction for Way 0.
* The PL310 has 8 sets of registers, one per possible CPU.
*/
for(i=0;i<8;i++)
{
Xil_Out32((XPS_L2CC_BASEADDR + (XPS_L2CC_CACHE_DLCKDWN_0_WAY_OFFSET + (i*8)) ), (0x00000000));
Xil_Out32((XPS_L2CC_BASEADDR + (XPS_L2CC_CACHE_ILCKDWN_0_WAY_OFFSET + (i*8)) ), (0x00000000));
}
/* Flush the Caches */
Xil_DCacheFlush();
Xil_DCacheInvalidate();
fsbl_printf(DEBUG_GENERAL,"\n\r Invalidate D cache \n\r");
/*Preload instruction from section starts from 0x31000000 to Cache Way 0*/
fsbl_printf(DEBUG_GENERAL,"Preload instructions uiSrcAddress = 0x%8x\n\r", uiSrcAddress);
fsbl_printf(DEBUG_GENERAL,"Preload instructions uiSize = 0x%8x\n\r", uiSize);
{
// Copy Applciation source adress to ro register
asm volatile ("mov r0,%0":: "r"(uiSrcAddress));
//Copy application size to r1 register
asm volatile ("mov r1,%0":: "r"(uiSize));
// Offset register i.e. r2
asm volatile ("mov r2, #0");
// Label
asm ("preload_inst:");
// Load r4 register from the r0+r2 (Source address + offset)
// This step create an valid entry of the address (Source address + offset) in L2 cache
asm volatile ("ldr r4, [r0,r2]");
// Increment the offset by one cache line
asm volatile ("add r2,r2,#4");
// Compare the offset with the Application size.
asm volatile ("cmp r1, r2");
// If not equal jump to Label
asm volatile ("bge preload_inst");
}
// lock both Data and instruction caches from Way 1 to 7.
// Lock Data and Instruction Caches for Way 0
for(i=0;i<8;i++)
{
Xil_Out32((XPS_L2CC_BASEADDR + (XPS_L2CC_CACHE_DLCKDWN_0_WAY_OFFSET + (i*8)) ), 0xffff);
Xil_Out32((XPS_L2CC_BASEADDR + (XPS_L2CC_CACHE_ILCKDWN_0_WAY_OFFSET + (i*8)) ), 0xffff);
}
fsbl_printf(DEBUG_GENERAL,"Lock both Data and instruction caches from Way 1 to 7\n\r");
// Enable all the Interrupts
Xil_ExceptionEnableMask(XIL_EXCEPTION_ALL);
// uiAlreadyProgrammed=uiVariable;
return - XST_SUCCESS;
}
#endif
extern char _image_start, _dataLMA, _dataVMA_start, _dataVMA_end, _vectorscopy, __vectors_start, __vectors_end;
extern char _dataXVtableLMA, _dataXVtableVMA_start,_dataXVtableVMA_end;
extern unsigned int _ncSTART_ADDR;
static void copy(char *src, char *dstStart, char *dstEnd) {
/* ROM has data at end of text; copy it. */
while (dstStart < dstEnd) {
*dstStart++ = *src++;
}
}
#define WRITE_VEC_BASE_ADDR(value) mtcp(XREG_CP15_VEC_BASE_ADDR,value)
#define READ_VEC_BASE_ADDR(value) value = mfcp(XREG_CP15_VEC_BASE_ADDR)
以上添加完毕后会有一些报错 是因为 lscript.ld 文件还未修改 因此一些变量还未定义 所以不必关心!!!!
2.1.3 添加 data 拷贝
添加在mian() 函数中 变量定义后 原文本第 242 行 上面的修改后在第 355行
添加的文本如下:
copy(&_dataLMA,&_dataVMA_start,&_dataVMA_end);
copy(&_dataXVtableLMA,&_dataXVtableVMA_start,&_dataXVtableVMA_end);
以上添加完毕后会有一些报错 是因为 lscript.ld 文件还未修改 因此一些变量还未定义 所以不必关心!!!!
2.1.4 添加一些FSBL 数据地址的打印(可以不添加)
main() 函数中
上面的内容添加后在第 411行
添加的文本如下
/*
* Print the FSBL Banner
*/
fsbl_printf(DEBUG_GENERAL,"\n\rXilinx First Stage Boot Loader \n\r");
fsbl_printf(DEBUG_GENERAL,"Release %d.%d %s-%s\r\n",
SDK_RELEASE_YEAR, SDK_RELEASE_QUARTER,
__DATE__,__TIME__);
/*****************************以下为添加的内容********上面是原来就有的*********************/
//fsbl_printf(DEBUG_GENERAL,"_image_start \t= 0x%8x\n\r", &_image_start);
fsbl_printf(DEBUG_GENERAL,"_dataLMA \t= 0x%8x\n\r", &_dataLMA);
fsbl_printf(DEBUG_GENERAL,"_dataVMA_start \t= 0x%8x\n\r", &_dataVMA_start);
fsbl_printf(DEBUG_GENERAL,"_dataVMA_end \t= 0x%8x\n\r", &_dataVMA_end);
//fsbl_printf(DEBUG_GENERAL,"_vectorscopy \t= 0x%8x\n\r", &_vectorscopy);
//fsbl_printf(DEBUG_GENERAL,"__vectors_start \t= 0x%8x\n\r", &__vectors_start);
//fsbl_printf(DEBUG_GENERAL,"__vectors_end \t= 0x%8x\n\r", &__vectors_end);
fsbl_printf(DEBUG_GENERAL,"_dataXVtableLMA \t= 0x%8x\n\r", &_dataXVtableLMA);
fsbl_printf(DEBUG_GENERAL,"_dataXVtableVMA_start \t= 0x%8x\n\r", &_dataXVtableVMA_start);
fsbl_printf(DEBUG_GENERAL,"_dataXVtableVMA_end \t= 0x%8x\n\r", &_dataXVtableVMA_end);
2.1.5 对DDRInit 添加条件语句进行屏蔽
main() 函数中
上面的内容修改后 在第425 行
添加 DDRLESS_SYSTEM 条件
#ifndef DDRLESS_SYSTEM
#endif
添加后 内容如下:
#ifndef DDRLESS_SYSTEM
/*
* DDR Read/write test
*/
Status = DDRInitCheck();
if (Status == XST_FAILURE) {
fsbl_printf(DEBUG_GENERAL,"DDR_INIT_FAIL \r\n");
/* Error Handling here */
OutputStatus(DDR_INIT_FAIL);
/*
* Calling FsblHookFallback instead of Fallback
* since, devcfg driver is not yet initialized
*/
FsblHookFallback();
}
#endif
2.1.6 添加 flash 地址
main() 函数中:
上面内容添加后在 该文件第535 行
文本如下:
FlashReadBaseAddress = XPS_QSPI_LINEAR_BASEADDR;
添加后 内容如下:
#ifdef MMC_SUPPORT
/*
* To support MMC boot
* QSPI boot mode detection ignored
*/
if (BootModeRegister == QSPI_MODE) {
BootModeRegister = MMC_MODE;
}
#endif
if (BootModeRegister == QSPI_MODE) {
fsbl_printf(DEBUG_GENERAL,"Boot mode is QSPI\n\r");
InitQspi();
MoveImage = QspiAccess;
FlashReadBaseAddress = XPS_QSPI_LINEAR_BASEADDR;//添加语句!!!!!!!在这里
fsbl_printf(DEBUG_INFO,"QSPI Init Done \r\n");
} else
#endif
2.1.7 boot 镜像加载后添加 对 一级数据缓存操作
main() 函数中
上面内容添加后在该文件第 703 行
添加内容如下:
Xil_L1DCacheEnable();
Xil_L1ICacheEnable();
Xil_L1DCacheInvalidate();
Xil_L1ICacheInvalidate();
fsbl_printf(DEBUG_GENERAL,"-> FsblFallback\n\r");
//OutputStatus(NO_DDR);
添加后 文本如下:
/*
* Load boot image
*/
HandoffAddress = LoadBootImage();
Xil_L1DCacheEnable();
Xil_L1ICacheEnable();
Xil_L1DCacheInvalidate();
Xil_L1ICacheInvalidate();
2.1.8 main() 最后去掉 OutputStatus(NO_DDR);
main() 函数中:
以上内容修改后 在文件第 726 行 在该函数最后 return 之前
原内容如下:
#else
OutputStatus(NO_DDR);
FsblFallback();
#endif
return Status;
修改后如下:
#else
fsbl_printf(DEBUG_GENERAL,"-> FsblFallback\n\r");/* 还添加了一个debug 语句 可以不要 */
//OutputStatus(NO_DDR);/* 这句话 !!! 屏蔽掉 */
FsblFallback();
#endif
return Status;
2.1.9 FsblHandoff() 函数 修改
FsblHandoff() 函数中!!!!!
以上内容修改后 在该文件第 912 行
原内容如下:
Status = FsblHookBeforeHandoff();
修改后如下 添加了一个传入的参数 该修改后 也会报错!!!! 因为原函数还未更改!!!
Status = FsblHookBeforeHandoff(FsblStartAddr);
以上 至此 main.c文件修改完成
2.2 fsbl.h
该文件 537 行
main() 函数中添加了 preload_funct() 函数 该函数在其它文件中有调用 所以 添加一下 函数声明
添加内容如下:
int preload_funct(unsigned int uiSrcAddress, unsigned int uiSize);/* __attribute__ ((section ("ncmemory")));*/
2.3 fsbl_handoff.S
因为程序不在DDR中执行,需要修改FsblHandoffExit段
源文件第85 行 140 行 198行 该文件中有三处对 FsblHandoffExit段的定义 不知道具体用哪一个 就全部都修改了吧
修改后 文本如下:
FsblHandoffExit:
#ifdef DDRLESS_SYSTEM
mov lr, r0 /* move the destination address into link register */
bx lr /* force the switch, destination should have been in r0 */
#else
mov lr, r0 /* move the destination address into link register */
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