ZYNQ上无DDR加载应用
1、背景介紹
為了節(jié)約成本和降低功耗,現(xiàn)在板載BMC全部選擇了ZYNQ7010,無(wú)外掛DDR,存儲(chǔ)空間使用QSPI,借助板載OCM執(zhí)行應(yīng)用程序。
xilinx網(wǎng)站上提供了一種解決方案,鏈接如下:
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/18842377/Zynq-7000+AP+SoC+Boot+-+Booting+and+Running+Without+External+Memory+Tech+Tip
注:建議使用vivado2017.3及以上版本進(jìn)行硬件工程設(shè)計(jì)。
?
2、fsbl修改
vivado產(chǎn)生bit之后,導(dǎo)入SDK,根據(jù)新的硬件工程產(chǎn)生fsbl和fsbl_bsp。
首先需要對(duì)fsbl_bsp進(jìn)行修改
?
Translation_table.s修改
需要修改地方如下:
?
/****************************************************************************** * * Copyright (C) 2009 - 2015 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /*****************************************************************************/ /** * @file translation_table.s * * @addtogroup a9_boot_code * @{ * <h2> translation_table.S </h2> * translation_table.S contains a static page table required by MMU for * cortex-A9. This translation table is flat mapped (input address = output * address) with default memory attributes defined for zynq architecture. It * utilizes short descriptor translation table format with each section defining * 1MB of memory. * * The overview of translation table memory attributes is described below. * *| | Memory Range | Definition in Translation Table | *|-----------------------|-------------------------|-----------------------------------| *| DDR | 0x00000000 - 0x3FFFFFFF | Normal write-back Cacheable | *| PL | 0x40000000 - 0xBFFFFFFF | Strongly Ordered | *| Reserved | 0xC0000000 - 0xDFFFFFFF | Unassigned | *| Memory mapped devices | 0xE0000000 - 0xE02FFFFF | Device Memory | *| Reserved | 0xE0300000 - 0xE0FFFFFF | Unassigned | *| NAND, NOR | 0xE1000000 - 0xE3FFFFFF | Device memory | *| SRAM | 0xE4000000 - 0xE5FFFFFF | Normal write-back Cacheable | *| Reserved | 0xE6000000 - 0xF7FFFFFF | Unassigned | *| AMBA APB Peripherals | 0xF8000000 - 0xF8FFFFFF | Device Memory | *| Reserved | 0xF9000000 - 0xFBFFFFFF | Unassigned | *| Linear QSPI - XIP | 0xFC000000 - 0xFDFFFFFF | Normal write-through cacheable | *| Reserved | 0xFE000000 - 0xFFEFFFFF | Unassigned | *| OCM | 0xFFF00000 - 0xFFFFFFFF | Normal inner write-back cacheable | * * @note * * For region 0x00000000 - 0x3FFFFFFF, a system where DDR is less than 1GB, * region after DDR and before PL is marked as undefined/reserved in translation * table. In 0xF8000000 - 0xF8FFFFFF, 0xF8000C00 - 0xF8000FFF, 0xF8010000 - * 0xF88FFFFF and 0xF8F03000 to 0xF8FFFFFF are reserved but due to granual size * of 1MB, it is not possible to define separate regions for them. For region * 0xFFF00000 - 0xFFFFFFFF, 0xFFF00000 to 0xFFFB0000 is reserved but due to 1MB * granual size, it is not possible to define separate region for it * * <pre> * MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- --------------------------------------------------- * 1.00a ecm 10/20/09 Initial version * 3.04a sdm 01/13/12 Updated MMU table to mark DDR memory as Shareable * 3.07a sgd 07/05/2012 Configuring device address spaces as shareable device * instead of strongly-ordered. * 3.07a asa 07/17/2012 Changed the property of the ".mmu_tbl" section. * 4.2 pkp 09/02/2014 added entries for 0xfe000000 to 0xffefffff as reserved * and 0xe0000000 - 0xe1ffffff is broken down into * 0xe0000000 - 0xe02fffff (memory mapped devides) * 0xe0300000 - 0xe0ffffff (reserved) and * 0xe1000000 - 0xe1ffffff (NAND) * 5.2 pkp 06/08/2015 put a check for XPAR_PS7_DDR_0_S_AXI_BASEADDR to confirm * if DDR is present or not and accordingly generate the * translation table * 6.1 pkp 07/11/2016 Corrected comments for memory attributes * </pre> * * ******************************************************************************/ #include "xparameters.h".globl MMUTable.section .mmu_tbl,"a"MMUTable:/* Each table entry occupies one 32-bit word and there are* 4096 entries, so the entire table takes up 16KB.* Each entry covers a 1MB section.*/ .set SECT, 0#ifdef XPAR_PS7_DDR_0_S_AXI_BASEADDR .set DDR_START, XPAR_PS7_DDR_0_S_AXI_BASEADDR .set DDR_END, XPAR_PS7_DDR_0_S_AXI_HIGHADDR .set DDR_SIZE, (DDR_END - DDR_START)+1 .set DDR_REG, DDR_SIZE/0x100000 #else .set DDR_REG, 0 #endif.set UNDEF_REG, 0x3FF - DDR_REG/*0x00000000 - 0x00100000 (cacheable )*/ .word SECT + 0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ .set SECT, SECT+0x100000.rept DDR_REG /* (DDR Cacheable) */ .word SECT + 0x15de6 /* S=b1 TEX=b101 AP=b11, Domain=b1111, C=b0, B=b1 */ .set SECT, SECT+0x100000 .endr.rept UNDEF_REG /* (unassigned/reserved).* Generates a translation fault if accessed */ .word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ .set SECT, SECT+0x100000 .endr.rept 0x0400 /* 0x40000000 - 0x7fffffff (FPGA slave0) */ .word SECT + 0xc02 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */ .set SECT, SECT+0x100000 .endr.rept 0x0400 /* 0x80000000 - 0xbfffffff (FPGA slave1) */ .word SECT + 0xc02 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b0 */ .set SECT, SECT+0x100000 .endr.rept 0x0200 /* 0xc0000000 - 0xdfffffff (unassigned/reserved).* Generates a translation fault if accessed */ .word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ .set SECT, SECT+0x100000 .endr.rept 0x003 /* 0xe0000000 - 0xe02fffff (Memory mapped devices)* UART/USB/IIC/SPI/CAN/GEM/GPIO/QSPI/SD/NAND */ .word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ .set SECT, SECT+0x100000 .endr.rept 0x0D /* 0xe0300000 - 0xe0ffffff (unassigned/reserved).* Generates a translation fault if accessed */ .word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ .set SECT, SECT+0x100000 .endr.rept 0x0010 /* 0xe1000000 - 0xe1ffffff (NAND) */ .word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ .set SECT, SECT+0x100000 .endr.rept 0x0020 /* 0xe2000000 - 0xe3ffffff (NOR) */ .word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ .set SECT, SECT+0x100000 .endr.rept 0x0020 /* 0xe4000000 - 0xe5ffffff (SRAM) */ .word SECT + 0xc0e /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b1, B=b1 */ .set SECT, SECT+0x100000 .endr.rept 0x0120 /* 0xe6000000 - 0xf7ffffff (unassigned/reserved).* Generates a translation fault if accessed */ .word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ .set SECT, SECT+0x100000 .endr/* 0xf8000c00 to 0xf8000fff, 0xf8010000 to 0xf88fffff and0xf8f03000 to 0xf8ffffff are reserved but due to granual size of1MB, it is not possible to define separate regions for them */.rept 0x0010 /* 0xf8000000 - 0xf8ffffff (AMBA APB Peripherals) */.word SECT + 0xc06 /* S=b0 TEX=b000 AP=b11, Domain=b0, C=b0, B=b1 */ .set SECT, SECT+0x100000 .endr.rept 0x0030 /* 0xf9000000 - 0xfbffffff (unassigned/reserved).* Generates a translation fault if accessed */ .word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, 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 .rept 0x001F /* 0xfe000000 - 0xffefffff (unassigned/reserved).* Generates a translation fault if accessed */ .word SECT + 0x0 /* S=b0 TEX=b000 AP=b00, Domain=b0, C=b0, B=b0 */ .set SECT, SECT+0x100000 .endr/* 0xfff00000 to 0xfffb0000 is reserved but due to granual size of1MB, it is not possible to define separate region for it0xfff00000 - 0xffffffff256K OCM when mapped to high address spaceinner-cacheable */ .word SECT + 0x4c0e /* S=b0 TEX=b100 AP=b11, Domain=b0, C=b1, B=b1 */ .set SECT, SECT+0x100000.end /** * @} End of "addtogroup a9_boot_code". */增加的代碼使用了QSPI內(nèi)部的存儲(chǔ)空間,用于執(zhí)行FSBL,這里將QSPI配置為線性模式,分為2段XIP,7MB和25MB。這與后面提到的產(chǎn)生BIN文件時(shí)使用XIP模塊相對(duì)應(yīng),同時(shí)0XFC000000這個(gè)地址將會(huì)用在fsbl的lscript.ld中。
xil_exception.c修改
如下圖
修改完fsbl_bsp后,下面開(kāi)始修改fsbl工程下的文件
Fsbl工程下需要修改的文件如下:
?
Main.c修改
Main.c中修改的地方較多,具體參考修改后的main.c代碼,下面只做簡(jiǎn)述:
增加preload_funct函數(shù)和copy函數(shù),作用如下
?
在main主函數(shù)中取消DDR初始化
在main主函數(shù)中對(duì)L1cache使能
/****************************************************************************** * * Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /*****************************************************************************/ /** * * @file main.c * * The main file for the First Stage Boot Loader (FSBL). * * <pre> * MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- ------------------------------------------------------- * 1.00a jz 06/04/11 Initial release * 2.00a mb 25/05/12 standalone based FSBL * 3.00a np/mb 08/03/12 Added call to FSBL user hook - before handoff. * DDR ECC initialization added * fsbl print with verbose added * Performance measurement added * Flushed the UART Tx buffer * Added the performance time for ECC DDR init * Added clearing of ECC Error Code * Added the watchdog timer value * 4.00a sgd 02/28/13 Code Cleanup * Fix for CR#681014 - ECC init in FSBL should not * call fabric_init() * Fix for CR#689077 - FSBL hangs at Handoff clearing the * TX UART buffer when using UART0 * instead of UART1 * Fix for CR#694038 - FSBL debug logs always prints 14.3 * as the Revision number - this is * incorrect * Fix for CR#694039 - FSBL prints "unsupported silicon * version for v3.0" 3.0 Silicon * Fix for CR#699475 - FSBL functionality is broken and * its not able to boot in QSPI/NAND * bootmode * Removed DDR initialization check * Removed DDR ECC initialization code * Modified hand off address check to 1MB * Added RSA authentication support * Watchdog disabled for AES E-Fuse encryption * 5.00a sgd 05/17/13 Fallback support for E-Fuse encryption * Fix for CR#708728 - Issues seen while making HP * interconnect 32 bit wide * 6.00a kc 07/30/13 Fix for CR#708316 - PS7_init.tcl file should have * Error mechanism for all mask_poll * Fix for CR#691150 - ps7_init does not check for * peripheral initialization failures * or timeout on polls * Fix for CR#724165 - Partition Header used by FSBL is * not authenticated * Fix for CR#724166 - FSBL doesn’t use PPK authenticated * by Boot ROM for authenticating * the Partition images * Fix for CR#722979 - Provide customer-friendly * changelogs in FSBL * Fix for CR#732865 - Backward compatibility for ps7_init * function * 7.00a kc 10/18/13 Integrated SD/MMC driver * 8.00a kc 02/20/14 Fix for CR#775631 - FSBL: FsblGetGlobalTimer() * is not proper * 9.00a kc 04/16/14 Fix for CR#724166 - SetPpk() will fail on secure * fallback unless FSBL* and FSBL * are identical in length * 10.00a kc 07/24/14 Fix for CR#809336 - Minor code cleanup * kc 08/27/14 Fix for CR#820356 - FSBL compilation fails with * IAR compiler * 11.00a kv 10/08/14 Fix for CR#826030 - LinearBootDeviceFlag should * be initialized to 0 in IO mode * case * 15.00a gan 07/21/16 Fix for CR# 953654 -(2016.3)FSBL - * In pcap.c/pcap.h/main.c, * Fabric Initialization sequence * is modified to check the PL power * before sequence starts and checking * INIT_B reset status twice in case * of failure. * </pre> * * @note * FSBL runs from OCM, Based on the boot mode selected, FSBL will copy * the partitions from the flash device. If the partition is bitstream then * the bitstream is programmed in the Fabric and for an partition that is * an application , FSBL will copy the application into DDR and does a * handoff.The application should not be starting at the OCM address, * FSBL does not remap the DDR. Application should use DDR starting from 1MB * * FSBL can be stitched along with bitstream and application using bootgen * * Refer to fsbl.h file for details on the compilation flags supported in FSBL * ******************************************************************************//***************************** Include Files *********************************/#include "fsbl.h" #include "qspi.h" #include "nand.h" #include "nor.h" #include "sd.h" #include "pcap.h" #include "image_mover.h" #include "xparameters.h" #include "xil_cache.h" #include "xil_cache_l.h" #include "xil_exception.h" #include "xstatus.h" #include "fsbl_hooks.h" #include "xtime_l.h" #include "xl2cc.h" #ifdef XPAR_XWDTPS_0_BASEADDR #include "xwdtps.h" #endif#ifdef STDOUT_BASEADDRESS #ifdef XPAR_XUARTPS_0_BASEADDR #include "xuartps_hw.h" #endif #endif#ifdef RSA_SUPPORT #include "rsa.h" #endif/************************** Constant Definitions *****************************/#ifdef XPAR_XWDTPS_0_BASEADDR #define WDT_DEVICE_ID XPAR_XWDTPS_0_DEVICE_ID #define WDT_EXPIRE_TIME 100 #define WDT_CRV_SHIFT 12 #endif/**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************/#ifdef XPAR_XWDTPS_0_BASEADDR XWdtPs Watchdog; /* Instance of WatchDog Timer */ #endif /************************** Function Prototypes ******************************/ extern int ps7_init(); extern char* getPS7MessageInfo(unsigned key); #ifdef PS7_POST_CONFIG extern int ps7_post_config(); #endifstatic void Update_MultiBootRegister(void); /* Exception handlers */ static void RegisterHandlers(void); static void Undef_Handler (void); static void SVC_Handler (void); static void PreFetch_Abort_Handler (void); static void Data_Abort_Handler (void); static void IRQ_Handler (void); static void FIQ_Handler (void);#ifdef XPAR_XWDTPS_0_BASEADDR int InitWatchDog(void); u32 ConvertTime_WdtCounter(u32 seconds); void CheckWDTReset(void); #endifu32 NextValidImageCheck(void);u32 DDRInitCheck(void);/************************** Variable Definitions *****************************/ /** Base Address for the Read Functionality for Image Processing*/ u32 FlashReadBaseAddress = 0; /** Silicon Version*/ u32 Silicon_Version;/** Boot Device flag*/ #ifdef QSPI_XIP u8 LinearBootDeviceFlag=1; #else u8 LinearBootDeviceFlag=0; #endifu32 PcapCtrlRegVal;u8 SystemInitFlag;extern ImageMoverType MoveImage; extern XDcfg *DcfgInstPtr; extern u8 BitstreamFlag; #ifdef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR extern u32 QspiFlashSize; #endif #ifdef DDRLESS_SYSTEM #define WAY_SIZE 65536 #define MAX_NUM_WAYS 8 int preload_funct(unsigned int uiSrcAddress, unsigned int uiSize);/* __attribute__ ((section ("ncmemory")));*/ /*****************************************************************************/ /** * * 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 interruptXil_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 registerasm volatile ("mov r0,%0":: "r"(uiSrcAddress));//Copy application size to r1 registerasm volatile ("mov r1,%0":: "r"(uiSize));// Offset register i.e. r2asm volatile ("mov r2, #0");// Labelasm ("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 cacheasm volatile ("ldr r4, [r0,r2]");// Increment the offset by one cache lineasm volatile ("add r2,r2,#4");// Compare the offset with the Application size.asm volatile ("cmp r1, r2");// If not equal jump to Labelasm volatile ("bge preload_inst");}// lock both Data and instruction caches from Way 1 to 7.// Lock Data and Instruction Caches for Way 0for(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 InterruptsXil_ExceptionEnableMask(XIL_EXCEPTION_ALL); // uiAlreadyProgrammed=uiVariable;return - XST_SUCCESS;} #endif /*****************************************************************************/ /** * * This is the main function for the FSBL ROM code. * * * @param None. * * @return * - XST_SUCCESS to indicate success * - XST_FAILURE.to indicate failure * * @note * ****************************************************************************/ 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) int main(void) {u32 BootModeRegister = 0;u32 HandoffAddress = 0;u32 Status = XST_SUCCESS;copy(&_dataLMA,&_dataVMA_start,&_dataVMA_end);copy(&_dataXVtableLMA,&_dataXVtableVMA_start,&_dataXVtableVMA_end);/** PCW initialization for MIO,PLL,CLK and DDR*/Status = ps7_init();if (Status != FSBL_PS7_INIT_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"PS7_INIT_FAIL : %s\r\n",getPS7MessageInfo(Status));OutputStatus(PS7_INIT_FAIL);/** Calling FsblHookFallback instead of Fallback* since, devcfg driver is not yet initialized*/FsblHookFallback();}/** Unlock SLCR for SLCR register write*/SlcrUnlock();/* If Performance measurement is required * then read the Global Timer value , Please note that the* time taken for mio, clock and ddr initialisation* done in the ps7_init function is not accounted in the FSBL**/ #ifdef FSBL_PERFXTime tCur = 0;FsblGetGlobalTime(&tCur); #endif/** Flush the Caches*/Xil_DCacheFlush();/** Disable Data Cache*/Xil_DCacheDisable();/** Register the Exception handlers*/RegisterHandlers();/** 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);#ifdef XPAR_PS7_DDR_0_S_AXI_BASEADDR#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/** PCAP initialization*/Status = InitPcap();if (Status == XST_FAILURE) {fsbl_printf(DEBUG_GENERAL,"PCAP_INIT_FAIL \n\r");OutputStatus(PCAP_INIT_FAIL);/** Calling FsblHookFallback instead of Fallback* since, devcfg driver is not yet initialized*/FsblHookFallback();}fsbl_printf(DEBUG_INFO,"Devcfg driver initialized \r\n");/** Get the Silicon Version*/GetSiliconVersion();#ifdef XPAR_XWDTPS_0_BASEADDR/** Check if WDT Reset has occurred or not*/CheckWDTReset();/** Initialize the Watchdog Timer so that it is ready to use*/Status = InitWatchDog();if (Status == XST_FAILURE) {fsbl_printf(DEBUG_GENERAL,"WATCHDOG_INIT_FAIL \n\r");OutputStatus(WDT_INIT_FAIL);FsblFallback();}fsbl_printf(DEBUG_INFO,"Watchdog driver initialized \r\n"); #endif/** Get PCAP controller settings*/PcapCtrlRegVal = XDcfg_GetControlRegister(DcfgInstPtr);/** Check for AES source key*/if (PcapCtrlRegVal & XDCFG_CTRL_PCFG_AES_FUSE_MASK) {/** For E-Fuse AES encryption Watch dog Timer disabled and* User not allowed to do system reset*/ #ifdef XPAR_XWDTPS_0_BASEADDRfsbl_printf(DEBUG_INFO,"Watchdog Timer Disabled\r\n");XWdtPs_Stop(&Watchdog); #endiffsbl_printf(DEBUG_INFO,"User not allowed to do ""any system resets\r\n");}/** Store FSBL run state in Reboot Status Register*/MarkFSBLIn();/** Read bootmode register*/BootModeRegister = Xil_In32(BOOT_MODE_REG);BootModeRegister &= BOOT_MODES_MASK;/** QSPI BOOT MODE*/ #ifdef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR#ifdef MMC_SUPPORT/** To support MMC boot* QSPI boot mode detection ignored*/if (BootModeRegister == QSPI_MODE) {BootModeRegister = MMC_MODE;} #endifif (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/** NAND BOOT MODE*/ #ifdef XPAR_PS7_NAND_0_BASEADDRif (BootModeRegister == NAND_FLASH_MODE) {/** Boot ROM always initialize the nand at lower speed* This is the chance to put it to an optimum speed for your nand* device*/fsbl_printf(DEBUG_GENERAL,"Boot mode is NAND\n");Status = InitNand();if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"NAND_INIT_FAIL \r\n");/** Error Handling here*/OutputStatus(NAND_INIT_FAIL);FsblFallback();}MoveImage = NandAccess;fsbl_printf(DEBUG_INFO,"NAND Init Done \r\n");} else #endif/** NOR BOOT MODE*/if (BootModeRegister == NOR_FLASH_MODE) {fsbl_printf(DEBUG_GENERAL,"Boot mode is NOR\n\r");/** Boot ROM always initialize the nor at lower speed* This is the chance to put it to an optimum speed for your nor* device*/InitNor();fsbl_printf(DEBUG_INFO,"NOR Init Done \r\n");MoveImage = NorAccess;} else/** SD BOOT MODE*/ #if defined(XPAR_PS7_SD_0_S_AXI_BASEADDR) || defined(XPAR_XSDPS_0_BASEADDR)if (BootModeRegister == SD_MODE) {fsbl_printf(DEBUG_GENERAL,"Boot mode is SD\r\n");/** SD initialization returns file open error or success*/Status = InitSD("BOOT.BIN");if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"SD_INIT_FAIL\r\n");OutputStatus(SD_INIT_FAIL);FsblFallback();}MoveImage = SDAccess;fsbl_printf(DEBUG_INFO,"SD Init Done \r\n");} elseif (BootModeRegister == MMC_MODE) {fsbl_printf(DEBUG_GENERAL,"Booting Device is MMC\r\n");/** MMC initialization returns file open error or success*/Status = InitSD("BOOT.BIN");if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"MMC_INIT_FAIL\r\n");OutputStatus(SD_INIT_FAIL);FsblFallback();}MoveImage = SDAccess;fsbl_printf(DEBUG_INFO,"MMC Init Done \r\n");} else#endif/** JTAG BOOT MODE*/if (BootModeRegister == JTAG_MODE) {fsbl_printf(DEBUG_GENERAL,"Boot mode is JTAG\r\n");/** Stop the Watchdog before JTAG handoff*/ #ifdef XPAR_XWDTPS_0_BASEADDRXWdtPs_Stop(&Watchdog); #endif/** Clear our mark in reboot status register*/ClearFSBLIn();/** SLCR lock*/SlcrLock();FsblHandoffJtagExit();} else {fsbl_printf(DEBUG_GENERAL,"ILLEGAL_BOOT_MODE \r\n");OutputStatus(ILLEGAL_BOOT_MODE);/** fallback starts, no return*/FsblFallback();}fsbl_printf(DEBUG_INFO,"Flash Base Address: 0x%08lx\r\n", FlashReadBaseAddress);/** Check for valid flash address*/if ((FlashReadBaseAddress != XPS_QSPI_LINEAR_BASEADDR) &&(FlashReadBaseAddress != XPS_NAND_BASEADDR) &&(FlashReadBaseAddress != XPS_NOR_BASEADDR) &&(FlashReadBaseAddress != XPS_SDIO0_BASEADDR)) {fsbl_printf(DEBUG_GENERAL,"INVALID_FLASH_ADDRESS \r\n");OutputStatus(INVALID_FLASH_ADDRESS);FsblFallback();}/** NOR and QSPI (parallel) are linear boot devices*/if ((FlashReadBaseAddress == XPS_NOR_BASEADDR)) {fsbl_printf(DEBUG_INFO, "Linear Boot Device\r\n");LinearBootDeviceFlag = 1;}#ifdef XPAR_XWDTPS_0_BASEADDR/** Prevent WDT reset*/XWdtPs_RestartWdt(&Watchdog); #endif/** This used only in case of E-Fuse encryption* For image search*/SystemInitFlag = 1;/** Load boot image*/HandoffAddress = LoadBootImage();Xil_L1DCacheEnable();Xil_L1ICacheEnable();Xil_L1DCacheInvalidate();Xil_L1ICacheInvalidate();fsbl_printf(DEBUG_INFO,"Handoff Address original : 0x%08lx\r\n",HandoffAddress); // HandoffAddress = 0x10000;//fsbl_printf(DEBUG_INFO,"Handoff Address modified : 0x%08lx\r\n",HandoffAddress);/** For Performance measurement*/ #ifdef FSBL_PERFXTime tEnd = 0;fsbl_printf(DEBUG_GENERAL,"Total Execution time is ");FsblMeasurePerfTime(tCur,tEnd); #endif/** FSBL handoff to valid handoff address or* exit in JTAG*///for debug // int x = 1; // while (x==1);FsblHandoff(HandoffAddress);#elsefsbl_printf(DEBUG_GENERAL,"-> FsblFallback\n\r"); // OutputStatus(NO_DDR);FsblFallback(); #endifreturn Status; }/******************************************************************************/ /** * * This function reset the CPU and goes for Boot ROM fallback handling * * @param None * * @return None * * @note None * ****************************************************************************/ void FsblFallback(void) {u32 RebootStatusReg;u32 Status;u32 HandoffAddr;u32 BootModeRegister;/** Read bootmode register*/BootModeRegister = Xil_In32(BOOT_MODE_REG);BootModeRegister &= BOOT_MODES_MASK;/** Fallback support check*/if (!((BootModeRegister == QSPI_MODE) ||(BootModeRegister == NAND_FLASH_MODE) ||(BootModeRegister == NOR_FLASH_MODE))) {fsbl_printf(DEBUG_INFO,"\r\n""This Boot Mode Doesn't Support Fallback\r\n");ClearFSBLIn();FsblHookFallback();}/** update the Multiboot Register for Golden search hunt*/Update_MultiBootRegister();/** Notify Boot ROM something is wrong*/RebootStatusReg = Xil_In32(REBOOT_STATUS_REG);/** Set the FSBL Fail mask*/Xil_Out32(REBOOT_STATUS_REG, RebootStatusReg | FSBL_FAIL_MASK);/** Barrier for synchronization*/__asm("dsb\n\t""isb");/** Check for AES source key*/if (PcapCtrlRegVal & XDCFG_CTRL_PCFG_AES_FUSE_MASK) {/** Next valid image search can happen only* when system initialization done*/if (SystemInitFlag == 1) {/** Clean the Fabric*/FabricInit();#ifdef RSA_SUPPORT/** Making sure PPK is set for efuse error cases*/SetPpk(); #endif/** Search for next valid image*/Status = NextValidImageCheck();if(Status != XST_SUCCESS){fsbl_printf(DEBUG_INFO,"\r\nNo Image Found\r\n");ClearFSBLIn();FsblHookFallback();}/** Load next valid image*/HandoffAddr = LoadBootImage();/** Handoff to next image*/FsblHandoff(HandoffAddr);} else {fsbl_printf(DEBUG_INFO,"System Initialization Failed\r\n");fsbl_printf(DEBUG_INFO,"\r\nNo Image Search\r\n");ClearFSBLIn();FsblHookFallback();}}/** Reset PS, so Boot ROM will restart*/Xil_Out32(PS_RST_CTRL_REG, PS_RST_MASK); }/******************************************************************************/ /** * * This function hands the A9/PS to the loaded user code. * * @param none * * @return none * * @note This function does not return. * ****************************************************************************/ void FsblHandoff(u32 FsblStartAddr) {u32 Status;/** Enable level shifter*/if(BitstreamFlag) {/** FSBL will not enable the level shifters for a NON PS instantiated* Bitstream* CR# 671028* This flag can be set during compilation for a NON PS instantiated* bitstream*/ #ifndef NON_PS_INSTANTIATED_BITSTREAM #ifdef PS7_POST_CONFIGps7_post_config();/** Unlock SLCR for SLCR register write*/SlcrUnlock(); #else/** Set Level Shifters DT618760*/Xil_Out32(PS_LVL_SHFTR_EN, LVL_PL_PS);fsbl_printf(DEBUG_INFO,"Enabling Level Shifters PL to PS ""Address = 0x%x Value = 0x%x \n\r",PS_LVL_SHFTR_EN, Xil_In32(PS_LVL_SHFTR_EN));/** Enable AXI interface*/Xil_Out32(FPGA_RESET_REG, 0);fsbl_printf(DEBUG_INFO,"AXI Interface enabled \n\r");fsbl_printf(DEBUG_INFO, "FPGA Reset Register ""Address = 0x%x , Value = 0x%x \r\n",FPGA_RESET_REG ,Xil_In32(FPGA_RESET_REG)); #endif #endif}/** FSBL user hook call before handoff to the application*/Status = FsblHookBeforeHandoff(FsblStartAddr);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"FSBL_HANDOFF_HOOK_FAIL\r\n");OutputStatus(FSBL_HANDOFF_HOOK_FAIL);FsblFallback();}#ifdef XPAR_XWDTPS_0_BASEADDRXWdtPs_Stop(&Watchdog); #endif/** Clear our mark in reboot status register*/ClearFSBLIn();if(FsblStartAddr == 0) {/** SLCR lock*/SlcrLock();fsbl_printf(DEBUG_INFO,"No Execution Address JTAG handoff \r\n");FsblHandoffJtagExit();} else {fsbl_printf(DEBUG_GENERAL,"SUCCESSFUL_HANDOFF\r\n");OutputStatus(SUCCESSFUL_HANDOFF);FsblHandoffExit(FsblStartAddr);}OutputStatus(ILLEGAL_RETURN);FsblFallback(); }/******************************************************************************/ /** * * This function outputs the status for the provided State in the boot process. * * @param State is where in the boot process the output is desired. * * @return None. * * @note None. * ****************************************************************************/ void OutputStatus(u32 State) { #ifdef STDOUT_BASEADDRESS #ifdef XPAR_XUARTPS_0_BASEADDRu32 UartReg = 0; #endiffsbl_printf(DEBUG_GENERAL,"FSBL Status = 0x%.4lx\r\n", State);/** The TX buffer needs to be flushed out* If this is not done some of the prints will not appear on the* serial output*/ #ifdef XPAR_XUARTPS_0_BASEADDRUartReg = Xil_In32(STDOUT_BASEADDRESS + XUARTPS_SR_OFFSET);while ((UartReg & XUARTPS_SR_TXEMPTY) != XUARTPS_SR_TXEMPTY) {UartReg = Xil_In32(STDOUT_BASEADDRESS + XUARTPS_SR_OFFSET);} #endif #endif }/******************************************************************************/ /** * * This function handles the error and lockdown processing and outputs the status * for the provided State in the boot process. * * This function is called upon exceptions. * * @param State - where in the boot process the error occured. * * @return None. * * @note This function does not return, the PS block is reset * ****************************************************************************/ void ErrorLockdown(u32 State) {/** Store the error status*/OutputStatus(State);/** Fall back*/FsblFallback(); }/******************************************************************************/ /** * * This function copies a memory region to another memory region * * @param s1 is starting address for destination * @param s2 is starting address for the source * @param n is the number of bytes to copy * * @return Starting address for destination * ****************************************************************************/ void *(memcpy_rom)(void * s1, const void * s2, u32 n) {char *dst = (char *)s1;const char *src = (char *)s2;/** Loop and copy*/while (n-- != 0)*dst++ = *src++;return s1; } /******************************************************************************/ /** * * This function copies a string to another, the source string must be null- * terminated. * * @param Dest is starting address for the destination string * @param Src is starting address for the source string * * @return Starting address for the destination string * ****************************************************************************/ char *strcpy_rom(char *Dest, const char *Src) {unsigned i;for (i=0; Src[i] != '\0'; ++i)Dest[i] = Src[i];Dest[i] = '\0';return Dest; }/******************************************************************************/ /** * * This function sets FSBL is running mask in reboot status register * * @param None. * * @return None. * * @note None. * ****************************************************************************/ void MarkFSBLIn(void) {Xil_Out32(REBOOT_STATUS_REG,Xil_In32(REBOOT_STATUS_REG) | FSBL_IN_MASK); }/******************************************************************************/ /** * * This function clears FSBL is running mask in reboot status register * * @param None. * * @return None. * * @note None. * ****************************************************************************/ void ClearFSBLIn(void) {Xil_Out32(REBOOT_STATUS_REG,(Xil_In32(REBOOT_STATUS_REG)) & ~(FSBL_FAIL_MASK)); }/******************************************************************************/ /** * * This function Registers the Exception Handlers * * @param None. * * @return None. * * @note None. * ****************************************************************************/ static void RegisterHandlers(void) {Xil_ExceptionInit();/** Initialize the vector table. Register the stub Handler for each* exception.*/Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_UNDEFINED_INT,(Xil_ExceptionHandler)Undef_Handler,(void *) 0);Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_SWI_INT,(Xil_ExceptionHandler)SVC_Handler,(void *) 0);Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_PREFETCH_ABORT_INT,(Xil_ExceptionHandler)PreFetch_Abort_Handler,(void *) 0);Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_DATA_ABORT_INT,(Xil_ExceptionHandler)Data_Abort_Handler,(void *) 0);Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,(Xil_ExceptionHandler)IRQ_Handler,(void *) 0);Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_FIQ_INT,(Xil_ExceptionHandler)FIQ_Handler,(void *) 0);Xil_ExceptionEnable();}static void Undef_Handler (void) {fsbl_printf(DEBUG_GENERAL,"UNDEFINED_HANDLER\r\n");ErrorLockdown (EXCEPTION_ID_UNDEFINED_INT); }static void SVC_Handler (void) {fsbl_printf(DEBUG_GENERAL,"SVC_HANDLER \r\n");ErrorLockdown (EXCEPTION_ID_SWI_INT); }static void PreFetch_Abort_Handler (void) {fsbl_printf(DEBUG_GENERAL,"PREFETCH_ABORT_HANDLER \r\n");ErrorLockdown (EXCEPTION_ID_PREFETCH_ABORT_INT); }static void Data_Abort_Handler (void) {fsbl_printf(DEBUG_GENERAL,"DATA_ABORT_HANDLER \r\n");ErrorLockdown (EXCEPTION_ID_DATA_ABORT_INT); }static void IRQ_Handler (void) {fsbl_printf(DEBUG_GENERAL,"IRQ_HANDLER \r\n");ErrorLockdown (EXCEPTION_ID_IRQ_INT); }static void FIQ_Handler (void) {fsbl_printf(DEBUG_GENERAL,"FIQ_HANDLER \r\n");ErrorLockdown (EXCEPTION_ID_FIQ_INT); }/******************************************************************************/ /** * * This function Updates the Multi boot Register to enable golden image * search for boot rom * * @param None * * @return * return none * ****************************************************************************/ static void Update_MultiBootRegister(void) {u32 MultiBootReg = 0;if (Silicon_Version != SILICON_VERSION_1) {/** Read the mulitboot register*/MultiBootReg = XDcfg_ReadReg(DcfgInstPtr->Config.BaseAddr,XDCFG_MULTIBOOT_ADDR_OFFSET);/** Incrementing multiboot register by one*/MultiBootReg++;XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr,XDCFG_MULTIBOOT_ADDR_OFFSET,MultiBootReg);fsbl_printf(DEBUG_INFO,"Updated MultiBootReg = 0x%08lx\r\n",MultiBootReg);} }/****************************************************************************** * * This function reset the CPU and goes for Boot ROM fallback handling * * @param None * * @return None * * @note None * *******************************************************************************/u32 GetResetReason(void) {u32 Regval;/* We are using REBOOT_STATUS_REG, we have to use bits 23:16 *//* for storing the RESET_REASON register value*/Regval = ((Xil_In32(REBOOT_STATUS_REG) >> 16) & 0xFF);return Regval; }/****************************************************************************** * * This function Gets the ticks from the Global Timer * * @param Current time * * @return * None * * @note None * *******************************************************************************/ #ifdef FSBL_PERF void FsblGetGlobalTime (XTime *tCur) {XTime_GetTime(tCur); }/****************************************************************************** * * This function Measures the execution time * * @param Current time , End time * * @return * None * * @note None * *******************************************************************************/ void FsblMeasurePerfTime (XTime tCur, XTime tEnd) {double tDiff = 0.0;double tPerfSeconds;XTime_GetTime(&tEnd);tDiff = (double)tEnd - (double)tCur;/** Convert tPerf into Seconds*/tPerfSeconds = tDiff/COUNTS_PER_SECOND;#if defined(STDOUT_BASEADDRESS)printf("%f seconds \r\n",tPerfSeconds); #endif} #endif/****************************************************************************** * * This function initializes the Watchdog driver and starts the timer * * @param None * * @return * - XST_SUCCESS if the Watchdog driver is initialized * - XST_FAILURE if Watchdog driver initialization fails * * @note None * *******************************************************************************/ #ifdef XPAR_XWDTPS_0_BASEADDR int InitWatchDog(void) {u32 Status = XST_SUCCESS;XWdtPs_Config *ConfigPtr; /* Config structure of the WatchDog Timer */u32 CounterValue = 1;ConfigPtr = XWdtPs_LookupConfig(WDT_DEVICE_ID);Status = XWdtPs_CfgInitialize(&Watchdog,ConfigPtr,ConfigPtr->BaseAddress);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_INFO,"Watchdog Driver init Failed \n\r");return XST_FAILURE;}/** Setting the divider value*/XWdtPs_SetControlValue(&Watchdog,XWDTPS_CLK_PRESCALE,XWDTPS_CCR_PSCALE_4096);/** Convert time to Watchdog counter reset value*/CounterValue = ConvertTime_WdtCounter(WDT_EXPIRE_TIME);/** Set the Watchdog counter reset value*/XWdtPs_SetControlValue(&Watchdog,XWDTPS_COUNTER_RESET,CounterValue);/** enable reset output, as we are only using this as a basic counter*/XWdtPs_EnableOutput(&Watchdog, XWDTPS_RESET_SIGNAL);/** Start the Watchdog timer*/XWdtPs_Start(&Watchdog);XWdtPs_RestartWdt(&Watchdog);return XST_SUCCESS; }/******************************************************************************/ /** * * This function checks whether WDT reset has happened during FSBL run * * If WDT reset happened during FSBL run, then need to fallback * * @param None. * * @return * None * * @note None * ****************************************************************************/ void CheckWDTReset(void) {u32 ResetReason;u32 RebootStatusRegister;RebootStatusRegister = Xil_In32(REBOOT_STATUS_REG);/** For 1.0 Silicon the reason for Reset is in the ResetReason Register* Hence this register can be read to know the cause for previous reset* that happened.* Check if that reset is a Software WatchDog reset that happened*/if (Silicon_Version == SILICON_VERSION_1) {ResetReason = Xil_In32(RESET_REASON_REG);} else {ResetReason = GetResetReason();}/** If the FSBL_IN_MASK Has not been cleared, WDT happened* before FSBL exits*/if ((ResetReason & RESET_REASON_SWDT) == RESET_REASON_SWDT ) {if ((RebootStatusRegister & FSBL_FAIL_MASK) == FSBL_IN_MASK) {/** Clear the SWDT Reset bit*/ResetReason &= ~RESET_REASON_SWDT;if (Silicon_Version == SILICON_VERSION_1) {/** for 1.0 Silicon we need to write* 1 to the RESET REASON Clear register */Xil_Out32(RESET_REASON_CLR, 1);} else {Xil_Out32(REBOOT_STATUS_REG, ResetReason);}fsbl_printf(DEBUG_GENERAL,"WDT_RESET_OCCURED \n\r");}} }/****************************************************************************** * * This function converts time into Watchdog counter value * * @param watchdog expire time in seconds * * @return * Counter value for Watchdog * * @note None * *******************************************************************************/ u32 ConvertTime_WdtCounter(u32 seconds) {double time = 0.0;double CounterValue;u32 Crv = 0;u32 Prescaler,PrescalerValue;Prescaler = XWdtPs_GetControlValue(&Watchdog, XWDTPS_CLK_PRESCALE);if (Prescaler == XWDTPS_CCR_PSCALE_0008)PrescalerValue = 8;if (Prescaler == XWDTPS_CCR_PSCALE_0064)PrescalerValue = 64;if (Prescaler == XWDTPS_CCR_PSCALE_4096)PrescalerValue = 4096;time = (double)(PrescalerValue) / (double)XPAR_PS7_WDT_0_WDT_CLK_FREQ_HZ;CounterValue = seconds / time;Crv = (u32)CounterValue;Crv >>= WDT_CRV_SHIFT;return Crv; }#endif/****************************************************************************** * * This function Gets the Silicon Version stores in global variable * * @param None * * @return None * * @note None * *******************************************************************************/ void GetSiliconVersion(void) {/** Get the silicon version*/Silicon_Version = XDcfg_GetPsVersion(DcfgInstPtr);if(Silicon_Version == SILICON_VERSION_3_1) {fsbl_printf(DEBUG_GENERAL,"Silicon Version 3.1\r\n");} else {fsbl_printf(DEBUG_GENERAL,"Silicon Version %lu.0\r\n",Silicon_Version + 1);} }/****************************************************************************** * * This function HeaderChecksum will calculates the header checksum and * compares with checksum read from flash * * @param FlashOffsetAddress Flash offset address * * @return * - XST_SUCCESS if ID matches * - XST_FAILURE if ID mismatches * * @note None * *******************************************************************************/ u32 HeaderChecksum(u32 FlashOffsetAddress){u32 Checksum = 0;u32 Count;u32 TempValue = 0;for (Count = 0; Count < IMAGE_HEADER_CHECKSUM_COUNT; Count++) {/** Read the word from the header*/MoveImage(FlashOffsetAddress + IMAGE_WIDTH_CHECK_OFFSET + (Count*4), (u32)&TempValue, 4);/** Update checksum*/Checksum += TempValue;}/** Invert checksum, last bit of error checking*/Checksum ^= 0xFFFFFFFF;MoveImage(FlashOffsetAddress + IMAGE_CHECKSUM_OFFSET, (u32)&TempValue, 4);/** Validate the checksum*/if (TempValue != Checksum){fsbl_printf(DEBUG_INFO, "Checksum = %8.8lx\r\n", Checksum);return XST_FAILURE;}return XST_SUCCESS; }/****************************************************************************** * * This function ImageCheckID will do check for XLNX pattern * * @param FlashOffsetAddress Flash offset address * * @return * - XST_SUCCESS if ID matches * - XST_FAILURE if ID mismatches * * @note None * *******************************************************************************/ u32 ImageCheckID(u32 FlashOffsetAddress){u32 ID;/** Read in the header info*/MoveImage(FlashOffsetAddress + IMAGE_IDENT_OFFSET, (u32)&ID, 4);/** Check the ID, make sure image is XLNX format*/if (ID != IMAGE_IDENT){return XST_FAILURE;}return XST_SUCCESS; }/****************************************************************************** * * This function NextValidImageCheck search for valid boot image * * @param None * * @return * - XST_SUCCESS if valid image found * - XST_FAILURE if no image found * * @note None * *******************************************************************************/ u32 NextValidImageCheck(void) {u32 ImageBaseAddr;u32 MultiBootReg;u32 BootDevMaxSize=0;fsbl_printf(DEBUG_GENERAL, "Searching For Next Valid Image");/** Setting variable with maximum flash size based on boot mode*/ #ifdef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDRif (FlashReadBaseAddress == XPS_QSPI_LINEAR_BASEADDR) {BootDevMaxSize = QspiFlashSize;} #endifif (FlashReadBaseAddress == XPS_NAND_BASEADDR) {BootDevMaxSize = NAND_FLASH_SIZE;}if (FlashReadBaseAddress == XPS_NOR_BASEADDR) {BootDevMaxSize = NOR_FLASH_SIZE;}/** Read the multiboot register*/MultiBootReg = XDcfg_ReadReg(DcfgInstPtr->Config.BaseAddr,XDCFG_MULTIBOOT_ADDR_OFFSET);/** Compute the image start address*/ImageBaseAddr = (MultiBootReg & PCAP_MBOOT_REG_REBOOT_OFFSET_MASK)* GOLDEN_IMAGE_OFFSET;/** Valid image search continue till end of the flash* With increment 32KB in each iteration*/while (ImageBaseAddr < BootDevMaxSize) {fsbl_printf(DEBUG_INFO,".");/** Valid image search using XLNX pattern at fixed offset* and header checksum*/if ((ImageCheckID(ImageBaseAddr) == XST_SUCCESS) &&(HeaderChecksum(ImageBaseAddr) == XST_SUCCESS)) {fsbl_printf(DEBUG_GENERAL, "\r\nImage found, offset: 0x%.8lx\r\n",ImageBaseAddr);/** Update multiboot register*/XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr,XDCFG_MULTIBOOT_ADDR_OFFSET,MultiBootReg);return XST_SUCCESS;}/** Increment mulitboot count*/MultiBootReg++;/** Compute the image start address*/ImageBaseAddr = (MultiBootReg & PCAP_MBOOT_REG_REBOOT_OFFSET_MASK)* GOLDEN_IMAGE_OFFSET;}return XST_FAILURE; }/******************************************************************************/ /** * * This function Checks for the ddr initialization completion * * @param None. * * @return * - XST_SUCCESS if the initialization is successful * - XST_FAILURE if the initialization is NOT successful * * @note None. * ****************************************************************************/ u32 DDRInitCheck(void) {u32 ReadVal;/** Write and Read from the DDR location for sanity checks*/Xil_Out32(DDR_START_ADDR, DDR_TEST_PATTERN);ReadVal = Xil_In32(DDR_START_ADDR);if (ReadVal != DDR_TEST_PATTERN) {return XST_FAILURE;}/** Write and Read from the DDR location for sanity checks*/Xil_Out32(DDR_START_ADDR + DDR_TEST_OFFSET, DDR_TEST_PATTERN);ReadVal = Xil_In32(DDR_START_ADDR + DDR_TEST_OFFSET);if (ReadVal != DDR_TEST_PATTERN) {return XST_FAILURE;}return XST_SUCCESS; }Image_mover.c修改
具體參看代碼部分,這里只做簡(jiǎn)述:
Loadbootimage函數(shù)中對(duì)L2cache禁用
/****************************************************************************** * * Copyright (C) 2011 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /*****************************************************************************/ /** * * @file image_mover.c * * Move partitions to either DDR to execute or to program FPGA. * It performs partition walk. * * <pre> * MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- ------------------------------------------------------- * 1.00a jz 05/24/11 Initial release * 2.00a jz 06/30/11 Updated partition header defs for 64-byte * alignment change in data2mem tool * 2.00a mb 05/25/12 Updated for standalone based bsp FSBL * Nand/SD encryption and review comments * 3.00a np 08/30/12 Added FSBL user hook calls * (before and after bitstream download.) * 4.00a sgd 02/28/13 Fix for CR#691148 Secure bootmode error in devcfg test * Fix for CR#695578 FSBL failed to load standalone * application in secure bootmode * * 4.00a sgd 04/23/13 Fix for CR#710128 FSBL failed to load standalone * application in secure bootmode * 5.00a kc 07/30/13 Fix for CR#724165 Partition Header used by FSBL * is not authenticated * Fix for CR#724166 FSBL doesn�t use PPK authenticated * by Boot ROM for authenticating the Partition images * Fix for CR#732062 FSBL fails to build if UART not * available * 7.00a kc 10/30/13 Fix for CR#755245 FSBL does not load partition * if eMMC has only one partition * 8.00a kc 01/16/13 Fix for CR#767798 FSBL MD5 Checksum failure * for encrypted images * Fix for CR#761895 FSBL should authenticate image * only if partition owner was not set to u-boot * 9.00a kc 04/16/14 Fix for CR#785778 FSBL takes 8 seconds to * authenticate (RSA) a bitstream on zc706 * 10.00a kc 07/15/14 Fix for CR#804595 Zynq FSBL - Issues with * fallback image offset handling using MD5 * Fix for PR#782309 Fallback support for AES * encryption with E-Fuse - Enhancement * * </pre> * * @note * A partition is either an executable or a bitstream to program FPGA * ******************************************************************************//***************************** Include Files *********************************/ #include "fsbl.h" #include "image_mover.h" #include "xil_printf.h" #include "xreg_cortexa9.h" #include "pcap.h" #include "fsbl_hooks.h" #include "md5.h" #include "xil_cache.h" #include "xil_cache_l.h"#ifdef XPAR_XWDTPS_0_BASEADDR #include "xwdtps.h" #endif#ifdef RSA_SUPPORT #include "rsa.h" #include "xil_cache.h" #endif /************************** Constant Definitions *****************************//* We are 32-bit machine */ #define MAXIMUM_IMAGE_WORD_LEN 0x40000000 #define MD5_CHECKSUM_SIZE 16/**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************//************************** Function Prototypes ******************************/ u32 ValidateParition(u32 StartAddr, u32 Length, u32 ChecksumOffset); u32 GetPartitionChecksum(u32 ChecksumOffset, u8 *Checksum); u32 CalcPartitionChecksum(u32 SourceAddr, u32 DataLength, u8 *Checksum);/************************** Variable Definitions *****************************/ /** Partition information flags*/ u8 EncryptedPartitionFlag; u8 PLPartitionFlag; u8 PSPartitionFlag; u8 SignedPartitionFlag; u8 PartitionChecksumFlag; u8 BitstreamFlag; u8 ApplicationFlag;u32 ExecutionAddress; ImageMoverType MoveImage;/** Header array*/ PartHeader PartitionHeader[MAX_PARTITION_NUMBER]; u32 PartitionCount; u32 FsblLength;#ifdef XPAR_XWDTPS_0_BASEADDR extern XWdtPs Watchdog; /* Instance of WatchDog Timer */ #endifextern u32 Silicon_Version; extern u32 FlashReadBaseAddress; extern u8 LinearBootDeviceFlag; extern XDcfg *DcfgInstPtr;/*****************************************************************************/ /** * * This function * * @param * * @return * * * @note None * ****************************************************************************/ u32 LoadBootImage(void) {u32 RebootStatusRegister = 0;u32 MultiBootReg = 0;u32 ImageStartAddress = 0;u32 PartitionNum;u32 PartitionDataLength;u32 PartitionImageLength;u32 PartitionTotalSize;u32 PartitionExecAddr;u32 PartitionAttr;u32 ExecAddress = 0;u32 PartitionLoadAddr;u32 PartitionStartAddr;u32 PartitionChecksumOffset;u8 ExecAddrFlag = 0 ;u32 Status;PartHeader *HeaderPtr;u32 EfuseStatusRegValue; #ifdef RSA_SUPPORTu32 HeaderSize; #endif/** Resetting the Flags*/BitstreamFlag = 0;ApplicationFlag = 0;RebootStatusRegister = Xil_In32(REBOOT_STATUS_REG);fsbl_printf(DEBUG_INFO,"Reboot status register: 0x%08lx\r\n",RebootStatusRegister);if (Silicon_Version == SILICON_VERSION_1) {/** Clear out fallback mask from previous run* We start from the first partition again*/if ((RebootStatusRegister & FSBL_FAIL_MASK) ==FSBL_FAIL_MASK) {fsbl_printf(DEBUG_INFO,"Reboot status shows previous run falls back\r\n");RebootStatusRegister &= ~(FSBL_FAIL_MASK);Xil_Out32(REBOOT_STATUS_REG, RebootStatusRegister);}/** Read the image start address*/ImageStartAddress = *(u32 *)BASEADDR_HOLDER;} else {/** read the multiboot register*/MultiBootReg = XDcfg_ReadReg(DcfgInstPtr->Config.BaseAddr,XDCFG_MULTIBOOT_ADDR_OFFSET);fsbl_printf(DEBUG_INFO,"Multiboot Register: 0x%08lx\r\n",MultiBootReg);/** Compute the image start address*/ImageStartAddress = (MultiBootReg & PCAP_MBOOT_REG_REBOOT_OFFSET_MASK)* GOLDEN_IMAGE_OFFSET;}fsbl_printf(DEBUG_INFO,"Image Start Address: 0x%08lx\r\n",ImageStartAddress);/** Get partitions header information*/Status = GetPartitionHeaderInfo(ImageStartAddress);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL, "Partition Header Load Failed\r\n");OutputStatus(GET_HEADER_INFO_FAIL);FsblFallback();}/** RSA is not implemented in 1.0 and 2.0* silicon*/if ((Silicon_Version != SILICON_VERSION_1) &&(Silicon_Version != SILICON_VERSION_2)) {/** Read Efuse Status Register*/EfuseStatusRegValue = Xil_In32(EFUSE_STATUS_REG);if (EfuseStatusRegValue & EFUSE_STATUS_RSA_ENABLE_MASK) {fsbl_printf(DEBUG_GENERAL,"RSA enabled for Chip\r\n"); #ifdef RSA_SUPPORT/** Set the Ppk*/SetPpk();/** Read partition header with signature*/Status = GetImageHeaderAndSignature(ImageStartAddress,(u32 *)DDR_TEMP_START_ADDR);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"Read Partition Header signature Failed\r\n");OutputStatus(GET_HEADER_INFO_FAIL);FsblFallback();}HeaderSize=TOTAL_HEADER_SIZE+RSA_SIGNATURE_SIZE;Status = AuthenticatePartition((u8 *)DDR_TEMP_START_ADDR, HeaderSize);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"Partition Header signature Failed\r\n");OutputStatus(GET_HEADER_INFO_FAIL);FsblFallback();} #else/** In case user not enabled RSA authentication feature*/fsbl_printf(DEBUG_GENERAL,"RSA_SUPPORT_NOT_ENABLED_FAIL\r\n");OutputStatus(RSA_SUPPORT_NOT_ENABLED_FAIL);FsblFallback(); #endif}}#ifdef MMC_SUPPORT/** In case of MMC support* boot image preset in MMC will not have FSBL partition*/PartitionNum = 0; #else/** First partition header was ignored by FSBL* As it contain FSBL partition information*/PartitionNum = 1; #endifwhile (PartitionNum < PartitionCount) {fsbl_printf(DEBUG_INFO, "Partition Number: %lu\r\n", PartitionNum);HeaderPtr = &PartitionHeader[PartitionNum];/** Print partition header information*/HeaderDump(HeaderPtr);/** Validate partition header*/Status = ValidateHeader(HeaderPtr);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL, "INVALID_HEADER_FAIL\r\n");OutputStatus(INVALID_HEADER_FAIL);FsblFallback();}/** Load partition header information in to local variables*/PartitionDataLength = HeaderPtr->DataWordLen;PartitionImageLength = HeaderPtr->ImageWordLen;PartitionExecAddr = HeaderPtr->ExecAddr;PartitionAttr = HeaderPtr->PartitionAttr;PartitionLoadAddr = HeaderPtr->LoadAddr;PartitionChecksumOffset = HeaderPtr->CheckSumOffset;PartitionStartAddr = HeaderPtr->PartitionStart;PartitionTotalSize = HeaderPtr->PartitionWordLen;#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;} #endifif (PartitionAttr & ATTRIBUTE_PL_IMAGE_MASK) {fsbl_printf(DEBUG_INFO, "Bitstream\r\n");PLPartitionFlag = 1;PSPartitionFlag = 0;BitstreamFlag = 1;if (ApplicationFlag == 1) { #ifdef STDOUT_BASEADDRESSxil_printf("\r\nFSBL Warning !!!""Bitstream not loaded into PL\r\n");xil_printf("Partition order invalid\r\n"); #endifbreak;}}if (PartitionAttr & ATTRIBUTE_PS_IMAGE_MASK) {fsbl_printf(DEBUG_INFO, "Application\r\n");PSPartitionFlag = 1;PLPartitionFlag = 0;ApplicationFlag = 1;}/** Encrypted partition will have different value* for Image length and data length*/if (PartitionDataLength != PartitionImageLength) {fsbl_printf(DEBUG_INFO, "Encrypted\r\n");EncryptedPartitionFlag = 1;} else {EncryptedPartitionFlag = 0;}/** Check for partition checksum check*/if (PartitionAttr & ATTRIBUTE_CHECKSUM_TYPE_MASK) {PartitionChecksumFlag = 1;} else {PartitionChecksumFlag = 0;}/** RSA signature check*/if (PartitionAttr & ATTRIBUTE_RSA_PRESENT_MASK) {fsbl_printf(DEBUG_INFO, "RSA Signed\r\n");SignedPartitionFlag = 1;} else {SignedPartitionFlag = 0;}/** Load address check* Loop will break when PS load address zero and partition is* un-signed or un-encrypted*/ #ifndef DDRLESS_SYSTEMif ((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/** Load execution address of first PS partition*/if (PSPartitionFlag && (!ExecAddrFlag)) {ExecAddrFlag++;ExecAddress = PartitionExecAddr;}/** FSBL user hook call before bitstream download*/if (PLPartitionFlag) {Status = FsblHookBeforeBitstreamDload();if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"FSBL_BEFORE_BSTREAM_HOOK_FAIL\r\n");OutputStatus(FSBL_BEFORE_BSTREAM_HOOK_FAIL);FsblFallback();}}/** Move partitions from boot device*/ #ifdef DDRLESS_SYSTEMXil_L2CacheEnable();Xil_L1DCacheDisable();Xil_L1ICacheDisable(); #endifStatus = 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");}if ((SignedPartitionFlag) || (PartitionChecksumFlag)) {if(PLPartitionFlag) {/** PL partition loaded in to DDR temporary address* for authentication and checksum verification*/PartitionStartAddr = DDR_TEMP_START_ADDR;} else {PartitionStartAddr = PartitionLoadAddr;}if (PartitionChecksumFlag) {/** Validate the partition data with checksum*/Status = ValidateParition(PartitionStartAddr,(PartitionTotalSize << WORD_LENGTH_SHIFT),ImageStartAddress +(PartitionChecksumOffset << WORD_LENGTH_SHIFT));if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"PARTITION_CHECKSUM_FAIL\r\n");OutputStatus(PARTITION_CHECKSUM_FAIL);FsblFallback();}fsbl_printf(DEBUG_INFO, "Partition Validation Done\r\n");}/** Authentication Partition*/if (SignedPartitionFlag == 1 ) { #ifdef RSA_SUPPORTXil_DCacheEnable();Status = AuthenticatePartition((u8*)PartitionStartAddr,(PartitionTotalSize << WORD_LENGTH_SHIFT));if (Status != XST_SUCCESS) {Xil_DCacheFlush();Xil_DCacheDisable();fsbl_printf(DEBUG_GENERAL,"AUTHENTICATION_FAIL\r\n");OutputStatus(AUTHENTICATION_FAIL);FsblFallback();}fsbl_printf(DEBUG_INFO,"Authentication Done\r\n");Xil_DCacheFlush();Xil_DCacheDisable(); #else/** In case user not enabled RSA authentication feature*/fsbl_printf(DEBUG_GENERAL,"RSA_SUPPORT_NOT_ENABLED_FAIL\r\n");OutputStatus(RSA_SUPPORT_NOT_ENABLED_FAIL);FsblFallback(); #endif}/** Decrypt PS partition*/if (EncryptedPartitionFlag && PSPartitionFlag) {Status = DecryptPartition(PartitionStartAddr,PartitionDataLength,PartitionImageLength);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"DECRYPTION_FAIL\r\n");OutputStatus(DECRYPTION_FAIL);FsblFallback();}}/** Load Signed PL partition in Fabric*/if (PLPartitionFlag) {Status = PcapLoadPartition((u32*)PartitionStartAddr,(u32*)PartitionLoadAddr,PartitionImageLength,PartitionDataLength,EncryptedPartitionFlag);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"BITSTREAM_DOWNLOAD_FAIL\r\n");OutputStatus(BITSTREAM_DOWNLOAD_FAIL);FsblFallback();}}}/** FSBL user hook call after bitstream download*/if (PLPartitionFlag) {Status = FsblHookAfterBitstreamDload();if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"FSBL_AFTER_BSTREAM_HOOK_FAIL\r\n");OutputStatus(FSBL_AFTER_BSTREAM_HOOK_FAIL);FsblFallback();}}/** Increment partition number*/PartitionNum++;}return ExecAddress; }/*****************************************************************************/ /** * * This function loads all partition header information in global array * * @param ImageAddress is the start address of the image * * @return - XST_SUCCESS if Get partition Header information successful * - XST_FAILURE if Get Partition Header information failed * * @note None * ****************************************************************************/ u32 GetPartitionHeaderInfo(u32 ImageBaseAddress) {u32 PartitionHeaderOffset;u32 Status;/** Get the length of the FSBL from BootHeader*/Status = GetFsblLength(ImageBaseAddress, &FsblLength);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL, "Get Header Start Address Failed\r\n");return XST_FAILURE;}/** Get the start address of the partition header table*/Status = GetPartitionHeaderStartAddr(ImageBaseAddress,&PartitionHeaderOffset);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL, "Get Header Start Address Failed\r\n");return XST_FAILURE;}/** Header offset on flash*/PartitionHeaderOffset += ImageBaseAddress;fsbl_printf(DEBUG_INFO,"Partition Header Offset:0x%08lx\r\n",PartitionHeaderOffset);/** Load all partitions header data in to global variable*/Status = LoadPartitionsHeaderInfo(PartitionHeaderOffset,&PartitionHeader[0]);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL, "Header Information Load Failed\r\n");return XST_FAILURE;}/** Get partitions count from partitions header information*/PartitionCount = GetPartitionCount(&PartitionHeader[0]);fsbl_printf(DEBUG_INFO, "Partition Count: %lu\r\n", PartitionCount);/** Partition Count check*/if (PartitionCount >= MAX_PARTITION_NUMBER) {fsbl_printf(DEBUG_GENERAL, "Invalid Partition Count\r\n");return XST_FAILURE; #ifndef MMC_SUPPORT} else if (PartitionCount <= 1) {fsbl_printf(DEBUG_GENERAL, "There is no partition to load\r\n");return XST_FAILURE; #endif}return XST_SUCCESS; }/*****************************************************************************/ /** * * This function goes to the partition header of the specified partition * * @param ImageAddress is the start address of the image * * @return Offset Partition header address of the image * * @return - XST_SUCCESS if Get Partition Header start address successful * - XST_FAILURE if Get Partition Header start address failed * * @note None * ****************************************************************************/ u32 GetPartitionHeaderStartAddr(u32 ImageAddress, u32 *Offset) {u32 Status;Status = MoveImage(ImageAddress + IMAGE_PHDR_OFFSET, (u32)Offset, 4);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"Move Image failed\r\n");return XST_FAILURE;}return XST_SUCCESS; }/*****************************************************************************/ /** * * This function goes to the partition header of the specified partition * * @param ImageAddress is the start address of the image * * @return Offset to Image header table address of the image * * @return - XST_SUCCESS if Get Partition Header start address successful * - XST_FAILURE if Get Partition Header start address failed * * @note None * ****************************************************************************/ u32 GetImageHeaderStartAddr(u32 ImageAddress, u32 *Offset) {u32 Status;Status = MoveImage(ImageAddress + IMAGE_HDR_OFFSET, (u32)Offset, 4);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"Move Image failed\r\n");return XST_FAILURE;}return XST_SUCCESS; } /*****************************************************************************/ /** * * This function gets the length of the FSBL * * @param ImageAddress is the start address of the image * * @return FsblLength is the length of the fsbl * * @return - XST_SUCCESS if fsbl length reading is successful * - XST_FAILURE if fsbl length reading failed * * @note None * ****************************************************************************/ u32 GetFsblLength(u32 ImageAddress, u32 *FsblLength) {u32 Status;Status = MoveImage(ImageAddress + IMAGE_TOT_BYTE_LEN_OFFSET,(u32)FsblLength, 4);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"Move Image failed reading FsblLength\r\n");return XST_FAILURE;}return XST_SUCCESS; }#ifdef RSA_SUPPORT /*****************************************************************************/ /** * * This function goes to read the image headers and its signature. Image * header consists of image header table, image headers, partition * headers * * @param ImageBaseAddress is the start address of the image header * * @return Offset Partition header address of the image * * @return - XST_SUCCESS if Get Partition Header start address successful * - XST_FAILURE if Get Partition Header start address failed * * @note None * ****************************************************************************/ u32 GetImageHeaderAndSignature(u32 ImageBaseAddress, u32 *Offset) {u32 Status;u32 ImageHeaderOffset;/** Get the start address of the partition header table*/Status = GetImageHeaderStartAddr(ImageBaseAddress, &ImageHeaderOffset);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL, "Get Header Start Address Failed\r\n");return XST_FAILURE;}Status = MoveImage(ImageBaseAddress+ImageHeaderOffset, (u32)Offset,TOTAL_HEADER_SIZE + RSA_SIGNATURE_SIZE);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"Move Image failed\r\n");return XST_FAILURE;}return XST_SUCCESS; } #endif /*****************************************************************************/ /** * * This function get the header information of the all the partitions and load into * global array * * @param PartHeaderOffset Offset address where the header information present * * @param Header Partition header pointer * * @return - XST_SUCCESS if Load Partitions Header information successful * - XST_FAILURE if Load Partitions Header information failed * * @note None * ****************************************************************************/ u32 LoadPartitionsHeaderInfo(u32 PartHeaderOffset, PartHeader *Header) {u32 Status;Status = MoveImage(PartHeaderOffset, (u32)Header, sizeof(PartHeader)*MAX_PARTITION_NUMBER);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"Move Image failed\r\n");return XST_FAILURE;}return XST_SUCCESS; }/*****************************************************************************/ /** * * This function dumps the partition header. * * @param Header Partition header pointer * * @return None * * @note None * ******************************************************************************/ void HeaderDump(PartHeader *Header) {fsbl_printf(DEBUG_INFO, "Header Dump\r\n");fsbl_printf(DEBUG_INFO, "Image Word Len: 0x%08lx\r\n",Header->ImageWordLen);fsbl_printf(DEBUG_INFO, "Data Word Len: 0x%08lx\r\n",Header->DataWordLen);fsbl_printf(DEBUG_INFO, "Partition Word Len:0x%08lx\r\n",Header->PartitionWordLen);fsbl_printf(DEBUG_INFO, "Load Addr: 0x%08lx\r\n",Header->LoadAddr);fsbl_printf(DEBUG_INFO, "Exec Addr: 0x%08lx\r\n",Header->ExecAddr);fsbl_printf(DEBUG_INFO, "Partition Start: 0x%08lx\r\n",Header->PartitionStart);fsbl_printf(DEBUG_INFO, "Partition Attr: 0x%08lx\r\n",Header->PartitionAttr);fsbl_printf(DEBUG_INFO, "Partition Checksum Offset: 0x%08lx\r\n",Header->CheckSumOffset);fsbl_printf(DEBUG_INFO, "Section Count: 0x%08lx\r\n",Header->SectionCount);fsbl_printf(DEBUG_INFO, "Checksum: 0x%08lx\r\n",Header->CheckSum); }/******************************************************************************/ /** * * This function calculates the partitions count from header information * * @param Header Partition header pointer * * @return Count Partition count * * @note None * *******************************************************************************/ u32 GetPartitionCount(PartHeader *Header) {u32 Count=0;struct HeaderArray *Hap;for(Count = 0; Count < MAX_PARTITION_NUMBER; Count++) {Hap = (struct HeaderArray *)&Header[Count];if(IsLastPartition(Hap)!=XST_FAILURE)break;}return Count; }/******************************************************************************/ /** * This function check whether the current partition is the end of partitions * * The partition is the end of the partitions if it looks like this: * 0x00000000 * 0x00000000 * .... * 0x00000000 * 0x00000000 * 0xFFFFFFFF * * @param H is a pointer to struct HeaderArray * * @return * - XST_SUCCESS if it is the last partition * - XST_FAILURE if it is not last partition * ****************************************************************************/ u32 IsLastPartition(struct HeaderArray *H) {int Index;if (H->Fields[PARTITION_HDR_CHECKSUM_WORD_COUNT] != 0xFFFFFFFF) {return XST_FAILURE;}for (Index = 0; Index < PARTITION_HDR_WORD_COUNT - 1; Index++) {if (H->Fields[Index] != 0x0) {return XST_FAILURE;}}return XST_SUCCESS; }/******************************************************************************/ /** * * This function validates the partition header. * * @param Header Partition header pointer * * @return * - XST_FAILURE if bad header. * - XST_SUCCESS if successful. * * @note None * *******************************************************************************/ u32 ValidateHeader(PartHeader *Header) {struct HeaderArray *Hap;Hap = (struct HeaderArray *)Header;/** If there are no partitions to load, fail*/if (IsEmptyHeader(Hap) == XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL, "IMAGE_HAS_NO_PARTITIONS\r\n");return XST_FAILURE;}/** Validate partition header checksum*/if (ValidatePartitionHeaderChecksum(Hap) != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL, "PARTITION_HEADER_CORRUPTION\r\n");return XST_FAILURE;}/** Validate partition data size*/if (Header->ImageWordLen > MAXIMUM_IMAGE_WORD_LEN) {fsbl_printf(DEBUG_GENERAL, "INVALID_PARTITION_LENGTH\r\n");return XST_FAILURE;}return XST_SUCCESS; }/******************************************************************************/ /** * This function check whether the current partition header is empty. * A partition header is considered empty if image word length is 0 and the * last word is 0. * * @param H is a pointer to struct HeaderArray * * @return * - XST_SUCCESS , If the partition header is empty * - XST_FAILURE , If the partition header is NOT empty * * @note Caller is responsible to make sure the address is valid. * * ****************************************************************************/ u32 IsEmptyHeader(struct HeaderArray *H) {int Index;for (Index = 0; Index < PARTITION_HDR_WORD_COUNT; Index++) {if (H->Fields[Index] != 0x0) {return XST_FAILURE;}}return XST_SUCCESS; }/******************************************************************************/ /** * * This function checks the header checksum If the header checksum is not valid * XST_FAILURE is returned. * * @param H is a pointer to struct HeaderArray * * @return * - XST_SUCCESS is header checksum is ok * - XST_FAILURE if the header checksum is not correct * * @note None. * ****************************************************************************/ u32 ValidatePartitionHeaderChecksum(struct HeaderArray *H) {u32 Checksum;u32 Count;Checksum = 0;for (Count = 0; Count < PARTITION_HDR_CHECKSUM_WORD_COUNT; Count++) {/** Read the word from the header*/Checksum += H->Fields[Count];}/** Invert checksum, last bit of error checking*/Checksum ^= 0xFFFFFFFF;/** Validate the checksum*/if (H->Fields[PARTITION_HDR_CHECKSUM_WORD_COUNT] != Checksum) {fsbl_printf(DEBUG_GENERAL, "Error: Checksum 0x%8.8lx != 0x%8.8lx\r\n",Checksum, H->Fields[PARTITION_HDR_CHECKSUM_WORD_COUNT]);return XST_FAILURE;}return XST_SUCCESS; }/******************************************************************************/ /** * * This function load the partition from boot device * * @param ImageBaseAddress Base address on flash * @param Header Partition header pointer * * @return * - XST_SUCCESS if partition move successful * - XST_FAILURE if check failed move failed * * @note None * *******************************************************************************/ u32 PartitionMove(u32 ImageBaseAddress, PartHeader *Header) {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;/** Add flash base address for linear boot devices*/if (LinearBootDeviceFlag) {SourceAddr += FlashReadBaseAddress;}/** Partition encrypted*/if(EncryptedPartitionFlag) {SecureTransferFlag = 1;}/** For Signed or checksum enabled partition, * Total partition image need to copied to DDR*/if (SignedPartitionFlag || PartitionChecksumFlag) {ImageWordLen = Header->PartitionWordLen;DataWordLen = Header->PartitionWordLen;}/** Encrypted and Signed PS partition need to be loaded on to DDR* without decryption*/if (PSPartitionFlag &&(SignedPartitionFlag || PartitionChecksumFlag) &&EncryptedPartitionFlag) {SecureTransferFlag = 0;}/** 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_SYSTEMfsbl_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;}} #elseStatus = 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}if ((LinearBootDeviceFlag && PLPartitionFlag &&(SignedPartitionFlag || PartitionChecksumFlag)) ||(LinearBootDeviceFlag && PSPartitionFlag) ||((!LinearBootDeviceFlag) && PSPartitionFlag && SecureTransferFlag)) {/** PL signed partition copied to DDR temporary location* using non-secure PCAP for linear boot device*/if(PLPartitionFlag){SecureTransferFlag = 0;LoadAddr = DDR_TEMP_START_ADDR;}/** Data transfer using PCAP*/Status = PcapDataTransfer((u32*)SourceAddr,(u32*)LoadAddr,ImageWordLen,DataWordLen,SecureTransferFlag);if(Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL, "PCAP Data Transfer Failed\r\n");return XST_FAILURE;}/** As image present at load address*/SourceAddr = LoadAddr;}/** Load Bitstream partition in to fabric only* if checksum and authentication bits are not set*/if (PLPartitionFlag && (!(SignedPartitionFlag || PartitionChecksumFlag))) {SourceAddr += FlashReadBaseAddress;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; }/******************************************************************************/ /** * * This function load the decrypts partition * * @param StartAddr Source start address * @param DataLength Data length in words * @param ImageLength Image length in words * * @return * - XST_SUCCESS if decryption successful * - XST_FAILURE if decryption failed * * @note None * *******************************************************************************/ u32 DecryptPartition(u32 StartAddr, u32 DataLength, u32 ImageLength) {u32 Status;u8 SecureTransferFlag =1;/** Data transfer using PCAP*/Status = PcapDataTransfer((u32*)StartAddr,(u32*)StartAddr,ImageLength,DataLength,SecureTransferFlag);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_GENERAL,"PCAP Data Transfer failed \r\n");return XST_FAILURE;}return XST_SUCCESS; }/******************************************************************************/ /** * * This function Validate Partition Data by using checksum preset in image * * @param Partition header pointer * @param Partition check sum offset * @return * - XST_SUCCESS if partition data is ok * - XST_FAILURE if partition data is corrupted * * @note None * *******************************************************************************/ u32 ValidateParition(u32 StartAddr, u32 Length, u32 ChecksumOffset) {u8 Checksum[MD5_CHECKSUM_SIZE];u8 CalcChecksum[MD5_CHECKSUM_SIZE];u32 Status;u32 Index;#ifdef XPAR_XWDTPS_0_BASEADDR/** Prevent WDT reset*/XWdtPs_RestartWdt(&Watchdog); #endif/** Get checksum from flash*/Status = GetPartitionChecksum(ChecksumOffset, &Checksum[0]);if(Status != XST_SUCCESS) {return XST_FAILURE;}fsbl_printf(DEBUG_INFO, "Actual checksum\r\n");for (Index = 0; Index < MD5_CHECKSUM_SIZE; Index++) {fsbl_printf(DEBUG_INFO, "0x%0x ",Checksum[Index]);}fsbl_printf(DEBUG_INFO, "\r\n");/** Calculate checksum for the partition*/Status = CalcPartitionChecksum(StartAddr, Length, &CalcChecksum[0]);if(Status != XST_SUCCESS) {return XST_FAILURE;}fsbl_printf(DEBUG_INFO, "Calculated checksum\r\n");for (Index = 0; Index < MD5_CHECKSUM_SIZE; Index++) {fsbl_printf(DEBUG_INFO, "0x%0x ",CalcChecksum[Index]);}fsbl_printf(DEBUG_INFO, "\r\n");/** Compare actual checksum with the calculated checksum*/for (Index = 0; Index < MD5_CHECKSUM_SIZE; Index++) {if(Checksum[Index] != CalcChecksum[Index]) {fsbl_printf(DEBUG_GENERAL, "Error: ""Partition DataChecksum 0x%0x!= 0x%0x\r\n",Checksum[Index], CalcChecksum[Index]);return XST_FAILURE;}}return XST_SUCCESS; }/******************************************************************************/ /** * * This function gets partition checksum from flash * * @param Check sum offset * @param Checksum pointer * @return * - XST_SUCCESS if checksum read success * - XST_FAILURE if unable get checksum * * @note None * *******************************************************************************/ u32 GetPartitionChecksum(u32 ChecksumOffset, u8 *Checksum) {u32 Status;Status = MoveImage(ChecksumOffset, (u32)Checksum, MD5_CHECKSUM_SIZE);if(Status != XST_SUCCESS) {return XST_FAILURE;}return XST_SUCCESS; }/******************************************************************************/ /** * * This function calculates the checksum preset in image * * @param Start address * @param Length of the data * @param Checksum pointer * * @return * - XST_SUCCESS if Checksum calculate successful * - XST_FAILURE if Checksum calculate failed * * @note None * *******************************************************************************/ u32 CalcPartitionChecksum(u32 SourceAddr, u32 DataLength, u8 *Checksum) {/** Calculate checksum using MD5 algorithm*/md5((u8*)SourceAddr, DataLength, Checksum, 0 );return XST_SUCCESS; }Qspi.c修改
由于FSBL需要在QSPI中執(zhí)行,所以Qspi.c中需要在InitQspi函數(shù)中取消對(duì)QSPI FLASH的再次初始化,同時(shí)修改QSPIAccess函數(shù)中對(duì)QSPI FLASH的訪問(wèn)方式,強(qiáng)制為線性模式訪問(wèn)。具體參考代碼。
/****************************************************************************** * * Copyright (C) 2012 - 2016 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /*****************************************************************************/ /** * * @file qspi.c * * Contains code for the QSPI FLASH functionality. * * <pre> * MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- ------------------------------------------------------- * 1.00a ecm 01/10/10 Initial release * 3.00a mb 25/06/12 InitQspi, data is read first and required config bits * are set * 4.00a sg 02/28/13 Cleanup * Removed LPBK_DLY_ADJ register setting code as we use * divisor 8 * 5.00a sgd 05/17/13 Added Flash Size > 128Mbit support * Dual Stack support * Fix for CR:721674 - FSBL- Failed to boot from Dual * stacked QSPI * 6.00a kc 08/30/13 Fix for CR#722979 - Provide customer-friendly * changelogs in FSBL * Fix for CR#739711 - FSBL not able to read Large QSPI * (512M) in IO Mode * 7.00a kc 10/25/13 Fix for CR#739968 - FSBL should do the QSPI config * settings for Dual parallel * configuration in IO mode * 14.0 gan 01/13/16 Fix for CR#869081 - (2016.1)FSBL picks the qspi read * command from LQSPI_CFG register * instead of hard coded read * command (0x6B). * * </pre> * * @note * ******************************************************************************//***************************** Include Files *********************************/#include "qspi.h" #include "image_mover.h"#ifdef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDR #include "xqspips_hw.h" #include "xqspips.h"/************************** Constant Definitions *****************************//** The following constants map to the XPAR parameters created in the* xparameters.h file. They are defined here such that a user can easily* change all the needed parameters in one place.*/ #define QSPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID/** The following constants define the commands which may be sent to the FLASH* device.*/ #define QUAD_READ_CMD 0x6B #define READ_ID_CMD 0x9F#define WRITE_ENABLE_CMD 0x06 #define BANK_REG_RD 0x16 #define BANK_REG_WR 0x17 /* Bank register is called Extended Address Reg in Micron */ #define EXTADD_REG_RD 0xC8 #define EXTADD_REG_WR 0xC5#define COMMAND_OFFSET 0 /* FLASH instruction */ #define ADDRESS_1_OFFSET 1 /* MSB byte of address to read or write */ #define ADDRESS_2_OFFSET 2 /* Middle byte of address to read or write */ #define ADDRESS_3_OFFSET 3 /* LSB byte of address to read or write */ #define DATA_OFFSET 4 /* Start of Data for Read/Write */ #define DUMMY_OFFSET 4 /* Dummy byte offset for fast, dual and quadreads */ #define DUMMY_SIZE 1 /* Number of dummy bytes for fast, dual andquad reads */ #define RD_ID_SIZE 4 /* Read ID command + 3 bytes ID response */ #define BANK_SEL_SIZE 2 /* BRWR or EARWR command + 1 byte bank value */ #define WRITE_ENABLE_CMD_SIZE 1 /* WE command */ /** The following constants specify the extra bytes which are sent to the* FLASH on the QSPI interface, that are not data, but control information* which includes the command and address*/ #define OVERHEAD_SIZE 4/** The following constants specify the max amount of data and the size of the* the buffer required to hold the data and overhead to transfer the data to* and from the FLASH.*/ #define DATA_SIZE 4096/** The following defines are for dual flash interface.*/ #define LQSPI_CR_FAST_QUAD_READ 0x0000006B /* Fast Quad Read output */ #define LQSPI_CR_1_DUMMY_BYTE 0x00000100 /* 1 Dummy Byte betweenaddress and return data */#define SINGLE_QSPI_CONFIG_QUAD_READ (XQSPIPS_LQSPI_CR_LINEAR_MASK | \LQSPI_CR_1_DUMMY_BYTE | \LQSPI_CR_FAST_QUAD_READ)#define DUAL_QSPI_CONFIG_QUAD_READ (XQSPIPS_LQSPI_CR_LINEAR_MASK | \XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \XQSPIPS_LQSPI_CR_SEP_BUS_MASK | \LQSPI_CR_1_DUMMY_BYTE | \LQSPI_CR_FAST_QUAD_READ)#define DUAL_STACK_CONFIG_READ (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \LQSPI_CR_1_DUMMY_BYTE | \LQSPI_CR_FAST_QUAD_READ)#define SINGLE_QSPI_IO_CONFIG_QUAD_READ (LQSPI_CR_1_DUMMY_BYTE | \LQSPI_CR_FAST_QUAD_READ)#define DUAL_QSPI_IO_CONFIG_QUAD_READ (XQSPIPS_LQSPI_CR_TWO_MEM_MASK | \XQSPIPS_LQSPI_CR_SEP_BUS_MASK | \LQSPI_CR_1_DUMMY_BYTE | \LQSPI_CR_FAST_QUAD_READ)/**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************//************************** Function Prototypes ******************************//************************** Variable Definitions *****************************/XQspiPs QspiInstance; XQspiPs *QspiInstancePtr; u32 QspiFlashSize; u32 QspiFlashMake; extern u32 FlashReadBaseAddress; extern u8 LinearBootDeviceFlag;/** The following variables are used to read and write to the eeprom and they* are global to avoid having large buffers on the stack*/ u8 ReadBuffer[DATA_SIZE + DATA_OFFSET + DUMMY_SIZE]; u8 WriteBuffer[DATA_OFFSET + DUMMY_SIZE];/******************************************************************************/ /** * * This function initializes the controller for the QSPI interface. * * @param None * * @return None * * @note None * ****************************************************************************/ u32 InitQspi(void) { #ifdef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDRu32 QspiControlReg = 0;u32 QspiDelayReg = 0;u32 Prescaler = XQSPIPS_CLK_PRESCALE_8;#ifndef QSPI_XIP/* 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 #endifreturn XST_SUCCESS;}/****************************************************************************** * * This function reads serial FLASH ID connected to the SPI interface. * It then deduces the make and size of the flash and obtains the * connection mode to point to corresponding parameters in the flash * configuration table. The flash driver will function based on this and * it presently supports Micron and Spansion - 128, 256 and 512Mbit and * Winbond 128Mbit * * @param none * * @return XST_SUCCESS if read id, otherwise XST_FAILURE. * * @note None. *******************************************************************************/ u32 FlashReadID(void) {u32 Status;/** Read ID in Auto mode.*/WriteBuffer[COMMAND_OFFSET] = READ_ID_CMD;WriteBuffer[ADDRESS_1_OFFSET] = 0x00; /* 3 dummy bytes */WriteBuffer[ADDRESS_2_OFFSET] = 0x00;WriteBuffer[ADDRESS_3_OFFSET] = 0x00;Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, ReadBuffer,RD_ID_SIZE);if (Status != XST_SUCCESS) {return XST_FAILURE;}fsbl_printf(DEBUG_INFO,"Single Flash Information\r\n");fsbl_printf(DEBUG_INFO,"FlashID=0x%x 0x%x 0x%x\r\n", ReadBuffer[1],ReadBuffer[2],ReadBuffer[3]);/** Deduce flash make*/if (ReadBuffer[1] == MICRON_ID) {QspiFlashMake = MICRON_ID;fsbl_printf(DEBUG_INFO, "MICRON ");} else if(ReadBuffer[1] == SPANSION_ID) {QspiFlashMake = SPANSION_ID;fsbl_printf(DEBUG_INFO, "SPANSION ");} else if(ReadBuffer[1] == WINBOND_ID) {QspiFlashMake = WINBOND_ID;fsbl_printf(DEBUG_INFO, "WINBOND ");}/** Deduce flash Size*/if (ReadBuffer[3] == FLASH_SIZE_ID_128M) {QspiFlashSize = FLASH_SIZE_128M;fsbl_printf(DEBUG_INFO, "128M Bits\r\n");} else if (ReadBuffer[3] == FLASH_SIZE_ID_256M) {QspiFlashSize = FLASH_SIZE_256M;fsbl_printf(DEBUG_INFO, "256M Bits\r\n");} else if (ReadBuffer[3] == FLASH_SIZE_ID_512M) {QspiFlashSize = FLASH_SIZE_512M;fsbl_printf(DEBUG_INFO, "512M Bits\r\n");} else if (ReadBuffer[3] == FLASH_SIZE_ID_1G) {QspiFlashSize = FLASH_SIZE_1G;fsbl_printf(DEBUG_INFO, "1G Bits\r\n");}return XST_SUCCESS; }/****************************************************************************** * * This function reads from the serial FLASH connected to the * QSPI interface. * * @param Address contains the address to read data from in the FLASH. * @param ByteCount contains the number of bytes to read. * * @return None. * * @note None. * ******************************************************************************/ void FlashRead(u32 Address, u32 ByteCount) {/** Setup the write command with the specified address and data for the* FLASH*/WriteBuffer[COMMAND_OFFSET] = QUAD_READ_CMD;WriteBuffer[ADDRESS_1_OFFSET] = (u8)((Address & 0xFF0000) >> 16);WriteBuffer[ADDRESS_2_OFFSET] = (u8)((Address & 0xFF00) >> 8);WriteBuffer[ADDRESS_3_OFFSET] = (u8)(Address & 0xFF);ByteCount += DUMMY_SIZE;/** Send the read command to the FLASH to read the specified number* of bytes from the FLASH, send the read command and address and* receive the specified number of bytes of data in the data buffer*/XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, ReadBuffer,ByteCount + OVERHEAD_SIZE); }/******************************************************************************/ /** * * This function provides the QSPI FLASH interface for the Simplified header * functionality. * * @param SourceAddress is address in FLASH data space * @param DestinationAddress is address in DDR data space * @param LengthBytes is the length of the data in Bytes * * @return * - XST_SUCCESS if the write completes correctly * - XST_FAILURE if the write fails to completes correctly * * @note none. * ****************************************************************************/ u32 QspiAccess( u32 SourceAddress, u32 DestinationAddress, u32 LengthBytes) { #ifdef XPAR_PS7_QSPI_LINEAR_0_S_AXI_BASEADDRu32 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++;} #endifreturn XST_SUCCESS; }/****************************************************************************** * * This functions selects the current bank * * @param BankSel is the bank to be selected in the flash device(s). * * @return XST_SUCCESS if bank selected * XST_FAILURE if selection failed * @note None. * ******************************************************************************/ u32 SendBankSelect(u8 BankSel) {u32 Status;/** bank select commands for Micron and Spansion are different*/if (QspiFlashMake == MICRON_ID) {/** For micron command WREN should be sent first* except for some specific feature set*/WriteBuffer[COMMAND_OFFSET] = WRITE_ENABLE_CMD;Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, NULL,WRITE_ENABLE_CMD_SIZE);if (Status != XST_SUCCESS) {return XST_FAILURE;}/** Send the Extended address register write command* written, no receive buffer required*/WriteBuffer[COMMAND_OFFSET] = EXTADD_REG_WR;WriteBuffer[ADDRESS_1_OFFSET] = BankSel;Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, NULL,BANK_SEL_SIZE);if (Status != XST_SUCCESS) {return XST_FAILURE;}}if (QspiFlashMake == SPANSION_ID) {WriteBuffer[COMMAND_OFFSET] = BANK_REG_WR;WriteBuffer[ADDRESS_1_OFFSET] = BankSel;/** Send the Extended address register write command* written, no receive buffer required*/Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, NULL,BANK_SEL_SIZE);if (Status != XST_SUCCESS) {return XST_FAILURE;}}/** For testing - Read bank to verify*/if (QspiFlashMake == SPANSION_ID) {WriteBuffer[COMMAND_OFFSET] = BANK_REG_RD;WriteBuffer[ADDRESS_1_OFFSET] = 0x00;/** Send the Extended address register write command* written, no receive buffer required*/Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, ReadBuffer,BANK_SEL_SIZE);if (Status != XST_SUCCESS) {return XST_FAILURE;}}if (QspiFlashMake == MICRON_ID) {WriteBuffer[COMMAND_OFFSET] = EXTADD_REG_RD;WriteBuffer[ADDRESS_1_OFFSET] = 0x00;/** Send the Extended address register write command* written, no receive buffer required*/Status = XQspiPs_PolledTransfer(QspiInstancePtr, WriteBuffer, ReadBuffer,BANK_SEL_SIZE);if (Status != XST_SUCCESS) {return XST_FAILURE;}}if (ReadBuffer[1] != BankSel) {fsbl_printf(DEBUG_INFO, "BankSel %d != Register Read %d\n\r", BankSel,ReadBuffer[1]);return XST_FAILURE;}return XST_SUCCESS; } #endifQspi.h修改
Qspi.h中需要增加三個(gè)宏定義,如下。
/****************************************************************************** * * Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /*****************************************************************************/ /** * * @file qspi.h * * This file contains the interface for the QSPI FLASH functionality * * <pre> * MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- ------------------------------------------------------- * 1.00a ecm 01/10/10 Initial release * 3.00a mb 01/09/12 Added the Delay Values defines for qspi * 5.00a sgd 05/17/13 Added Flash Size > 128Mbit support * Dual Stack support * </pre> * * @note * ******************************************************************************/ #ifndef ___QSPI_H___ #define ___QSPI_H___#include "fsbl.h" #ifdef __cplusplus extern "C" { #endif/***************************** Include Files *********************************/ #include "fsbl.h"/************************** Constant Definitions *****************************/ #define SINGLE_FLASH_CONNECTION 0 #define DUAL_STACK_CONNECTION 1 #define DUAL_PARALLEL_CONNECTION 2 #define FLASH_SIZE_16MB 0x1000000/** Bank mask*/ #define BANKMASK 0xF000000/** Identification of Flash* Micron:* Byte 0 is Manufacturer ID;* Byte 1 is first byte of Device ID - 0xBB or 0xBA* Byte 2 is second byte of Device ID describes flash size:* 128Mbit : 0x18; 256Mbit : 0x19; 512Mbit : 0x20* Spansion:* Byte 0 is Manufacturer ID;* Byte 1 is Device ID - Memory Interface type - 0x20 or 0x02* Byte 2 is second byte of Device ID describes flash size:* 128Mbit : 0x18; 256Mbit : 0x19; 512Mbit : 0x20*/#define MICRON_ID 0x20 #define SPANSION_ID 0x01 #define WINBOND_ID 0xEF#define FLASH_SIZE_ID_128M 0x18 #define FLASH_SIZE_ID_256M 0x19 #define FLASH_SIZE_ID_512M 0x20 #define FLASH_SIZE_ID_1G 0x21/** Size in bytes*/ #define FLASH_SIZE_128M 0x1000000 #define FLASH_SIZE_256M 0x2000000 #define FLASH_SIZE_512M 0x4000000 #define FLASH_SIZE_1G 0x8000000#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) /************************** Function Prototypes ******************************/ u32 InitQspi(void);u32 QspiAccess( u32 SourceAddress,u32 DestinationAddress,u32 LengthBytes);u32 FlashReadID(void); u32 SendBankSelect(u8 BankSel); /************************** Variable Definitions *****************************/#ifdef __cplusplus } #endif#endif /* ___QSPI_H___ */?
Pcap.c修改
修改了FabricInit函數(shù),具體參考代碼
/****************************************************************************** * * Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /*****************************************************************************/ /** * * @file pcap.c * * Contains code for enabling and accessing the PCAP * * <pre> * MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- ------------------------------------------------------- * 1.00a ecm 02/10/10 Initial release * 2.00a jz 05/28/11 Add SD support * 2.00a mb 25/05/12 using the EDK provided devcfg driver * Nand/SD encryption and review comments * 3.00a mb 16/08/12 Added the poll function * Removed the FPGA_RST_CTRL define * Added the flag for NON PS instantiated bitstream * 4.00a sgd 02/28/13 Fix for CR#681014 - ECC init in FSBL should not call * fabric_init() * Fix for CR#689026 - FSBL doesn't hold PL resets active * during bit download * Fix for CR#699475 - FSBL functionality is broken and * its not able to boot in QSPI/NAND * bootmode * Fix for CR#705664 - FSBL fails to decrypt the * bitstream when the image is AES * encrypted using non-zero key value * 6.00a kc 08/30/13 Fix for CR#722979 - Provide customer-friendly * changelogs in FSBL * 7.00a kc 10/25/13 Fix for CR#724620 - How to handle PCAP_MODE after * bitstream configuration * Fix for CR#726178 - FabricInit() PROG_B is kept active * for 5mS. * Fix for CR#731839 - FSBL has to check the * HMAC error status after decryption * 12/04/13 Fix for CR#764382 - How to handle PCAP_MODE after * bitstream configuration - PCAP_MODE * and PCAP_PR bits are not modified * 8.00a kc 2/20/14 Fix for CR#775631 - FSBL: FsblGetGlobalTimer() * is not proper * 10.00a kc 07/24/14 Fix for CR#809336 - Minor code cleanup * 13.00a ssc 04/10/15 Fix for CR#846899 - Corrected logic to clear * DMA done count * </pre> * * @note * ******************************************************************************//***************************** Include Files *********************************/#include "pcap.h" #include "nand.h" /* For NAND geometry information */ #include "fsbl.h" #include "image_mover.h" /* For MoveImage */ #include "xparameters.h" #include "xil_exception.h" #include "xdevcfg.h" #include "sleep.h"#ifdef XPAR_XWDTPS_0_BASEADDR #include "xwdtps.h" #endif /************************** Constant Definitions *****************************/ /** The following constants map to the XPAR parameters created in the* xparameters.h file. They are only defined here such that a user can easily* change all the needed parameters in one place.*/#define DCFG_DEVICE_ID XPAR_XDCFG_0_DEVICE_ID/**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************//************************** Function Prototypes ******************************/ extern int XDcfgPollDone(u32 MaskValue, u32 MaxCount);/************************** Variable Definitions *****************************/ /* Devcfg driver instance */ static XDcfg DcfgInstance; XDcfg *DcfgInstPtr;#ifdef XPAR_XWDTPS_0_BASEADDR extern XWdtPs Watchdog; /* Instance of WatchDog Timer */ #endif/******************************************************************************/ /** * * This function transfer data using PCAP * * @param SourceDataPtr is a pointer to where the data is read from * @param DestinationDataPtr is a pointer to where the data is written to * @param SourceLength is the length of the data to be moved in words * @param DestinationLength is the length of the data to be moved in words * @param SecureTransfer indicated the encryption key location, 0 for * non-encrypted * * @return * - XST_SUCCESS if the transfer is successful * - XST_FAILURE if the transfer fails * * @note None * ****************************************************************************/ u32 PcapDataTransfer(u32 *SourceDataPtr, u32 *DestinationDataPtr,u32 SourceLength, u32 DestinationLength, u32 SecureTransfer) {u32 Status;u32 IntrStsReg;u32 PcapTransferType = XDCFG_CONCURRENT_NONSEC_READ_WRITE;/** Check for secure transfer*/if (SecureTransfer) {PcapTransferType = XDCFG_CONCURRENT_SECURE_READ_WRITE;}#ifdef FSBL_PERFXTime tXferCur = 0;FsblGetGlobalTime(&tXferCur); #endif/** Clear the PCAP status registers*/Status = ClearPcapStatus();if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_INFO,"PCAP_CLEAR_STATUS_FAIL \r\n");return XST_FAILURE;}#ifdef XPAR_XWDTPS_0_BASEADDR/** Prevent WDT reset*/XWdtPs_RestartWdt(&Watchdog); #endif/** PCAP single DMA transfer setup*/SourceDataPtr = (u32*)((u32)SourceDataPtr | PCAP_LAST_TRANSFER);DestinationDataPtr = (u32*)((u32)DestinationDataPtr | PCAP_LAST_TRANSFER);/** Transfer using Device Configuration*/Status = XDcfg_Transfer(DcfgInstPtr, (u8 *)SourceDataPtr,SourceLength,(u8 *)DestinationDataPtr,DestinationLength, PcapTransferType);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_INFO,"Status of XDcfg_Transfer = %lu \r \n",Status);return XST_FAILURE;}/** Dump the PCAP registers*/PcapDumpRegisters();/** Poll for the DMA done*/Status = XDcfgPollDone(XDCFG_IXR_DMA_DONE_MASK, MAX_COUNT);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_INFO,"PCAP_DMA_DONE_FAIL \r\n");return XST_FAILURE;}fsbl_printf(DEBUG_INFO,"DMA Done ! \n\r");/** 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;}/** For Performance measurement*/ #ifdef FSBL_PERFXTime tXferEnd = 0;fsbl_printf(DEBUG_GENERAL,"Time taken is ");FsblMeasurePerfTime(tXferCur,tXferEnd); #endifreturn XST_SUCCESS; }/******************************************************************************/ /** * * This function loads PL partition using PCAP * * @param SourceDataPtr is a pointer to where the data is read from * @param DestinationDataPtr is a pointer to where the data is written to * @param SourceLength is the length of the data to be moved in words * @param DestinationLength is the length of the data to be moved in words * @param SecureTransfer indicated the encryption key location, 0 for * non-encrypted * * @return * - XST_SUCCESS if the transfer is successful * - XST_FAILURE if the transfer fails * * @note None * ****************************************************************************/ u32 PcapLoadPartition(u32 *SourceDataPtr, u32 *DestinationDataPtr,u32 SourceLength, u32 DestinationLength, u32 SecureTransfer) {u32 Status;u32 IntrStsReg;u32 PcapTransferType = XDCFG_NON_SECURE_PCAP_WRITE;/** Check for secure transfer*/if (SecureTransfer) {PcapTransferType = XDCFG_SECURE_PCAP_WRITE;}#ifdef FSBL_PERFXTime tXferCur = 0;FsblGetGlobalTime(&tXferCur); #endif/** Clear the PCAP status registers*/Status = ClearPcapStatus();if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_INFO,"PCAP_CLEAR_STATUS_FAIL \r\n");return XST_FAILURE;}/** For Bitstream case destination address will be 0xFFFFFFFF*/DestinationDataPtr = (u32*)XDCFG_DMA_INVALID_ADDRESS;/** New Bitstream download initialization sequence*/FabricInit();#ifdef XPAR_XWDTPS_0_BASEADDR/** Prevent WDT reset*/XWdtPs_RestartWdt(&Watchdog); #endif/** PCAP single DMA transfer setup*/SourceDataPtr = (u32*)((u32)SourceDataPtr | PCAP_LAST_TRANSFER);DestinationDataPtr = (u32*)((u32)DestinationDataPtr | PCAP_LAST_TRANSFER);/** Transfer using Device Configuration*/Status = XDcfg_Transfer(DcfgInstPtr, (u8 *)SourceDataPtr,SourceLength,(u8 *)DestinationDataPtr,DestinationLength, PcapTransferType);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_INFO,"Status of XDcfg_Transfer = %lu \r \n",Status);return XST_FAILURE;}/** Dump the PCAP registers*/PcapDumpRegisters();/** Poll for the DMA done*/Status = XDcfgPollDone(XDCFG_IXR_DMA_DONE_MASK, MAX_COUNT);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_INFO,"PCAP_DMA_DONE_FAIL \r\n");return XST_FAILURE;}fsbl_printf(DEBUG_INFO,"DMA Done ! \n\r");/** Poll for FPGA Done*/Status = XDcfgPollDone(XDCFG_IXR_PCFG_DONE_MASK, MAX_COUNT);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_INFO,"PCAP_FPGA_DONE_FAIL\r\n");return XST_FAILURE;}fsbl_printf(DEBUG_INFO,"FPGA Done ! \n\r");#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/** For Performance measurement*/ #ifdef FSBL_PERFXTime tXferEnd = 0;fsbl_printf(DEBUG_GENERAL,"Time taken is ");FsblMeasurePerfTime(tXferCur,tXferEnd); #endifreturn XST_SUCCESS; }/******************************************************************************/ /** * * This function Initializes the PCAP driver. * * @param none * * @return * - XST_SUCCESS if the pcap driver initialization is successful * - XST_FAILURE if the pcap driver initialization fails * * @note none * ****************************************************************************/ int InitPcap(void) {XDcfg_Config *ConfigPtr;int Status = XST_SUCCESS;DcfgInstPtr = &DcfgInstance;/** Initialize the Device Configuration Interface driver.*/ConfigPtr = XDcfg_LookupConfig(DCFG_DEVICE_ID);Status = XDcfg_CfgInitialize(DcfgInstPtr, ConfigPtr,ConfigPtr->BaseAddr);if (Status != XST_SUCCESS) {fsbl_printf(DEBUG_INFO, "XDcfg_CfgInitialize failed \n\r");return XST_FAILURE;}return XST_SUCCESS; }/******************************************************************************/ /** * * This function programs the Fabric for use. * * @param None * * @return None * - XST_SUCCESS if the Fabric initialization is successful * - XST_FAILURE if the Fabric initialization fails * @note None * ****************************************************************************/ void FabricInit(void) {u32 PcapReg; u32 PcapCtrlRegVal;u32 StatusReg;/** Set Level Shifters DT618760 - PS to PL enabling*/Xil_Out32(PS_LVL_SHFTR_EN, LVL_PS_PL);fsbl_printf(DEBUG_INFO,"Level Shifter Value = 0x%lx \r\n",Xil_In32(PS_LVL_SHFTR_EN));/** Get DEVCFG controller settings*/PcapReg = XDcfg_ReadReg(DcfgInstPtr->Config.BaseAddr,XDCFG_CTRL_OFFSET);/** Setting PCFG_PROG_B signal to high*/XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,(PcapReg | XDCFG_CTRL_PCFG_PROG_B_MASK));/** Check for AES source key*/PcapCtrlRegVal = XDcfg_GetControlRegister(DcfgInstPtr);if (PcapCtrlRegVal & XDCFG_CTRL_PCFG_AES_FUSE_MASK) {/** 5msec delay*/usleep(5000);}/** Setting PCFG_PROG_B signal to low*/XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,(PcapReg & ~XDCFG_CTRL_PCFG_PROG_B_MASK));/** Check for AES source key*/if (PcapCtrlRegVal & XDCFG_CTRL_PCFG_AES_FUSE_MASK) {/** 5msec delay*/usleep(5000);}/** Polling the PCAP_INIT status for Reset*/while(XDcfg_GetStatusRegister(DcfgInstPtr) &XDCFG_STATUS_PCFG_INIT_MASK);/** Setting PCFG_PROG_B signal to high*/XDcfg_WriteReg(DcfgInstPtr->Config.BaseAddr, XDCFG_CTRL_OFFSET,(PcapReg | XDCFG_CTRL_PCFG_PROG_B_MASK));/** Polling the PCAP_INIT status for Set*/while(!(XDcfg_GetStatusRegister(DcfgInstPtr) &XDCFG_STATUS_PCFG_INIT_MASK));/** Get Device configuration status*/StatusReg = XDcfg_GetStatusRegister(DcfgInstPtr);fsbl_printf(DEBUG_INFO,"Devcfg Status register = 0x%lx \r\n",StatusReg);fsbl_printf(DEBUG_INFO,"PCAP:Fabric is Initialized done\r\n"); }/******************************************************************************/ /** * * This function Clears the PCAP status registers. * * @param None * * @return * - XST_SUCCESS if the pcap status registers are cleared * - XST_FAILURE if errors are there * - XST_DEVICE_BUSY if Pcap device is busy * @note None * ****************************************************************************/ u32 ClearPcapStatus(void) {u32 StatusReg;u32 IntStatusReg;/** Clear it all, so if Boot ROM comes back, it can proceed*/XDcfg_IntrClear(DcfgInstPtr, 0xFFFFFFFF);/** Get PCAP Interrupt Status Register*/IntStatusReg = XDcfg_IntrGetStatus(DcfgInstPtr);if (IntStatusReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) {fsbl_printf(DEBUG_INFO,"FATAL errors in PCAP %lx\r\n",IntStatusReg);return XST_FAILURE;}/** Read the PCAP status register for DMA status*/StatusReg = XDcfg_GetStatusRegister(DcfgInstPtr);fsbl_printf(DEBUG_INFO,"PCAP:StatusReg = 0x%.8lx\r\n", StatusReg);/** If the queue is full, return w/ XST_DEVICE_BUSY*/if ((StatusReg & XDCFG_STATUS_DMA_CMD_Q_F_MASK) ==XDCFG_STATUS_DMA_CMD_Q_F_MASK) {fsbl_printf(DEBUG_INFO,"PCAP_DEVICE_BUSY\r\n");return XST_DEVICE_BUSY;}fsbl_printf(DEBUG_INFO,"PCAP:device ready\r\n");/** There are unacknowledged DMA commands outstanding*/if ((StatusReg & XDCFG_STATUS_DMA_CMD_Q_E_MASK) !=XDCFG_STATUS_DMA_CMD_Q_E_MASK) {IntStatusReg = XDcfg_IntrGetStatus(DcfgInstPtr);if ((IntStatusReg & XDCFG_IXR_DMA_DONE_MASK) !=XDCFG_IXR_DMA_DONE_MASK){/** Error state, transfer cannot occur*/fsbl_printf(DEBUG_INFO,"PCAP:IntStatus indicates error\r\n");return XST_FAILURE;}else {/** clear out the status*/XDcfg_IntrClear(DcfgInstPtr, XDCFG_IXR_DMA_DONE_MASK);}}if ((StatusReg & XDCFG_STATUS_DMA_DONE_CNT_MASK) != 0) {XDcfg_SetStatusRegister(DcfgInstPtr, StatusReg |XDCFG_STATUS_DMA_DONE_CNT_MASK);}fsbl_printf(DEBUG_INFO,"PCAP:Clear done\r\n");return XST_SUCCESS; }/******************************************************************************/ /** * * This function prints PCAP register status. * * @param none * * @return none * * @note none * ****************************************************************************/ void PcapDumpRegisters (void) {fsbl_printf(DEBUG_INFO,"PCAP register dump:\r\n");fsbl_printf(DEBUG_INFO,"PCAP CTRL 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_CTRL_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_CTRL_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP LOCK 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_LOCK_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_LOCK_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP CONFIG 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_CFG_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_CFG_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP ISR 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_STS_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_STS_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP IMR 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_MASK_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_INT_MASK_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP STATUS 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_STATUS_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_STATUS_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP DMA SRC ADDR 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_ADDR_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_ADDR_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP DMA DEST ADDR 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_ADDR_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_ADDR_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP DMA SRC LEN 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_LEN_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_SRC_LEN_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP DMA DEST LEN 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_LEN_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_DMA_DEST_LEN_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP ROM SHADOW CTRL 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_ROM_SHADOW_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_ROM_SHADOW_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP MBOOT 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_MULTIBOOT_ADDR_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_MULTIBOOT_ADDR_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP SW ID 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_SW_ID_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_SW_ID_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP UNLOCK 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_UNLOCK_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_UNLOCK_OFFSET));fsbl_printf(DEBUG_INFO,"PCAP MCTRL 0x%x: 0x%08lx\r\n",XPS_DEV_CFG_APB_BASEADDR + XDCFG_MCTRL_OFFSET,Xil_In32(XPS_DEV_CFG_APB_BASEADDR + XDCFG_MCTRL_OFFSET)); }/******************************************************************************/ /** * * This function Polls for the DMA done or FPGA done. * * @param none * * @return * - XST_SUCCESS if polling for DMA/FPGA done is successful * - XST_FAILURE if polling for DMA/FPGA done fails * * @note none * ****************************************************************************/ 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_SYSTEMif (IntrStsReg & FSBL_XDCFG_IXR_ERROR_FLAGS_MASK) {fsbl_printf(DEBUG_INFO,"FATAL errors in PCAP %lx\r\n",IntrStsReg);PcapDumpRegisters();return XST_FAILURE;} #endifif(!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; }Pcap.h修改
修改FabricInit()函數(shù)返回類(lèi)型。
/****************************************************************************** * * Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /*****************************************************************************/ /** * * @file pcap.h * * This file contains the interface for intiializing and accessing the PCAP * * * <pre> * MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- ------------------------------------------------------- * 1.00a ecm 02/10/10 Initial release * 2.00a mb 16/08/12 Added the macros and function prototypes * </pre> * * @note * ******************************************************************************/ #ifndef ___PCAP_H___ #define ___PCAP_H___#ifdef __cplusplus extern "C" { #endif/***************************** Include Files *********************************/ #include "xdevcfg.h"/************************** Function Prototypes ******************************//* Multiboot register offset mask */ #define PCAP_MBOOT_REG_REBOOT_OFFSET_MASK 0x1FFF #define PCAP_CTRL_PCFG_AES_FUSE_EFUSE_MASK 0x1000#define PCAP_LAST_TRANSFER 1 #define MAX_COUNT 1000000000 #define LVL_PL_PS 0x0000000F #define LVL_PS_PL 0x0000000A/* Fix for #672779 */ #define FSBL_XDCFG_IXR_ERROR_FLAGS_MASK (XDCFG_IXR_AXI_WERR_MASK | \XDCFG_IXR_AXI_RTO_MASK | \XDCFG_IXR_AXI_RERR_MASK | \XDCFG_IXR_RX_FIFO_OV_MASK | \XDCFG_IXR_DMA_CMD_ERR_MASK |\XDCFG_IXR_DMA_Q_OV_MASK | \XDCFG_IXR_P2D_LEN_ERR_MASK |\XDCFG_IXR_PCFG_HMAC_ERR_MASK)int InitPcap(void); void PcapDumpRegisters(void); u32 ClearPcapStatus(void); void FabricInit(void); int XDcfgPollDone(u32 MaskValue, u32 MaxCount); u32 PcapLoadPartition(u32 *SourceData, u32 *DestinationData, u32 SourceLength,u32 DestinationLength, u32 Flags); u32 PcapDataTransfer(u32 *SourceData, u32 *DestinationData, u32 SourceLength,u32 DestinationLength, u32 Flags); /************************** Variable Definitions *****************************/ #ifdef __cplusplus } #endif#endif /* ___PCAP_H___ */Fsbl_handoff.S修改
由于程序不在DDR中執(zhí)行,需要修改FsblHandoffExit段
#ifdef __GNUC__ /****************************************************************************** * * Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /*****************************************************************************/ /** * * @file handoff.S * * Contains the code that does the handoff to the loaded application. This * code lives high in the ROM. * * <pre> * MODIFICATION HISTORY: * * Ver Who Date.word Changes * ----- ---- -------- ------------------------------------------------------- * 1.00a ecm 03/01/10 Initial release * 7.00a kc 10/23/13 Added support for armcc compiler * </pre> * * @note * Assumes that the starting address of the FSBL is provided by the calling routine * in R0. * ******************************************************************************/.globl FsblHandoffJtagExit.globl FsblHandoffExit.section .handoff,"axS"/***************************** Include Files *********************************//************************** Constant Definitions *****************************//**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************//************************** Function Prototypes ******************************//************************** Variable Definitions *****************************/FsblHandoffJtagExit:mcr 15,0,r0,cr7,cr5,0 /* Invalidate Instruction cache */mcr 15,0,r0,cr7,cr5,6 /* Invalidate branch predictor array */dsbisb /* make sure it completes */ldr r4, =0mcr 15,0,r4,cr1,cr0,0 /* disable the ICache and MMU */isb /* make sure it completes */ Loop:wfeb LoopFsblHandoffExit: #ifdef DDRLESS_SYSTEMmov lr, r0 /* move the destination address into link register */bx lr /* force the switch, destination should have been in r0 */ #elsemov 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 */dsbisb /* make sure it completes */ldr r4, =0mcr 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#elif defined (__IASMARM__)PUBLIC FsblHandoffJtagExitPUBLIC FsblHandoffExitSECTION .handoff:CODE:NOROOT(2)/***************************** Include Files *********************************//************************** Constant Definitions *****************************//**************************** Type Definitions *******************************//***************** Macros (Inline Functions) Definitions *********************//************************** Function Prototypes ******************************//************************** Variable Definitions *****************************/FsblHandoffJtagExitmcr p15,0,r0,c7,c5,0 ;/* Invalidate Instruction cache */mcr p15,0,r0,c7,c5,6 ;/* Invalidate branch predictor array */dsbisb ;/* make sure it completes */ldr r4, =0mcr p15,0,r4,c1,c0,0 ;/* disable the ICache and MMU */isb ;/* make sure it completes */ Loopwfeb LoopFsblHandoffExit #ifdef DDRLESS_SYSTEMmov lr, r0 /* move the destination address into link register */bx lr /* force the switch, destination should have been in r0 */ #elsemov lr, r0 ;/* move the destination address into link register */mcr p15,0,r0,c7,c5,0 ;/* Invalidate Instruction cache */mcr p15,0,r0,c7,c5,6 ;/* Invalidate branch predictor array */dsbisb ;/* make sure it completes */ldr r4, =0mcr p15,0,r4,c1,c0,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#elseEXPORT FsblHandoffJtagExitEXPORT FsblHandoffExitAREA |.handoff|,CODE;/***************************** Include Files *********************************/;/************************** Constant Definitions *****************************/;/**************************** Type Definitions *******************************/;/***************** Macros (Inline Functions) Definitions *********************/;/************************** Function Prototypes ******************************/;/************************** Variable Definitions *****************************/FsblHandoffJtagExitmcr p15,0,r0,c7,c5,0 ;/* Invalidate Instruction cache */mcr p15,0,r0,c7,c5,6 ;/* Invalidate branch predictor array */dsbisb ;/* make sure it completes */ldr r4, =0mcr p15,0,r4,c1,c0,0 ;/* disable the ICache and MMU */isb ;/* make sure it completes */ Loopwfeb LoopFsblHandoffExit #ifdef DDRLESS_SYSTEMmov lr, r0 /* move the destination address into link register */bx lr /* force the switch, destination should have been in r0 */ #elsemov lr, r0 ;/* move the destination address into link register */mcr p15,0,r0,c7,c5,0 ;/* Invalidate Instruction cache */mcr p15,0,r0,c7,c5,6 ;/* Invalidate branch predictor array */dsbisb ;/* make sure it completes */ldr r4, =0mcr p15,0,r4,c1,c0,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 #endif?
Fsbl_hooks.c修改
修改部分如下:
/******************************************************************************** Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved.** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:** The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.** Use of the Software is limited solely to applications:* (a) running on a Xilinx device, or* (b) that interact with a Xilinx device through a bus or interconnect.** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE* SOFTWARE.** Except as contained in this notice, the name of the Xilinx shall not be used* in advertising or otherwise to promote the sale, use or other dealings in* this Software without prior written authorization from Xilinx.*******************************************************************************//******************************************************************************* @file fsbl_hooks.c** This file provides functions that serve as user hooks. The user can add the* additional functionality required into these routines. This would help retain* the normal FSBL flow unchanged.** <pre>* MODIFICATION HISTORY:** Ver Who Date Changes* ----- ---- -------- -------------------------------------------------------* 3.00a np 08/03/12 Initial release* </pre>** @note*******************************************************************************/#include "fsbl.h" #include "xstatus.h" #include "fsbl_hooks.h"/************************** Variable Definitions *****************************//************************** Function Prototypes ******************************//******************************************************************************* This function is the hook which will be called before the bitstream download.* The user can add all the customized code required to be executed before the* bitstream download to this routine.** @param None** @return* - XST_SUCCESS to indicate success* - XST_FAILURE.to indicate failure*****************************************************************************/ u32 FsblHookBeforeBitstreamDload(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 FsblHookBeforeBitstreamDload function \r\n");return (Status); }/******************************************************************************* This function is the hook which will be called after the bitstream download.* The user can add all the customized code required to be executed after the* bitstream download to this routine.** @param None** @return* - XST_SUCCESS to indicate success* - XST_FAILURE.to indicate failure*****************************************************************************/ u32 FsblHookAfterBitstreamDload(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 FsblHookAfterBitstreamDload function \r\n");return (Status); }/******************************************************************************* This function is the hook which will be called before the FSBL does a handoff* to the application. The user can add all the customized code required to be* executed before the handoff to this routine.** @param None** @return* - XST_SUCCESS to indicate success* - XST_FAILURE.to indicate failure*****************************************************************************/ 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); }/******************************************************************************* This function is the hook which will be called in case FSBL fall back** @param None** @return None*****************************************************************************/ void FsblHookFallback(void) {/** User logic to be added here.* Errors to be stored in the status variable and returned*/fsbl_printf(DEBUG_INFO, "In FsblHookFallback function \r\n");while (1); }?
Fsbl_hook.h修改
/****************************************************************************** * * Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /*****************************************************************************/ /** * * @file fsbl_hooks.h * * Contains the function prototypes, defines and macros required by fsbl_hooks.c * * <pre> * MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- ------------------------------------------------------- * 3.00a np/mb 10/08/12 Initial release * Corrected the prototype * * </pre> * * @note * ******************************************************************************/ #ifndef FSBL_HOOKS_H_ #define FSBL_HOOKS_H_#ifdef __cplusplus extern "C" { #endif/***************************** Include Files *********************************/ #include "fsbl.h"/************************** Function Prototypes ******************************//* FSBL hook function which is called before bitstream download */ u32 FsblHookBeforeBitstreamDload(void);/* FSBL hook function which is called after bitstream download */ u32 FsblHookAfterBitstreamDload(void);/* FSBL hook function which is called before handoff to the application */ u32 FsblHookBeforeHandoff(u32 FsblStartAddr);/* FSBL hook function which is called in FSBL fallback */ void FsblHookFallback(void);#ifdef __cplusplus } #endif#endif /* end of protection macro */?
Lscript.ld修改
該文件為生成.elf過(guò)程中的鏈接文件,主要修改MEMORY地址,如下。
?
Fsb中使用的空間包括OCM 0-191KB 及后面256字節(jié),FLASH 8KB-3MB。
各section的配置參看具體代碼。
/****************************************************************************** * * Copyright (C) 2012 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/_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 = 0x0002FF00ps7_ram_0_S_AXI_BASEADDR_1 : ORIGIN = 0x0002FF00, LENGTH = 0x0000100 FLASH : ORIGIN = 0xFC000000 + 0x2000, 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 .init : {KEEP (*(.init)) } > FLASH .fini : {KEEP (*(.fini)) } > FLASH .rodata : {__rodata_start = .;*(.rodata)*(.rodata.*)*(.gnu.linkonce.r.*)__rodata_end = .; } > FLASH .data : {_dataVMA_start = .;*(.data)*(.data.*)*(.gnu.linkonce.d.*)*(.jcr)*(.got)*(.got.plt)_dataVMA_end = .; } > ps7_ram_0_S_AXI_BASEADDR AT> FLASH_dataLMA = LOADADDR(.data);.eh_frame : {*(.eh_frame) } > FLASH.sbss (NOLOAD) : {__sbss_start = .;*(.sbss)*(.sbss.*)*(.gnu.linkonce.sb.*)__sbss_end = .; } > ps7_ram_0_S_AXI_BASEADDR.bss (NOLOAD) : {__bss_start = .;*(.bss)*(.bss.*)*(.gnu.linkonce.b.*)*(COMMON)__bss_end = .; } > ps7_ram_0_S_AXI_BASEADDR.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.mmu_tbl ALIGN(0x4000): {__mmu_tbl_start = .;*(.mmu_tbl)__mmu_tbl_end = .; } > FLASH/* _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_0_S_AXI_BASEADDR_1 AT> FLASH_dataXVtableLMA = LOADADDR(.XVtable);_end = .; }?
當(dāng)前ZYNQ中地址分配如下:
?
OCM地址從0x0-0x0003ffff,QSPI地址從0xfc000000-0xfdffffff。Fsbl中會(huì)用到這兩段地址,上面的memory中ps7_ram_0_S_AXI_BASEADDR和ps7_ram_0_S_AXI_BASEADDR_1使用了OCM空間,FLASH使用了QSPI FLASH空間。
?
通過(guò)查看fsbl.elf文件,可以查看目前sections的分配,對(duì)于其中具有READONLY屬性的section,可以放在QSPI FLASH中運(yùn)行,即XIP模式。
以下是一個(gè)FSBL.elf示例
?
上圖中.text,.handoff等都是READONLY屬性,所以在ldscript.ld中將他們放在FLASH中。
?
對(duì)于不是READONLY屬性的section,如下
?
需要直接在OCM中為其分配地址
?
對(duì).data段進(jìn)行特殊處理,需要load,即從QSPI FLASH中搬到ocm中,如下:
?
添加宏定義
代碼修改完后,在fsbl工程中添加兩個(gè)宏定義。
?
編譯,會(huì)發(fā)現(xiàn).data未分配,這個(gè)錯(cuò)誤不用管,能順利得到fsbl.elf文件
?
3、APP修改
應(yīng)用程序需要修改的地方如下
Main.c修改
在main函數(shù)中需要增加將.data拷貝到OCM中的操作
/****************************************************************************** * * (c) Copyright 2011-2012 Xilinx, Inc. All rights reserved. * * This file contains confidential and proprietary information of Xilinx, Inc. * and is protected under U.S. and international copyright and other * intellectual property laws. * * DISCLAIMER * This disclaimer is not a license and does not grant any rights to the * materials distributed herewith. Except as otherwise provided in a valid * license issued to you by Xilinx, and to the maximum extent permitted by * applicable law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL * FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, * IMPLIED, OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF * MERCHANTABILITY, NON-INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; * and (2) Xilinx shall not be liable (whether in contract or tort, including * negligence, or under any other theory of liability) for any loss or damage * of any kind or nature related to, arising under or in connection with these * materials, including for any direct, or any indirect, special, incidental, * or consequential loss or damage (including loss of data, profits, goodwill, * or any type of loss or damage suffered as a result of any action brought by * a third party) even if such damage or loss was reasonably foreseeable or * Xilinx had been advised of the possibility of the same. * * CRITICAL APPLICATIONS * Xilinx products are not designed or intended to be fail-safe, or for use in * any application requiring fail-safe performance, such as life-support or * safety devices or systems, Class III medical devices, nuclear facilities, * applications related to the deployment of airbags, or any other applications * that could lead to death, personal injury, or severe property or * environmental damage (individually and collectively, "Critical * Applications"). Customer assumes the sole risk and liability of any use of * Xilinx products in Critical Applications, subject only to applicable laws * and regulations governing limitations on product liability. * * THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE * AT ALL TIMES. * *******************************************************************************/ /*****************************************************************************/ /** * * @file Application.c * * The Appliation file is small application. * * <pre> * MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- -------------------------------------------------------******************************************************************************//***************************** Include Files *********************************/ #include <stdio.h> //#include "platform.h" #include "xil_print.h"#define XPS_L2CC_BASEADDR 0xF8F02000 #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 0xE000D000extern 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; }int 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);xil_printf("Application Starts hello world\n\r");return 0;}?
standalone修改
將實(shí)例工程里面的src目錄下standalone目錄拷貝到應(yīng)用工程中,注意將其中兩個(gè)xparameters.h替換為實(shí)際工程的
Ldscript.ld修改
同fsbl一樣,APP中也需要指定地址空間
_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x2000; _HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x2000;MEMORY {FLASH : ORIGIN = 0xFC700000, LENGTH = 0x100000ps7_ram_0_S_AXI_BASEADDR : ORIGIN = 0x00010000, LENGTH = 0x0001FF00ps7_ram_1_S_AXI_BASEADDR : ORIGIN = 0x0002ff00, LENGTH = 0x00000100 }ENTRY(_startcode)SECTIONS {/DISCARD/ : {*(.ARM.exidx) } .ro : ALIGN(0x40){*(.text)*(.rodata)} > FLASH.rw : ALIGN(0x40){_dataVMA_start = .;*(.data)*(.bss) *(COMMON)_dataVMA_end = .;}> ps7_ram_0_S_AXI_BASEADDR AT> FLASH_dataLMA = LOADADDR(.rw); .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; }> ps7_ram_0_S_AXI_BASEADDR.XVtable : {_dataXVtableVMA_start = .;*(XVtable)_dataXVtableVMA_end = .; } > ps7_ram_1_S_AXI_BASEADDR AT> FLASH_dataXVtableLMA = LOADADDR(.XVtable); }?
APP使用FLASH區(qū)域?yàn)?MB-8MB,使用OCM區(qū)域?yàn)?4KB-191KB以及后續(xù)256字節(jié),從下圖中能看到bootrom執(zhí)行后系統(tǒng)內(nèi)存空間變化情況。
?
當(dāng)bootrom執(zhí)行后OCM MEMORY為0-192KB,fsbl和app都只能使用這段區(qū)域。
通過(guò)查看app.elf文件,也能看到READONLY屬性的段,這些段也放在QSPI FLASH中即可,另一些段從QSPI FLASH中拷貝到OCM中執(zhí)行。
?
?
?
4、生成boot.bin
生成boot.bin需要使用bif文件,需要注意設(shè)置xip模式
//arch = zynq; split = false; format = BIN the_ROM_image: {[bootloader, xip_mode,offset = 0x2000]F:\Reference_Design_Files\test\FSBL_XIP.elf[offset = 0x200000]F:\Reference_Design_Files\test\system_top_wrapper.bit[offset = 0x700000]F:\Reference_Design_Files\test\Application.elf }?
如上圖所示,fsbl_xip.elf從QSPI FLASH的0x2000地址開(kāi)始存儲(chǔ),與fsbl中l(wèi)script.ld內(nèi)存空間FLASH地址一致。Bit文件從2MB位置開(kāi)始存儲(chǔ),應(yīng)用程序從7MB位置開(kāi)始存儲(chǔ),這又與app中l(wèi)script.ld內(nèi)存空間FLASH地址一致。
生成boot.bin時(shí)不能通過(guò)SDK圖形化方式產(chǎn)生,必須要使用命令行方式
?
最后將boot.bin燒入QSPI FLASH即可。
總結(jié)
以上是生活随笔為你收集整理的ZYNQ上无DDR加载应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: C. Chocolate Bunny(思
- 下一篇: 算法的时间复杂度表示法(大O表示法)