STM32f407 网络接收 fpga 的 bin 文件并更新到 fpga series7(3)

STM32f407 网络接收 fpga 的 bin 文件并更新到 fpga series7(3)

简介

实验 3:在搭建好 tcp 服务器,并拟定好协议的前提下,接收每一个 bin 文件的块,配置到 fpga。

原理图

fpga
在这里插入图片描述

fpga1
在这里插入图片描述

stm32
在这里插入图片描述

接线总结

// fpga引脚 stm32引脚
// 用不到D_OUT
#define PROGRAM_B PB0
#define INT_B     PB1
#define CCLK      PC10
#define D01_DIN   PC12
#define DONE      PD3

手册

搜索下载关键词:Xilinx XAPP583 Using a Microprocessor to Configure Xilinx 7 Series FPGAs

引脚

在这里插入图片描述

时序

在这里插入图片描述

伪代码在手册里,自己看

stm32cube 配置

在这里插入图片描述

单片机代码

load_fpga.c

#include "load_fpga.h"

#include <stdio.h>
#include "main.h"

#define WRITE_PROGRAM_B(x) HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, x)
#define WRITE_CCLK(x)      HAL_GPIO_WritePin(GPIOC, GPIO_PIN_10, x)
#define WRITE_D01_DIN(x)   HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, x)
#define READ_INT_B()       HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_1)
#define READ_DONE()        HAL_GPIO_ReadPin(GPIOD, GPIO_PIN_3)

/// @brief 交换4字节顺序
/// eg: 0xaabbccdd -> 0xddccbbaas
/// @param data
/// @return
unsigned int swap_uint32(unsigned int data) {
    unsigned int swapped;
    swapped = ((data << 24) & 0xFF000000) | ((data << 8) & 0x00FF0000) |
              ((data >> 8) & 0x0000FF00) | ((data >> 24) & 0x000000FF);
    return swapped;
}


/// @brief 产生count个时钟上升沿
/// @param drvdata
/// @param count
void shift_cclk(unsigned int count) {
    int i;
    // WRITE_CCLK(0); // 感觉有点多余,影响接收速度了
    for (i = 0; i < count; ++i) {
        WRITE_CCLK(1);
        WRITE_CCLK(0);
    }
}


/// @brief 写入每一位,从高位开始
/// @param data32
void shift_word_out(unsigned int data32) {
    int i;
    unsigned int data;

    for (i = 31; i >= 0; i--) {
        data = (data32 & 1 << i) ? 1 : 0;
        WRITE_D01_DIN(data);
        shift_cclk(1);
    }
}


/// @brief 准备写入
/// 配置准备下入状态
/// @param
/// @return 成功返回0
int program_init(void) {
    int i = 0;
    /* Configuration Reset */
    WRITE_PROGRAM_B(0);
    HAL_Delay(1);  // 1us
    WRITE_PROGRAM_B(1);

    /* Wait for Device Initialization */
    while (READ_INT_B() == 0) {
        ++i;
        if (i > 0x00010000) {
            printf("INIT_B has not gone high\n");
            return -1;
        }
    }
    return 0;
}


/// @brief 写入fpga
/// @param buf
/// @param len
/// @return 成功返回0
int program_data(char *buf, int len) {
    int i;
    for (i = 0; i < len; i += 4) {
        shift_word_out(swap_uint32(*(uint32_t *)(buf + i)));
        if (READ_INT_B() == 0) {
            printf("INIT_B error\n");
            return -1;
        }
    }
    return 0;
}


/// @brief 写入完成
/// @param
/// @return 成功返回0
int program_done(void) {
    /* Check INIT_B */
    if (READ_INT_B() == 0) {
        printf("INIT_B error\n");
        return -1;
    }

    /* Wait for DONE to assert */
    int i = 0;
    while (READ_DONE() == 0) {
        shift_cclk(1);  // 不加会导致又概率失败
        ++i;
        if (i > 0x00010000) {
            printf("DONE has not gone high\n");
            return -1;
        }
    }

    /* Compensate for Special Startup Conditions */
    shift_cclk(8);
    return 0;
}

tcp_echo.c

#include "tcp_echo.h"
#include "lwip/opt.h"
#include "lwip/tcp.h"
#include "load_fpga.h"
#if LWIP_NETCONN

    #include "lwip/sys.h"
    #include "lwip/api.h"

    #define TCPECHO_THREAD_PRIO (tskIDLE_PRIORITY + 4)

    #define kbuffer_len  1024
    #define kheader_size 24
    #define kdata_len    1000
    #define kmagic       0xaa5555aa

char buffer[kbuffer_len];

struct tcp_package_header {
    uint32_t magic;
    uint32_t type;
    uint32_t data_offset;
    uint32_t data_len;
    uint32_t order;
    uint32_t magic1;
};

/// @brief TCP服务函数
/// @param arg
static void tcpecho_thread(void *arg) {
    struct netconn *conn, *newconn;
    err_t err, accept_err;
    struct netbuf *buf;
    void *data;
    u16_t len;
    int ret = 0;
    LWIP_UNUSED_ARG(arg);
    #if 1
    /* Create a new connection identifier. */
    conn = netconn_new(NETCONN_TCP);

    if (conn != NULL) {
        /* Bind connection to well known port number 7. */
        err = netconn_bind(conn, NULL, 7);

        if (err == ERR_OK) {
            /* Tell connection to go into listening mode. */
            netconn_listen(conn);

            while (1) {
                /* Grab new connection. */
                accept_err = netconn_accept(conn, &newconn);

                /* Process the new connection. */
                if (accept_err == ERR_OK) {
                    while (netconn_recv(newconn, &buf) == ERR_OK) {
                        netbuf_data(buf, &data, &len);
                        do {
                            // 1 拿到帧头
                            struct tcp_package_header *head;
                            head = (struct tcp_package_header *)data;
                            // 2 判断type
                            switch (head->type) {
                                case 0xA: ret = program_init(); break;
                                case 0xB:
                                    ret = program_data(
                                        (char *)data + sizeof(struct tcp_package_header),
                                        head->data_len);
                                    break;
                                case 0xC: ret = program_done(); break;
                                default: break;
                            }

                            // 3 回发给tcp_client
                            if (ret < 0) {
                                head->data_offset = 1;
                            } else {
                                head->data_offset = 0;
                            }
                            netconn_write(newconn, head, sizeof(struct tcp_package_header),
                                          NETCONN_COPY);

                        } while (netbuf_next(buf) >= 0);

                        netbuf_delete(buf);
                    }

                    /* Close connection and discard connection identifier. */
                    netconn_close(newconn);
                    netconn_delete(newconn);
                }
            }
        } else {
            netconn_delete(newconn);
        }
    }
    #endif
}

// 创建tcp服务函数任务
void tcpecho_init(void) {
    sys_thread_new("tcpecho_thread", tcpecho_thread, NULL, DEFAULT_THREAD_STACKSIZE,
                   TCPECHO_THREAD_PRIO);
}

#endif /* LWIP_NETCONN */

加载前

在这里插入图片描述
加载后
在这里插入图片描述

上位机在这里插入图片描述

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值