STM32F103RCT6 升级FPGA(EP2C8Q208)


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启动方式,硬件连接图可以如下所示:

STM32F103RCT6 升级FPGA(EP2C8Q208)_第1张图片
PS启动

MSEL等硬件连接需要按照如下所示:

STM32F103RCT6 升级FPGA(EP2C8Q208)_第2张图片
MSEL启动模式

在开始传输时,要将nCONFIG引脚输出一个从低到高的电平。在nSTATUS为高电平的时候,单片机类控制芯片需要在DATA[0]上一直放置数据。

写一下每个引脚以及应有的含义:

引脚 输入输出 功能
nCONFIG 输出 开始配置
nSTATUS 输入 升级响应标记位以及出错标志
CONFIG_DONE 输入 升级完成标志位
DCLK 输出 升级数据时钟
DATA[0] 输出 升级数据

在黑金开发板上设置为PS模式的时候,需要做到:

引脚名称 引脚号 FPGA接线
MSEL1 125 GND,已经为低电平
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 数据组织格式

发送数据格式为LSB,也就是说首先发送低位。举个例子:

02 1B EE 01 FA
0100-0000 1101-1000 0111-0111 1000-0000 0101-1111

数据在DCLK的上升沿锁存。FPGA在CONFIG_DONE为高电平的时候进入初始化状态。

注意要将DCLK的速率设置在系统的运行频率以下。

如果FPGA接收了所有的数据,但是CONFIG_DONE或者INIT_DONE并没有变为高电平。单片机等控制类芯片需要重新配置FPGA。

控制时序图如下所示:

STM32F103RCT6 升级FPGA(EP2C8Q208)_第3张图片
PS模式时序图
STM32F103RCT6 升级FPGA(EP2C8Q208)_第4张图片
PS模式时间参数1
STM32F103RCT6 升级FPGA(EP2C8Q208)_第5张图片
PS模式时间参数2

3 控制流程

下面说说使用PS方式给FPGA升级程序的流程:

1 . 在上电后,先将nCONFIG和DCLK设置为高电平,时间在100ms,然后将nCONFIG设置为低电平,时间在2us。
2 . 检测nSTATUS,如果为0,表示FPGA已经响应配置,可以进行配置了。否则就是报错了,正常情况下,在nCONFIG=0后1us之内,nSTATUS就会为0。
3 . nCONFIG为1,等待nSTATUS为高,如果超过5us,则说明有错误,跳出到步骤1。
4 . 发送数据,并且设置DCLK=1,然后延时。
5 . DCLK=0,检测nSTATUS,如果为0,则说明有错误,则需要重新开始传送数据。
6 . 再次发送数据,循环4,5两步步骤,一直等到数据发送完成。
7 . 数据发送完成之后,nCONFIG将会置1。若数据发送完成后,数据不为1,则说明数据发送有误,需要重新开始配置。
8 . 配置完成之后,需要等待40个DCLK周期,等待FPGA初始化完成。不过最好是检测状态,如果INIT_DONE不为高,说明有误,需要跳到步骤1。

具体可参考下面的图示:

STM32F103RCT6 升级FPGA(EP2C8Q208)_第6张图片
FPGA程序升级步骤

上图要注意几点:
1.FPGA上电启动过程会持续100ms。
2.配置过程有三阶段:复位,配置和初始化。
3.nCONFIG或者nSTATUS引脚电平为低,FPGA会在复位的状态。
4.要判断CONFIG_DONE和INIT_DONE引脚电平,超时则表示错误。

4 出错处理

在配置的时候,如果出错,nSTATUS引脚会变低,形成内部自己复位。我们在做PS升级FPGA程序的时候,需要将Auto-restart configuration after error选项关闭,实现自己控制。

5 程序

实验可以这样做:STM32开发板上有ENC28J60网络芯片或者其他的网络芯片,使用TFTP下载FPGA生成了的实验性.rbf文件,将该文件下载到STM32的SPI FLASH上,然后,使用上面1~4部分说明的内容,给FPGA升级程序,现在贴出关于升级FPGA的实验性代码,注意,要多做出错处理。

#include "stm32_fpga.h"
#include 

#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

提供给外部接口的有三个函数:

1.stm32_send_start_to_fpga(),作用是传输起始信号
2.stm32_send_byte_to_fpga(),作用是传输数据
3.stm32_get_fpga_config_done_flag(),作用是读取配置完成的标志,还需要加上INIT_DONE标志

这个程序,经过测算,一个74K的程序,需要6s的时间。

你可能感兴趣的:(STM32F103RCT6 升级FPGA(EP2C8Q208))