Здравствуйте.
Я делал такой проект - при этом линии загрузки FPGA потом использовались в загруженной конфигурации как сигналы управления SPI.
Файл .RBF преобразовывается в соответствующий .С файл самописной утилитой, для того чтобы использовать передачу по SPI со старшего бита (в RBF файле младший бит первого байта должен уходить в FPGA первым).
Вот исходники утилиты (я использую 16 bit SPI для ускорения передачи - при программном управлении так быстрее получается).
Передача из FLASH по DMA во многих процессорах не поддерживается.
тфу, не удается присоединить файл. Превышен объём... Вот исходник утилиты.
CODE
#include <stdio.h>
// Функция разворота младших восьми бит
static unsigned revbits8(unsigned v)
{
unsigned b = v & 0xff;
b = ((b * 0x0802LU & 0x22110LU) | (b * 0x8020LU & 0x88440LU)) * 0x10101LU >> 16;
return b & 0xff;
}
int main(int argc, char* argv[])
{
if (argc < 2)
return 1;
FILE * fpi = fopen(argv [1], "rb");
if (fpi != NULL)
{
enum { ROWSOZE = 8 };
int pos = 0;
unsigned int words = 0;
unsigned int bytes = 0;
fprintf(stdout, "/* $Id: $ */\n");
fprintf(stdout, "/* Automaticaly generated header from file '%s' */\n", argv [1]);
fprintf(stdout, "static const FLASHMEM uint16_t rbfimage [] =\n");
fprintf(stdout, "{\n");
for (;;)
{
unsigned pv;
const int c1 = fgetc(fpi);
if (c1 == EOF)
break;
++ bytes;
const int c2 = fgetc(fpi);
if (c2 == EOF)
pv = revbits8((unsigned char) c1) * 256 | 0xff;
else
{
++ bytes;
pv = revbits8((unsigned char) c1) * 256 | revbits8((unsigned char) c2);
}
fprintf(stdout, " 0x%04X,%s", pv, ((pos + 1) >= ROWSOZE) ? "\n" : "");
pos = (pos + 1) % ROWSOZE;
++ words;
}
if (pos != 0)
fprintf(stdout, "\n");
fprintf(stdout, "};\n");
fprintf(stdout, "static const size_t rbflength = sizeof rbfimage / sizeof rbfimage [0]; /* %u 16-bit words (0x%08lx)*/\n", words, words);
fprintf(stderr, "file '%s', %u bytes converted to %u words.\n", argv [1], bytes, words);
}
return 0;
}
Ну и вот функция что грузит FPGA.
CODE
/* получение сигнала завершения конфигурации FPGA. Возврат: 0 - конфигурация не завершена */
static uint_fast8_t board_fpga_get_CONF_DONE(void)
{
return (FPGA_CONF_DONE_INPUT & FPGA_CONF_DONE_BIT) != 0;
}
static uint_fast8_t board_fpga_get_NSTATUS(void)
{
return (FPGA_NSTATUS_INPUT & FPGA_NSTATUS_BIT) != 0;
}
static void board_fpga_initialize(void)
{
HARDWARE_FPGA_LOADER_INITIALIZE();
}
/* FPGA загружается процессором с помощью SPI */
static void board_fpga_load_PS(void)
{
#include "rbfimage.h" // До 880 килобайт данных
//debug_printf_P(PSTR("fpga: board_fpga_load_PS start\n"));
do {
/* After power up, the Cyclone IV device holds nSTATUS low during POR delay. */
/* 1) Выставить "1" на nCONFIG */
//debug_printf_P(PSTR("fpga: FPGA_NCONFIG_BIT=1\n"));
FPGA_NCONFIG_PORT_C(FPGA_NCONFIG_BIT);
/* x) Дождаться "0" на nSTATUS */
//debug_printf_P(PSTR("fpga: waiting for FPGA_NSTATUS_BIT==0\n"));
while (board_fpga_get_NSTATUS() != 0)
;
FPGA_NCONFIG_PORT_S(FPGA_NCONFIG_BIT);
/* 2) Дождаться "1" на nSTATUS */
//debug_printf_P(PSTR("fpga: waiting for FPGA_NSTATUS_BIT==1\n"));
while (board_fpga_get_NSTATUS() == 0)
;
/* 3) Выдать байты (бладший бит .rbf файла первым) */
//debug_printf_P(PSTR("fpga: start sending RBF image (%lu of 16-bit words)\n"), rbflength);
if (rbflength != 0)
{
unsigned wcd = 0;
size_t n = rbflength - 1;
const uint16_t * p = rbfimage;
//
hardware_spi_connect16w(SPIC_SPEEDUFAST, SPIC_MODE3);
hardware_spi_word_p1(* p ++);
while (n --)
{
if (board_fpga_get_CONF_DONE() != 0)
{
//debug_printf_P(PSTR("fpga: Unexpected state of CONF_DONE==1\n"));
break;
}
hardware_spi_word_p2(* p ++);
}
//debug_printf_P(PSTR("fpga: done sending RBF image, waiting for CONF_DONE==1\n"));
/* 4) Дождаться "1" на CONF_DONE */
while (board_fpga_get_CONF_DONE() == 0)
{
++ wcd;
hardware_spi_word_p2(0xffff);
}
hardware_spi_complete();
hardware_spi_disconnect();
//debug_printf_P(PSTR("fpga: CONF_DONE asserted, wcd=%u\n"), wcd);
/*
After the configuration data is accepted and CONF_DONE goes
high, Cyclone IV devices require 3,192 clock cycles to initialize properly and enter
user mode.
*/
}
} while (board_fpga_get_NSTATUS() == 0); // если ошибка - повторяем
/* проверяем, проинициализировалась ли FPGA (вошла в user mode). */
while (HARDWARE_FPGA_IS_USER_MODE() == 0)
;
//debug_printf_P(PSTR("fpga: board_fpga_load_PS done\n"));
}