/* * stm-fpgacfg.h * --------- * Functions and defines for accessing the FPGA config memory and controlling * the low-level status of the FPGA (reset registers/reboot etc.). * * Copyright (c) 2016, NORDUnet A/S All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of the NORDUnet nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef __STM32_FPGACFG_H #define __STM32_FPGACFG_H #include "stm32f4xx_hal.h" #include "spiflash_n25q128.h" /* Pins connected to the FPGA config memory (SPI flash) */ #define PROM_FPGA_DIS_Pin GPIO_PIN_14 #define PROM_FPGA_DIS_GPIO_Port GPIOI #define PROM_ARM_ENA_Pin GPIO_PIN_6 #define PROM_ARM_ENA_GPIO_Port GPIOF #define PROM_CS_N_Pin GPIO_PIN_12 #define PROM_CS_N_GPIO_Port GPIOB /* Pins for controlling the FPGA */ #define FPGA_INIT_Port GPIOJ #define FPGA_INIT_Pin GPIO_PIN_7 #define FPGA_PROGRAM_Port GPIOJ #define FPGA_PROGRAM_Pin GPIO_PIN_8 /* FPGA status */ #define FPGA_DONE_Port GPIOJ #define FPGA_DONE_Pin GPIO_PIN_15 #define FPGACFG_GPIO_INIT() \ __GPIOI_CLK_ENABLE(); \ __GPIOF_CLK_ENABLE(); \ __GPIOB_CLK_ENABLE(); \ __GPIOJ_CLK_ENABLE(); \ /* Configure GPIO pins for FPGA access control: PROM_FPGA_DIS, PROM_ARM_ENA */ \ gpio_output(PROM_FPGA_DIS_GPIO_Port, PROM_FPGA_DIS_Pin, GPIO_PIN_RESET); \ gpio_output(PROM_ARM_ENA_GPIO_Port, PROM_ARM_ENA_Pin, GPIO_PIN_RESET); \ /* Configure GPIO pin for FPGA config memory chip select : PROM_CS_N */ \ gpio_output(PROM_CS_N_GPIO_Port, PROM_CS_N_Pin, GPIO_PIN_SET); \ /* Configure GPIO pins FPGA_INIT and FPGA_PROGRAM to reset the FPGA */ \ gpio_output(FPGA_INIT_Port, FPGA_INIT_Pin, GPIO_PIN_RESET); \ gpio_output(FPGA_PROGRAM_Port, FPGA_PROGRAM_Pin, GPIO_PIN_SET); \ /* Configure FPGA_DONE input pin */ \ gpio_input(FPGA_DONE_Port, FPGA_DONE_Pin, GPIO_PULLUP) enum fpgacfg_access_ctrl { ALLOW_NONE, ALLOW_FPGA, ALLOW_ARM, }; enum fpgacfg_reset { RESET_FULL, RESET_REGISTERS, }; extern SPI_HandleTypeDef hspi_fpgacfg; extern int fpgacfg_check_id(void); extern int fpgacfg_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len); extern int fpgacfg_erase_sectors(int num); extern void fpgacfg_access_control(enum fpgacfg_access_ctrl access); /* Reset the FPGA */ extern void fpgacfg_reset_fpga(enum fpgacfg_reset reset); /* Check status of FPGA bitstream loading */ extern int fpgacfg_check_done(void); #endif /* __STM32_FPGACFG_H */ ' href='#n16'>16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
/*
 * mgmt-fpga.c
 * -----------
 * CLI code to manage the FPGA configuration etc.
 *
 * Copyright (c) 2016, NORDUnet A/S All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of the NORDUnet nor the names of its contributors may
 *   be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "stm-init.h"
#include "stm-uart.h"
#include "stm-fpgacfg.h"

#include "mgmt-cli.h"
#include "mgmt-fpga.h"
#include "mgmt-misc.h"

#include <string.h>


static volatile uint32_t dfu_offset = 0;



static int _flash_write_callback(uint8_t *buf, size_t len) {
    int res = fpgacfg_write_data(dfu_offset, buf, BITSTREAM_UPLOAD_CHUNK_SIZE) == 1;
    dfu_offset += BITSTREAM_UPLOAD_CHUNK_SIZE;
    return res;
}

static int cmd_fpga_bitstream_upload(struct cli_def *cli, const char *command, char *argv[], int argc)
{
    uint8_t buf[BITSTREAM_UPLOAD_CHUNK_SIZE];

    dfu_offset = 0;

    fpgacfg_access_control(ALLOW_ARM);

    cli_print(cli, "Checking if FPGA config memory is accessible");
    if (fpgacfg_check_id() != 1) {
	cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed.");
	return CLI_ERROR;
    }

    cli_receive_data(cli, &buf[0], sizeof(buf), _flash_write_callback);

    fpgacfg_access_control(ALLOW_FPGA);

    cli_print(cli, "DFU offset now: %li (%li chunks)", dfu_offset, dfu_offset / BITSTREAM_UPLOAD_CHUNK_SIZE);
    return CLI_OK;
}

static int cmd_fpga_bitstream_erase(struct cli_def *cli, const char *command, char *argv[], int argc)
{
    fpgacfg_access_control(ALLOW_ARM);

    cli_print(cli, "Checking if FPGA config memory is accessible");
    if (fpgacfg_check_id() != 1) {
	cli_print(cli, "ERROR: FPGA config memory not accessible. Check that jumpers JP7 and JP8 are installed.");
	return CLI_ERROR;
    }

    /* Erasing the whole config memory takes a while, we just need to erase the first sector.
     * The bitstream has an EOF marker, so even if the next bitstream uploaded is shorter than
     * the current one there should be no problem.
     *
     * This command could be made to accept an argument indicating the whole memory should be erased.
     */
    if (! fpgacfg_erase_sectors(1)) {
	cli_print(cli, "Erasing first sector in FPGA config memory failed");
	return CLI_ERROR;
    }

    cli_print(cli, "Erased FPGA config memory");
    fpgacfg_access_control(ALLOW_FPGA);

    return CLI_OK;
}

static int cmd_fpga_reset(struct cli_def *cli, const char *command, char *argv[], int argc)
{
    fpgacfg_access_control(ALLOW_FPGA);
    fpgacfg_reset_fpga(RESET_FULL);
    cli_print(cli, "FPGA has been reset");

    return CLI_OK;
}

static int cmd_fpga_reset_registers(struct cli_def *cli, const char *command, char *argv[], int argc)
{
    fpgacfg_access_control(ALLOW_FPGA);
    fpgacfg_reset_fpga(RESET_REGISTERS);
    cli_print(cli, "FPGA registers have been reset");

    return CLI_OK;
}

void configure_cli_fpga(struct cli_def *cli)
{
    struct cli_command *c = cli_register_command(cli, NULL, "fpga", NULL, 0, 0, NULL);

    /* fpga reset */
    struct cli_command *c_reset = cli_register_command(cli, c, "reset", cmd_fpga_reset, 0, 0, "Reset FPGA (config reset)");

    /* fpga reset registers */
    cli_register_command(cli, c_reset, "registers", cmd_fpga_reset_registers, 0, 0, "Reset FPGA registers (soft reset)");

    struct cli_command *c_bitstream = cli_register_command(cli, c, "bitstream", NULL, 0, 0, NULL);

    /* fpga bitstream upload */
    cli_register_command(cli, c_bitstream, "upload", cmd_fpga_bitstream_upload, 0, 0, "Upload new FPGA bitstream");

    /* fpga bitstream erase */
    cli_register_command(cli, c_bitstream, "erase", cmd_fpga_bitstream_erase, 0, 0, "Erase FPGA config memory");
}