📄 m5i20cfg.c
字号:
*/static int programdunq(void){ return (inl(P_5I20PRGMDUN) & M_5I20PRGMDUN) == M_5I20PRGMDUNNOW ;}/*---------------------------------------------------------------------------*//* Function: wait4dun Purpose: Wait for the FPGA to finish programming. Used by: Local functions. Returns: Done/timeout status. Notes: -Failure to become DONE may be caused by an attempt to load an invalid FPGA code image, or an I/O address conflict. Revision history: 1) Monday February 21, 2005 -- 20:12:17.*/static signed wait4dun(void){ clock_t then ; unsigned waitcount ; /* Wait at least long enough for the FPGA to finish its post-programming tomfoolery. This time is generally masked by software overhead, but the programmer needs to be aware of it. */ then = (clock() + ((CLOCKS_PER_SEC / 10000) + 1)) ; /* 100 uS. should be enough. */ while(clock() < then) { ; } /* The DONE bit should now indicate end of programming. */ if(programdunq()) { /* Programming seems to be complete; make sure the state sticks and we're not seeing some sort of I/O conflict-related foo. */ for(waitcount = 100 ; waitcount != 0 ; --waitcount) { if(!programdunq()) { return -1 ; /* (Shouldn't.) */ } } return 0 ; /* Success. */ } else { return -1 ; /* Failure -- didn't become DONE. */ }}/*---------------------------------------------------------------------------*//* Function: delay100us Purpose: Wait for 100 uS. Used by: Local functions. Returns: Nothing. Notes: Revision history: 1) Monday February 21, 2005 -- 20:12:17.*/static void delay100us(void){ clock_t then ; then = (clock() + ((CLOCKS_PER_SEC / 10000) + 1)) ; while(clock() < then) { ; }}/*---------------------------------------------------------------------------*//* Function: filelengthq Purpose: Determine the length of the specified file. Used by: Local functions. Returns: The file length, or -1 on failure. Notes: Revision history: 1) Monday February 21, 2005 -- 20:12:17. 2) Thursday February 24, 2005 -- 12:12:48. -We now return unsigned long instead of off_t.*/static unsigned long filelengthq(FILE *f){ struct stat fileinfo ; fstat(fileno(f), &fileinfo) ; return fileinfo.st_size ;}/*---------------------------------------------------------------------------*//* Function: saybytesfromfile Purpose: Send the bytes from the specified offset in the specified open file to standard out. Used by: Local functions. Returns: The number of bytes read. Notes: -It is assumed that numbytes includes the trailing '\0'. -The file position is not restored to its original value. -Don't try to output 0 bytes. Revision history: 1) Monday February 21, 2005 -- 20:12:17.*/static size_t saybytesfromfile(FILE *f, long fromoffset, size_t numbytes, FILE *str){ int c ; size_t len = 0 ; if(fseek(f, fromoffset, SEEK_SET) != 0) { return 0 ; } while(numbytes-- != 0) { if((c = getc(f)) == EOF) { break ; } ++len ; if(c == '\0') { break ; } fputc(c, str) ; } return len ;}/*---------------------------------------------------------------------------*//* Function: readbytesfromfile Purpose: Read the specified number of bytes from the specified offset in the specified open file to the specified address. Used by: Local functions. Returns: The number of bytes read. Notes: -The file position is not restored to its original value. -Don't try to read 0 bytes. Revision history: 1) Monday February 21, 2005 -- 20:12:17.*/static size_t readbytesfromfile(FILE *f, long fromoffset, size_t numbytes, ubyte *bufptr){ if(fseek(f, fromoffset, SEEK_SET) != 0) { return 0 ; } return fread(bufptr, 1, numbytes, f) ;}/*---------------------------------------------------------------------------*//* Function: sayfileinfo Purpose: Display some bytes from our configuration file on standard out. Used by: Local functions. Returns: Nothing. Notes: -It is assumed that numbytes includes the trailing '\0'. -The file position is not restored to its original value. -Don't try to output 0 bytes. Revision history: 1) Monday February 21, 2005 -- 20:12:17.*/static void sayfileinfo(signed long *infobaseptr, FILE *str){ size_t len ; ubyte b[2] ; if(readbytesfromfile(ConfigFile, *infobaseptr, sizeof(b), b) != sizeof(b)) { ioerror: fatalerror(EC_FILE, "File I/O error. Unexpected end of file?") ; } len = ((b[0] << 8) | b[1]) ; /* (Bigendian.) */ if(saybytesfromfile(ConfigFile, (*infobaseptr + sizeof(b)), len, str) != len) { goto ioerror ; } *infobaseptr += (sizeof(b) + (signed long)len + 1) ; /* Skip over length field, text field, and tag. */}/*---------------------------------------------------------------------------*//* Function: selectfiletype Purpose: Set up for processing the input file. Used by: Local functions. Returns: Nothing. Notes: Revision history: 1) Monday February 21, 2005 -- 20:12:17.*/static void selectfiletype(void){ ubyte b[14] ; FILE *bitstr; bitstr = (PrintConfig)? OutStr: InfoStr; /* Read in the interesting parts of the file header. */ if(readbytesfromfile(ConfigFile, 0, sizeof(b), b) != sizeof(b)) { ioerror: fatalerror(EC_FILE, "File I/O error. Unexpected end of file?") ; } /* Figure out what kind of file we have. */ if((b[0] == 0x00) && (b[1] == 0x09) && (b[11] == 0x00) && (b[12] == 0x01) && (b[13] == 'a')) { /* Looks like a .BIT file. */ signed long base ; fprintf(InfoStr, "\nLooks like a .BIT file:") ; base = 14 ; /* Offset of design name length field. */ /* Display file particulars. */ if(PrintConfig) fprintf(bitstr, "/*"); fprintf(bitstr, "\n Design name: ") ; sayfileinfo(&base, bitstr) ; fprintf(bitstr, "\n Part I.D.: ") ; sayfileinfo(&base, bitstr) ; fprintf(bitstr, "\n Design date: ") ; sayfileinfo(&base, bitstr) ; fprintf(bitstr, "\n Design time: ") ; sayfileinfo(&base, bitstr) ; if(readbytesfromfile(ConfigFile, base, 4, b) != 4) { goto ioerror ; } ImageLen = (((unsigned long)b[0] << 24) | ((unsigned long)b[1] << 16) | ((unsigned long)b[2] << 8) | (unsigned long)b[3]) ; fprintf(bitstr, "\n Configuration length: %lu bytes", ImageLen) ; if(PrintConfig) fprintf(bitstr, "\n*/\n"); DataOutFuncPtr = outdata8wswap ; /* We have to swap bits in .BIT files. */ /* We leave the file position set to the next byte in the file, which should be the first byte of the body of the data image. */ } else if((b[0] == 0xFF) && (b[4] == 0x55) && (b[5] == 0x99) && (b[6] == 0xAA) && (b[7] == 0x66)) { /* Looks like a PROM file. */ fprintf(InfoStr, "\nLooks like a PROM file:") ; DataOutFuncPtr = outdata8noswap ; /* No bit swap in PROM files. */ ImageLen = filelengthq(ConfigFile); ; if(ImageLen < 0) { seekerror: fatalerror(EC_SYS, "File seek error.") ; } fprintf(InfoStr, "\n Configuration length: %lu bytes", ImageLen) ; /* PROM file data starts at offset 0, so we have to back up. */ if(fseek(ConfigFile, 0, SEEK_SET) != 0) { goto seekerror ; } } else { /* It isn't something we know about. */ fatalerror(EC_FILE, "Unknown file type.") ; } fputc('\n', InfoStr) ; fflush(InfoStr) ; /* (Make sure the user can see all output to date.) */}/*---------------------------------------------------------------------------*//* Function: signon Purpose: Display the signon message. Used by: Local functions. Returns: Nothing. Notes: Revision history: 1) Monday February 21, 2005 -- 20:12:17.*/static void signon(void){ fprintf(InfoStr, "%s", SIGNONMESSAGE) ; fprintf(InfoStr, "Mesa Electronics 5I20 configuration utility for Linux.\n") ; fflush(InfoStr) ;}/*---------------------------------------------------------------------------*//* Function: pcl Purpose: Collect parameters from the command line. Used by: Local functions. Returns: Nothing. Notes: Revision history: 1) Monday February 21, 2005 -- 20:12:17.*/static const char FileNameInfo[] = "\n""filename.ext specifies the name of the configuration file to be loaded." ;static const char CardInfo[] = "\n""card is the number of the PCI card. (For use with multiple 5I20 cards.)" ;static const char PurposeInfo[] = "\n""Purpose: 5I20 configuration upload." ;static void pcl(unsigned argc, char *argv[]){ unsigned cardnum = 0 ; if((argc != 2) && (argc != 3)) { fprintf(InfoStr, "\n%s program usage:\n%s filename.ext [<card>]", ProgNameMsg, ProgNameMsg) ; fprintf(InfoStr, "\nWhere:") ; fprintf(InfoStr, "%s", FileNameInfo) ; fprintf(InfoStr, "%s", CardInfo) ; fprintf(InfoStr, "%s", PurposeInfo) ; fputc('\n', InfoStr) ; fflush(InfoStr) ; exit(EC_BADCL) ; } if((ConfigFile = fopen(argv[1], "rb")) == 0) /* (Binary mode.) */ { fatalerror(EC_USER, "File not found: %s", argv[1]) ; } if(argc == 2) { PrintConfig = 1; } else { if(sscanf(argv[2], "%u", &cardnum) != 1) { badcardnum: fatalerror(EC_USER, "Invalid card number: %s", argv[2]) ; } if(cardnum > 15) { goto badcardnum ; } findpcicard(cardnum) ; } selectfiletype() ;}/*---------------------------------------------------------------------------*//* Function: programfpga Purpose: Initialize the FPGA with the contents of file ConfigFile. Used by: Local functions. Returns: Nothing. Notes: Revision history: 1) Monday February 21, 2005 -- 20:12:17.*/#define FORMATSTRING "%-6lu"static void programfpga(void){ signed long bytesleft ; unsigned long numbytes ; size_t count ; static ubyte filebuffer[16384] ; ubyte *bptr ; /* Enable programming. */ fprintf(InfoStr, "\nProgramming...\n") ; fflush(InfoStr) ; if(PrintConfig) { fprintf(OutStr, "\nstatic hal_u8_t\n"); fprintf(OutStr, "fpgaConfig[] = {"); } else { programdisable() ; /* Reset the FPGA. */ if(programdunq()) { /* Note that if we see DONE at the start of programming, it's most likely due to an attempt to access the FPGA at the wrong I/O location. */ fatalerror(EC_HDW, "<DONE> status bit indicates busy at start of programming.") ; } programenable() ; /* Delay for at least 100 uS. to allow the FPGA to finish its reset sequencing. (In reality, the time taken for the initial file access makes this this delay redundant.) */ delay100us() ; } /* Program the card. */ numbytes = 0 ; bytesleft = ImageLen ; for( ; ; ) { /* Write the file to the FPGA. */ errno = 0 ; count = fread(filebuffer, 1, sizeof(filebuffer), ConfigFile) ; if(count == 0) { /* 0 bytes could be end of file or error; must check. */ if(errno != 0) { if(!PrintConfig) programdisable() ; fatalerror(EC_SYS, "File I/O error.") ; } else { fprintf(InfoStr, FORMATSTRING, 0L) ; fflush(InfoStr) ; break ; /* Done. */ } } else { /* Write the block to the FPGA data port. */ fprintf(InfoStr, FORMATSTRING "\r", bytesleft) ; fflush(InfoStr) ; bytesleft -= (signed long)count ; bptr = filebuffer ; do { if(PrintConfig && ((numbytes & 0x7) == 0)) fprintf(OutStr, "\n "); DataOutFuncPtr(*bptr++) ; numbytes++; } while(--count != 0) ; } } fclose(ConfigFile) ; /* Wait for completion of programming. */ if(!PrintConfig && (wait4dun() < 0)) { fatalerror(EC_HDW, "Error: Not <DONE>; programming not completed.") ; } if(PrintConfig) { fprintf(OutStr, "\n};\n"); fflush(OutStr); } else { /* Send configuration completion clocks. */ sendcompletionclocks() ; } fprintf(InfoStr, "\nSuccessfully programmed %lu bytes.", numbytes) ; fflush(InfoStr) ;}/*---------------------------------------------------------------------------*//* Function: main Purpose: Program entry point. Used by: Program launcher. Returns: Exit status. Notes: Revision history: 1) Monday February 21, 2005 -- 20:12:17.*/int main(int argc, char *argv[]){ InfoStr = stderr; ErrStr = stderr; OutStr = stdout; signon() ; pcl(argc, argv) ; programfpga() ; cleanup() ; fprintf(InfoStr, "\n\nFunction complete.\n") ; fflush(InfoStr) ; return 0 ;}/*---------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -