diff options
author | Fredrik Thulin <fredrik@thulin.net> | 2016-05-20 17:19:54 +0200 |
---|---|---|
committer | Fredrik Thulin <fredrik@thulin.net> | 2016-05-20 17:19:54 +0200 |
commit | fd5774fdebc04f92983e677f4bc210c75e8fcc94 (patch) | |
tree | 5732b6439ba2a2b61ae0375dc3e3375767c1293d | |
parent | a45288fc7e0e622615202c41304d34a510fb4e85 (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.c | 68 | ||||
-rw-r--r-- | spiflash_n25q128.c | 1 | ||||
-rw-r--r-- | stm-fpgacfg.c | 43 | ||||
-rw-r--r-- | stm-fpgacfg.h | 51 | ||||
-rw-r--r-- | stm-init.c | 81 | ||||
-rw-r--r-- | stm-led.h | 2 |
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 */ @@ -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 @@ -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) |