📄 fpga.c
字号:
/* * fpga.c * * Xilinx FPGA programming module. * This code uses GPIOs to program the Xilinx SpartanII family of FPGA * using the slave paraller mode to load the bit file. * It recognizes as input the .bit file generated by the VHDL compiler, * and expects an address of where the file is located in memory as argument. * * by Thomas E. Arvanitis (tharvan@inaccessnetworks.com) * by Dimitris Economou (decon@inaccessnetworks.com) */#include "config.h"#if INCLUDE_FPGA#include "SA-1100.h"#include "fpga.h"#include "genlib.h"#include "stddefs.h"#include "monapp.h"#include "tfs.h"#include "tfsprivate.h"void set_gpio_dirpin(int pin, int dir){ unsigned long reg_val; reg_val = 0; reg_val = rdreg(&GPDR); switch(dir){ case 1: reg_val |= (1<<pin); break; case 0: reg_val &= ~(1<<pin); break; default: ; } wrreg(&GPDR, reg_val);}void set_gpio_setpin(int pin){ GPSR |= (1<<pin);}void set_gpio_clspin(int pin){ GPCR |= (1<<pin);}unsigned long check_gpio_pin(int pin){ unsigned long reg_val, ret_val; reg_val = 0; reg_val = rdreg(&GPLR); ret_val = reg_val & (1<<pin); return ret_val;}void udelay(int us){ volatile int i; int loops; loops = us * LoopsPerSecond/1000000; for (i=0; i<loops; i++);}/* * XILINX clean memory: * Initiate a memory clean configuration cycle */intfpga_mem_clean(void){ unsigned long reg_val; reg_val = 0; reg_val = rdreg(&GPDR); set_gpio_dirpin(FPGA_PROG_PIN, OUTDIR); set_gpio_dirpin(FPGA_INIT_PIN, INDIR); set_gpio_clspin(FPGA_PROG_PIN); udelay(WAIT_TIME); set_gpio_setpin(FPGA_PROG_PIN); D(if (!check_gpio_pin(FPGA_INIT_PIN)) printf("After PROGRAM goes HIGH INIT stays LOW for a while\n");) /* * Wait until the init goes down, * means mem is clear. */ while (!check_gpio_pin(FPGA_INIT_PIN)); return OK;}/* * XILINX programing mode: * Enter the fpga programming mode. * Download a byte sequence located at address_in. */int fpga_program(unsigned long *address_in){ register int i, j, k, cnt; register unsigned char xbuf, tmp, rbyte; register unsigned char *dst; register unsigned long *buf; register unsigned long ltmp; int bitf_ok; buf = address_in; dst = (unsigned char *) FPGA_PROG_ADDR; /* * Search for the dummy byte in the bit file, * and start from there on, to skip the embedded useless header * of the bit file. * * We only search the first 512 bytes, else it is obvious * it is not a bit file. */ bitf_ok = 0; cnt = 0; while ((cnt < 4) && (buf < address_in+0x200)) { for (j=0; j<4; j++) { ltmp = *buf >> (j*8); xbuf = (unsigned char) (ltmp & 0xff); if (xbuf == XLNX_DBYTE) { cnt++; D(printf("Address of buf = 0x%08x\n", buf);) } else cnt = 0; if (cnt == 4) { bitf_ok = 1; break; } } buf++; } if (bitf_ok == 0) return ERR_BITF; buf--; /* go back one word */ j++; /* buf has the address of current word and j points first byte after the DUMMY WORD*/ for (k=0; k<4; k++) {/* Write the DUMMY WORD*/ *dst = XLNX_DBYTE; D(printf("Downloaded word: 0x%x\n", XLNX_DBYTE);) } for (; j<4; j++) { rbyte = 0; ltmp = *buf >> (j*8); xbuf = (unsigned char) (ltmp & 0xff); for (k=0; k<8; k++) { tmp = xbuf >> k; tmp &= 1; rbyte |= tmp<<(7-k); } *dst = rbyte; D(printf("Downloaded word: 0x%x\n", rbyte);) } buf++; /* Buf points to the next of DUMMY_WORD word */ for (i=0; i<FPGA_BYTE_LENGTH/4; i++) { /* Reverse byte endianess */ for (j=0; j<4; j++) { rbyte = 0; ltmp = *buf >> (j*8); xbuf = (unsigned char) (ltmp & 0xff); for (k=0; k<8; k++) { tmp = xbuf >> k; tmp &= 1; rbyte |= tmp<<(7-k); } *dst = rbyte; D(if (i<5) { printf("Downloaded word: 0x%x\n", rbyte); }) } buf++; udelay(WAIT_WRITE); } /* More accesses on FPGA_PROG_ADDR in order to pass the startup phase */ for (i=0; i<10; i++) { *dst = 0; } udelay(WAIT_TIME); if (!check_gpio_pin(FPGA_INIT_PIN)){ printf("fpga error: INIT is LOW. It has to be HIGH\n"); return ERROR; } return OK;}char *XlnxHelp[] = { "Xilinx Spartan-II programming", "-[c] -[p:] -[f:]", "", "Options:", "-c clear configuration memory", "-p addr program loading directly from addr", "-f file program reading from TFS file", "", "addr: source address in hex of Xilinx bit file.", "file: filename of bit file in TFS.", "", "NOTE: In both programming modes -c is implicitly applied", 0};int Xlnx(int argc, char *argv[]){ unsigned long *address, *pr_addr; char *filename; int opt, addr_prog, file_prog, clear_mem; int rval; TFILE *fp; if (argc < 2) { printf("No arguments, exiting... use help\n"); return(0); } addr_prog = file_prog = clear_mem = 0; while((opt=getopt(argc,argv,"cf:p:")) != -1) { switch(opt) { case 'c': clear_mem = 1; break; case 'f': filename = optarg; file_prog = 1; break; case 'p': address = (unsigned long *)(strtol(optarg, (char **)0, 16)); addr_prog = 1; break; default: return(0); } } printf("Cleaning FPGA memory... "); if (fpga_mem_clean() < 0) { printf("xlnx error: not cleaned\n"); return(0); } printf("OK\n"); if (addr_prog) { pr_addr = address; } else if (file_prog){ fp = tfsstat(filename); if (fp == 0) { printf("xlnx error: file %s not found!\n", filename); return(0); } pr_addr = (unsigned long *)TFS_BASE(fp); } if (addr_prog || file_prog) { printf("Programming FPGA memory... "); if ((rval = fpga_program(pr_addr)) < 0) { if (rval == ERR_BITF) { printf("xlnx error: invalid bit file\n"); } else { printf("xlnx error: failed\n"); } return(0); } printf("OK\n"); } return(0);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -