aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFredrik Thulin <fredrik@thulin.net>2016-05-20 17:19:54 +0200
committerFredrik Thulin <fredrik@thulin.net>2016-05-20 17:19:54 +0200
commitfd5774fdebc04f92983e677f4bc210c75e8fcc94 (patch)
tree5732b6439ba2a2b61ae0375dc3e3375767c1293d
parenta45288fc7e0e622615202c41304d34a510fb4e85 (diff)
Add code to reset FPGA using FPGA_PROGRAM_B and FPGA_INIT_B.
Also add code to erase FPGA config memory and check status of FPGA_DONE.
-rw-r--r--projects/cli-test/cli-test.c68
-rw-r--r--spiflash_n25q128.c1
-rw-r--r--stm-fpgacfg.c43
-rw-r--r--stm-fpgacfg.h51
-rw-r--r--stm-init.c81
-rw-r--r--stm-led.h2
6 files changed, 189 insertions, 57 deletions
diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c
index e7d49a7..92eb7c0 100644
--- a/projects/cli-test/cli-test.c
+++ b/projects/cli-test/cli-test.c
@@ -92,6 +92,12 @@ int cmd_filetransfer(struct cli_def *cli, const char *command, char *argv[], int
return CLI_OK;
}
+int cmd_show_fpga_status(struct cli_def *cli, const char *command, char *argv[], int argc)
+{
+ cli_print(cli, "FPGA has %sloaded a bitstream", fpgacfg_check_done() ? "":"NOT ");
+ return CLI_OK;
+}
+
/* The chunk size have to be a multiple of the SPI flash page size (256 bytes),
and it has to match the chunk size in the program sending the bitstream over the UART.
*/
@@ -165,6 +171,51 @@ int cmd_fpga_bitstream_upload(struct cli_def *cli, const char *command, char *ar
return CLI_OK;
}
+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;
+}
+
+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;
+}
+
+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;
+}
+
int cmd_reboot(struct cli_def *cli, const char *command, char *argv[], int argc)
{
cli_print(cli, "\n\n\nRebooting\n\n\n");
@@ -189,15 +240,27 @@ main()
struct cli_command cmd_show_cpuspeed_s = {(char *) "cpuspeed", cmd_show_cpuspeed, 0,
(char *) "Show the speed at which the CPU currently operates",
PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL};
+ struct cli_command cmd_show_fpga_s = {(char *) "fpga", NULL, 0, NULL, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL};
+ struct cli_command cmd_show_fpga_status_s = {(char *) "status", cmd_show_fpga_status, 0, NULL, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL};
+
struct cli_command cmd_filetransfer_s = {(char *) "filetransfer", cmd_filetransfer, 0,
(char *) "Test file transfering",
PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL};
struct cli_command cmd_fpga_s = {(char *) "fpga", NULL, 0, NULL, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL};
+ struct cli_command cmd_fpga_reset_s = {(char *) "reset", cmd_fpga_reset, 0,
+ (char *) "Reset FPGA (config reset)",
+ PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL};
+ struct cli_command cmd_fpga_reset_registerss = {(char *) "registers", cmd_fpga_reset_registers, 0,
+ (char *) "Reset FPGA registers (soft reset)",
+ PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL};
struct cli_command cmd_fpga_bitstream_s = {(char *) "bitstream", NULL, 0, NULL, PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL};
struct cli_command cmd_fpga_bitstream_upload_s = {(char *) "upload", cmd_fpga_bitstream_upload, 0,
(char *) "Upload new FPGA bitstream",
PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL};
+ struct cli_command cmd_fpga_bitstream_erase_s = {(char *) "erase", cmd_fpga_bitstream_erase, 0,
+ (char *) "Erase FPGA config memory",
+ PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL};
struct cli_command cmd_reboot_s = {(char *) "reboot", cmd_reboot, 0,
(char *) "Reboot the STM32",
PRIVILEGE_UNPRIVILEGED, MODE_EXEC, NULL, NULL, NULL};
@@ -212,12 +275,17 @@ main()
cli_register_command2(&cli, &cmd_show_s, NULL);
cli_register_command2(&cli, &cmd_show_cpuspeed_s, &cmd_show_s);
+ cli_register_command2(&cli, &cmd_show_fpga_s, &cmd_show_s);
+ cli_register_command2(&cli, &cmd_show_fpga_status_s, &cmd_show_fpga_s);
cli_register_command2(&cli, &cmd_filetransfer_s, NULL);
cli_register_command2(&cli, &cmd_fpga_s, NULL);
+ cli_register_command2(&cli, &cmd_fpga_reset_s, &cmd_fpga_s);
+ cli_register_command2(&cli, &cmd_fpga_reset_registerss, &cmd_fpga_reset_s);
cli_register_command2(&cli, &cmd_fpga_bitstream_s, &cmd_fpga_s);
cli_register_command2(&cli, &cmd_fpga_bitstream_upload_s, &cmd_fpga_bitstream_s);
+ cli_register_command2(&cli, &cmd_fpga_bitstream_erase_s, &cmd_fpga_bitstream_s);
cli_register_command2(&cli, &cmd_reboot_s, NULL);
diff --git a/spiflash_n25q128.c b/spiflash_n25q128.c
index 10f5954..985e727 100644
--- a/spiflash_n25q128.c
+++ b/spiflash_n25q128.c
@@ -317,7 +317,6 @@ int n25q128_write_data(struct spiflash_ctx *ctx, uint32_t offset, const uint8_t
}
for (page = 0; page < len / N25Q128_PAGE_SIZE; page++) {
- /* Wait until the flash memory is done writing (wip = Write In Progress) */
if (! _wait_while_wip(ctx, 1000)) return -5;
if (! n25q128_write_page(ctx, offset / N25Q128_PAGE_SIZE, buf)) {
diff --git a/stm-fpgacfg.c b/stm-fpgacfg.c
index f8ff6fa..9e2a307 100644
--- a/stm-fpgacfg.c
+++ b/stm-fpgacfg.c
@@ -1,7 +1,8 @@
/*
* stm-fpgacfg.c
* ----------
- * Functions for accessing the FPGA config memory.
+ * Functions 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.
*
@@ -69,3 +70,43 @@ void fpgacfg_access_control(enum fpgacfg_access_ctrl access)
HAL_GPIO_WritePin(GPIOF, PROM_ARM_ENA_Pin, GPIO_PIN_SET);
}
}
+
+void fpgacfg_reset_fpga(enum fpgacfg_reset reset)
+{
+ if (reset == RESET_FULL) {
+ /* The delay should be at least 250 uS. With HAL_Delay(1) the pulse is very close
+ * to that, and With HAL_Delay(3) the pulse is close to 2 ms. */
+ HAL_GPIO_WritePin(FPGA_PROGRAM_Port, FPGA_PROGRAM_Pin, GPIO_PIN_RESET);
+ HAL_Delay(3);
+ HAL_GPIO_WritePin(FPGA_PROGRAM_Port, FPGA_PROGRAM_Pin, GPIO_PIN_SET);
+ } else if (reset == RESET_REGISTERS) {
+ HAL_GPIO_WritePin(FPGA_INIT_Port, FPGA_INIT_Pin, GPIO_PIN_SET);
+ HAL_Delay(3);
+ HAL_GPIO_WritePin(FPGA_INIT_Port, FPGA_INIT_Pin, GPIO_PIN_RESET);
+ }
+}
+
+int fpgacfg_check_done(void)
+{
+ GPIO_PinState status = HAL_GPIO_ReadPin(FPGA_DONE_Port, FPGA_DONE_Pin);
+ return (status == GPIO_PIN_SET);
+}
+
+int fpgacfg_erase_sectors(int num)
+{
+ if (num > N25Q128_NUM_SECTORS - 1 || num < 0) num = N25Q128_NUM_SECTORS - 1;
+ while (num) {
+ int timeout = 1000;
+ while (timeout--) {
+ int i = n25q128_get_wip_flag(&fpgacfg_ctx);
+ if (i < 0) return 0;
+ if (! i) break;
+ HAL_Delay(10);
+ }
+
+ if (! n25q128_erase_sector(&fpgacfg_ctx, num--)) {
+ return 0;
+ }
+ }
+ return 1;
+}
diff --git a/stm-fpgacfg.h b/stm-fpgacfg.h
index ad86a89..367aa3d 100644
--- a/stm-fpgacfg.h
+++ b/stm-fpgacfg.h
@@ -1,7 +1,8 @@
/*
* stm-fpgacfg.h
* ---------
- * Functions and defines for accessing the FPGA config memory.
+ * 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.
*
@@ -38,24 +39,60 @@
#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) \
+ 1
enum fpgacfg_access_ctrl {
- ALLOW_NONE,
- ALLOW_FPGA,
- ALLOW_ARM,
+ ALLOW_NONE,
+ ALLOW_FPGA,
+ ALLOW_ARM,
};
-extern int fpgacfg_check_id();
-extern int fpgacfg_write_data(uint32_t offset, const uint8_t *buf, const uint32_t len);
-extern void fpgacfg_access_control(enum fpgacfg_access_ctrl access);
+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 */
diff --git a/stm-init.c b/stm-init.c
index 2c19d58..8711cc1 100644
--- a/stm-init.c
+++ b/stm-init.c
@@ -139,65 +139,50 @@ static void MX_USART2_UART_Init(void)
#endif
#ifdef HAL_GPIO_MODULE_ENABLED
-/** Configure pins as
- * Analog
- * Input
- * Output
- * EVENT_OUT
- * EXTI
-*/
+
+#define gpio_output(output_port, output_pins, output_level) \
+ /* Configure GPIO pin Output Level */ \
+ HAL_GPIO_WritePin(output_port, output_pins, output_level); \
+ /* Configure pin as output */ \
+ GPIO_InitStruct.Pin = output_pins; \
+ GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; \
+ GPIO_InitStruct.Pull = GPIO_NOPULL; \
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \
+ HAL_GPIO_Init(output_port, &GPIO_InitStruct)
+
+#define gpio_input(input_port, input_pin, input_pull) \
+ GPIO_InitStruct.Pin = input_pin; \
+ GPIO_InitStruct.Mode = GPIO_MODE_INPUT; \
+ GPIO_InitStruct.Pull = input_pull; \
+ GPIO_InitStruct.Speed = GPIO_SPEED_LOW; \
+ HAL_GPIO_Init(input_port, &GPIO_InitStruct)
+
+
+/* Configure General Purpose Input/Output pins */
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIO Ports Clock Enable */
- __GPIOK_CLK_ENABLE();
-
- /* Configure LED GPIO pins PJ1==red, PJ2==yellow, PJ3==green, PJ4==blue */
- GPIO_InitStruct.Pin = LED_RED | LED_YELLOW | LED_GREEN | LED_BLUE;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_LOW;
- HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
-
-
+ LED_CLK_ENABLE();
+ /* Configure LED GPIO pins */
+ gpio_output(LED_PORT, LED_RED | LED_YELLOW | LED_GREEN | LED_BLUE, GPIO_PIN_RESET);
#ifdef HAL_SPI_MODULE_ENABLED
- /* Set up GPIOs to manage access to the FPGA config memory. */
-
+ /* Set up GPIOs to manage access to the FPGA config memory.
+ * FPGACFG_GPIO_INIT is defined in stm-fpgacfg.h.
+ */
/* GPIO Ports Clock Enable */
- __GPIOI_CLK_ENABLE();
- __GPIOF_CLK_ENABLE();
- __GPIOB_CLK_ENABLE();
-
- /*Configure GPIO pin Output Level */
- HAL_GPIO_WritePin(PROM_FPGA_DIS_GPIO_Port, PROM_FPGA_DIS_Pin, GPIO_PIN_RESET);
- HAL_GPIO_WritePin(PROM_ARM_ENA_GPIO_Port, PROM_ARM_ENA_Pin, GPIO_PIN_RESET);
- HAL_GPIO_WritePin(PROM_CS_N_GPIO_Port, PROM_CS_N_Pin, GPIO_PIN_SET); // active-low!!!
-
- /*Configure GPIO pin : PROM_FPGA_DIS */
- GPIO_InitStruct.Pin = PROM_FPGA_DIS_Pin;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- HAL_GPIO_Init(PROM_FPGA_DIS_GPIO_Port, &GPIO_InitStruct);
-
- /*Configure GPIO pin : PROM_ARM_ENA */
- GPIO_InitStruct.Pin = PROM_ARM_ENA_Pin;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- HAL_GPIO_Init(PROM_ARM_ENA_GPIO_Port, &GPIO_InitStruct);
-
- /*Configure GPIO pin : PROM_CS_N */
- GPIO_InitStruct.Pin = PROM_CS_N_Pin;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_NOPULL;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
- HAL_GPIO_Init(PROM_CS_N_GPIO_Port, &GPIO_InitStruct);
+ FPGACFG_GPIO_INIT();
+ /*
+ __GPIOJ_CLK_ENABLE();
+ gpio_output(FPGA_INIT_Port, FPGA_INIT_Pin, GPIO_PIN_RESET);
+ gpio_output(FPGA_PROGRAM_Port, FPGA_PROGRAM_Pin, GPIO_PIN_SET);
+ */
#endif /* HAL_SPI_MODULE_ENABLED */
}
+#undef gpio_output
#endif
#ifdef HAL_I2C_MODULE_ENABLED
diff --git a/stm-led.h b/stm-led.h
index 7c20879..e2453e4 100644
--- a/stm-led.h
+++ b/stm-led.h
@@ -43,6 +43,8 @@
#define LED_GREEN GPIO_PIN_5
#define LED_BLUE GPIO_PIN_4
+#define LED_CLK_ENABLE __GPIOK_CLK_ENABLE
+
#define led_on(pin) HAL_GPIO_WritePin(LED_PORT,pin,SET)
#define led_off(pin) HAL_GPIO_WritePin(LED_PORT,pin,RESET)
#define led_toggle(pin) HAL_GPIO_TogglePin(LED_PORT,pin)