1 基本說明
EP2C8Q208封裝為208個引腳枢赔,也就是52*4的封裝格式鉴吹。
FPGA啟動方式有三種:jtag驰坊,AS和PS嗡载。使用STM32F103RCT6啟動FPGA窑多,使用的是PS方式。
AS全稱為active serial洼滚,DCLK可以運行在40MHz的頻率上埂息。
PS全稱為passive serial,
JTAG全稱為Joint Test Action Group。
FPGA啟動千康,可以接受的文件有.rbf享幽,.hex和.ttf格式。
使用PS啟動方式拾弃,硬件連接圖可以如下所示:
MSEL等硬件連接需要按照如下所示:
在開始傳輸時值桩,要將nCONFIG引腳輸出一個從低到高的電平。在nSTATUS為高電平的時候豪椿,單片機類控制芯片需要在DATA[0]上一直放置數(shù)據(jù)奔坟。
寫一下每個引腳以及應(yīng)有的含義:
引腳 | 輸入輸出 | 功能 |
---|---|---|
nCONFIG | 輸出 | 開始配置 |
nSTATUS | 輸入 | 升級響應(yīng)標(biāo)記位以及出錯標(biāo)志 |
CONFIG_DONE | 輸入 | 升級完成標(biāo)志位 |
DCLK | 輸出 | 升級數(shù)據(jù)時鐘 |
DATA[0] | 輸出 | 升級數(shù)據(jù) |
在黑金開發(fā)板上設(shè)置為PS模式的時候,需要做到:
引腳名稱 | 引腳號 | FPGA接線 |
---|---|---|
MSEL1 | 125 | GND搭盾,已經(jīng)為低電平 |
MSEL0 | 126 | 拉高咳秉,在第三面的22號腳上 |
nCONFIG | 26 | 可以接在R3上或者AS的J1的5號引腳上 |
nSTATUS | 121 | 接在R4上 |
CONFIG_DONE | 123 | 接在J1上的3號引腳上 |
DCLK | 21 | 接在J1上的1號引腳上 |
DATA[0] | 20 | 接在J1上的7號引腳上 |
INIT_DONE | 107 | 只能飛線接上去 |
2 數(shù)據(jù)組織格式
發(fā)送數(shù)據(jù)格式為LSB,也就是說首先發(fā)送低位鸯隅。舉個例子:
02 1B EE 01 FA
0100-0000 1101-1000 0111-0111 1000-0000 0101-1111
數(shù)據(jù)在DCLK的上升沿鎖存澜建。FPGA在CONFIG_DONE為高電平的時候進(jìn)入初始化狀態(tài)。
注意要將DCLK的速率設(shè)置在系統(tǒng)的運行頻率以下蝌以。
如果FPGA接收了所有的數(shù)據(jù)炕舵,但是CONFIG_DONE或者INIT_DONE并沒有變?yōu)楦唠娖健纹瑱C等控制類芯片需要重新配置FPGA饼灿。
控制時序圖如下所示:
3 控制流程
下面說說使用PS方式給FPGA升級程序的流程:
1 . 在上電后幕侠,先將nCONFIG和DCLK設(shè)置為高電平帝美,時間在100ms碍彭,然后將nCONFIG設(shè)置為低電平,時間在2us悼潭。
2 . 檢測nSTATUS庇忌,如果為0,表示FPGA已經(jīng)響應(yīng)配置舰褪,可以進(jìn)行配置了皆疹。否則就是報錯了,正常情況下占拍,在nCONFIG=0后1us之內(nèi)略就,nSTATUS就會為0。
3 . nCONFIG為1晃酒,等待nSTATUS為高表牢,如果超過5us,則說明有錯誤贝次,跳出到步驟1崔兴。
4 . 發(fā)送數(shù)據(jù),并且設(shè)置DCLK=1,然后延時敲茄。
5 . DCLK=0位谋,檢測nSTATUS,如果為0堰燎,則說明有錯誤掏父,則需要重新開始傳送數(shù)據(jù)。
6 . 再次發(fā)送數(shù)據(jù)秆剪,循環(huán)4损同,5兩步步驟,一直等到數(shù)據(jù)發(fā)送完成鸟款。
7 . 數(shù)據(jù)發(fā)送完成之后膏燃,nCONFIG將會置1。若數(shù)據(jù)發(fā)送完成后何什,數(shù)據(jù)不為1组哩,則說明數(shù)據(jù)發(fā)送有誤,需要重新開始配置处渣。
8 . 配置完成之后伶贰,需要等待40個DCLK周期,等待FPGA初始化完成罐栈。不過最好是檢測狀態(tài)黍衙,如果INIT_DONE不為高,說明有誤荠诬,需要跳到步驟1琅翻。
具體可參考下面的圖示:
上圖要注意幾點:
1.FPGA上電啟動過程會持續(xù)100ms。
2.配置過程有三階段:復(fù)位柑贞,配置和初始化方椎。
3.nCONFIG或者nSTATUS引腳電平為低,F(xiàn)PGA會在復(fù)位的狀態(tài)钧嘶。
4.要判斷CONFIG_DONE和INIT_DONE引腳電平棠众,超時則表示錯誤。
4 出錯處理
在配置的時候有决,如果出錯闸拿,nSTATUS引腳會變低,形成內(nèi)部自己復(fù)位书幕。我們在做PS升級FPGA程序的時候新荤,需要將Auto-restart configuration after error選項關(guān)閉,實現(xiàn)自己控制按咒。
5 程序
實驗可以這樣做:STM32開發(fā)板上有ENC28J60網(wǎng)絡(luò)芯片或者其他的網(wǎng)絡(luò)芯片迟隅,使用TFTP下載FPGA生成了的實驗性.rbf文件但骨,將該文件下載到STM32的SPI FLASH上,然后智袭,使用上面1~4部分說明的內(nèi)容奔缠,給FPGA升級程序,現(xiàn)在貼出關(guān)于升級FPGA的實驗性代碼吼野,注意校哎,要多做出錯處理。
#include "stm32_fpga.h"
#include <stm32f10x.h>
#define nSTATUS_rcc RCC_APB2Periph_GPIOA
#define nSTATUS_gpio GPIOA
#define nSTATUS_pin (GPIO_Pin_2)
#define CONFIG_DONE_rcc RCC_APB2Periph_GPIOA
#define CONFIG_DONE_gpio GPIOA
#define CONFIG_DONE_pin (GPIO_Pin_3)
#define nCONFIG_rcc RCC_APB2Periph_GPIOA
#define nCONFIG_gpio GPIOA
#define nCONFIG_pin (GPIO_Pin_1)
#define DCLK_rcc RCC_APB2Periph_GPIOB
#define DCLK_gpio GPIOB
#define DCLK_pin (GPIO_Pin_0)
#define DATA_rcc RCC_APB2Periph_GPIOB
#define DATA_gpio GPIOB
#define DATA_pin (GPIO_Pin_1)
#define FPGA_IO_SET 1
#define FPGA_IO_RESET 0
static void stm32_fpga_delay_us(unsigned int u_delay);
void set_nCONFIG_io_output(unsigned char val);
void set_DCLK_io_output(unsigned char val);
void set_DATA_io_output(unsigned char val);
/*
* copyright wit_yuan 2017-07-19
*
* PA1-----LED1----nCONFIG
* PA2-----LED2----nSTATUS
* PA3-----LED3----CONFIG_DONE
* PB0-----LED4----DCLK
* PB1-----LED5----DATA[0]
*/
void STM32_FPGA_IO_Init( void )
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(nSTATUS_rcc|CONFIG_DONE_rcc|nCONFIG_rcc|DCLK_rcc|DATA_rcc,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = nSTATUS_pin;
GPIO_Init(nSTATUS_gpio, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = CONFIG_DONE_pin;
GPIO_Init(CONFIG_DONE_gpio, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = nCONFIG_pin;
GPIO_Init(nCONFIG_gpio, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = DCLK_pin;
GPIO_Init(DCLK_gpio, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = DATA_pin;
GPIO_Init(DATA_gpio, &GPIO_InitStructure);
set_nCONFIG_io_output(FPGA_IO_SET);
set_DCLK_io_output(FPGA_IO_RESET);
set_DATA_io_output(FPGA_IO_RESET);
}
/*
* copyright wit_yuan 2017-07-19
*
*/
void set_nCONFIG_io_output(unsigned char val){
switch(val){
case 0:
GPIO_ResetBits(nCONFIG_gpio, nCONFIG_pin);
break;
case 1:
GPIO_SetBits(nCONFIG_gpio, nCONFIG_pin);
break;
}
}
/*
* copyright wit_yuan 2017-07-19
*
*
*/
void set_DCLK_io_output(unsigned char val){
switch(val){
case 0:
GPIO_ResetBits(DCLK_gpio, DCLK_pin);
break;
case 1:
GPIO_SetBits(DCLK_gpio, DCLK_pin);
break;
}
}
/*
* copyright wit_yuan 2017-07-19
*
*/
void set_DATA_io_output(unsigned char val){
switch(val){
case 0:
GPIO_ResetBits(DATA_gpio, DATA_pin);
break;
case 1:
GPIO_SetBits(DATA_gpio, DATA_pin);
break;
}
}
unsigned char get_nSTATUS_io_input( void )
{
return GPIO_ReadInputDataBit(nSTATUS_gpio, nSTATUS_pin);
}
unsigned char get_CONFIG_DONE_io_input( void )
{
return GPIO_ReadInputDataBit(CONFIG_DONE_gpio, CONFIG_DONE_pin);
}
static void stm32_fpga_delay_us(unsigned int u_delay)
{
int i = 0,j=0;
for( i = 0 ; i < 3 ; i++){
for(j=0;j<u_delay;j++){
;
}
}
}
unsigned char stm32_send_start_to_fpga( void )
{
stm32_fpga_delay_us(1000000);
if(get_nSTATUS_io_input() == 0)
{
rt_kprintf(" status first low \r\n");
}
set_nCONFIG_io_output(FPGA_IO_SET);
set_DCLK_io_output(FPGA_IO_RESET);
set_DATA_io_output(FPGA_IO_RESET);
stm32_fpga_delay_us(10);
/*nCONFIG=0*/
set_nCONFIG_io_output(FPGA_IO_RESET);
set_DCLK_io_output(FPGA_IO_RESET);
stm32_fpga_delay_us(2);
set_nCONFIG_io_output(FPGA_IO_SET);
if(get_nSTATUS_io_input() == 0)
{
rt_kprintf(" fpga reacked \r\n");
stm32_fpga_delay_us(1000);
if(get_nSTATUS_io_input()==0)
{
}
else
{
rt_kprintf(" status high is right \r\n");
}
}
else
{
return 1;
}
rt_kprintf(" fpga config start \r\n");
stm32_fpga_delay_us(5);
return 0;
}
/*
* copyright wit_yuan 2017-07-19
*
*
*/
unsigned char stm32_send_byte_to_fpga( unsigned char data )
{
int i = 0;
unsigned char tmp;
tmp = data;
for(i = 0 ; i < 8 ; i ++){
if(tmp & (1<<i)){
set_DATA_io_output(FPGA_IO_SET);
}
else
{
set_DATA_io_output(FPGA_IO_RESET);
}
stm32_fpga_delay_us(1);
set_DCLK_io_output(FPGA_IO_SET);
stm32_fpga_delay_us(1);
set_DCLK_io_output(FPGA_IO_RESET);
/*?ì2anSTATUS£?è?1??a0£?±íê?óD′í?ó*/
if(get_nSTATUS_io_input()==0){
return 1;
}
stm32_fpga_delay_us(1);
}
return 0;
}
unsigned char stm32_get_fpga_config_done_flag( )
{
if(get_CONFIG_DONE_io_input()==1){
rt_kprintf(" config done \r\n");
}
return get_CONFIG_DONE_io_input();
//stm32_fpga_delay_us(100000);
}
提供給外部接口的有三個函數(shù):
1.stm32_send_start_to_fpga()瞳步,作用是傳輸起始信號
2.stm32_send_byte_to_fpga()闷哆,作用是傳輸數(shù)據(jù)
3.stm32_get_fpga_config_done_flag(),作用是讀取配置完成的標(biāo)志单起,還需要加上INIT_DONE標(biāo)志
這個程序抱怔,經(jīng)過測算,一個74K的程序嘀倒,需要6s的時間屈留。