From 3b044e50d3295c04863bdb0587a6eef157e654b8 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Wed, 18 May 2016 14:10:09 +0200 Subject: FPGA config memory access code from Pavel. --- Makefile | 1 + .../TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h | 2 +- .../TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c | 36 ++- stm-fpgacfg.c | 279 +++++++++++++++++++++ stm-fpgacfg.h | 80 ++++++ stm-init.c | 67 +++++ 6 files changed, 463 insertions(+), 2 deletions(-) create mode 100644 stm-fpgacfg.c create mode 100644 stm-fpgacfg.h diff --git a/Makefile b/Makefile index d2fc5ef..f43bac4 100644 --- a/Makefile +++ b/Makefile @@ -54,6 +54,7 @@ export BOARD_OBJS = \ $(TOPLEVEL)/stm-fmc.o \ $(TOPLEVEL)/stm-uart.o \ $(TOPLEVEL)/stm-rtc.o \ + $(TOPLEVEL)/stm-fpgacfg.o \ $(TOPLEVEL)/syscalls.o \ $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/startup_stm32f429xx.o \ $(BOARD_DIR)/system_stm32f4xx.o \ diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h index 31c0e31..3844481 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_conf.h @@ -78,7 +78,7 @@ //#define HAL_RTC_MODULE_ENABLED //#define HAL_SAI_MODULE_ENABLED //#define HAL_SD_MODULE_ENABLED -//#define HAL_SPI_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED #define HAL_TIM_MODULE_ENABLED #define HAL_UART_MODULE_ENABLED //#define HAL_USART_MODULE_ENABLED diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c index a430c5e..c6a8a67 100644 --- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c +++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/stm32f4xx_hal_msp.c @@ -182,6 +182,8 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) GPIO_InitTypeDef GPIO_InitStruct; if (hi2c->Instance == I2C2) { /* + * External RTC chip. + * * I2C2 GPIO Configuration * PH5 ------> I2C2_SDA * PH4 ------> I2C2_SCL @@ -203,11 +205,43 @@ void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) { - if(hi2c->Instance == I2C2) { + if (hi2c->Instance == I2C2) { __I2C2_CLK_DISABLE(); HAL_GPIO_DeInit(GPIOH, GPIO_PIN_4 | GPIO_PIN_5); } } +void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi) +{ + GPIO_InitTypeDef GPIO_InitStruct; + if (hspi->Instance == SPI2) { + /* Peripheral clock enable */ + __HAL_RCC_SPI2_CLK_ENABLE(); + + /* SPI2 is the FPGA config memory. + * + * SPI2 GPIO Configuration + * PB13 ------> SPI2_SCK + * PB14 ------> SPI2_MISO + * PB15 ------> SPI2_MOSI + */ + GPIO_InitStruct.Pin = GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15; + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH; + GPIO_InitStruct.Alternate = GPIO_AF5_SPI2; + HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); + } +} + +void HAL_SPI_MspDeInit(SPI_HandleTypeDef* hspi) +{ + + if (hspi->Instance == SPI2) { + /* Peripheral clock disable */ + __HAL_RCC_SPI2_CLK_DISABLE(); + HAL_GPIO_DeInit(GPIOB, GPIO_PIN_13 | GPIO_PIN_14 | GPIO_PIN_15); + } +} /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stm-fpgacfg.c b/stm-fpgacfg.c new file mode 100644 index 0000000..0026b9e --- /dev/null +++ b/stm-fpgacfg.c @@ -0,0 +1,279 @@ +/* + * stm-fpgacfg.c + * ---------- + * Functions for accessing the FPGA config memory. + * + * 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 "stm32f4xx_hal.h" +#include "stm-fpgacfg.h" + +SPI_HandleTypeDef hspi_fpgacfg; + +int _n25q128_get_wel_flag(void); + + +int n25q128_check_id() +{ + // tx, rx buffers + uint8_t spi_tx[4]; + uint8_t spi_rx[4]; + + // result + HAL_StatusTypeDef ok; + + // send READ ID command + spi_tx[0] = N25Q128_COMMAND_READ_ID; + + // select, send command & read response, deselect + _n25q128_select(); + ok = HAL_SPI_TransmitReceive(N25Q128_SPI_HANDLE, spi_tx, spi_rx, 4, N25Q128_SPI_TIMEOUT); + HAL_Delay(1); + _n25q128_deselect(); + + // check + if (ok != HAL_OK) return 0; + + // parse response (note, that the very first byte was received during the + // transfer of the command byte, so it contains garbage and should + // be ignored here) + if (spi_rx[1] != N25Q128_ID_MANUFACTURER) return 0; + if (spi_rx[2] != N25Q128_ID_DEVICE_TYPE) return 0; + if (spi_rx[3] != N25Q128_ID_DEVICE_CAPACITY) return 0; + + // done + return 1; +} + + +int n25q128_read_page(uint32_t page_offset, uint8_t *page_buffer) +{ + // tx buffer + uint8_t spi_tx[4]; + + // result + HAL_StatusTypeDef ok; + + // check offset + if (page_offset >= N25Q128_NUM_PAGES) return 0; + + // calculate byte address + page_offset *= N25Q128_PAGE_SIZE; + + // prepare READ command + spi_tx[0] = N25Q128_COMMAND_READ_PAGE; + spi_tx[1] = (uint8_t)(page_offset >> 16); + spi_tx[2] = (uint8_t)(page_offset >> 8); + spi_tx[3] = (uint8_t)(page_offset >> 0); + + // activate, send command + _n25q128_select(); + ok = HAL_SPI_Transmit(N25Q128_SPI_HANDLE, spi_tx, 4, N25Q128_SPI_TIMEOUT); + HAL_Delay(1); + + // check + if (ok != HAL_OK) { + _n25q128_deselect(); + return 0; + } + + // read response, deselect + ok = HAL_SPI_Receive(N25Q128_SPI_HANDLE, page_buffer, N25Q128_PAGE_SIZE, N25Q128_SPI_TIMEOUT); + HAL_Delay(1); + _n25q128_deselect(); + + // check + if (ok != HAL_OK) return 0; + + // done + return 1; +} + + +int n25q128_write_page(uint32_t page_offset, uint8_t *page_buffer) +{ + // tx buffer + uint8_t spi_tx[4]; + + // result + HAL_StatusTypeDef ok; + + // check offset + if (page_offset >= N25Q128_NUM_PAGES) return 0; + + // enable writing + spi_tx[0] = N25Q128_COMMAND_WRITE_ENABLE; + + // activate, send command, deselect + _n25q128_select(); + ok = HAL_SPI_Transmit(N25Q128_SPI_HANDLE, spi_tx, 1, N25Q128_SPI_TIMEOUT); + HAL_Delay(1); + _n25q128_deselect(); + + // check + if (ok != HAL_OK) return 0; + + // make sure, that write enable did the job + int wel = _n25q128_get_wel_flag(); + if (wel != 1) return 0; + + // calculate byte address + page_offset *= N25Q128_PAGE_SIZE; + + // prepare PROGRAM PAGE command + spi_tx[0] = N25Q128_COMMAND_PAGE_PROGRAM; + spi_tx[1] = (uint8_t)(page_offset >> 16); + spi_tx[2] = (uint8_t)(page_offset >> 8); + spi_tx[3] = (uint8_t)(page_offset >> 0); + + // activate, send command + _n25q128_select(); + ok = HAL_SPI_Transmit(N25Q128_SPI_HANDLE, spi_tx, 4, N25Q128_SPI_TIMEOUT); + HAL_Delay(1); + + // check + if (ok != HAL_OK) { + _n25q128_deselect(); + return 0; + } + + // send data, deselect + ok = HAL_SPI_Transmit(N25Q128_SPI_HANDLE, page_buffer, N25Q128_PAGE_SIZE, N25Q128_SPI_TIMEOUT); + HAL_Delay(1); + _n25q128_deselect(); + + // check + if (ok != HAL_OK) return 0; + + // done + return 1; +} + + +int n25q128_get_wip_flag(void) +{ + // tx, rx buffers + uint8_t spi_tx[2]; + uint8_t spi_rx[2]; + + // result + HAL_StatusTypeDef ok; + + // send READ STATUS command + spi_tx[0] = N25Q128_COMMAND_READ_STATUS; + + // send command, read response, deselect + _n25q128_select(); + ok = HAL_SPI_TransmitReceive(N25Q128_SPI_HANDLE, spi_tx, spi_rx, 2, N25Q128_SPI_TIMEOUT); + HAL_Delay(1); + _n25q128_deselect(); + + // check + if (ok != HAL_OK) return -1; + + // done + return (spi_rx[1] & 1); +} + + +int n25q128_erase_sector(uint32_t sector_offset) +{ + // tx buffer + uint8_t spi_tx[4]; + + // result + HAL_StatusTypeDef ok; + + // check offset + if (sector_offset >= N25Q128_NUM_SECTORS) return 0; + + // enable writing + spi_tx[0] = N25Q128_COMMAND_WRITE_ENABLE; + + // select, send command, deselect + _n25q128_select(); + ok = HAL_SPI_Transmit(N25Q128_SPI_HANDLE, spi_tx, 1, N25Q128_SPI_TIMEOUT); + HAL_Delay(1); + _n25q128_deselect(); + + // check + if (ok != HAL_OK) return 0; + + // make sure, that write enable did the job + int wel = _n25q128_get_wel_flag(); + if (wel != 1) return 0; + + // calculate byte address + sector_offset *= N25Q128_SECTOR_SIZE; + + // send ERASE SUBSECTOR command + spi_tx[0] = N25Q128_COMMAND_ERASE_SECTOR; + spi_tx[1] = (uint8_t)(sector_offset >> 16); + spi_tx[2] = (uint8_t)(sector_offset >> 8); + spi_tx[3] = (uint8_t)(sector_offset >> 0); + + // activate, send command, deselect + _n25q128_select(); + ok = HAL_SPI_Transmit(N25Q128_SPI_HANDLE, spi_tx, 4, N25Q128_SPI_TIMEOUT); + HAL_Delay(1); + _n25q128_deselect(); + + // check + if (ok != HAL_OK) return 0; + + // done + return 1; +} + + +int _n25q128_get_wel_flag(void) +{ + // tx, rx buffers + uint8_t spi_tx[2]; + uint8_t spi_rx[2]; + + // result + HAL_StatusTypeDef ok; + + // send READ STATUS command + spi_tx[0] = N25Q128_COMMAND_READ_STATUS; + + // send command, read response, deselect + _n25q128_select(); + ok = HAL_SPI_TransmitReceive(N25Q128_SPI_HANDLE, spi_tx, spi_rx, 2, N25Q128_SPI_TIMEOUT); + HAL_Delay(1); + _n25q128_deselect(); + + // check + if (ok != HAL_OK) return -1; + + // done + return ((spi_rx[1] >> 1) & 1); +} diff --git a/stm-fpgacfg.h b/stm-fpgacfg.h new file mode 100644 index 0000000..bed3b38 --- /dev/null +++ b/stm-fpgacfg.h @@ -0,0 +1,80 @@ +/* + * stm-fpgacfg.h + * --------- + * Functions and defines for accessing the FPGA config memory. + * + * 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" + +#define N25Q128_SPI_HANDLE (&hspi_fpgacfg) + +#define N25Q128_COMMAND_READ_ID 0x9E +#define N25Q128_COMMAND_READ_PAGE 0x03 +#define N25Q128_COMMAND_READ_STATUS 0x05 +#define N25Q128_COMMAND_WRITE_ENABLE 0x06 +#define N25Q128_COMMAND_ERASE_SECTOR 0xD8 +#define N25Q128_COMMAND_PAGE_PROGRAM 0x02 + +#define N25Q128_PAGE_SIZE 0x100 // 256 +#define N25Q128_NUM_PAGES 0x10000 // 65536 + +#define N25Q128_SECTOR_SIZE 0x10000 // 65536 +#define N25Q128_NUM_SECTORS 0x100 // 256 + +#define N25Q128_SPI_TIMEOUT 1000 + +#define N25Q128_ID_MANUFACTURER 0x20 +#define N25Q128_ID_DEVICE_TYPE 0xBA +#define N25Q128_ID_DEVICE_CAPACITY 0x18 + +#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 + + +#define _n25q128_select() HAL_GPIO_WritePin(PROM_CS_N_GPIO_Port, PROM_CS_N_Pin, GPIO_PIN_RESET); +#define _n25q128_deselect() HAL_GPIO_WritePin(PROM_CS_N_GPIO_Port, PROM_CS_N_Pin, GPIO_PIN_SET); + +extern int n25q128_check_id(void); +extern int n25q128_get_wip_flag(void); +extern int n25q128_read_page(uint32_t page_offset, uint8_t *page_buffer); +extern int n25q128_write_page(uint32_t page_offset, uint8_t *page_buffer); +extern int n25q128_erase_sector(uint32_t sector_offset); + +extern SPI_HandleTypeDef hspi_fpgacfg; + +#endif /* __STM32_FPGACFG_H */ diff --git a/stm-init.c b/stm-init.c index af3d47b..ab1905b 100644 --- a/stm-init.c +++ b/stm-init.c @@ -47,6 +47,9 @@ #ifdef HAL_I2C_MODULE_ENABLED #include "stm-rtc.h" #endif +#ifdef HAL_SPI_MODULE_ENABLED +#include "stm-fpgacfg.h" +#endif /* Private variables ---------------------------------------------------------*/ @@ -61,6 +64,9 @@ static void MX_USART2_UART_Init(void); #ifdef HAL_I2C_MODULE_ENABLED static void MX_I2C2_Init(void); #endif +#ifdef HAL_SPI_MODULE_ENABLED +static void MX_SPI2_Init(void); +#endif void stm_init(void) { @@ -83,6 +89,9 @@ void stm_init(void) #ifdef HAL_I2C_MODULE_ENABLED MX_I2C2_Init(); #endif +#ifdef HAL_SPI_MODULE_ENABLED + MX_SPI2_Init(); +#endif } @@ -144,6 +153,44 @@ static void MX_GPIO_Init(void) GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct); + + + + +#ifdef HAL_SPI_MODULE_ENABLED + /* Set up GPIOs to manage access to the FPGA config memory. */ + + /* GPIO Ports Clock Enable */ + __HAL_RCC_GPIOI_CLK_ENABLE(); + __HAL_RCC_GPIOF_CLK_ENABLE(); + __HAL_RCC_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); +#endif /* HAL_SPI_MODULE_ENABLED */ } #endif @@ -167,6 +214,26 @@ void MX_I2C2_Init(void) } #endif +#ifdef HAL_SPI_MODULE_ENABLED +/* SPI2 (FPGA config memory) init function */ +void MX_SPI2_Init(void) +{ + hspi_fpgacfg.Instance = SPI2; + hspi_fpgacfg.Init.Mode = SPI_MODE_MASTER; + hspi_fpgacfg.Init.Direction = SPI_DIRECTION_2LINES; + hspi_fpgacfg.Init.DataSize = SPI_DATASIZE_8BIT; + hspi_fpgacfg.Init.CLKPolarity = SPI_POLARITY_LOW; + hspi_fpgacfg.Init.CLKPhase = SPI_PHASE_1EDGE; + hspi_fpgacfg.Init.NSS = SPI_NSS_SOFT; + hspi_fpgacfg.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2; + hspi_fpgacfg.Init.FirstBit = SPI_FIRSTBIT_MSB; + hspi_fpgacfg.Init.TIMode = SPI_TIMODE_DISABLE; + hspi_fpgacfg.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; + hspi_fpgacfg.Init.CRCPolynomial = 10; + HAL_SPI_Init(&hspi_fpgacfg); +} +#endif /* HAL_SPI_MODULE_ENABLED */ + /** * @brief This function is executed in case of error occurrence. * @param None -- cgit v1.2.3