赞
踩
FPGA有多种不通的加载模式,模式由FPGA_M0、FPGA_M1、FPGA_M2三个引脚决定
通过原理图可以看到当前单板使用的模式是M[2:0]=111,即为从串模式
模式: slave serial (从串模式)
使用从串模式加载fpga用到的管脚如下:
Signal Name | Direction | Description |
---|---|---|
CCLK | Input | Configuration clock. |
PROGRAM_B | Input | Active-Low reset to configuration logic. |
INIT_B | Input/Output | Active-Low FPGA initialization pin. Indicates when the device is ready to receive configuration data. Also indicates any configuration errors. Can be held Low externally to delay configuration. |
DONE | Input/Output | Indicates configuration is complete. Can be held Low externally to delay start-up. |
M[2:0] | Input | Configuration mode selection. |
D01_DIN | Input | Serial configuration data input. |
DOUT | Output | Data output for serial daisy chains. |
具体对应到CPU的GPIO:
FPGA_PROG_B GPIO0_C5
FPGA_INIT_B GPIO0_B7
FPGA_DONE GPIO0_C4
FPGA_CONFIG_DIN GPIO0_C0
FPGA_CONFIG_CLK GPIO0_C6
从手册中可以看到FPGA基本配置流程如下图:
手册中给到的伪代码如下:
- /* Global defines
- * Define the addresses for the I/O peripherals used to control and
- * monitor the target FPGA. Also define the location in memory the
- * bitstream is stored and its size. These are system dependent and
- * should be adjusted as needed
- */
- /* Output GPIO addresses */
- CCLK_GPIO_BASEADDR = 0x40020000
- PROGRAM_B_GPIO_BASEADDR = 0x40030000
- SERIAL_OUT_GPIO_BASEADDR = 0x40040000
- /* Input GPIO addresses */
- INIT_B_GPIO_BASEADDR = 0x40050000
- DONE_GPIO_BASEADDR = 0x40060000
- /* Location in memory and size of the target bitstream */
- MEMORY_BASEADDR = 0xC0000000
- BITSTREAM_START_ADDR = MEMORY_BASEADDR + 0x2000000
- BITSTREAM_SIZE_BYTES = 0xAEA68C
- /* PROGRAM_B pulse width. Check the target FPGA data sheet for the
- * TPROGRAM pulse width. One microsecond is safe for any 7 series FPGA
- */
- TPROGRAM = 1 /* Assumes sleep() is microseconds */
- /* Serialize a 32-bit word and clock each bit on the target's DIN and
- * CCLK pins */
- shift_word_out(data32)
- {
- *cclk = CCLK_GPIO_BASEADDR
- *serial_out = SERIAL_OUT_GPIO_BASEADDR
- *cclk = 0
- *serial_out = 0
- for (i = 31; i >= 0; --i){
- *serial_out = (data32 & 1 << i) ? 1 : 0
- shift_cclk(1)
- }
- }
- /* Assert and Deassert CCLK */
- shift_cclk(count)
- {
- *cclk = CCLK_GPIO_BASEADDR
- *cclk = 0
- for (i = 0; i < count; --i) {
- *cclk = 1
- *cclk = 0
- }
- }
- int main()
- {
- bits_start = BITSTREAM_START_ADDR
- bits_size = BITSTREAM_SIZE_BYTES
- *program_b = PROGRAM_B_GPIO_BASEADDR
- *init_b = INIT_B_GPIO_BASEADDR
- *done = DONE_GPIO_BASEADDR
- /* Configuration Reset */
- *program_b = 0
- sleep(TPROGRAM)
- *program_b = 1
- /* Wait for Device Initialization */
- while(*init_b == 0);
-
- /* Configuration (Bitstream) Load */
- for (i = 0; i < bits_size; i+=4) {
- shift_word_out(bits_start + i)
- }
- /* Check INIT_B */
- if (*init_b_pointer == 0) {
- return 1
- }
- /* Wait for DONE to assert */
- while(*done == 0)
- ;
- /* Compensate for Special Startup Conditions */
- shift_cclk(8)
- return 0
- }

参考手册,使用gpio加载
- #define _GNU_SOURCE
- #include <unistd.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <fcntl.h>
- #include <getopt.h>
- #include <sys/ioctl.h>
- #include <string.h>
- #include <linux/gpio.h>
- #include <assert.h>
- #include "fpga.h"
- typedef unsigned int uint32_t;
- /* PROGRAM_B pulse width. Check the target FPGA data sheet for the
- * TPROGRAM pulse width. One microsecond is safe for any 7 series FPGA
- */
- #define TPROGRAM 1 /* Assumes sleep() is microseconds */
- #define SWAP_BYTES 1
- #define FPGABUFSIZE 4
- #define FPGA_INIT_B 15
- #define FPGA_PROG_B 21
- #define FPGA_DONE 20
- #define FPGA_CFG_CLK 22
- #define FPGA_CFG_DIN 16
- #define FPGA_PATH_NAME "/userdata/fpga.bin"
- int g_fdclk, g_fddin;
- static const char values_str[] = "01";
- /* Assert and Deassert CCLK */
- void shift_cclk(uint32_t count)
- {
- int i;
- for (i = 0; i < count; ++i) {
- write(g_fdclk, &values_str[1], 1);
- write(g_fdclk, &values_str[0], 1);
- }
- }
- /* Serialize a 32-bit word and clock each bit on the target's DIN and
- * CCLK pins */
- void shift_word_out(uint32_t data32)
- {
- int i;
- for (i = 31; i >= 0; --i){
- write(g_fddin, &values_str[(data32 & 1 << i) ? 1 : 0], 1);
- shift_cclk(1);
- }
- }
- uint32_t swap_uint32(uint32_t data){
- uint32_t swapped;
- if (SWAP_BYTES == 1)
- swapped = ((data << 24) & 0xFF000000) |
- ((data << 8) & 0x00FF0000) |
- ((data >> 8) & 0x0000FF00) |
- ((data >> 24) & 0x000000FF);
- else
- swapped = data;
- //printf("0x%08X: ", swapped );
- return swapped;
- }
- static void progress(unsigned long count, unsigned long total)
- {
- unsigned long percent;
-
- percent = count * 100;
- if (total)
- percent = (unsigned) (percent / total);
-
- if((0 == count%100000) || (100 == percent))
- {
- printf("\r FpgaLoad: %lu/%lu (%u%%) ", count, total, (unsigned)percent);
- }
-
- fflush(NULL);
- }
- int bsp_fpga_bit_write(void)
- {
- int fd_f;
- char *filename;
- struct stat statb;
- unsigned long done;
- unsigned long rem;
- unsigned long count;
- unsigned char buffer[FPGABUFSIZE] = {0};
- //static const char values_str[] = "01";
- char pathclk[64], pathdin[64];
- filename = FPGA_PATH_NAME;
-
- fd_f = open(filename, O_RDONLY);
- if (fd_f < 0)
- {
- printf("%s , file not found.\n", FPGA_PATH_NAME);
- return -1;
- }
- fstat(fd_f, &statb);
- printf("Fpga size is %d.\n", statb.st_size);
-
- snprintf(pathclk, sizeof(pathclk), "/sys/class/gpio/gpio%d/value", FPGA_CFG_CLK);
- snprintf(pathdin, sizeof(pathdin), "/sys/class/gpio/gpio%d/value", FPGA_CFG_DIN);
- g_fdclk = open(pathclk, O_WRONLY);
- if (g_fdclk < 0) {
- printf("Failed to open gpio FPGA_CFG_CLK for writing!\n");
- return -1;
- }
- g_fddin = open(pathdin, O_WRONLY);
- if (g_fddin < 0) {
- printf("Failed to open gpio FPGA_CFG_DIN for writing!\n");
- return -1;
- }
- done = 0;
- count = FPGABUFSIZE;
- if (write(g_fdclk, &values_str[0], 1) < 0) {
- printf("Failed to write value!\n");
- close(g_fdclk);
- return -1;
- }
-
- while(1)
- {
- rem = statb.st_size - done;
- if (rem == 0)
- break;
- if (rem < FPGABUFSIZE)
- count = rem;
-
- read(fd_f, buffer, count);
-
- if (count < FPGABUFSIZE)
- memset((char*)buffer + count, 0, FPGABUFSIZE - count);
-
- shift_word_out( swap_uint32( *(uint32_t *)(buffer) ));
-
- if (gpio_read(FPGA_INIT_B) == 0) {
- printf("INIT_B error\n");
- close(g_fdclk);
- close(g_fddin);
- return -1;
- }
- progress(done, statb.st_size);
- done += count;
- }
- printf("FPGA write finished.\n");
- close(g_fdclk);
- close(g_fddin);
- close(fd_f);
- return 0;
- }
- int bsp_fpga_serial_load(void)
- {
- uint32_t i = 0;
- gpio_export(FPGA_INIT_B);
- gpio_export(FPGA_PROG_B);
- gpio_export(FPGA_DONE);
- gpio_export(FPGA_CFG_CLK);
- gpio_export(FPGA_CFG_DIN);
- gpio_direction(FPGA_PROG_B,1);
- gpio_direction(FPGA_CFG_CLK,1);
- gpio_direction(FPGA_CFG_DIN,1);
- /* Configuration Reset */
- gpio_write(FPGA_PROG_B, 0);
- sleep(TPROGRAM);
- gpio_write(FPGA_PROG_B, 1);
- /* Wait for Device Initialization */
- while(gpio_read(FPGA_INIT_B) == 0)
- {
- ++i;
- if (i > 0x00010000) {
- printf("waiting for INIT_B go high out of time.\n");
- return 1;
- }
- }
- printf("Downloading Bitstream to target FPGA.\n");
- /* Configuration (Bitstream) Load */
- if (bsp_fpga_bit_write() != 0)
- {
- printf("fpga bit write error.\n");
- return 1;
- }
- /* Check INIT_B */
- if (gpio_read(FPGA_INIT_B) == 0) {
- printf("INIT_B error\n");
- return 1;
- }
- /* Wait for DONE to assert */
- i = 0;
- while(gpio_read(FPGA_DONE) == 0)
- {
- shift_cclk(1);
- ++i;
- if (i > 0x00001000 ) {
- printf("DONE has not go high.\n");
- return 1;
- }
- }
- printf("FPGA Load successed!\n");
- /* Compensate for Special Startup Conditions */
- shift_cclk(8);
- return 0;
- }

使用gpio方式加载需要代码中shift时钟,效率较低,实测整个加载流程耗时8min,严重超时
预留管脚足以支撑spi的单向传输,改为使用spi加载
spi加载fpga代码
- int fpga_cfg_init(void)
- {
- int fd, ret = 0;
- char *device = "/dev/spidev0.0";
- fd = open(device, O_RDWR);
- if (fd < 0)
- pabort("can't open device");
- ret = ioctl(fd, SPI_IOC_WR_MODE32, &fmode);
- if (ret == -1)
- pabort("can't set spi mode");
- ret = ioctl(fd, SPI_IOC_RD_MODE32, &fmode);
- if (ret == -1)
- pabort("can't get spi mode");
- ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &fbits);
- if (ret == -1)
- pabort("can't set bits per word");
- ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &fbits);
- if (ret == -1)
- pabort("can't get bits per word");
- ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &fspeed);
- if (ret == -1)
- pabort("can't set max speed hz");
- ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &fspeed);
- if (ret == -1)
- pabort("can't get max speed hz");
- return fd;
- }
- static void progress(unsigned long count, unsigned long total)
- {
- unsigned long percent;
- unsigned long printsize = 1024*1024;
-
- percent = count * 100;
- if (total)
- percent = (unsigned) (percent / total);
- if((0 == count%printsize) || (100 == percent)){
- printf("\r FpgaLoad: %lu/%lu (%u%%) ", count, total, (unsigned)percent);
- }
-
- fflush(NULL);
- }
- #define FPGA_BUFFER_SIZE 32*1024
- void transfer_file(int fd, char *filename)
- {
- ssize_t bytes;
- struct stat sb;
- int tx_fd;
- uint8_t *tx;
- uint8_t *rx;
- unsigned long done;
- unsigned long rem;
- unsigned long count;
- if (stat(filename, &sb) == -1)
- pabort("can't stat input file");
- tx_fd = open(filename, O_RDONLY);
- if (tx_fd < 0)
- pabort("can't open input file");
- tx = malloc(FPGA_BUFFER_SIZE);
- if (!tx)
- pabort("can't allocate tx buffer");
- rx = malloc(FPGA_BUFFER_SIZE);
- if (!rx)
- pabort("can't allocate rx buffer");
- done = 0;
- count = FPGA_BUFFER_SIZE;
- while(1)
- {
- rem = sb.st_size - done;
- if (rem == 0)
- break;
- if (rem < FPGA_BUFFER_SIZE)
- count = rem;
- bytes = read(tx_fd, tx, count);
- if (bytes != count)
- pabort("failed to read input file");
-
- if (count < FPGA_BUFFER_SIZE)
- memset((char*)tx + count, 0, FPGA_BUFFER_SIZE - count);
-
- transfers(fd, tx, rx, count);
- progress(done, sb.st_size);
- done += count;
- }
- free(rx);
- free(tx);
- close(tx_fd);
- }

整个加载过程能在10s内完成,满足要求。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。