|
没有什么开篇语,这是献给用XUP开发板或者类似配置的开发板的朋友。也不用管你的fpga板子有多类似,只要都有SDRAM,CF即可。我就不做bootloader的详细普及了,简单说在这里,它就是用一个在bram中运行的小程序把在sdram中运行的程序elf文件从cf卡中读出来加载到sdram中。详细的bootloader介绍请参考这篇文章。
单独一段,严重感谢蝈蝈师兄,在我焦头烂额的时候继续这个艰苦的工作,呵呵,现在你在攒人品,下个月漫天offer会接踵而来的。那些今年来西电招应届生的,需要纯fpga方面人才的朋友,如果你们不招他,是你们的损失,不是他的,相信我。
下面就是具体的步骤介绍,有问题的朋友可以留言或者邮件联系,如有错误,敬请指正。
1.将待运行的elf程序转换为srec文件
在shell下运行以下命令
powerpc-eabi-objcopy -O srec executable.elf executable.srec
srec文件的格式介绍如下:
标记(char[2])|字节计数(char[2])|地址|数据|校验 S012 00006578 6563757461626C652E73726563F0
S315 00000000 9421FFF0906100089161000C3C600002 B1 S315 00000010 806372647D7FF2A6916300007D7EF2A6 06 … S315 00000020 916300047D6802A6916300087D6902A6 BB S315 0002719C 00026BE40000000100020000FFFFFFFF 8B S315 002999C4 3C000000600020E07C0803A64E800020 AD
S705 FFFFFFFC 01
其中标记部分规定了地址和数据部分的格式。 S0表示后面的地址固定为0000数据段中包含module name,version number,revision number,text comment. S1表示后面的地址部分为2byte,数据为将要load到memory的数据 S2表示后面的地址部分为3byte,数据为将要load到memory的数据 S3表示后面的地址部分为4byte,数据为将要load到memory的数据 S5表示后面的地址部分为2byte,数据为之前传输的S1,S2,S3的总的计数值 S7表示后面的地址部分为4byte,表示程序的起始执行地址,没有数据部分 S8表示后面的地址部分为3byte,表示程序的起始执行地址,没有数据部分 S9表示后面的地址部分为2byte,表示程序的起始执行地址,没有数据部分
2. 注意几点
a. 对于CF卡的读写缓存应该设置大一些可以设置为1MB左右。 b. 由于上面缓存设置相应会引起.bss段较大,所以在linkscript中将.bss段和heap,steak设置到外部SDRAM 中。 c. 修改linkscript中队外部SDRAM的声明将起始地址设置大一些,这样可以使相应的.bss .heap .steak都置于SDRAM的高端地址。因为bootloader工作后要将外部程序搬移到SDRAM的低端地址。
3. 按照下面步骤进行bootloader运行的全过程
a. 运行对周围设备的配置程序。 b. 对配置好的所有设备进行测试。 c. 将CF卡中的可执行文件(srec格式)读出放入SDRAM中以待处理。 d. 按照srec格式的要求加载程序。 e. 将程序指针跳转到_boot0段,这要程序会自动运行到.text段,对于内部bram运行的程序来说.text段恰好是内部bram的起始地址,而对于ld配置为sdram中运行的程序来说,bram的起始地址恰好是.boot0段。在程序跳转到现有的.text段时实际上.text段已经被修改成新程序的.boot0段了,所以程序可以加载。
#include “xparameters.h”
#include “stdio.h” #include “xutil.h” #include “ddr_header.h” #include “xsysace.h” #include “sysace_stdio.h” //This buffer is used to store executable file #define LOADER_BUFFER_BASSADDRESS (char *)0×1000000 //This number should not be smaller than the executable file size #define ELF_MAX_FILE_SIZE 104857600 //Define the executable file name in the CF card. #define EXE_FILE_NAME ” exe.sre”
void load_elf_from_cf( void ); //==================================================== int main (void) {
print(”***********************\r\n”); print(”** Start bootloader! **\r\n”); print(”***********************\r\n\r\n”);
/* Testing DDR Memory (DDR_256MB_32MX64_rank1_row13_col10_cl2_5)*/ { XStatus status;
print(”Starting SDRAM test:\r\n”); print(” Running 32-bit test…”); status = XUtil_MemoryTest32((Xuint32*)XPAR_DDR_SDRAM_32MX64_ECC_BASEADDR, 2048, 0, XUT_FIXEDPATTERN); if (status == XST_SUCCESS) { print(”PASSED!\r\n”); } else { print(”FAILED!\r\n”); } print(” Running 16-bit test…”); status = XUtil_MemoryTest16((Xuint16*)XPAR_DDR_SDRAM_32MX64_ECC_BASEADDR, 2048, 0xAA55, XUT_ALLMEMTESTS); if (status == XST_SUCCESS) { print(”PASSED!\r\n”); } else { print(”FAILED!\r\n”); } print(” Running 8-bit test…”); status = XUtil_MemoryTest8((Xuint8*)XPAR_DDR_SDRAM_32MX64_ECC_BASEADDR, 4096, 0xA5, XUT_ALLMEMTESTS); if (status == XST_SUCCESS) { print(”PASSED!\r\n”); } else { print(”FAILED!\r\n”); } }
//download program load_elf_from_cf();
__asm (”b _boot0″); return 0; }
//Reading out the executable file (srec format) and processing //it line to line void load_elf_from_cf( void )// TestApp_Memory { print(”\r\nStarting CF test…”); XStatus Status; XSysAce cf; SYSACE_FILE *fp; Xint32 filesize = 0,i=0,j=0,k=0; Xint32 Tstate=0; char filename[20]=EXE_FILE_NAME; char *buffer=LOADER_BUFFER_BASSADDRESS;
/* */ Status = XSysAce_Initialize( &cf,XPAR_SYSACE_COMPACTFLASH_DEVICE_ID ); if (Status != XST_SUCCESS) { print(”init FAILED!\r\n”); return; }
Status = XSysAce_SelfTest(&cf); if (Status != XST_SUCCESS) { print(”FAILED!\r\n”); return; } else print(”PASSED!\r\n”);
//Change directory //Tstate=sysace_chdir (”a:\\srec”); //xil_printf(”test %d \r\n”,Tstate);
//read file fp = sysace_fopen( filename,”r” ); if (fp <= 0) { print(" executable file open erro!\r\n"); return; } else print("\r\nLoading .srec file from CF...");
print("Wait...\r\n"); filesize = sysace_fread(&buffer[i],ELF_MAX_FILE_SIZE,1,fp);
if (filesize <= 0) { print(" executable file size erro! \r\n"); return; } else xil_printf(" The executable file size is %d bytes\r\n",filesize);
sysace_fclose( fp );
print("\r\nProcessing and downloading the executable file to SDRAM:\r\n");
Xint8 *address=0; Xint8 data; i=0;j=0;k=0; for(k=0;k { if(buffer[k]>=’A’ && buffer[k]<='F') buffer[k]-=7; } print(" pre-process step1 ok.\r\n"); while(i { if (buffer[i]=='S' && buffer[i+1]=='3') { //the count length of this section. k=(((buffer[i+2]-'0')<<4)+(buffer[i+3]-'0'))-5;
i+=4; //Get address address = ((buffer[i+0]-'0')<<28)+((buffer[i+1]-'0')<<24)+((buffer[i+2]-'0')<<20)+ ((buffer[i+3]-'0')<<16)+((buffer[i+4]-'0')<<12)+((buffer[i+5]-'0')<<8)+ ((buffer[i+6]-'0')<<4)+((buffer[i+7]-'0')); /* Used for debug if (address <0x2000000) address+=+ 0x2000000; */ i+=8; /* Used for debug if (address > 0×2026B00) xil_printf(”\r\n%7d %8X “,i,address); */ //Write data for(j=0;j { data = (((buffer[i+(j<<1)]-'0')<<4)+(buffer[i+(j<<1)+1]-'0')); *(address+j) = data; /* Used for debug if (address > 0×2026B00) xil_printf(” %2X”,data); */ } //next ‘S’ i=(i+((k+1)<<1)); } else i++; } print(” pre-process step2 ok.\r\n”); print(”\r\n***********************\r\n”); print(”** Boot done! ***\r\n”); print(”***********************\r\n”); print(”\r\n\r\n\r\n\r\n”); // while(1); }
|