zyqn 无ddr打印helloworld

建立一个helloworld工程,确保可以打印并可以实现下载到flash断电不丢失

然后取消勾选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	 15,0,r4,cr1,cr0,0		/* disable the ICache and MMU */

		isb					/* make sure it completes */


		bx		lr	/* force the switch, destination should have been in r0 */

#endif
.Ldone: b		.Ldone					/* Paranoia: we should never get here */
.end

就是添加了一个

#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
.......
#endif

不做任何处理 直接跳转
!!!!!! 三段 都修改!!!!

2.4 fsbl_hooks.c

mian() 函数中 FsblHookBeforeHandoff() 的使用添加了一个传入的参数 在该文件中修改 FsblHookBeforeHandoff 函数
源文件 在 第 126 行
该函数 原本内容如下:

u32 FsblHookBeforeHandoff(void)
{
	u32 Status;

	Status = XST_SUCCESS;

	/*
	 * User logic to be added here.
	 * Errors to be stored in the status variable and returned
	 */
	fsbl_printf(DEBUG_INFO,"In FsblHookBeforeHandoff function \r\n");

	return (Status);
}

修改后 该函数内容如下:

u32 FsblHookBeforeHandoff(u32 FsblStartAddr) {
	u32 Status;
	u32* ptr;
	u32 i;

	ptr = (u32*) FsblStartAddr;
	Status = XST_SUCCESS;

	/*
	 * User logic to be added here.
	 * Errors to be stored in the status variable and returned
	 */
	fsbl_printf(DEBUG_INFO, "In FsblHookBeforeHandoff function \r\n");
	for (i = 0; i < 8; i++) {
		fsbl_printf(DEBUG_INFO, "*(0x%x) = 0x%x\r\n", ptr, *(ptr));
		ptr++;

	}

	fsbl_printf(DEBUG_INFO,
			"Returning from FsblHookBeforeHandoff function \r\n");

	return (Status);
}

这里还是会报错 因为 头文件中该函数的声明与 函数原型不符 下面就去头文件修改 该函数的声明

2.5 fsbl_hooks.h

文件第 68 行 函数修改了之后也要修改一下头文件中的函数声明
修改后内容如下:

u32 FsblHookBeforeHandoff(u32 FsblStartAddr);

2.6 image_mover.c

2.6.1 添加头文件 文件第 90 行

#include "xil_cache.h"
#include "xil_cache_l.h"

2.6.2 添加条件语句去掉FSBL 对分区的验证

LoadBootImage() 函数中
以上修改后第 335 行
就是添加一个

#ifndef DDRLESS_SYSTEM
......
#endif

修改后 内容如下:

#ifndef DDRLESS_SYSTEM

		/*
		 * Partition owner should be FSBL to validate the partition
		 */
		if ((PartitionAttr & ATTRIBUTE_PARTITION_OWNER_MASK) !=
				ATTRIBUTE_PARTITION_OWNER_FSBL) {
			/*
			 * if FSBL is not the owner of partition,
			 * skip this partition, continue with next partition
			 */
			 fsbl_printf(DEBUG_INFO, "Skipping partition %0lx\r\n",
			 							PartitionNum);
			/*
			 * Increment partition number
			 */
			PartitionNum++;
			continue;
		}
#endif

2.6.3 添加条件语句取消 加载地址检查

LoadBootImage() 函数中
以上修改后在文件第 421 行
还是添加一个

#ifndef DDRLESS_SYSTEM
......
#endif

修改后内容如下:

		/*
		 * Load address check
		 * Loop will break when PS load address zero and partition is
		 * un-signed or un-encrypted
		 */

#ifndef DDRLESS_SYSTEM
		if ((PSPartitionFlag == 1) && (PartitionLoadAddr < DDR_START_ADDR)) {
			if ((PartitionLoadAddr == 0) &&
					(!((SignedPartitionFlag == 1) ||
							(EncryptedPartitionFlag == 1)))) {
				break;
			} else {
				fsbl_printf(DEBUG_GENERAL,
						"INVALID_LOAD_ADDRESS_FAIL\r\n");
				OutputStatus(INVALID_LOAD_ADDRESS_FAIL);
				FsblFallback();
			}
		}

		if (PSPartitionFlag && (PartitionLoadAddr > DDR_END_ADDR)) {
			fsbl_printf(DEBUG_GENERAL,
					"INVALID_LOAD_ADDRESS_FAIL\r\n");
			OutputStatus(INVALID_LOAD_ADDRESS_FAIL);
			FsblFallback();
		}
#endif

将内容注释掉即可 但 DDRLESS_SYSTEM 宏 我们还未定义 不要着急 在后面有定义

2.6.4 移动分区前 使能二级缓存 禁止一级缓存

LoadBootImage() 函数中
以上修改后在文件第 472 行

修改后内容如下

#ifdef DDRLESS_SYSTEM
		Xil_L2CacheEnable();
		Xil_L1DCacheDisable();
		Xil_L1ICacheDisable();
#endif
		Status = PartitionMove(ImageStartAddress, HeaderPtr);
		if (Status != XST_SUCCESS) {
			fsbl_printf(DEBUG_GENERAL,"PARTITION_MOVE_FAIL\r\n");
			OutputStatus(PARTITION_MOVE_FAIL);
			FsblFallback();
		}	else {
			fsbl_printf(DEBUG_GENERAL,"PARTITION_MOVE Successful\r\n");/* 这里添加了一个 debug 打印 不添加也可以 */

		}

其中

#ifdef DDRLESS_SYSTEM
		Xil_L2CacheEnable();
		Xil_L1DCacheDisable();
		Xil_L1ICacheDisable();
#endif
		......
			else {
			fsbl_printf(DEBUG_GENERAL,"PARTITION_MOVE Successful\r\n");/* 这里添加了一个 debug 打印 不添加也可以 */

		}

为添加部分

2.6.5 PartitionMove() 函数修改

2.6.5.1 添加变量

PartitionMove() 函数中
以上修改后在文件 1081 行
该函数的变量声明部分 添加一个变量 ExecuionAddr 并给该变量赋值
添加

......
    u32 ExecuionAddr;
......
	ExecuionAddr =  Header->ExecAddr;

修改后内容如下:

	u32 SourceAddr;
    u32 Status = 0;
    u8 SecureTransferFlag = 0;
    u32 LoadAddr;
    u32 ImageWordLen;
    u32 DataWordLen;
    u32 ExecuionAddr;

	SourceAddr = ImageBaseAddress;
	SourceAddr += Header->PartitionStart<<WORD_LENGTH_SHIFT;
	LoadAddr = Header->LoadAddr;
	ImageWordLen = Header->ImageWordLen;
	DataWordLen = Header->DataWordLen;
	ExecuionAddr =  Header->ExecAddr;

2.6.5.2 数据传输修改

PartitionMove() 函数中
以上修改后在文件 1134 行
添加


#ifdef DDRLESS_SYSTEM
		fsbl_printf(DEBUG_GENERAL,"Source Address %x\n\r",(FlashReadBaseAddress + SourceAddr));
		fsbl_printf(DEBUG_GENERAL,"DataWordLen %x\n\r",(DataWordLen << WORD_LENGTH_SHIFT));
		fsbl_printf(DEBUG_GENERAL,"LoadAddr %x\n\r",LoadAddr);
		if(ExecuionAddr &&(LoadAddr && FlashReadBaseAddress))
		{
			Status=preload_funct((FlashReadBaseAddress + SourceAddr), (ImageWordLen << WORD_LENGTH_SHIFT));
			if(Status != XST_SUCCESS) {
				fsbl_printf(DEBUG_GENERAL, "preload_funct failed\r\n");
				return XST_FAILURE;
			}

		}
#else
......
#endif

修改后内容如下:

	/*
	 * CPU is used for data transfer in case of non-linear
	 * boot device
	 */
	if (!LinearBootDeviceFlag) {
		/*
		 * PL partition copied to DDR temporary location
		 */
		if (PLPartitionFlag) {
			LoadAddr = DDR_TEMP_START_ADDR;
		}

#ifdef DDRLESS_SYSTEM
		fsbl_printf(DEBUG_GENERAL,"Source Address %x\n\r",(FlashReadBaseAddress + SourceAddr));
		fsbl_printf(DEBUG_GENERAL,"DataWordLen %x\n\r",(DataWordLen << WORD_LENGTH_SHIFT));
		fsbl_printf(DEBUG_GENERAL,"LoadAddr %x\n\r",LoadAddr);
		if(ExecuionAddr &&(LoadAddr && FlashReadBaseAddress))
		{
			Status=preload_funct((FlashReadBaseAddress + SourceAddr), (ImageWordLen << WORD_LENGTH_SHIFT));
			if(Status != XST_SUCCESS) {
				fsbl_printf(DEBUG_GENERAL, "preload_funct failed\r\n");
				return XST_FAILURE;
			}

		}
#else
		Status = MoveImage(SourceAddr,
						LoadAddr,
						(ImageWordLen << WORD_LENGTH_SHIFT));
		if(Status != XST_SUCCESS) {
			fsbl_printf(DEBUG_GENERAL, "Move Image Failed\r\n");
			return XST_FAILURE;
		}

		/*
		 * As image present at load address
		 */
		SourceAddr = LoadAddr;
#endif
	}

2.6.5.3 SourceAddr 地址修改

PartitionMove() 函数中
以上修改后在文件 1201 行 在该函数定义的最后部分 return 前面
添加

SourceAddr += FlashReadBaseAddress;

修改后内容如下:

	/*
	 * Load Bitstream partition in to fabric only
	 * if checksum and authentication bits are not set
	 */
	if (PLPartitionFlag && (!(SignedPartitionFlag || PartitionChecksumFlag))) {
		SourceAddr += FlashReadBaseAddress;/* 就这里添加了一句话 修改  SourceAddr 地址*/
		Status = PcapLoadPartition((u32*)SourceAddr,
					(u32*)Header->LoadAddr,
					Header->ImageWordLen,
					Header->DataWordLen,
					EncryptedPartitionFlag);
		if(Status != XST_SUCCESS) {
			fsbl_printf(DEBUG_GENERAL, "PCAP Bitstream Download Failed\r\n");
			return XST_FAILURE;
		}
	}

	return XST_SUCCESS;

以上 至此 image_mover.c 文件修改完毕

2.7 pcap.c

2.7.1 PcapLoadPartition() 函数中 屏蔽错误检查

源文件中第354 行
添加

#ifndef DDRLESS_SYSTEM
......
#endif

添加后内容如下

#ifndef DDRLESS_SYSTEM
	/*
	 * Check for errors
	 */
	IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
	if (IntrStsReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) {
		fsbl_printf(DEBUG_INFO,"Errors in PCAP \r\n");
		return XST_FAILURE;
	}

#endif

2.7.2 XDcfgPollDone() 函数中

以上修改后源文件第 793 行
添加

#ifndef DDRLESS_SYSTEM
......
#endif

添加后 该函数 内容如下:

int XDcfgPollDone(u32 MaskValue, u32 MaxCount)
{
	int Count = MaxCount;
	u32 IntrStsReg = 0;

	/*
	 * poll for the DMA done
	 */
	IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
	while ((IntrStsReg & MaskValue) !=
				MaskValue) {
		IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
		Count -=1;
#ifndef DDRLESS_SYSTEM

		if (IntrStsReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) {
				fsbl_printf(DEBUG_INFO,"FATAL errors in PCAP %lx\r\n",
						IntrStsReg);
				PcapDumpRegisters();
				return XST_FAILURE;
		}
#endif
		if(!Count) {
			fsbl_printf(DEBUG_GENERAL,"PCAP transfer timed out \r\n");
			return XST_FAILURE;
		}
		if (Count > (MAX_COUNT-100)) {
			fsbl_printf(DEBUG_GENERAL,".");
		}
	}

	fsbl_printf(DEBUG_GENERAL,"\n\r");

	XDcfg_IntrClear(DcfgInstPtr, IntrStsReg & MaskValue);

	return XST_SUCCESS;
}

2.8 qspi.c

2.8.1 InitQspi() 函数中 修改较多

该函数在源文件中 217 行 修改较多 建议直接全部复制粘贴
修改后 该函数如下:

u32 InitQspi(void)
{
#ifdef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR
	u32 QspiControlReg = 0;
	u32 QspiDelayReg = 0;
	u32 Prescaler = XQSPIPS_CLK_PRESCALE_8;

	/* Fix for  CR #664560 */
	QspiControlReg = Xil_In32((XPS_QSPI_BASEADDR + XQSPIPS_CR_OFFSET));

	/* Change the baud rate to DIV/8 prescaler value */
	QspiControlReg &= ~XQSPIPS_CR_PRESC_MASK;
	QspiControlReg |= (u32) (Prescaler & XQSPIPS_CR_PRESC_MAXIMUM) <<
				XQSPIPS_CR_PRESC_SHIFT;

	Xil_Out32((XPS_QSPI_BASEADDR + XQSPIPS_CR_OFFSET), QspiControlReg);
	/*
	 * Set the USE loopback bit
	 * Fix for the CR #664560
	 * Delay DLY1 = 0
	 * Delay DLY0 = 0
	 */

	QspiDelayReg = Xil_In32((XPS_QSPI_BASEADDR +
					XQSPIPS_LPBK_DLY_ADJ_OFFSET));

	QspiDelayReg &= FSBL_XQSPIPS_LPBK_DLY_ADJ_DLY_VALUE;

	Xil_Out32((XPS_QSPI_BASEADDR + XQSPIPS_LPBK_DLY_ADJ_OFFSET),
					QspiDelayReg);

	fsbl_printf(DEBUG_INFO, "QSPI initialized with Control value = 0x%x \n \r",
				Xil_In32(XPS_QSPI_BASEADDR +
				XQSPIPS_CR_OFFSET));
	fsbl_printf(DEBUG_INFO, "QSPI loopback register value = 0x%x \n \r",
				Xil_In32(XPS_QSPI_BASEADDR +
				XQSPIPS_LPBK_DLY_ADJ_OFFSET));


#endif
	return XST_SUCCESS;
}

修改后会有报错 因为 该宏还未定义 之后会修改 qspi.h 文件

2.8.2 QspiAccess() 函数

以上修改后 该函数位于 文件第 412 行
修改较多
也建议直接复制粘贴修改后 函数如下:

u32 QspiAccess( u32 SourceAddress, u32 DestinationAddress, u32 LengthBytes)
{
#ifdef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR
	u32 Data;
	u32 Count;
	u32 *SourceAddr;
	u32 *DestAddr;


	/* Check for non-word tail, add bytes to cover the end */
	if ((LengthBytes%4) != 0){
		LengthBytes += (4 - (LengthBytes & 0x00000003));
	}



	SourceAddr = (u32 *)(SourceAddress + FlashReadBaseAddress);

	DestAddr = (u32 *)(DestinationAddress);

	/* Word transfers, endianism isn't an	issue */
	for (Count=0; Count < (LengthBytes / 4); Count++){

		Data = Xil_In32((u32)(SourceAddr));
		SourceAddr++;
		Xil_Out32((u32)(DestAddr), Data);
		DestAddr++;
	}
#endif

	return XST_SUCCESS;
}

2.9 qspi.h

添加 在文件第 116 行 添加 qspi.c 文件中用到的宏
添加内容如下:

#define FSBL_XQSPIPS_LPBK_DLY_ADJ_DLY1 0
#define FSBL_XQSPIPS_LPBK_DLY_ADJ_DLY2 0
#define FSBL_XQSPIPS_LPBK_DLY_ADJ_DLY_VALUE (FSBL_XQSPIPS_LPBK_DLY_ADJ_DLY1 | \
											FSBL_XQSPIPS_LPBK_DLY_ADJ_DLY2)

2.10 lscript.ld

该文件为生成.elf过程中的链接文件,主要修改MEMORY地址,如下。

MEMORY
{
   ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0x00000000, LENGTH = 0x0002FF00
   ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0x0002FF00, LENGTH = 0x0000100
   FLASH : ORIGIN = 0xFC000000 + 0x1700, LENGTH = 0x2FE000
}

!!! 重要!!!

需要为该程序文件添加程序头!!! 使用下面的命令。

ENTRY(_vector_table)
PHDRS { text PT_LOAD; }/*!!! 添加 !!!重要!!!*/

修改后连接脚本文件如下:
注:主要是将一些文件直接写在Flash 中
并添加 XVtable 段。一定要添加

.XVtable(NOLOAD) : {
	 _dataXVtableVMA_start = .;
	*(XVtable)
	 _dataXVtableVMA_end = .;
} > ps7_ram_1_S_AXI_BASEADDR AT> FLASH

_dataXVtableLMA = LOADADDR(.XVtable);

并且需要注意 data 段中的段头尾改变了 main() 函数中使用的就是这个 改完就不会再报错了 这个也一定要更改


.data : {
   _dataVMA_start = .;
   *(.data)
   *(.data.*)
   *(.data1)
   *(.data1.*)
   *(.gnu.linkonce.d.*)
   *(.jcr)
   *(.got)
   *(.got.plt)
    _dataVMA_end = .;
} > ps7_ram_0_S_AXI_BASEADDR AT> FLASH


_dataLMA = LOADADDR(.data);

修改后的该文件全部 内容如下:


_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x6000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000;

_RSA_AC_SIZE = DEFINED(_RSA_AC_SIZE) ? _RSA_AC_SIZE : 0x1000;

_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;

/* Define Memories in the system */

MEMORY
{
   ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0x00000000, LENGTH = 0x0002FF00
   ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0x0002FF00, LENGTH = 0x0000100
   FLASH : ORIGIN = 0xFC000000 + 0x1700, LENGTH = 0x2FE000
}

/* Specify the default entry point to the program */

ENTRY(_vector_table)
PHDRS { text PT_LOAD; }

SECTIONS
{
.text : {
   *(.vectors)
   *(.boot)
   *(.text)
   *(.text.*)
   *(.gnu.linkonce.t.*)
   *(.plt)
   *(.gnu_warning)
   *(.gcc_execpt_table)
   *(.glue_7)
   *(.glue_7t)
   *(.vfp11_veneer)
   *(.ARM.extab)
   *(.gnu.linkonce.armextab.*)
} > FLASH : text	/* !!! : text !!! 也需要添加  重要   */

.init : {
   KEEP (*(.init))
} > FLASH

.fini : {
   KEEP (*(.fini))
} > FLASH

.rodata : {
   __rodata_start = .;
   *(.rodata)
   *(.rodata.*)
   *(.rodata1)
   *(.rodata1.*)
   *(.gnu.linkonce.r.*)
   __rodata_end = .;
} > FLASH


.data : {
   _dataVMA_start = .;
   *(.data)
   *(.data.*)
   *(.data1)
   *(.data1.*)
   *(.gnu.linkonce.d.*)
   *(.jcr)
   *(.got)
   *(.got.plt)
    _dataVMA_end = .;
} > ps7_ram_0_S_AXI_BASEADDR AT> FLASH


_dataLMA = LOADADDR(.data);



.sdata : {
   __sdata_start = .;
   *(.sdata)
   *(.sdata.*)
   *(.sdata2)
   *(.sdata2.*)
   *(.gnu.linkonce.s.*)
   *(.gnu.linkonce.s2.*)
   __sdata_end = .;
} > ps7_ram_0_S_AXI_BASEADDR  AT> FLASH
 

.tdata : {
   __tdata_start = .;
   *(.tdata)
   *(.tdata.*)
   *(.gnu.linkonce.td.*)
   __tdata_end = .;
} > ps7_ram_0_S_AXI_BASEADDR AT> FLASH

.init_array : {
   __init_array_start = .;
   KEEP (*(SORT(.init_array.*)))
   KEEP (*(.init_array))
   __init_array_end = .;
} > FLASH

.fini_array : {
   __fini_array_start = .;
   KEEP (*(SORT(.fini_array.*)))
   KEEP (*(.fini_array))
   __fini_array_end = .;
} > FLASH

.got : {
   *(.got)
} > FLASH

.ctors : {
   __CTOR_LIST__ = .;
   ___CTORS_LIST___ = .;
   KEEP (*crtbegin.o(.ctors))
   KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
   KEEP (*(SORT(.ctors.*)))
   KEEP (*(.ctors))
   __CTOR_END__ = .;
   ___CTORS_END___ = .;
} > FLASH

.dtors : {
   __DTOR_LIST__ = .;
   ___DTORS_LIST___ = .;
   KEEP (*crtbegin.o(.dtors))
   KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
   KEEP (*(SORT(.dtors.*)))
   KEEP (*(.dtors))
   __DTOR_END__ = .;
   ___DTORS_END___ = .;
} > FLASH

.fixup : {
   __fixup_start = .;
   *(.fixup)
   __fixup_end = .;
} > FLASH

.eh_frame : {
   *(.eh_frame)
} > FLASH

.eh_framehdr : {
   __eh_framehdr_start = .;
   *(.eh_framehdr)
   __eh_framehdr_end = .;
} > FLASH

.gcc_except_table : {
   *(.gcc_except_table)
} > FLASH

.mmu_tbl (ALIGN(0x4000)): {
   __mmu_tbl_start = .;
   *(.mmu_tbl)
   __mmu_tbl_end = .;
} > FLASH

.ARM.exidx : {
   __exidx_start = .;
   *(.ARM.exidx*)
   *(.gnu.linkonce.armexidix.*.*)
   __exidx_end = .;
} > FLASH

.preinit_array : {
   __preinit_array_start = .;
   KEEP (*(SORT(.preinit_array.*)))
   KEEP (*(.preinit_array))
   __preinit_array_end = .;
} > FLASH

.rsa_ac : {
	. = ALIGN(64);
	__rsa_ac_start = .;
	. += _RSA_AC_SIZE;
	__rsa_ac_end = .;
} > FLASH

.ARM.attributes : {
   __ARM.attributes_start = .;
   *(.ARM.attributes)
   __ARM.attributes_end = .;
} > FLASH



.sbss2 : {
   __sbss2_start = .;
   *(.sbss2)
   *(.sbss2.*)
   *(.gnu.linkonce.sb2.*)
   __sbss2_end = .;
} > ps7_ram_0_S_AXI_BASEADDR


.sbss (NOLOAD) : {
   __sbss_start = .;
   *(.sbss)
   *(.sbss.*)
   *(.gnu.linkonce.sb.*)
   __sbss_end = .;
} > ps7_ram_0_S_AXI_BASEADDR



.tbss : {
   __tbss_start = .;
   *(.tbss)
   *(.tbss.*)
   *(.gnu.linkonce.tb.*)
   __tbss_end = .;
} > ps7_ram_0_S_AXI_BASEADDR

.bss (NOLOAD) : {
   __bss_start = .;
   __bss_start__ = .;
   *(.bss)
   *(.bss.*)
   *(.gnu.linkonce.b.*)
   *(COMMON)
   __bss_end = .;
   __bss_end__ = .;
} > ps7_ram_0_S_AXI_BASEADDR

/*
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );

_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );

*/
/* Generate Stack and Heap definitions */

.heap (NOLOAD) : {
   . = ALIGN(16);
   _heap = .;
   HeapBase = .;
   _heap_start = .;
   . += _HEAP_SIZE;
   _heap_end = .;
   HeapLimit = .;
} > ps7_ram_0_S_AXI_BASEADDR

.stack (NOLOAD) : {
   . = ALIGN(16);
   _stack_end = .;
   . += _STACK_SIZE;
   _stack = .;
   __stack = _stack;
   . = ALIGN(16);
   _irq_stack_end = .;
   . += _STACK_SIZE;
   __irq_stack = .;
   _supervisor_stack_end = .;
   . += _SUPERVISOR_STACK_SIZE;
   . = ALIGN(16);
   __supervisor_stack = .;
   _abort_stack_end = .;
   . += _ABORT_STACK_SIZE;
   . = ALIGN(16);
   __abort_stack = .;
   _fiq_stack_end = .;
   . += _FIQ_STACK_SIZE;
   . = ALIGN(16);
   __fiq_stack = .;
   _undef_stack_end = .;
   . += _UNDEF_STACK_SIZE;
   . = ALIGN(16);
   __undef_stack = .;
} > ps7_ram_0_S_AXI_BASEADDR



.XVtable(NOLOAD) : {
	 _dataXVtableVMA_start = .;
	*(XVtable)
	 _dataXVtableVMA_end = .;
} > ps7_ram_1_S_AXI_BASEADDR AT> FLASH

_dataXVtableLMA = LOADADDR(.XVtable);


_end = .;
}

通过查看fsbl.elf文件,可以查看目前sections的分配,对于其中具有READONLY属性的section,可以放在QSPI FLASH中运行,即XIP模式。
其它的放在 ps7_ram_0_S_AXI_BASEADDR 中即可
在这里插入图片描述

2.11 添加宏定义

代码修改完后,在fsbl工程中添加两个宏定义。
在这里插入图片描述

至此 fsbl 文件全部修改完毕
接下来修改应用文件

3 application

3.1 application.c

该文件中添加代码
添加在 main() 函数上面即可
添加内容如下:

#define XPS_L2CC_EVNT_CNTRL_OFFSET		0x0200
#define XPS_L2CC_EVNT_CNT1_CTRL_OFFSET	0x0204
#define XPS_L2CC_EVNT_CNT0_CTRL_OFFSET	0x0208
#define XPS_L2CC_EVNT_CNT1_VAL_OFFSET	0x020C
#define XPS_L2CC_EVNT_CNT0_VAL_OFFSET	0x0210

#define QSPI_BaseAddress 0xE000D000


extern char _image_start, _dataLMA, _dataVMA_start, _dataVMA_end, _vectorscopy, __vectors_start, __vectors_end;
extern char _dataXVtableLMA, _dataXVtableVMA_start,_dataXVtableVMA_end;



static void copy(char *src, char *dstStart, char *dstEnd) {
	/* ROM has data at end of text; copy it. */
	while (dstStart < dstEnd)
	{

		*dstStart++ = *src++;
		asm volatile ("dsb sy");

	}
}

void Xil_Write32(unsigned int OutAddress, unsigned int Value)
{
	*(volatile unsigned int *) OutAddress = Value;
}

unsigned int Xil_Read32(unsigned int Addr)
{
	return *(volatile unsigned int *) Addr;
}

并在main() 函数中 添加数据段拷贝函数

	//copy the data section from FLASH(load region) to OCM(Execution region) memory region.
	copy(&_dataLMA,&_dataVMA_start,&_dataVMA_end);

	//Copy the Interrupt vector table from FLASH(load region) to OCM(Execution region) memory region.
	copy(&_dataXVtableLMA,&_dataXVtableVMA_start,&_dataXVtableVMA_end);

添加完成后和fsbl 的mian() 函数一样也会报错 也是因为 lscript.ld 中的数据段中还未更改

3.2 lscript.ld

该文件修改与fsbl 文件中的 lscript.ld 一样 注意点也是一样的 就不在赘述了 具体哪些放在FLASH 中 哪些放在 OCM 内存中也是看 application.elf 文件 !!!!!
修改完成后该文件内容如下

_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000;
_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000;

_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024;
_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048;
_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024;
_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024;
_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024;

/* Define Memories in the system */

MEMORY
{
   FLASH : ORIGIN = 0xFC700000, LENGTH = 0x100000
   ps7_ram_0 : ORIGIN = 0x00010000, LENGTH = 0x0001FF00
   ps7_ram_1 : ORIGIN = 0x0002ff00, LENGTH = 0x00000100   
}


/* Specify the default entry point to the program */

ENTRY(_vector_table)
PHDRS { text PT_LOAD; }

/* Define the sections, and where they are mapped in memory */

SECTIONS
{
.text : {
   KEEP (*(.vectors))
   *(.boot)
   *(.text)
   *(.text.*)
   *(.gnu.linkonce.t.*)
   *(.plt)
   *(.gnu_warning)
   *(.gcc_execpt_table)
   *(.glue_7)
   *(.glue_7t)
   *(.vfp11_veneer)
   *(.ARM.extab)
   *(.gnu.linkonce.armextab.*)
} > FLASH :text

.init : {
   KEEP (*(.init))
} > FLASH

.fini : {
   KEEP (*(.fini))
} > FLASH

.rodata : {
   __rodata_start = .;
   *(.rodata)
   *(.rodata.*)
   *(.gnu.linkonce.r.*)
   __rodata_end = .;
} > FLASH

.rodata1 : {
   __rodata1_start = .;
   *(.rodata1)
   *(.rodata1.*)
   __rodata1_end = .;
} > FLASH

.data : {
   _dataVMA_start  = .;
   *(.data)
   *(.data.*)
   *(.data1)
   *(.data1.*)
   *(.gnu.linkonce.d.*)
   *(.jcr)
   *(.got)
   *(.got.plt)
   _dataVMA_end = .;
} > ps7_ram_0 AT> FLASH

_dataLMA = LOADADDR(.data); 



.sdata : {
   __sdata_start = .;
   *(.sdata)
   *(.sdata.*)
   *(.gnu.linkonce.s.*)
   __sdata_end = .;
} > ps7_ram_0 AT> FLASH

.sdata2 : {
   __sdata2_start = .;
   *(.sdata2)
   *(.sdata2.*)
   *(.gnu.linkonce.s2.*)
   __sdata2_end = .;
} > ps7_ram_0 AT> FLASH

.tdata : {
   __tdata_start = .;
   *(.tdata)
   *(.tdata.*)
   *(.gnu.linkonce.td.*)
   __tdata_end = .;
} > ps7_ram_0 AT> FLASH

.got : {
   *(.got)
} > FLASH

.ctors : {
   __CTOR_LIST__ = .;
   ___CTORS_LIST___ = .;
   KEEP (*crtbegin.o(.ctors))
   KEEP (*(EXCLUDE_FILE(*crtend.o) .ctors))
   KEEP (*(SORT(.ctors.*)))
   KEEP (*(.ctors))
   __CTOR_END__ = .;
   ___CTORS_END___ = .;
} > FLASH

.dtors : {
   __DTOR_LIST__ = .;
   ___DTORS_LIST___ = .;
   KEEP (*crtbegin.o(.dtors))
   KEEP (*(EXCLUDE_FILE(*crtend.o) .dtors))
   KEEP (*(SORT(.dtors.*)))
   KEEP (*(.dtors))
   __DTOR_END__ = .;
   ___DTORS_END___ = .;
} > FLASH

.fixup : {
   __fixup_start = .;
   *(.fixup)
   __fixup_end = .;
} > FLASH

.eh_frame : {
   *(.eh_frame)
} > FLASH

.eh_framehdr : {
   __eh_framehdr_start = .;
   *(.eh_framehdr)
   __eh_framehdr_end = .;
} > FLASH

.gcc_except_table : {
   *(.gcc_except_table)
} > FLASH

.mmu_tbl (ALIGN(16384)) : {
   __mmu_tbl_start = .;
   *(.mmu_tbl)
   __mmu_tbl_end = .;
} > FLASH

.ARM.exidx : {
   __exidx_start = .;
   *(.ARM.exidx*)
   *(.gnu.linkonce.armexidix.*.*)
   __exidx_end = .;
} > FLASH

.preinit_array : {
   __preinit_array_start = .;
   KEEP (*(SORT(.preinit_array.*)))
   KEEP (*(.preinit_array))
   __preinit_array_end = .;
} > FLASH

.init_array : {
   __init_array_start = .;
   KEEP (*(SORT(.init_array.*)))
   KEEP (*(.init_array))
   __init_array_end = .;
} > FLASH

.fini_array : {
   __fini_array_start = .;
   KEEP (*(SORT(.fini_array.*)))
   KEEP (*(.fini_array))
   __fini_array_end = .;
} > FLASH

.ARM.attributes : {
   __ARM.attributes_start = .;
   *(.ARM.attributes)
   __ARM.attributes_end = .;
} > FLASH


.sbss2 : {
   __sbss2_start = .;
   *(.sbss2)
   *(.sbss2.*)
   *(.gnu.linkonce.sb2.*)
   __sbss2_end = .;
} > ps7_ram_0


.sbss (NOLOAD) : {
   __sbss_start = .;
   *(.sbss)
   *(.sbss.*)
   *(.gnu.linkonce.sb.*)
   __sbss_end = .;
} > ps7_ram_0


.tbss : {
   __tbss_start = .;
   *(.tbss)
   *(.tbss.*)
   *(.gnu.linkonce.tb.*)
   __tbss_end = .;
} > ps7_ram_0

.bss (NOLOAD) : {
   __bss_start = .;
   *(.bss)
   *(.bss.*)
   *(.gnu.linkonce.b.*)
   *(COMMON)
   __bss_end = .;
} > ps7_ram_0
/*
_SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 );

_SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 );
*/
/* Generate Stack and Heap definitions */

.heap (NOLOAD) : {
   . = ALIGN(16);
   _heap = .;
   HeapBase = .;
   _heap_start = .;
   . += _HEAP_SIZE;
   _heap_end = .;
   HeapLimit = .;
} > ps7_ram_0

.stack (NOLOAD) : {
   . = ALIGN(16);
   _stack_end = .;
   . += _STACK_SIZE;
   . = ALIGN(16);
   _stack = .;
   __stack = _stack;
   . = ALIGN(16);
   _irq_stack_end = .;
   . += _IRQ_STACK_SIZE;
   . = ALIGN(16);
   __irq_stack = .;
   _supervisor_stack_end = .;
   . += _SUPERVISOR_STACK_SIZE;
   . = ALIGN(16);
   __supervisor_stack = .;
   _abort_stack_end = .;
   . += _ABORT_STACK_SIZE;
   . = ALIGN(16);
   __abort_stack = .;
   _fiq_stack_end = .;
   . += _FIQ_STACK_SIZE;
   . = ALIGN(16);
   __fiq_stack = .;
   _undef_stack_end = .;
   . += _UNDEF_STACK_SIZE;
   . = ALIGN(16);
   __undef_stack = .;
} > ps7_ram_0

 .XVtable : {
	 _dataXVtableVMA_start = .;
	*(XVtable)
	 _dataXVtableVMA_end = .;
} > ps7_ram_1


_dataXVtableLMA = LOADADDR(.XVtable); 

_end = .;
}

4 生成BOOT.BIN

生成boot.bin需要使用bif文件,需要注意设置xip模式
修改过后的该文件内容如下 注意需要添加 xip_mode 和 offset !!! 重要!!!

//arch = zynq; split = false; format = BIN
the_ROM_image:
{
	[bootloader, xip_mode,offset = 0x1700]E:\chen\zynq\J5RPY_HF_CLY\J5RPY_HF_CLY\02_Pro\J5RPY_HF.sdk\fsbl\Debug\fsbl.elf
	[offset = 0x200000]E:\chen\zynq\J5RPY_HF_CLY\J5RPY_HF_CLY\02_Pro\J5RPY_HF.sdk\ARM_Core_wrapper_hw_platform_0\ARM_Core_wrapper.bit
	[offset = 0x700000]E:\chen\zynq\J5RPY_HF_CLY\J5RPY_HF_CLY\02_Pro\J5RPY_HF.sdk\hello_world\Debug\hello_world.elf
}

**注:需要使用一个正常的 未修改过 lscript.ld 的fsbl.elf 将 生成的BOOT.Bin文件烧录到板子里 !!! **

最后会有一些报错

Description	Resource	Path	Location	Type
fsbl.elf: section `.data' can't be allocated in segment 0	fsbl		 	C/C++ Problem

但这个报错不影响 所以不用管

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值